@lesomnus/grpc-dgram 0.0.1 → 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.
@@ -0,0 +1,144 @@
1
+ import { n as Conn } from "../conn-CmYPHTPR.mjs";
2
+ import { F as Latch, Y as noop, c as decodeEnvelope, it as unpack, u as encodeEnvelope } from "../wire-DqHx0oUs.mjs";
3
+ import { n as MessageTooLargeError, r as StatusError } from "../status-DZwMDWIn.mjs";
4
+ //#region src/transport/webtransport/index.ts
5
+ const DefaultMaxMessageSize = 1200;
6
+ function closeCauseOf(info) {
7
+ const i = info;
8
+ const code = typeof i?.closeCode === "number" ? i.closeCode : 0;
9
+ const reason = typeof i?.reason === "string" && i.reason !== "" ? `: ${i.reason}` : "";
10
+ if (code === 0 && reason === "") return void 0;
11
+ return /* @__PURE__ */ new Error(`webtransport: session closed with code ${code}${reason}`);
12
+ }
13
+ function bytesOf(v) {
14
+ if (v instanceof Uint8Array) return v;
15
+ if (ArrayBuffer.isView(v)) return new Uint8Array(v.buffer, v.byteOffset, v.byteLength);
16
+ if (v instanceof ArrayBuffer) return new Uint8Array(v);
17
+ }
18
+ var WebTransportDatagramTransport = class {
19
+ wt;
20
+ max;
21
+ writer;
22
+ reader;
23
+ opened = new Latch();
24
+ dead = new Latch();
25
+ err;
26
+ attached = false;
27
+ closed = false;
28
+ constructor(wt, opts = {}) {
29
+ this.wt = wt;
30
+ this.max = opts.maxMessageSize;
31
+ const ds = wt.datagrams;
32
+ let sink;
33
+ if (typeof ds.createWritable === "function") try {
34
+ sink = ds.createWritable();
35
+ } catch (e) {
36
+ this.fail(e);
37
+ }
38
+ else {
39
+ sink = ds.writable;
40
+ if (sink === void 0) throw new Error("webtransport: session exposes neither datagrams.createWritable() nor datagrams.writable");
41
+ }
42
+ this.writer = sink?.getWriter();
43
+ this.writer?.closed.catch(noop);
44
+ wt.ready.then(() => this.opened.trip(), (e) => this.fail(e));
45
+ wt.closed.then((info) => this.fail(closeCauseOf(info)), (e) => this.fail(e));
46
+ }
47
+ reliable() {
48
+ return false;
49
+ }
50
+ attachConn(conn) {
51
+ if (this.attached) throw new Error("webtransport: transport already attached to a Conn");
52
+ this.attached = true;
53
+ const reader = this.wt.datagrams.readable.getReader();
54
+ this.reader = reader;
55
+ this.pump(conn, reader);
56
+ this.dead.wait().then(() => {
57
+ conn.close(this.err);
58
+ this.close();
59
+ });
60
+ }
61
+ async pump(conn, reader) {
62
+ try {
63
+ for (;;) {
64
+ const { done, value } = await reader.read();
65
+ if (done) return;
66
+ if (this.dead.tripped) return;
67
+ const data = bytesOf(value);
68
+ if (data === void 0) continue;
69
+ let frames;
70
+ try {
71
+ frames = decodeEnvelope(data);
72
+ } catch {
73
+ continue;
74
+ }
75
+ unpack(frames, conn, {});
76
+ }
77
+ } catch {}
78
+ }
79
+ limit() {
80
+ if (this.max !== void 0) return this.max;
81
+ if (!this.opened.tripped) return DefaultMaxMessageSize;
82
+ const m = this.wt.datagrams.maxDatagramSize;
83
+ return typeof m === "number" && m > 0 ? m : DefaultMaxMessageSize;
84
+ }
85
+ check(data) {
86
+ const max = this.limit();
87
+ if (max > 0 && data.length > max) throw new MessageTooLargeError(`webtransport: ${data.length}-byte envelope over the ${max}-byte limit`);
88
+ }
89
+ sendFrames(frames) {
90
+ const data = encodeEnvelope(frames);
91
+ this.check(data);
92
+ return this.send(data);
93
+ }
94
+ handle(f) {
95
+ return this.sendFrames([f]);
96
+ }
97
+ async send(data) {
98
+ if (!this.opened.tripped) {
99
+ await Promise.race([this.opened.wait(), this.dead.wait()]);
100
+ if (this.dead.tripped) throw this.closedErr();
101
+ this.check(data);
102
+ }
103
+ const writer = this.writer;
104
+ if (writer === void 0 || this.dead.tripped) throw this.closedErr();
105
+ try {
106
+ await writer.write(data);
107
+ } catch (e) {
108
+ this.fail(e);
109
+ throw this.closedErr();
110
+ }
111
+ }
112
+ fail(err) {
113
+ if (!this.dead.tripped && this.err === void 0) this.err = err;
114
+ this.dead.trip();
115
+ }
116
+ closedErr() {
117
+ const e = new StatusError(14, `webtransport: session closed${this.err instanceof Error ? `: ${this.err.message}` : ""}`);
118
+ if (this.err !== void 0) e.cause = this.err;
119
+ return e;
120
+ }
121
+ close() {
122
+ if (this.closed) return;
123
+ this.closed = true;
124
+ this.fail(void 0);
125
+ try {
126
+ this.wt.close();
127
+ } catch {}
128
+ this.reader?.cancel().catch(noop);
129
+ }
130
+ };
131
+ function dialWebTransport(url, opts = {}) {
132
+ const ctor = globalThis.WebTransport;
133
+ if (ctor === void 0) throw new Error("webtransport: this runtime has no global WebTransport; construct one and pass it to new WebTransportDatagramTransport()");
134
+ const { allowPooling, congestionControl, protocols, requireUnreliable = true, serverCertificateHashes } = opts;
135
+ return new Conn(new WebTransportDatagramTransport(new ctor(url, {
136
+ allowPooling,
137
+ congestionControl,
138
+ protocols,
139
+ requireUnreliable,
140
+ serverCertificateHashes
141
+ }), opts), opts);
142
+ }
143
+ //#endregion
144
+ export { DefaultMaxMessageSize, WebTransportDatagramTransport, dialWebTransport };
@@ -1,10 +1,11 @@
1
- import { o as startInstance, t as isPageMessage } from "../protocol-K4Zy8MuQ.mjs";
1
+ import { o as startInstance, t as isPageMessage } from "../protocol-CTxSUZQF.mjs";
2
2
  //#region src/wasm/worker.ts
