toiljs 0.0.69 → 0.0.70
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 +5 -0
- package/build/cli/.tsbuildinfo +1 -1
- package/build/client/.tsbuildinfo +1 -1
- package/build/client/rpc.js +10 -4
- package/build/client/stream/client.js +108 -5
- package/build/compiler/.tsbuildinfo +1 -1
- package/build/compiler/index.d.ts +2 -0
- package/build/compiler/index.js +282 -2
- package/build/compiler/toil-docs.generated.js +1 -1
- package/build/compiler/vite.js +8 -0
- package/build/devserver/.tsbuildinfo +1 -1
- package/build/devserver/daemon/host.d.ts +1 -7
- package/build/devserver/daemon/host.js +5 -59
- package/build/devserver/daemon/index.d.ts +1 -0
- package/build/devserver/daemon/index.js +17 -4
- package/build/devserver/db/database.js +1 -1
- package/build/devserver/db/routeKinds.d.ts +6 -0
- package/build/devserver/db/routeKinds.js +40 -0
- package/build/devserver/index.d.ts +0 -1
- package/build/devserver/index.js +0 -1
- package/build/devserver/runtime/module.d.ts +1 -0
- package/build/devserver/runtime/module.js +18 -2
- package/build/devserver/stream/index.js +4 -3
- package/build/devserver/wasm/surface.d.ts +2 -0
- package/build/devserver/wasm/surface.js +35 -4
- package/docs/streams.md +3 -4
- package/examples/basic/server/services/Stats.ts +11 -3
- package/examples/basic/server/services/remotes.ts +8 -2
- package/package.json +3 -2
- package/server/runtime/exports/index.ts +8 -1
- package/server/runtime/index.ts +1 -0
- package/server/runtime/rpc/Rpc.ts +66 -0
- package/src/client/rpc.ts +21 -12
- package/src/client/stream/client.ts +133 -5
- package/src/compiler/index.ts +352 -2
- package/src/compiler/toil-docs.generated.ts +1 -1
- package/src/compiler/vite.ts +16 -0
- package/src/devserver/daemon/host.ts +10 -110
- package/src/devserver/daemon/index.ts +19 -6
- package/src/devserver/db/database.ts +1 -1
- package/src/devserver/db/routeKinds.ts +44 -0
- package/src/devserver/index.ts +0 -1
- package/src/devserver/runtime/host.ts +3 -7
- package/src/devserver/runtime/module.ts +30 -4
- package/src/devserver/stream/index.ts +8 -4
- package/src/devserver/wasm/surface.ts +33 -4
- package/test/daemon-build.test.ts +53 -0
- package/test/daemon-catalog.test.ts +78 -3
- package/test/daemon-emulation.test.ts +27 -29
- package/test/devserver-database.test.ts +93 -0
- package/test/fixtures/bignum-wire/spec.ts +3 -5
- package/test/fixtures/daemon-app.ts +25 -21
- package/test/rpc-dispatch.test.ts +132 -0
- package/test/rpc-kinds.test.ts +18 -0
- package/test/rpc.test.ts +20 -4
- package/build/devserver/mstore/store.d.ts +0 -18
- package/build/devserver/mstore/store.js +0 -82
- package/src/devserver/mstore/store.ts +0 -121
package/build/client/rpc.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
function restMissingStub(path) {
|
|
2
2
|
const call = () => {
|
|
3
3
|
throw new Error(`toiljs REST: ${path}() is unavailable. The generated REST client has not loaded - ` +
|
|
4
|
-
`
|
|
4
|
+
`run 'npm run build:server' to generate shared/server.ts; the client then attaches automatically.`);
|
|
5
5
|
};
|
|
6
6
|
return new Proxy(call, {
|
|
7
7
|
get(_target, prop) {
|
|
@@ -17,7 +17,7 @@ function restMissingStub(path) {
|
|
|
17
17
|
function streamMissingStub(path) {
|
|
18
18
|
const call = () => {
|
|
19
19
|
throw new Error(`toiljs Stream: ${path}() is unavailable. The generated stream client has not loaded - ` +
|
|
20
|
-
`
|
|
20
|
+
`run 'npm run build:server' to generate shared/server.ts; the client then attaches automatically.`);
|
|
21
21
|
};
|
|
22
22
|
return new Proxy(call, {
|
|
23
23
|
get(_target, prop) {
|
|
@@ -32,8 +32,8 @@ function streamMissingStub(path) {
|
|
|
32
32
|
}
|
|
33
33
|
function rpcStub(path) {
|
|
34
34
|
const call = () => {
|
|
35
|
-
throw new Error(`toiljs RPC: ${path}() is
|
|
36
|
-
`
|
|
35
|
+
throw new Error(`toiljs RPC: ${path}() is unavailable. The generated RPC client has not loaded - ` +
|
|
36
|
+
`run 'npm run build:server' to generate shared/server.ts; the client then attaches automatically.`);
|
|
37
37
|
};
|
|
38
38
|
return new Proxy(call, {
|
|
39
39
|
get(_target, prop) {
|
|
@@ -47,6 +47,11 @@ function rpcStub(path) {
|
|
|
47
47
|
const stream = globalThis.__toilStream;
|
|
48
48
|
return stream !== undefined ? stream : streamMissingStub('Server.Stream');
|
|
49
49
|
}
|
|
50
|
+
if (path === 'Server') {
|
|
51
|
+
const rpc = globalThis.__toilRpc;
|
|
52
|
+
if (rpc !== undefined && prop in rpc)
|
|
53
|
+
return rpc[prop];
|
|
54
|
+
}
|
|
50
55
|
return rpcStub(`${path}.${prop}`);
|
|
51
56
|
},
|
|
52
57
|
apply() {
|
|
@@ -55,3 +60,4 @@ function rpcStub(path) {
|
|
|
55
60
|
});
|
|
56
61
|
}
|
|
57
62
|
export const Server = rpcStub('Server');
|
|
63
|
+
globalThis.Server = Server;
|
|
@@ -5,9 +5,13 @@ function connectStream(url, encode) {
|
|
|
5
5
|
let opened = false;
|
|
6
6
|
let messageCb;
|
|
7
7
|
let closeCb;
|
|
8
|
+
const pending = [];
|
|
8
9
|
const channel = {
|
|
9
10
|
onMessage: (cb) => {
|
|
10
11
|
messageCb = cb;
|
|
12
|
+
for (const m of pending)
|
|
13
|
+
cb(m);
|
|
14
|
+
pending.length = 0;
|
|
11
15
|
},
|
|
12
16
|
onClose: (cb) => {
|
|
13
17
|
closeCb = cb;
|
|
@@ -16,7 +20,11 @@ function connectStream(url, encode) {
|
|
|
16
20
|
if (ws.readyState !== WebSocket.OPEN)
|
|
17
21
|
return;
|
|
18
22
|
const bytes = encode ? encode(data) : data;
|
|
19
|
-
|
|
23
|
+
try {
|
|
24
|
+
ws.send(bytes);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
}
|
|
20
28
|
},
|
|
21
29
|
close: () => {
|
|
22
30
|
ws.close();
|
|
@@ -27,8 +35,13 @@ function connectStream(url, encode) {
|
|
|
27
35
|
resolve(channel);
|
|
28
36
|
});
|
|
29
37
|
ws.addEventListener('message', (event) => {
|
|
30
|
-
if (event.data instanceof ArrayBuffer)
|
|
31
|
-
|
|
38
|
+
if (!(event.data instanceof ArrayBuffer))
|
|
39
|
+
return;
|
|
40
|
+
const bytes = new Uint8Array(event.data);
|
|
41
|
+
if (messageCb)
|
|
42
|
+
messageCb(bytes);
|
|
43
|
+
else
|
|
44
|
+
pending.push(bytes);
|
|
32
45
|
});
|
|
33
46
|
ws.addEventListener('close', (event) => {
|
|
34
47
|
if (!opened)
|
|
@@ -42,17 +55,107 @@ function connectStream(url, encode) {
|
|
|
42
55
|
});
|
|
43
56
|
});
|
|
44
57
|
}
|
|
58
|
+
function connectStreamWT(url, encode) {
|
|
59
|
+
return new Promise((resolve, reject) => {
|
|
60
|
+
if (!('WebTransport' in globalThis)) {
|
|
61
|
+
reject(new Error('WebTransport is not available in this browser'));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
let transport;
|
|
65
|
+
try {
|
|
66
|
+
transport = new WebTransport(url);
|
|
67
|
+
}
|
|
68
|
+
catch (e) {
|
|
69
|
+
reject(e instanceof Error ? e : new Error(String(e)));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
let messageCb;
|
|
73
|
+
let closeCb;
|
|
74
|
+
let writer;
|
|
75
|
+
let opened = false;
|
|
76
|
+
const pending = [];
|
|
77
|
+
const channel = {
|
|
78
|
+
onMessage: (cb) => {
|
|
79
|
+
messageCb = cb;
|
|
80
|
+
for (const m of pending)
|
|
81
|
+
cb(m);
|
|
82
|
+
pending.length = 0;
|
|
83
|
+
},
|
|
84
|
+
onClose: (cb) => {
|
|
85
|
+
closeCb = cb;
|
|
86
|
+
},
|
|
87
|
+
send: (data) => {
|
|
88
|
+
if (!writer)
|
|
89
|
+
return;
|
|
90
|
+
const bytes = encode ? encode(data) : data;
|
|
91
|
+
void writer.write(bytes).catch(() => { });
|
|
92
|
+
},
|
|
93
|
+
close: () => {
|
|
94
|
+
try {
|
|
95
|
+
transport.close();
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
transport.closed
|
|
102
|
+
.then((info) => {
|
|
103
|
+
if (opened)
|
|
104
|
+
closeCb?.(info?.closeCode ?? 0);
|
|
105
|
+
})
|
|
106
|
+
.catch(() => {
|
|
107
|
+
if (opened)
|
|
108
|
+
closeCb?.(1);
|
|
109
|
+
});
|
|
110
|
+
transport.ready
|
|
111
|
+
.then(() => {
|
|
112
|
+
opened = true;
|
|
113
|
+
writer = transport.datagrams.writable.getWriter();
|
|
114
|
+
const reader = transport.datagrams.readable.getReader();
|
|
115
|
+
void (async () => {
|
|
116
|
+
try {
|
|
117
|
+
for (;;) {
|
|
118
|
+
const { value, done } = await reader.read();
|
|
119
|
+
if (done)
|
|
120
|
+
break;
|
|
121
|
+
const bytes = value instanceof Uint8Array
|
|
122
|
+
? value
|
|
123
|
+
: new Uint8Array(value);
|
|
124
|
+
if (messageCb)
|
|
125
|
+
messageCb(bytes);
|
|
126
|
+
else
|
|
127
|
+
pending.push(bytes);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
}
|
|
132
|
+
})();
|
|
133
|
+
resolve(channel);
|
|
134
|
+
})
|
|
135
|
+
.catch((e) => reject(e instanceof Error ? e : new Error(String(e))));
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
function openChannel(url, encode) {
|
|
139
|
+
return url.startsWith('https://')
|
|
140
|
+
? connectStreamWT(url, encode)
|
|
141
|
+
: connectStream(url, encode);
|
|
142
|
+
}
|
|
45
143
|
function defaultOrigin() {
|
|
46
144
|
const loc = globalThis.location;
|
|
47
145
|
return `${loc.protocol === 'https:' ? 'wss:' : 'ws:'}//${loc.host}`;
|
|
48
146
|
}
|
|
147
|
+
function resolveStreamOrigin() {
|
|
148
|
+
const override = globalThis.__TOIL_STREAM_ORIGIN__;
|
|
149
|
+
if (typeof override === 'string' && override.length > 0)
|
|
150
|
+
return override;
|
|
151
|
+
return defaultOrigin();
|
|
152
|
+
}
|
|
49
153
|
export function makeStreamClient(routes, origin, encoders) {
|
|
50
|
-
const base = origin ?? defaultOrigin();
|
|
51
154
|
const client = {};
|
|
52
155
|
for (const [name, route] of Object.entries(routes)) {
|
|
53
156
|
const encode = encoders?.[name];
|
|
54
157
|
client[name] = {
|
|
55
|
-
connect: (path = '') =>
|
|
158
|
+
connect: (path = '') => openChannel(`${origin ?? resolveStreamOrigin()}${route}${path}`, encode),
|
|
56
159
|
};
|
|
57
160
|
}
|
|
58
161
|
return client;
|