@phreshos/client 0.1.0
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 +65 -0
- package/dist/channel.d.ts +8 -0
- package/dist/channel.js +16 -0
- package/dist/content.d.ts +7 -0
- package/dist/content.js +51 -0
- package/dist/current.d.ts +20 -0
- package/dist/current.js +58 -0
- package/dist/deadline.d.ts +7 -0
- package/dist/deadline.js +13 -0
- package/dist/domain.d.ts +93 -0
- package/dist/domain.js +285 -0
- package/dist/events.d.ts +16 -0
- package/dist/events.js +83 -0
- package/dist/host.d.ts +25 -0
- package/dist/host.js +149 -0
- package/dist/log.d.ts +6 -0
- package/dist/log.js +64 -0
- package/dist/main.d.ts +5 -0
- package/dist/main.js +4 -0
- package/dist/storage.d.ts +5 -0
- package/dist/storage.js +98 -0
- package/dist/wire.d.ts +34 -0
- package/dist/wire.js +226 -0
- package/package.json +30 -0
package/dist/events.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export const defaultTimeout = 10_000;
|
|
2
|
+
/** SDK-owned waits, queues and callbacks over boundary forwarding state. */
|
|
3
|
+
export default class Events {
|
|
4
|
+
listen;
|
|
5
|
+
listenAll;
|
|
6
|
+
constructor(listen, listenAll) {
|
|
7
|
+
this.listen = listen;
|
|
8
|
+
this.listenAll = listenAll;
|
|
9
|
+
}
|
|
10
|
+
subscribe(event, subscriber) {
|
|
11
|
+
return this.listen(event, subscriber);
|
|
12
|
+
}
|
|
13
|
+
waitFor(event, timeout = defaultTimeout) {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
let settled = false;
|
|
16
|
+
let stop = () => undefined;
|
|
17
|
+
const finish = (settle) => {
|
|
18
|
+
if (settled)
|
|
19
|
+
return;
|
|
20
|
+
settled = true;
|
|
21
|
+
clearTimeout(timer);
|
|
22
|
+
stop();
|
|
23
|
+
settle();
|
|
24
|
+
};
|
|
25
|
+
const timer = setTimeout(() => finish(() => reject(new Error(`Event promise timeout ${timeout}ms`))), timeout);
|
|
26
|
+
stop = this.listen(event, message => finish(() => resolve(message)), error => finish(() => reject(error)));
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
events(event, options = {}) {
|
|
30
|
+
const capacity = options.capacity ?? 64;
|
|
31
|
+
if (capacity !== Infinity && (!Number.isInteger(capacity) || capacity < 0)) {
|
|
32
|
+
throw new Error("An event queue capacity must be a non-negative integer or Infinity");
|
|
33
|
+
}
|
|
34
|
+
const listen = this.listen;
|
|
35
|
+
return (async function* () {
|
|
36
|
+
const queue = [];
|
|
37
|
+
let ended = false;
|
|
38
|
+
let failure = null;
|
|
39
|
+
let wake = null;
|
|
40
|
+
const stop = listen(event, message => {
|
|
41
|
+
if (ended || failure)
|
|
42
|
+
return;
|
|
43
|
+
if (queue.length >= capacity)
|
|
44
|
+
failure = new Error(`Event queue exceeded its capacity of ${capacity}`);
|
|
45
|
+
else
|
|
46
|
+
queue.push(message);
|
|
47
|
+
wake?.();
|
|
48
|
+
wake = null;
|
|
49
|
+
}, error => {
|
|
50
|
+
if (ended || failure)
|
|
51
|
+
return;
|
|
52
|
+
failure = error;
|
|
53
|
+
wake?.();
|
|
54
|
+
wake = null;
|
|
55
|
+
});
|
|
56
|
+
const abort = () => {
|
|
57
|
+
ended = true;
|
|
58
|
+
wake?.();
|
|
59
|
+
wake = null;
|
|
60
|
+
};
|
|
61
|
+
options.signal?.addEventListener("abort", abort, { once: true });
|
|
62
|
+
try {
|
|
63
|
+
while (!ended) {
|
|
64
|
+
if (queue.length) {
|
|
65
|
+
yield queue.shift();
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (failure)
|
|
69
|
+
throw failure;
|
|
70
|
+
await new Promise(resolve => { wake = resolve; });
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
ended = true;
|
|
75
|
+
stop();
|
|
76
|
+
options.signal?.removeEventListener("abort", abort);
|
|
77
|
+
}
|
|
78
|
+
})();
|
|
79
|
+
}
|
|
80
|
+
observe(observer) {
|
|
81
|
+
return this.listenAll((event, message) => observer({ event, message }));
|
|
82
|
+
}
|
|
83
|
+
}
|
package/dist/host.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Layer, ServedFile, Subscribable } from "@phreshos/core";
|
|
2
|
+
/** Pointer coordinates relative to the desktop display core. */
|
|
3
|
+
export type PointerPosition = Readonly<{
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
}>;
|
|
7
|
+
/** One desktop layer's available workspace. */
|
|
8
|
+
export type Surface = Readonly<{
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
gutter: number;
|
|
12
|
+
}>;
|
|
13
|
+
/** Session-local desktop events available to a Client endpoint. */
|
|
14
|
+
export type HostEvents = {
|
|
15
|
+
surface: Surface;
|
|
16
|
+
pointerMove: PointerPosition;
|
|
17
|
+
};
|
|
18
|
+
/** Desktop capabilities structurally available to a Client endpoint. */
|
|
19
|
+
export interface Host<Events extends object = {}> extends Subscribable<HostEvents & Events, never> {
|
|
20
|
+
pointerPosition(): Promise<PointerPosition | null>;
|
|
21
|
+
surface(layer?: Layer): Promise<Surface>;
|
|
22
|
+
serve(value: unknown): Promise<ServedFile>;
|
|
23
|
+
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
|
|
24
|
+
}
|
|
25
|
+
export declare const host: Host;
|
package/dist/host.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { content } from "./content.js";
|
|
2
|
+
import Events from "./events.js";
|
|
3
|
+
import wire from "./wire.js";
|
|
4
|
+
class ClientHost extends Events {
|
|
5
|
+
pointerListeners = 0;
|
|
6
|
+
samplePointer = (event) => wire.samplePointer(event.movementX, event.movementY);
|
|
7
|
+
constructor() {
|
|
8
|
+
super((event, listener, impossible) => this.withPointerSampling(event === "pointerMove", wire.on("host-end", event, listener, null, impossible)), observer => this.withPointerSampling(true, combine(wire.on("host-end", "surface", value => observer("surface", value)), wire.on("host-end", "pointerMove", value => observer("pointerMove", value)))));
|
|
9
|
+
}
|
|
10
|
+
async pointerPosition() {
|
|
11
|
+
const answer = await wire.request(["pointerPosition"]);
|
|
12
|
+
return answer[0];
|
|
13
|
+
}
|
|
14
|
+
async surface(layer) {
|
|
15
|
+
const answer = await wire.request(["surface", undefined, layer]);
|
|
16
|
+
return answer[0];
|
|
17
|
+
}
|
|
18
|
+
async serve(value) {
|
|
19
|
+
const source = content(value);
|
|
20
|
+
const channel = new MessageChannel();
|
|
21
|
+
const abort = () => channel.port1.postMessage("abort");
|
|
22
|
+
try {
|
|
23
|
+
const answer = await wire.request(["serve", source.body, { extension: source.extension, type: source.type }, channel.port2], undefined, source.body instanceof ReadableStream ? [source.body, channel.port2] : [channel.port2]);
|
|
24
|
+
channel.port1.close();
|
|
25
|
+
return answer[0];
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
abort();
|
|
29
|
+
channel.port1.close();
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
async fetch(input, init) {
|
|
34
|
+
const request = new Request(input, {
|
|
35
|
+
...init,
|
|
36
|
+
...init?.body instanceof ReadableStream ? { duplex: "half" } : {}
|
|
37
|
+
});
|
|
38
|
+
const body = request.body;
|
|
39
|
+
const control = new MessageChannel();
|
|
40
|
+
const abort = () => control.port1.postMessage("abort");
|
|
41
|
+
if (request.signal.aborted) {
|
|
42
|
+
control.port1.close();
|
|
43
|
+
control.port2.close();
|
|
44
|
+
throw request.signal.reason;
|
|
45
|
+
}
|
|
46
|
+
request.signal.addEventListener("abort", abort, { once: true });
|
|
47
|
+
const description = {
|
|
48
|
+
body: body !== null,
|
|
49
|
+
cache: request.cache,
|
|
50
|
+
credentials: request.credentials,
|
|
51
|
+
headers: requestHeaders(request.headers, init?.headers),
|
|
52
|
+
integrity: request.integrity,
|
|
53
|
+
keepalive: request.keepalive,
|
|
54
|
+
method: request.method,
|
|
55
|
+
mode: request.mode,
|
|
56
|
+
redirect: request.redirect,
|
|
57
|
+
referrer: request.referrer,
|
|
58
|
+
referrerPolicy: request.referrerPolicy,
|
|
59
|
+
url: request.url
|
|
60
|
+
};
|
|
61
|
+
let result;
|
|
62
|
+
try {
|
|
63
|
+
const answer = await wire.request(["fetch", description, body, control.port2], undefined, body ? [body, control.port2] : [control.port2]);
|
|
64
|
+
result = answer[0];
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
abort();
|
|
68
|
+
closeControl(request.signal, control.port1, abort);
|
|
69
|
+
throw request.signal.aborted ? request.signal.reason : error;
|
|
70
|
+
}
|
|
71
|
+
const responseBody = result.body
|
|
72
|
+
? controlled(result.body, abort, () => closeControl(request.signal, control.port1, abort))
|
|
73
|
+
: null;
|
|
74
|
+
if (!responseBody)
|
|
75
|
+
closeControl(request.signal, control.port1, abort);
|
|
76
|
+
const response = new Response(responseBody, {
|
|
77
|
+
headers: result.headers,
|
|
78
|
+
status: result.status,
|
|
79
|
+
statusText: result.statusText
|
|
80
|
+
});
|
|
81
|
+
Object.defineProperties(response, {
|
|
82
|
+
redirected: { configurable: true, enumerable: true, value: result.redirected },
|
|
83
|
+
type: { configurable: true, enumerable: true, value: result.type },
|
|
84
|
+
url: { configurable: true, enumerable: true, value: result.url }
|
|
85
|
+
});
|
|
86
|
+
return response;
|
|
87
|
+
}
|
|
88
|
+
withPointerSampling(sample, stop) {
|
|
89
|
+
if (!sample)
|
|
90
|
+
return stop;
|
|
91
|
+
if (this.pointerListeners++ === 0)
|
|
92
|
+
window.addEventListener("pointermove", this.samplePointer);
|
|
93
|
+
let active = true;
|
|
94
|
+
return () => {
|
|
95
|
+
if (!active)
|
|
96
|
+
return;
|
|
97
|
+
active = false;
|
|
98
|
+
stop();
|
|
99
|
+
this.pointerListeners--;
|
|
100
|
+
if (this.pointerListeners === 0)
|
|
101
|
+
window.removeEventListener("pointermove", this.samplePointer);
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function requestHeaders(normalized, supplied) {
|
|
106
|
+
if (!supplied)
|
|
107
|
+
return [...normalized.entries()];
|
|
108
|
+
const explicit = supplied instanceof Headers
|
|
109
|
+
? [...supplied.entries()]
|
|
110
|
+
: Array.isArray(supplied)
|
|
111
|
+
? supplied.map(([name, value]) => [name, value])
|
|
112
|
+
: Object.entries(supplied);
|
|
113
|
+
const names = new Set(explicit.map(([name]) => name.toLowerCase()));
|
|
114
|
+
return [...normalized.entries()].filter(([name]) => !names.has(name.toLowerCase())).concat(explicit);
|
|
115
|
+
}
|
|
116
|
+
function controlled(body, abort, close) {
|
|
117
|
+
const reader = body.getReader();
|
|
118
|
+
return new ReadableStream({
|
|
119
|
+
async pull(controller) {
|
|
120
|
+
try {
|
|
121
|
+
const next = await reader.read();
|
|
122
|
+
if (next.done) {
|
|
123
|
+
close();
|
|
124
|
+
controller.close();
|
|
125
|
+
}
|
|
126
|
+
else
|
|
127
|
+
controller.enqueue(next.value);
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
close();
|
|
131
|
+
controller.error(error);
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
async cancel(reason) {
|
|
135
|
+
abort();
|
|
136
|
+
close();
|
|
137
|
+
await reader.cancel(reason);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function closeControl(signal, port, abort) {
|
|
142
|
+
signal.removeEventListener("abort", abort);
|
|
143
|
+
port.close();
|
|
144
|
+
}
|
|
145
|
+
function combine(...cleanups) {
|
|
146
|
+
return () => { for (const cleanup of cleanups)
|
|
147
|
+
cleanup(); };
|
|
148
|
+
}
|
|
149
|
+
export const host = new ClientHost();
|
package/dist/log.d.ts
ADDED
package/dist/log.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** Mirrors browser output through the private boundary without changing it. */
|
|
2
|
+
export default function captureClientOutput(wire) {
|
|
3
|
+
if (typeof document === "undefined")
|
|
4
|
+
return;
|
|
5
|
+
const output = console;
|
|
6
|
+
let relaying = false;
|
|
7
|
+
const relay = (kind, values) => queueMicrotask(() => {
|
|
8
|
+
if (relaying)
|
|
9
|
+
return;
|
|
10
|
+
relaying = true;
|
|
11
|
+
try {
|
|
12
|
+
wire.send("boundary", "log", kind, values.map(printable).join(" "));
|
|
13
|
+
}
|
|
14
|
+
catch { /* Output is emit-and-forget. */ }
|
|
15
|
+
finally {
|
|
16
|
+
relaying = false;
|
|
17
|
+
}
|
|
18
|
+
});
|
|
19
|
+
for (const kind of ["debug", "log", "info", "warn", "error"]) {
|
|
20
|
+
const original = output[kind].bind(console);
|
|
21
|
+
output[kind] = (...values) => {
|
|
22
|
+
original(...values);
|
|
23
|
+
relay(kind, values);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
window.addEventListener("error", event => relay("error", [event.error ?? event.message]));
|
|
27
|
+
window.addEventListener("unhandledrejection", event => relay("error", [`Unhandled rejection: ${printable(event.reason)}`]));
|
|
28
|
+
}
|
|
29
|
+
function printable(value) {
|
|
30
|
+
if (typeof value === "string")
|
|
31
|
+
return value;
|
|
32
|
+
if (value instanceof Error)
|
|
33
|
+
return value.stack ?? `${value.name}: ${value.message}`;
|
|
34
|
+
if (typeof value === "undefined")
|
|
35
|
+
return "undefined";
|
|
36
|
+
if (typeof value === "bigint")
|
|
37
|
+
return `${value}n`;
|
|
38
|
+
if (typeof value === "symbol" || typeof value === "function")
|
|
39
|
+
return String(value);
|
|
40
|
+
try {
|
|
41
|
+
const seen = new WeakSet();
|
|
42
|
+
const json = JSON.stringify(value, (_key, nested) => {
|
|
43
|
+
if (typeof nested === "bigint")
|
|
44
|
+
return `${nested}n`;
|
|
45
|
+
if (nested instanceof Error)
|
|
46
|
+
return { name: nested.name, message: nested.message, stack: nested.stack };
|
|
47
|
+
if (typeof nested !== "object" || nested === null)
|
|
48
|
+
return nested;
|
|
49
|
+
if (seen.has(nested))
|
|
50
|
+
return "[Circular]";
|
|
51
|
+
seen.add(nested);
|
|
52
|
+
return nested;
|
|
53
|
+
});
|
|
54
|
+
if (json !== undefined)
|
|
55
|
+
return json;
|
|
56
|
+
}
|
|
57
|
+
catch { /* Fall through. */ }
|
|
58
|
+
try {
|
|
59
|
+
return String(value);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return "[Unprintable value]";
|
|
63
|
+
}
|
|
64
|
+
}
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { host, type Host, type HostEvents, type PointerPosition, type Surface } from "./host.js";
|
|
2
|
+
export { current, type Current, type CurrentServer } from "./current.js";
|
|
3
|
+
export { type Channel, type ChannelCapture, type ChannelEvents, type ChannelMessage } from "./channel.js";
|
|
4
|
+
export { Client, Endpoint, Process, Program, Server, Window, type AnswerCapture, type AnswerMessage, type AnswerObserver, type AskCapture, type AskMessage, type AskObserver, type ClientTraffic, type EndpointTraffic, type ServerTraffic, type TrafficCapture, type TrafficEvents, type TrafficMessage } from "./domain.js";
|
|
5
|
+
export type { Askable, Capture, Captures, ClientDeclaration, Cleanup, DirectoryStat, EndpointDeclaration, EntryStat, EventMessage, EventName, EventObserver, EventOptions, EventSubscriber, Exit, FileStat, Launch, LaunchClient, Layer, LogKind, LogRecord, LogSource, Message, OtherStat, Outcome, Position, ProgramArea, ProgramEvents, ProgramProcessExit, ProgramServerStop, ProgramSql, ProgramStore, ProcessEvents, Publishable, ServedFile, Size, Subscribable, TimedAskable, Value, WindowEvents, WindowState } from "@phreshos/core";
|
package/dist/main.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ProgramArea, ProgramSql, ProgramStore } from "@phreshos/core";
|
|
2
|
+
/** Client-side Program storage, structurally scoped by the iframe boundary. */
|
|
3
|
+
export declare function area(which: "data" | "cache"): ProgramArea;
|
|
4
|
+
export declare function store(): ProgramStore;
|
|
5
|
+
export declare function sql(kind: "database" | "logs"): ProgramSql;
|
package/dist/storage.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { content } from "./content.js";
|
|
2
|
+
import wire from "./wire.js";
|
|
3
|
+
/** Client-side Program storage, structurally scoped by the iframe boundary. */
|
|
4
|
+
export function area(which) {
|
|
5
|
+
async function ask(operation, ...values) {
|
|
6
|
+
const answer = await wire.request([which, undefined, operation, ...values]);
|
|
7
|
+
return answer[0];
|
|
8
|
+
}
|
|
9
|
+
async function transfer(operation, path, body = null) {
|
|
10
|
+
const channel = new MessageChannel();
|
|
11
|
+
const abort = () => channel.port1.postMessage("abort");
|
|
12
|
+
const close = () => channel.port1.close();
|
|
13
|
+
try {
|
|
14
|
+
const answer = await wire.request([which, undefined, operation, path, body, channel.port2], undefined, body instanceof ReadableStream ? [body, channel.port2] : [channel.port2]);
|
|
15
|
+
if (operation === "write") {
|
|
16
|
+
close();
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
if (!(answer[0] instanceof ReadableStream))
|
|
20
|
+
throw new Error("The storage response has no byte stream");
|
|
21
|
+
return controlled(answer[0], abort, close);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
abort();
|
|
25
|
+
close();
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function stream(...path) {
|
|
30
|
+
const body = await transfer("stream", path);
|
|
31
|
+
if (!body)
|
|
32
|
+
throw new Error("The storage response has no body");
|
|
33
|
+
return body;
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
stream,
|
|
37
|
+
async bytes(...path) { return new Uint8Array(await new Response(await stream(...path)).arrayBuffer()); },
|
|
38
|
+
async text(...path) { return new Response(await stream(...path)).text(); },
|
|
39
|
+
async json(...path) { return JSON.parse(await new Response(await stream(...path)).text()); },
|
|
40
|
+
async write(...args) {
|
|
41
|
+
if (args.length < 2)
|
|
42
|
+
throw new Error("Writing takes a file name and what to write");
|
|
43
|
+
await transfer("write", args.slice(0, -1), content(args.at(-1)).body);
|
|
44
|
+
},
|
|
45
|
+
stat: (...path) => ask("stat", ...path),
|
|
46
|
+
list: (...path) => ask("list", ...path),
|
|
47
|
+
delete: (...path) => ask("delete", ...path),
|
|
48
|
+
clear: () => ask("clear")
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export function store() {
|
|
52
|
+
async function ask(operation, ...values) {
|
|
53
|
+
const answer = await wire.request(["store", undefined, operation, ...values]);
|
|
54
|
+
return answer[0];
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
get: (key) => ask("get", key),
|
|
58
|
+
set: (key, value, ttl) => ask("set", key, value, ttl),
|
|
59
|
+
delete: (key) => ask("delete", key),
|
|
60
|
+
has: (key) => ask("has", key),
|
|
61
|
+
clear: () => ask("clear")
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export function sql(kind) {
|
|
65
|
+
return {
|
|
66
|
+
async query(statement, ...rest) {
|
|
67
|
+
const text = typeof statement === "string" ? statement : statement.raw.join("?");
|
|
68
|
+
const values = typeof statement === "string" ? (Array.isArray(rest[0]) ? rest[0] : []) : rest;
|
|
69
|
+
const answer = await wire.request([kind, undefined, text, values]);
|
|
70
|
+
return answer[0];
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function controlled(body, abort, close) {
|
|
75
|
+
const reader = body.getReader();
|
|
76
|
+
return new ReadableStream({
|
|
77
|
+
async pull(controller) {
|
|
78
|
+
try {
|
|
79
|
+
const next = await reader.read();
|
|
80
|
+
if (next.done) {
|
|
81
|
+
close();
|
|
82
|
+
controller.close();
|
|
83
|
+
}
|
|
84
|
+
else
|
|
85
|
+
controller.enqueue(next.value);
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
close();
|
|
89
|
+
controller.error(error);
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
async cancel(reason) {
|
|
93
|
+
abort();
|
|
94
|
+
close();
|
|
95
|
+
await reader.cancel(reason);
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
}
|
package/dist/wire.d.ts
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Cleanup } from "@phreshos/core";
|
|
2
|
+
import Deadline from "./deadline.js";
|
|
3
|
+
type Handler = (...values: unknown[]) => unknown;
|
|
4
|
+
type Failure = (error: Error) => void;
|
|
5
|
+
type TrafficKind = "publish" | "ask" | "answer";
|
|
6
|
+
/** The client endpoint's sole postMessage adapter. */
|
|
7
|
+
declare class Wire {
|
|
8
|
+
private readonly parent;
|
|
9
|
+
private readonly pending;
|
|
10
|
+
private readonly subscribers;
|
|
11
|
+
private readonly every;
|
|
12
|
+
private readonly impossible;
|
|
13
|
+
private readonly boundarySubscriptions;
|
|
14
|
+
private readonly observations;
|
|
15
|
+
readonly identity: Promise<string>;
|
|
16
|
+
constructor();
|
|
17
|
+
send(route: string, ...values: unknown[]): void;
|
|
18
|
+
request(values: unknown[], timeout?: number, transfer?: Transferable[]): Promise<unknown>;
|
|
19
|
+
requestWithin(values: unknown[], deadline: Deadline, transfer?: Transferable[]): Promise<unknown>;
|
|
20
|
+
askServerWithin(event: string, payload: unknown, deadline: Deadline): Promise<unknown>;
|
|
21
|
+
private question;
|
|
22
|
+
expectWithin(question: string, deadline: Deadline): Promise<unknown>;
|
|
23
|
+
forget(question: string): void;
|
|
24
|
+
on(route: string, event: string, handler: Handler, subject?: string | null, impossible?: Failure): Cleanup;
|
|
25
|
+
onAll(route: string, handler: Handler, subject?: string | null): Cleanup;
|
|
26
|
+
observe(target: string, half: "server" | "client", kind: TrafficKind, event: string | null, handler: Handler, impossible?: Failure): Cleanup;
|
|
27
|
+
samplePointer(movementX: number, movementY: number): void;
|
|
28
|
+
private register;
|
|
29
|
+
private unregister;
|
|
30
|
+
private deliver;
|
|
31
|
+
private settle;
|
|
32
|
+
}
|
|
33
|
+
declare const wire: Wire;
|
|
34
|
+
export default wire;
|