@phreshos/client 0.1.7 → 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 +7 -6
- package/dist/current.d.ts +0 -3
- package/dist/current.js +0 -25
- package/dist/domain.d.ts +6 -3
- package/dist/domain.js +37 -0
- package/dist/messagepack.d.ts +3 -0
- package/dist/messagepack.js +130 -0
- package/dist/wire.d.ts +1 -0
- package/dist/wire.js +54 -3
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -128,10 +128,11 @@ The same rule applies to Client-visible traffic destinations.
|
|
|
128
128
|
|
|
129
129
|
Client-visible Program handles can operate only within their own Program.
|
|
130
130
|
They deliberately omit `install()` and `fork()`, and their storage areas never
|
|
131
|
-
expose host filesystem paths.
|
|
132
|
-
subscribable
|
|
133
|
-
|
|
134
|
-
|
|
131
|
+
expose host filesystem paths. Every Client-side Window handle exposes the same
|
|
132
|
+
authoritative, subscribable Window capability and its `window.local` physical
|
|
133
|
+
representation on this desktop. Local reads and updates have no events and do
|
|
134
|
+
not change Server state. `current.window` is only convenient access to the
|
|
135
|
+
executing Client's canonical Window; it has no additional authority.
|
|
135
136
|
When both dimensions must change, `setGeometry({ position, size })` commits
|
|
136
137
|
them through one authoritative request and produces one `geometry` event.
|
|
137
138
|
Calling `move()` and `resize()` sequentially or through `Promise.all()` remains
|
|
@@ -140,12 +141,12 @@ two independent operations and can expose an intermediate state remotely.
|
|
|
140
141
|
An `under` or `over` representation may request one local host-rendered Surface:
|
|
141
142
|
|
|
142
143
|
```ts
|
|
143
|
-
await current.
|
|
144
|
+
await current.window.local.surface.set({
|
|
144
145
|
opacity: 0.65,
|
|
145
146
|
radius: "large"
|
|
146
147
|
}, { duration: 240, easing: "ease-out", wait: true })
|
|
147
148
|
|
|
148
|
-
await current.
|
|
149
|
+
await current.window.local.surface.remove()
|
|
149
150
|
```
|
|
150
151
|
|
|
151
152
|
The desktop holds local state only for the lifetime of that iframe
|
package/dist/current.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { LocalWindow } from "@phreshos/core";
|
|
2
1
|
import { type Channel } from "./channel.js";
|
|
3
2
|
import { Client, Server, type Process, type Program, type Window } from "./domain.js";
|
|
4
3
|
/** The current Process's canonical Server handle. */
|
|
@@ -9,8 +8,6 @@ export interface Current<Events extends object = {}> extends Channel<Events>, Pi
|
|
|
9
8
|
readonly server: CurrentServer;
|
|
10
9
|
/** Presentation capability of this current Client. */
|
|
11
10
|
readonly window: Window;
|
|
12
|
-
/** Physical Window representation belonging only to this Client iframe. */
|
|
13
|
-
readonly localWindow: LocalWindow;
|
|
14
11
|
/** The same permission capability exposed by the current Program. */
|
|
15
12
|
readonly permissions: Program["permissions"];
|
|
16
13
|
/** Returns the Process represented by this Client. */
|
package/dist/current.js
CHANGED
|
@@ -84,7 +84,6 @@ currentClient = new CurrentClientHandle(owner);
|
|
|
84
84
|
class ClientCurrent {
|
|
85
85
|
server = currentServer;
|
|
86
86
|
window = currentClient.window;
|
|
87
|
-
localWindow = new LocalWindowHandle();
|
|
88
87
|
permissions = currentProgramPermissions;
|
|
89
88
|
constructor() {
|
|
90
89
|
bindChannel(this, channel);
|
|
@@ -105,30 +104,6 @@ class ClientCurrent {
|
|
|
105
104
|
async stop() { await wire.request(["stop-current"]); }
|
|
106
105
|
service() { return endpointService(null, "client"); }
|
|
107
106
|
}
|
|
108
|
-
class LocalWindowHandle {
|
|
109
|
-
surface = new LocalWindowSurfaceHandle();
|
|
110
|
-
async state() {
|
|
111
|
-
const answer = await wire.request(["localWindow"]);
|
|
112
|
-
return answer[0];
|
|
113
|
-
}
|
|
114
|
-
async title() { return (await this.state()).title; }
|
|
115
|
-
async position() { return (await this.state()).position; }
|
|
116
|
-
async size() { return (await this.state()).size; }
|
|
117
|
-
async minimized() { return (await this.state()).minimized; }
|
|
118
|
-
async front() { return (await this.state()).front; }
|
|
119
|
-
async layer() { return (await this.state()).layer; }
|
|
120
|
-
async location() { return (await this.state()).location; }
|
|
121
|
-
async move(position, transaction) { await wire.request(["localWindowMove", position, transaction]); }
|
|
122
|
-
async resize(size, transaction) { await wire.request(["localWindowResize", size, transaction]); }
|
|
123
|
-
async setGeometry(geometry, transaction) { await wire.request(["localWindowGeometry", geometry, transaction]); }
|
|
124
|
-
async minimize(minimized = true) { await wire.request(["localWindowMinimize", minimized]); }
|
|
125
|
-
async changeTitle(title) { await wire.request(["localWindowTitle", title]); }
|
|
126
|
-
async raise() { await wire.request(["localWindowRaise"]); }
|
|
127
|
-
}
|
|
128
|
-
class LocalWindowSurfaceHandle {
|
|
129
|
-
async set(settings = {}, transaction) { await wire.request(["localWindowSurfaceSet", settings, transaction]); }
|
|
130
|
-
async remove() { await wire.request(["localWindowSurfaceRemove"]); }
|
|
131
|
-
}
|
|
132
107
|
function bindChannel(target, source) {
|
|
133
108
|
Object.assign(target, {
|
|
134
109
|
publish: source.publish.bind(source),
|
package/dist/domain.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Client as CoreClient, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, Server as CoreServer, type AnswerCapture as CoreAnswerCapture, type AnswerMessage as CoreAnswerMessage, type AnswerObserver as CoreAnswerObserver, type AskCapture as CoreAskCapture, type AskMessage as CoreAskMessage, type AskObserver as CoreAskObserver, type Cleanup, type ClientTraffic as CoreClientTraffic, type ClientDeclaration, type EndpointTraffic as CoreEndpointTraffic, type EndpointDeclaration, type Exit, type Launch, type Permissions, type ServerTraffic as CoreServerTraffic, type TrafficMessage as CoreTrafficMessage, type TrafficCapture as CoreTrafficCapture, type TrafficEvents as CoreTrafficEvents, type Window as CoreWindow, type WindowState } from "@phreshos/core";
|
|
1
|
+
import { Client as CoreClient, Endpoint as CoreEndpoint, Process as CoreProcess, Program as CoreProgram, Server as CoreServer, type AnswerCapture as CoreAnswerCapture, type AnswerMessage as CoreAnswerMessage, type AnswerObserver as CoreAnswerObserver, type AskCapture as CoreAskCapture, type AskMessage as CoreAskMessage, type AskObserver as CoreAskObserver, type Cleanup, type ClientTraffic as CoreClientTraffic, type ClientDeclaration, type EndpointTraffic as CoreEndpointTraffic, type EndpointDeclaration, type Exit, type Launch, type LocalWindow, type Permissions, type ServerTraffic as CoreServerTraffic, type TrafficMessage as CoreTrafficMessage, type TrafficCapture as CoreTrafficCapture, type TrafficEvents as CoreTrafficEvents, type Window as CoreWindow, type WindowState } from "@phreshos/core";
|
|
2
2
|
import Events from "./events.js";
|
|
3
3
|
export interface HandleAddress {
|
|
4
4
|
identity: string;
|
|
@@ -102,8 +102,11 @@ export type Client<Events extends object = {}> = Omit<CoreClient<Events>, "proce
|
|
|
102
102
|
/** Returns the Process that owns this Client. */
|
|
103
103
|
process(): Promise<Process>;
|
|
104
104
|
};
|
|
105
|
-
/** Authoritative
|
|
106
|
-
export type Window = CoreWindow
|
|
105
|
+
/** Authoritative Window state plus its representation on this desktop. */
|
|
106
|
+
export type Window = CoreWindow & {
|
|
107
|
+
/** Physical representation of this Window on the current desktop. */
|
|
108
|
+
readonly local: LocalWindow;
|
|
109
|
+
};
|
|
107
110
|
export declare class TrafficHandle extends Events {
|
|
108
111
|
protected readonly target: HandleAddress | null;
|
|
109
112
|
protected readonly kind: "server" | "client";
|
package/dist/domain.js
CHANGED
|
@@ -206,9 +206,11 @@ class ClientHandle extends ClientBase {
|
|
|
206
206
|
}
|
|
207
207
|
class WindowHandle extends Events {
|
|
208
208
|
target;
|
|
209
|
+
local;
|
|
209
210
|
constructor(target) {
|
|
210
211
|
super(...deferredScoped("host-end", target, (_event, values) => values[0]));
|
|
211
212
|
this.target = target;
|
|
213
|
+
this.local = new LocalWindowHandle(target);
|
|
212
214
|
}
|
|
213
215
|
async state() {
|
|
214
216
|
const answer = await wire.request(["window", await this.target()]);
|
|
@@ -228,6 +230,41 @@ class WindowHandle extends Events {
|
|
|
228
230
|
async changeTitle(title) { await wire.request(["changeTitle", await this.target(), title]); }
|
|
229
231
|
async raise() { await wire.request(["raise", await this.target()]); }
|
|
230
232
|
}
|
|
233
|
+
class LocalWindowHandle {
|
|
234
|
+
target;
|
|
235
|
+
surface;
|
|
236
|
+
constructor(target) {
|
|
237
|
+
this.target = target;
|
|
238
|
+
this.surface = new LocalWindowSurfaceHandle(target);
|
|
239
|
+
}
|
|
240
|
+
async state() {
|
|
241
|
+
const answer = await wire.request(["windowLocal", await this.target()]);
|
|
242
|
+
return answer[0];
|
|
243
|
+
}
|
|
244
|
+
async title() { return (await this.state()).title; }
|
|
245
|
+
async position() { return (await this.state()).position; }
|
|
246
|
+
async size() { return (await this.state()).size; }
|
|
247
|
+
async minimized() { return (await this.state()).minimized; }
|
|
248
|
+
async front() { return (await this.state()).front; }
|
|
249
|
+
async layer() { return (await this.state()).layer; }
|
|
250
|
+
async location() { return (await this.state()).location; }
|
|
251
|
+
async move(position, transaction) { await wire.request(["windowLocalMove", await this.target(), position, transaction]); }
|
|
252
|
+
async resize(size, transaction) { await wire.request(["windowLocalResize", await this.target(), size, transaction]); }
|
|
253
|
+
async setGeometry(geometry, transaction) { await wire.request(["windowLocalGeometry", await this.target(), geometry, transaction]); }
|
|
254
|
+
async minimize(minimized = true) { await wire.request(["windowLocalMinimize", await this.target(), minimized]); }
|
|
255
|
+
async changeTitle(title) { await wire.request(["windowLocalTitle", await this.target(), title]); }
|
|
256
|
+
async raise() { await wire.request(["windowLocalRaise", await this.target()]); }
|
|
257
|
+
}
|
|
258
|
+
class LocalWindowSurfaceHandle {
|
|
259
|
+
target;
|
|
260
|
+
constructor(target) {
|
|
261
|
+
this.target = target;
|
|
262
|
+
}
|
|
263
|
+
async set(settings = {}, transaction) {
|
|
264
|
+
await wire.request(["windowLocalSurfaceSet", await this.target(), settings, transaction]);
|
|
265
|
+
}
|
|
266
|
+
async remove() { await wire.request(["windowLocalSurfaceRemove", await this.target()]); }
|
|
267
|
+
}
|
|
231
268
|
function deferredScoped(route, target, convert) {
|
|
232
269
|
return [
|
|
233
270
|
(event, listener, impossible) => {
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { decode, encode, ExtensionCodec } from "@msgpack/msgpack";
|
|
2
|
+
class Attachment {
|
|
3
|
+
index;
|
|
4
|
+
constructor(index) {
|
|
5
|
+
this.index = index;
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
class BigInteger {
|
|
9
|
+
value;
|
|
10
|
+
constructor(value) {
|
|
11
|
+
this.value = value;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
class Undefined {
|
|
15
|
+
}
|
|
16
|
+
const textEncoder = new TextEncoder();
|
|
17
|
+
const textDecoder = new TextDecoder("utf-8", { fatal: true });
|
|
18
|
+
const extensions = new ExtensionCodec();
|
|
19
|
+
const serializePrepared = (value, context) => encode(value, { context, extensionCodec: extensions });
|
|
20
|
+
const deserializePrepared = (bytes, context) => decode(bytes, { context, extensionCodec: extensions });
|
|
21
|
+
extensions.register({
|
|
22
|
+
type: 0,
|
|
23
|
+
encode: value => value instanceof Attachment ? uint32(value.index) : null,
|
|
24
|
+
decode: (bytes, _type, context) => {
|
|
25
|
+
const attachment = context.incoming?.[readUint32(bytes)];
|
|
26
|
+
if (attachment === undefined)
|
|
27
|
+
throw new Error("The MessagePack attachment is absent");
|
|
28
|
+
return attachment;
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
extensions.register({
|
|
32
|
+
type: 1,
|
|
33
|
+
encode: (value, context) => value instanceof Map ? serializePrepared([...value], context) : null,
|
|
34
|
+
decode: (bytes, _type, context) => new Map(deserializePrepared(bytes, context))
|
|
35
|
+
});
|
|
36
|
+
extensions.register({
|
|
37
|
+
type: 2,
|
|
38
|
+
encode: (value, context) => value instanceof Set ? serializePrepared([...value], context) : null,
|
|
39
|
+
decode: (bytes, _type, context) => new Set(deserializePrepared(bytes, context))
|
|
40
|
+
});
|
|
41
|
+
extensions.register({
|
|
42
|
+
type: 3,
|
|
43
|
+
encode: (value, context) => value instanceof RegExp ? serializePrepared([value.source, value.flags, value.lastIndex], context) : null,
|
|
44
|
+
decode: (bytes, _type, context) => {
|
|
45
|
+
const [source, flags, lastIndex] = deserializePrepared(bytes, context);
|
|
46
|
+
const expression = new RegExp(source, flags);
|
|
47
|
+
expression.lastIndex = lastIndex;
|
|
48
|
+
return expression;
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
extensions.register({
|
|
52
|
+
type: 4,
|
|
53
|
+
encode: value => value instanceof URL ? textEncoder.encode(value.href) : null,
|
|
54
|
+
decode: bytes => new URL(textDecoder.decode(bytes))
|
|
55
|
+
});
|
|
56
|
+
extensions.register({
|
|
57
|
+
type: 5,
|
|
58
|
+
encode: (value, context) => value instanceof Error ? serializePrepared(prepare({
|
|
59
|
+
cause: value.cause,
|
|
60
|
+
message: value.message,
|
|
61
|
+
name: value.name,
|
|
62
|
+
stack: value.stack
|
|
63
|
+
}, context), context) : null,
|
|
64
|
+
decode: (bytes, _type, context) => {
|
|
65
|
+
const value = deserializePrepared(bytes, context);
|
|
66
|
+
const error = new Error(value.message, { cause: value.cause });
|
|
67
|
+
error.name = value.name;
|
|
68
|
+
if (value.stack !== undefined)
|
|
69
|
+
error.stack = value.stack;
|
|
70
|
+
return error;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
extensions.register({
|
|
74
|
+
type: 6,
|
|
75
|
+
encode: value => value instanceof BigInteger ? textEncoder.encode(value.value.toString()) : null,
|
|
76
|
+
decode: bytes => BigInt(textDecoder.decode(bytes))
|
|
77
|
+
});
|
|
78
|
+
extensions.register({
|
|
79
|
+
type: 7,
|
|
80
|
+
encode: value => value instanceof Undefined ? new Uint8Array() : null,
|
|
81
|
+
decode: () => undefined
|
|
82
|
+
});
|
|
83
|
+
export const serialize = (value, attachments = []) => {
|
|
84
|
+
const outgoing = new Map(attachments.map((attachment, index) => [attachment, index]));
|
|
85
|
+
const context = { outgoing };
|
|
86
|
+
return serializePrepared(prepare(value, context), context);
|
|
87
|
+
};
|
|
88
|
+
export const deserialize = (bytes, attachments = []) => {
|
|
89
|
+
return deserializePrepared(bytes, { incoming: attachments });
|
|
90
|
+
};
|
|
91
|
+
const prepare = (value, context) => {
|
|
92
|
+
if (value === undefined)
|
|
93
|
+
return new Undefined();
|
|
94
|
+
if (typeof value === "bigint")
|
|
95
|
+
return new BigInteger(value);
|
|
96
|
+
if (typeof value === "function" || typeof value === "symbol")
|
|
97
|
+
return null;
|
|
98
|
+
if (value === null || typeof value !== "object")
|
|
99
|
+
return value;
|
|
100
|
+
const attachment = context.outgoing?.get(value);
|
|
101
|
+
if (attachment !== undefined)
|
|
102
|
+
return new Attachment(attachment);
|
|
103
|
+
if (value instanceof Date || value instanceof RegExp || value instanceof URL || value instanceof Error)
|
|
104
|
+
return value;
|
|
105
|
+
if (value instanceof ArrayBuffer)
|
|
106
|
+
return new Uint8Array(value);
|
|
107
|
+
if (ArrayBuffer.isView(value))
|
|
108
|
+
return Uint8Array.from(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
|
|
109
|
+
if (value instanceof Map)
|
|
110
|
+
return new Map([...value].map(([key, entry]) => [prepare(key, context), prepare(entry, context)]));
|
|
111
|
+
if (value instanceof Set)
|
|
112
|
+
return new Set([...value].map(entry => prepare(entry, context)));
|
|
113
|
+
if (Array.isArray(value))
|
|
114
|
+
return value.map(entry => prepare(entry, context));
|
|
115
|
+
if ("toJSON" in value && typeof value.toJSON === "function")
|
|
116
|
+
return prepare(value.toJSON(), context);
|
|
117
|
+
return Object.fromEntries(Object.entries(value)
|
|
118
|
+
.filter(([, entry]) => typeof entry !== "function")
|
|
119
|
+
.map(([key, entry]) => [key, prepare(entry, context)]));
|
|
120
|
+
};
|
|
121
|
+
const uint32 = (value) => {
|
|
122
|
+
const bytes = new Uint8Array(4);
|
|
123
|
+
new DataView(bytes.buffer).setUint32(0, value);
|
|
124
|
+
return bytes;
|
|
125
|
+
};
|
|
126
|
+
const readUint32 = (bytes) => {
|
|
127
|
+
if (bytes.byteLength !== 4)
|
|
128
|
+
throw new Error("The MessagePack attachment reference is invalid");
|
|
129
|
+
return new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(0);
|
|
130
|
+
};
|
package/dist/wire.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ declare class Wire {
|
|
|
25
25
|
reference: string;
|
|
26
26
|
}>;
|
|
27
27
|
private question;
|
|
28
|
+
private post;
|
|
28
29
|
expectWithin(question: string, deadline: Deadline): Promise<unknown>;
|
|
29
30
|
forget(question: string): void;
|
|
30
31
|
on(route: string, event: string, handler: Handler, subject?: string | null, impossible?: Failure): Cleanup;
|
package/dist/wire.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import Deadline from "./deadline.js";
|
|
2
2
|
import { defaultTimeout } from "./events.js";
|
|
3
3
|
import captureClientOutput from "./log.js";
|
|
4
|
+
import { deserialize, serialize } from "./messagepack.js";
|
|
4
5
|
/** The client endpoint's sole postMessage adapter. */
|
|
5
6
|
class Wire {
|
|
6
7
|
parent = window.parent === window ? null : window.parent;
|
|
@@ -14,7 +15,19 @@ class Wire {
|
|
|
14
15
|
window.addEventListener("message", event => {
|
|
15
16
|
if (event.source !== this.parent || !Array.isArray(event.data))
|
|
16
17
|
return;
|
|
17
|
-
const [
|
|
18
|
+
const [bytes, ...attachments] = event.data;
|
|
19
|
+
if (!(bytes instanceof Uint8Array))
|
|
20
|
+
return;
|
|
21
|
+
let message;
|
|
22
|
+
try {
|
|
23
|
+
message = deserialize(bytes, attachments);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (!Array.isArray(message) || typeof message[0] !== "string")
|
|
29
|
+
return;
|
|
30
|
+
const [route, ...values] = message;
|
|
18
31
|
if (route === "boundary") {
|
|
19
32
|
const [operation, ...rest] = values;
|
|
20
33
|
if (operation === "impossible" && typeof rest[0] === "string" && typeof rest[1] === "string") {
|
|
@@ -31,7 +44,7 @@ class Wire {
|
|
|
31
44
|
});
|
|
32
45
|
}
|
|
33
46
|
send(route, ...values) {
|
|
34
|
-
this.
|
|
47
|
+
this.post([route, ...values]);
|
|
35
48
|
}
|
|
36
49
|
request(values, timeout = defaultTimeout, transfer = []) {
|
|
37
50
|
return this.question("end-host", values, timeout, transfer);
|
|
@@ -108,7 +121,7 @@ class Wire {
|
|
|
108
121
|
? [route, "wait", question, publicId, ...values]
|
|
109
122
|
: [route, "wait", question, ...values];
|
|
110
123
|
try {
|
|
111
|
-
this.
|
|
124
|
+
this.post(message, transfer);
|
|
112
125
|
}
|
|
113
126
|
catch (error) {
|
|
114
127
|
this.pending.delete(question);
|
|
@@ -126,6 +139,13 @@ class Wire {
|
|
|
126
139
|
});
|
|
127
140
|
});
|
|
128
141
|
}
|
|
142
|
+
post(message, transfer = []) {
|
|
143
|
+
if (!this.parent)
|
|
144
|
+
return;
|
|
145
|
+
const attachments = nativeAttachments(message, transfer);
|
|
146
|
+
const bytes = serialize(message, attachments);
|
|
147
|
+
this.parent.postMessage([bytes, ...attachments], "*", [bytes.buffer, ...transfer]);
|
|
148
|
+
}
|
|
129
149
|
expectWithin(question, deadline) {
|
|
130
150
|
this.send("boundary", "expect", question);
|
|
131
151
|
return new Promise((resolve, reject) => {
|
|
@@ -254,6 +274,37 @@ function once(cleanup) {
|
|
|
254
274
|
cleanup();
|
|
255
275
|
};
|
|
256
276
|
}
|
|
277
|
+
function nativeAttachments(value, transfer) {
|
|
278
|
+
const attachments = [...transfer];
|
|
279
|
+
const known = new Set(attachments);
|
|
280
|
+
const visit = (entry) => {
|
|
281
|
+
if (entry === null || typeof entry !== "object" || known.has(entry))
|
|
282
|
+
return;
|
|
283
|
+
known.add(entry);
|
|
284
|
+
if (entry instanceof Blob) {
|
|
285
|
+
attachments.push(entry);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
if (entry instanceof Date || entry instanceof RegExp || entry instanceof URL || entry instanceof Error || entry instanceof ArrayBuffer || ArrayBuffer.isView(entry))
|
|
289
|
+
return;
|
|
290
|
+
if (entry instanceof Map) {
|
|
291
|
+
for (const [key, item] of entry) {
|
|
292
|
+
visit(key);
|
|
293
|
+
visit(item);
|
|
294
|
+
}
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
if (entry instanceof Set) {
|
|
298
|
+
for (const item of entry)
|
|
299
|
+
visit(item);
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
for (const item of Array.isArray(entry) ? entry : Object.values(entry))
|
|
303
|
+
visit(item);
|
|
304
|
+
};
|
|
305
|
+
visit(value);
|
|
306
|
+
return attachments;
|
|
307
|
+
}
|
|
257
308
|
const wire = new Wire();
|
|
258
309
|
captureClientOutput(wire);
|
|
259
310
|
export default wire;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phreshos/client",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "The SDK used by a Program's client endpoint.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/main.js",
|
|
@@ -48,6 +48,9 @@
|
|
|
48
48
|
"peerDependencies": {
|
|
49
49
|
"@phreshos/core": "^0.1.6"
|
|
50
50
|
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@msgpack/msgpack": "^3.1.3"
|
|
53
|
+
},
|
|
51
54
|
"devDependencies": {
|
|
52
55
|
"@phreshos/core": "^0.1.6",
|
|
53
56
|
"typescript": "^6.0.3"
|