3
3
  const GOODBYE = /* @__PURE__ */ new Uint8Array(0);
4
4
  function serveIn(scope) {
5
5
  const ports = /* @__PURE__ */ new Set();
6
6
  let instance;
7
7
  let gone = false;
8
+ let answered = false;
8
9
  const bury = () => {
9
10
  gone = true;
10
11
  for (const port of ports) farewell(port);
@@ -14,13 +15,20 @@ function serveIn(scope) {
14
15
  const msg = ev.data;
15
16
  if (!isPageMessage(msg)) return;
16
17
  if (msg.drpc === "start") {
17
- if (instance !== void 0) return;
18
+ if (instance !== void 0) {
19
+ if (answered) scope.postMessage({
20
+ drpc: "error",
21
+ message: "this worker already runs an instance — a second server in it is a second entry point, dialled with sock.dial({ entryPoint }), not a second open()"
22
+ });
23
+ return;
24
+ }
18
25
  instance = startInstance(msg.app, {
19
26
  entryPoint: msg.entryPoint,
20
27
  readyTimeoutMs: msg.readyTimeoutMs,
21
28
  wasmExec: msg.wasmExec
22
29
  });
23
30
  instance.then((inst) => {
31
+ answered = true;
24
32
  scope.postMessage({ drpc: "ready" });
25
33
  inst.exited.then((cause) => {
26
34
  bury();
@@ -30,6 +38,7 @@ function serveIn(scope) {
30
38
  });
31
39
  });
32
40
  }, (e) => {
41
+ answered = true;
33
42
  bury();
34
43
  scope.postMessage({
35
44
  drpc: "error",
@@ -46,14 +55,20 @@ function serveIn(scope) {
46
55
  }
47
56
  ports.add(port);
48
57
  instance.then((inst) => {
58
+ let served;
49
59
  try {
50
- inst.serve(port);
60
+ served = inst.serve(port, msg.entryPoint, msg.readyTimeoutMs);
51
61
  } catch {
52
- ports.delete(port);
53
- farewell(port);
62
+ abandon(port);
63
+ return;
54
64
  }
65
+ served.catch(() => abandon(port));
55
66
  }, () => {});
56
67
  });
68
+ function abandon(port) {
69
+ ports.delete(port);
70
+ farewell(port);
71
+ }
57
72
  }
58
73
  function farewell(port) {
59
74
  try {
package/dist/wasm.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as Conn, r as ConnOptions } from "./conn-DTWG9vIx.mjs";
1
+ import { i as ConnOptions, r as Conn } from "./conn-Dc57BC-h.mjs";
2
2
  import { PortOptions } from "./transport/port.mjs";
3
3
  //#region src/wasm/instance.d.ts
4
4
  declare const DefaultEntryPoint = "drpcServe";
@@ -25,12 +25,16 @@ interface OpenOptions extends PortOptions {
25
25
  readyTimeoutMs?: number;
26
26
  go?: GoLike;
27
27
  }
28
+ interface DialOptions extends ConnOptions {
29
+ entryPoint?: string;
30
+ readyTimeoutMs?: number;
31
+ }
28
32
  interface WasmSock {
29
33
  readonly worker?: WasmWorker;
30
34
  readonly exited: Promise<unknown>;
31
- dial(opts?: ConnOptions): Conn;
35
+ dial(opts?: DialOptions): Conn;
32
36
  close(): void;
33
37
  }
34
38
  declare function open(app: WasmApp, opts?: OpenOptions): Promise<WasmSock>;
35
39
  //#endregion
36
- export { DefaultEntryPoint, DefaultReadyTimeoutMs, DefaultWasmExec, type GoLike, OpenOptions, type WasmApp, WasmSock, WasmWorker, open };
40
+ export { DefaultEntryPoint, DefaultReadyTimeoutMs, DefaultWasmExec, DialOptions, type GoLike, OpenOptions, type WasmApp, WasmSock, WasmWorker, open };
package/dist/wasm.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { n as Conn } from "./conn-DOmx4nbt.mjs";
1
+ import { n as Conn } from "./conn-CmYPHTPR.mjs";
2
2
  import { PortTransport } from "./transport/port.mjs";
3
- import { a as DefaultWasmExec, i as DefaultReadyTimeoutMs, n as isWorkerMessage, o as startInstance, r as DefaultEntryPoint } from "./protocol-K4Zy8MuQ.mjs";
3
+ import { a as DefaultWasmExec, i as DefaultReadyTimeoutMs, n as isWorkerMessage, o as startInstance, r as DefaultEntryPoint } from "./protocol-CTxSUZQF.mjs";
4
4
  //#region src/wasm/index.ts
5
5
  async function open(app, opts = {}) {
6
6
  if (opts.worker === false) return new HereSock(await startInstance(app, opts), opts);
@@ -38,9 +38,10 @@ var Sock = class {
38
38
  const what = this.closed ? "this sock is closed" : "the wasm instance has exited";
39
39
  throw new Error(`wasm: ${what}${this.dead.cause instanceof Error ? `: ${this.dead.cause.message}` : ""}`);
40
40
  }
41
- const tx = this.connect();
41
+ const { entryPoint, readyTimeoutMs, ...connOpts } = opts;
42
+ const tx = this.connect(entryPoint, readyTimeoutMs);
42
43
  this.txs.add(tx);
43
- return new Conn(tx, opts);
44
+ return new Conn(tx, connOpts);
44
45
  }
45
46
  close() {
46
47
  if (this.closed) return;
@@ -53,7 +54,14 @@ var Sock = class {
53
54
  let tx;
54
55
  try {
55
56
  tx = new PortTransport(ch.port1, this.o);
56
- handover(ch.port2);
57
+ const handed = handover(ch.port2);
58
+ if (handed !== void 0) {
59
+ const t = tx;
60
+ handed.catch((e) => {
61
+ this.txs.delete(t);
62
+ t.close(e);
63
+ });
64
+ }
57
65
  return tx;
58
66
  } catch (e) {
59
67
  tx?.close(e);
@@ -105,8 +113,12 @@ var WorkerSock = class extends Sock {
105
113
  this.worker.postMessage(start);
106
114
  return this.readiness;
107
115
  }
108
- connect() {
109
- const serve = { drpc: "serve" };
116
+ connect(entryPoint, readyTimeoutMs) {
117
+ const serve = {
118
+ drpc: "serve",
119
+ ...entryPoint === void 0 ? {} : { entryPoint },
120
+ ...readyTimeoutMs === void 0 ? {} : { readyTimeoutMs }
121
+ };
110
122
  return this.channelTo((port) => this.worker.postMessage(serve, [port]));
111
123
  }
112
124
  stop() {
@@ -147,8 +159,8 @@ var HereSock = class extends Sock {
147
159
  this.inst = inst;
148
160
  inst.exited.then((cause) => this.bury(cause));
149
161
  }
150
- connect() {
151
- return this.channelTo((port) => this.inst.serve(port));
162
+ connect(entryPoint, readyTimeoutMs) {
163
+ return this.channelTo((port) => this.inst.serve(port, entryPoint, readyTimeoutMs));
152
164
  }
153
165
  stop() {}
154
166
  };