@av-pi-studio/relay 0.0.10 → 0.0.12

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 CHANGED
@@ -34,6 +34,23 @@ Defaults to `0.0.0.0:7000` if neither `--listen` nor `PI_STUDIO_RELAY_LISTEN` is
34
34
  - A WebSocket endpoint (root path) — where daemons and clients connect.
35
35
  - `GET /health` → `200 ok` — liveness probe.
36
36
 
37
+ ### Logging
38
+
39
+ The relay logs its full operational lifecycle with pino: every connection open (id + remote
40
+ address), session registration (session id, peer count), peer detach, and connection close (close
41
+ code, duration, bytes in/out) — plus warns on pre-registration garbage and errors on socket
42
+ failures. Frame forwarding is logged at `trace` with **sizes only**: the relay is zero-knowledge
43
+ by construction and never sees (so never logs) message contents.
44
+
45
+ | Variable | Default | Purpose |
46
+ |---|---|---|
47
+ | `PI_STUDIO_RELAY_LOG_LEVEL` | `info` | pino level (`trace`\|`debug`\|`info`\|`warn`\|`error`\|`fatal`\|`silent`) |
48
+ | `PI_STUDIO_RELAY_LOG_DIR` | _(unset)_ | Also write rotating NDJSON files here (stdout always gets logs too) |
49
+
50
+ stdout always receives logs — NDJSON in non-TTY (so `docker logs` / journald work out of the box),
51
+ pretty-printed on a TTY. `pi-studio relay start` (CLI) runs the relay detached with `stdio`
52
+ ignored, so it configures a rotating file under `$PI_STUDIO_HOME/logs/` instead.
53
+
37
54
  Shuts down cleanly on `SIGINT`/`SIGTERM`.
38
55
 
39
56
  ### From the Pi-Studio CLI
@@ -64,11 +81,27 @@ env vars) to dial out to the relay you started above:
64
81
  }
65
82
  ```
66
83
 
67
- Env equivalents: `PI_STUDIO_RELAY_ENDPOINT`, `PI_STUDIO_RELAY_USE_TLS`,
84
+ Env equivalents: `PI_STUDIO_RELAY_ENABLED`, `PI_STUDIO_RELAY_ENDPOINT`, `PI_STUDIO_RELAY_USE_TLS`,
68
85
  `PI_STUDIO_RELAY_PUBLIC_ENDPOINT`, `PI_STUDIO_RELAY_PUBLIC_USE_TLS`. With `relay.enabled` unset
69
86
  (the default, `false`), the daemon behaves exactly as if this package didn't exist — the relay is
70
87
  fully opt-in and never affects direct WebSocket connections.
71
88
 
89
+ ### Pairing a browser client through the relay
90
+
91
+ Once the daemon dials the relay (above), `pi-studio daemon pair` prints a pairing link that
92
+ carries the relay's client-facing endpoint (`daemon.relay.publicEndpoint`/`publicUseTls`, falling
93
+ back to `endpoint`/`useTls`) instead of a direct host — see `@av-pi-studio/cli`'s
94
+ `buildPairingUrl`. A browser (`@av-pi-studio/web-client`) or any `@av-pi-studio/client` consumer
95
+ opening that link connects via `createRelayTransport`, deriving the SAME rendezvous session id
96
+ (`deriveRelaySessionId(daemonPublicKey)`) the daemon registered under — no session id needs to be
97
+ transmitted separately, and the link keeps working across relay reconnects (the daemon always
98
+ re-registers under this deterministic id, never a fresh random one per connection).
99
+
100
+ The same pairing link can be opened by more than one client over the daemon's lifetime (a browser
101
+ reload, a second tab, or handing the link to a different machine) — each one gets its own fresh
102
+ E2EE handshake against the daemon's single long-lived relay channel; the daemon does not require
103
+ re-pairing or lock onto whichever client connected first.
104
+
72
105
  ## Library API
73
106
 
74
107
  For embedding directly (custom relay deployments, tests, or building the daemon/client transports
@@ -91,12 +124,19 @@ import { startRelayServer } from "@av-pi-studio/relay/server";
91
124
 
92
125
  | Export | Subpath | Role | Purpose |
93
126
  |---|---|---|---|
94
- | `createDaemonChannel(opts)` | `.` | daemon | E2EE channel over an abstract `Transport`; waits for the client's `e2ee_hello`, replies `e2ee_ready` |
95
- | `createClientChannel(opts)` | `.` | client | E2EE channel; generates a fresh ephemeral keypair, sends `e2ee_hello` |
127
+ | `createDaemonChannel(opts)` | `.` | daemon | E2EE channel over an abstract `Transport`; waits for the client's `e2ee_hello`, replies `e2ee_ready`; `send()`/`sendBinary()` for text/binary app traffic |
128
+ | `createClientChannel(opts)` | `.` | client | E2EE channel; generates a fresh ephemeral keypair, sends `e2ee_hello`; `send()`/`sendBinary()` for text/binary app traffic |
96
129
  | `RelaySessionBridge` | `.` | relay server | Platform-agnostic verbatim frame bridge, keyed by session id — the zero-knowledge core |
97
130
  | `createCloudflareRelayHandler(opts)` | `.` | relay server | Thin Cloudflare Workers `WebSocketPair` wrapper around `RelaySessionBridge` |
131
+ | `deriveRelaySessionId(publicKey)` | `.` | both | Deterministic rendezvous session id from a daemon's public key — lets a pairing link survive relay reconnects (see § Pairing note below) |
98
132
  | `encodeBase64` / `decodeBase64` | `.` | both | Pure-JS base64 codec (no Node `Buffer`) — runs identically in Node and browser/RN |
99
- | `startRelayServer(opts)` | `./server` | relay server | Self-hosted `ws`-based relay (what `pi-studio-relay`/`pi-studio relay start` run) |
133
+ | `startRelayServer(opts)` | `./server` | relay server | Self-hosted `ws`-based relay (what `pi-studio-relay`/`pi-studio relay start` run); accepts an optional `logger` |
134
+ | `createRelayLogger(opts)` | `./server` | relay server | pino operational logger: stdout always (pretty TTY / NDJSON otherwise), optional rotating file via `logDir` |
135
+
136
+ `RelaySessionBridge`'s constructor takes an optional `RelayBridgeEvents` (`onRegister`,
137
+ `onRegisterRejected`, `onForward`, `onUnregister`) — metadata-only lifecycle hooks (session ids,
138
+ peer counts, frame **sizes**, never contents) that `startRelayServer` wires to its logger; use
139
+ them for your own metrics/logging when embedding the bridge.
100
140
 
101
141
  Both channel constructors expose an **identical** API — the daemon and client use symmetric code
102
142
  paths. Neither channel accepts app messages before its handshake completes; a daemon's channel
@@ -105,10 +145,13 @@ shared key from that same known public key before the handshake even starts.
105
145
 
106
146
  ```ts
107
147
  // Minimal self-hosted relay, embedded rather than run as a separate process:
108
- import { startRelayServer } from "@av-pi-studio/relay/server";
148
+ import { startRelayServer, createRelayLogger } from "@av-pi-studio/relay/server";
109
149
 
110
- const handle = await startRelayServer({ host: "0.0.0.0", port: 7000 });
111
- console.log(`relay up on ws://${handle.host}:${handle.port}`);
150
+ const handle = await startRelayServer({
151
+ host: "0.0.0.0",
152
+ port: 7000,
153
+ logger: createRelayLogger({ level: "info" }), // optional; omit for silent
154
+ });
112
155
  // handle.bridge is the underlying RelaySessionBridge, if you need to inspect peerCount(sessionId)
113
156
  await handle.close();
114
157
  ```
@@ -119,10 +162,18 @@ await handle.close();
119
162
  `{"type":"relay_register","sessionId":"<uuid>"}` — sent as the first frame by both the daemon
120
163
  and the client; pairs sockets sharing the same session id.
121
164
  - Handshake (plaintext, visible to the relay): `{"type":"e2ee_hello","ephemeralPublicKey":"<base64>"}`
122
- (client→daemon), `{"type":"e2ee_ready"}` (daemon→client).
123
- - App traffic: `{"type":"e2ee_app","frame":"<base64(24-byte nonce ++ ciphertext)>"}`
165
+ (client→daemon), `{"type":"e2ee_ready"}` (daemon→client). A daemon channel accepts a fresh
166
+ `e2ee_hello` at any point — including after it's already completed one — re-deriving the shared
167
+ key and replying `e2ee_ready` again; the relay imposes no cap on how many client sockets attach
168
+ to one session id over the daemon's (long-lived, single-dial) connection.
169
+ - App traffic (text — RPC/control messages): `{"type":"e2ee_app","frame":"<base64(24-byte nonce ++ ciphertext)>"}`
124
170
  (XSalsa20-Poly1305, `nacl.box`/`nacl.box.open`). Auth failure → frame silently dropped, never
125
171
  thrown into the transport's message loop.
172
+ - App traffic (binary — terminal I/O, file-transfer chunks): `{"type":"e2ee_bin","frame":"<base64(24-byte nonce ++ ciphertext)>"}`.
173
+ Identical crypto/framing to `e2ee_app`, just fed raw bytes instead of UTF-8 text and dispatched
174
+ to a separate `onBinaryMessage` handler on receipt. Still travels as a JSON text WS frame — no
175
+ raw binary WebSocket frames cross the relay, so `RelaySessionBridge`/the self-hosted relay/the
176
+ Cloudflare adapter needed zero changes to support this.
126
177
 
127
178
  ## Security notes
128
179
 
@@ -136,12 +187,29 @@ await handle.close();
136
187
  check — this is enforced structurally, not by convention: nothing in its forwarding path ever
137
188
  calls `JSON.parse` on post-registration traffic.
138
189
 
190
+ ## Performance notes (binary-over-relay)
191
+
192
+ - The relay process itself pays **zero** extra cost for binary traffic — `RelaySessionBridge`
193
+ forwards `e2ee_bin` frames exactly like `e2ee_app`: verbatim, unparsed, byte-for-byte. All the
194
+ cost below is paid by the two ENDPOINTS (daemon + client), never the relay.
195
+ - Wrapping binary as base64-in-JSON (rather than a raw binary WS frame) costs ~33% more wire bytes
196
+ plus a small JSON envelope per frame. Deliberate tradeoff (see "Wire protocol" above) to avoid
197
+ touching the relay's zero-knowledge bridging core for this.
198
+ - Terminal I/O: negligible in practice. Output is already coalesced into ~4ms batches server-side
199
+ (`packages/server`'s `TerminalManager`) before it ever reaches the wire, and input is small,
200
+ human-paced keystrokes — a few KB encrypted with pure-JS `nacl.box` is sub-millisecond.
201
+ - Large file transfers over relay pay proportionally more: every base64+encrypt/decrypt pass adds
202
+ up across many large chunks. Still bounded (pure-JS `nacl.box` throughput is tens of MB/s), but
203
+ a direct (non-relay) connection remains the faster path for bulk transfer.
204
+
139
205
  ## Development
140
206
 
141
207
  ```bash
142
208
  npm run build # tsc -b (also chmod +x's the pi-studio-relay binary)
143
- npm test -- --project packages/relay
209
+ npx vitest run packages/relay
144
210
  ```
145
211
 
146
- Zero non-crypto runtime dependencies beyond `tweetnacl` (crypto) and `ws` (WebSocket server/client
147
- framing) — no framework, no HTTP client library beyond Node's own `node:http`.
212
+ Runtime dependencies: `tweetnacl` (crypto) and `ws` (WebSocket framing) for the channel/bridge
213
+ core, plus `pino` + `pino-pretty` + `rotating-file-stream` used only by the Node-only `./server`
214
+ subpath (operational logging). The main barrel stays free of platform-specific imports — no
215
+ framework, no HTTP client library beyond Node's own `node:http`.
package/dist/.tsbuildinfo CHANGED
@@ -1 +1 @@
1
- {"fileNames":["../../../node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/typescript/lib/lib.es2021.d.ts","../../../node_modules/typescript/lib/lib.es2022.d.ts","../../../node_modules/typescript/lib/lib.es2023.d.ts","../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/typescript/lib/lib.es2021.promise.d.ts","../../../node_modules/typescript/lib/lib.es2021.string.d.ts","../../../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../../node_modules/typescript/lib/lib.es2021.intl.d.ts","../../../node_modules/typescript/lib/lib.es2022.array.d.ts","../../../node_modules/typescript/lib/lib.es2022.error.d.ts","../../../node_modules/typescript/lib/lib.es2022.intl.d.ts","../../../node_modules/typescript/lib/lib.es2022.object.d.ts","../../../node_modules/typescript/lib/lib.es2022.string.d.ts","../../../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2023.array.d.ts","../../../node_modules/typescript/lib/lib.es2023.collection.d.ts","../../../node_modules/typescript/lib/lib.es2023.intl.d.ts","../../../node_modules/typescript/lib/lib.decorators.d.ts","../../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../src/base64.ts","../src/session-bridge.ts","../src/cf-adapter.ts","../../../node_modules/tweetnacl/nacl.d.ts","../src/channel.ts","../src/index.ts","../../../node_modules/@types/node/compatibility/disposable.d.ts","../../../node_modules/@types/node/compatibility/indexable.d.ts","../../../node_modules/@types/node/compatibility/iterators.d.ts","../../../node_modules/@types/node/compatibility/index.d.ts","../../../node_modules/@types/node/globals.typedarray.d.ts","../../../node_modules/@types/node/buffer.buffer.d.ts","../../../node_modules/@types/node/globals.d.ts","../../../node_modules/@types/node/web-globals/abortcontroller.d.ts","../../../node_modules/@types/node/web-globals/domexception.d.ts","../../../node_modules/@types/node/web-globals/events.d.ts","../../../node_modules/undici-types/header.d.ts","../../../node_modules/undici-types/readable.d.ts","../../../node_modules/undici-types/file.d.ts","../../../node_modules/undici-types/fetch.d.ts","../../../node_modules/undici-types/formdata.d.ts","../../../node_modules/undici-types/connector.d.ts","../../../node_modules/undici-types/client.d.ts","../../../node_modules/undici-types/errors.d.ts","../../../node_modules/undici-types/dispatcher.d.ts","../../../node_modules/undici-types/global-dispatcher.d.ts","../../../node_modules/undici-types/global-origin.d.ts","../../../node_modules/undici-types/pool-stats.d.ts","../../../node_modules/undici-types/pool.d.ts","../../../node_modules/undici-types/handlers.d.ts","../../../node_modules/undici-types/balanced-pool.d.ts","../../../node_modules/undici-types/agent.d.ts","../../../node_modules/undici-types/mock-interceptor.d.ts","../../../node_modules/undici-types/mock-agent.d.ts","../../../node_modules/undici-types/mock-client.d.ts","../../../node_modules/undici-types/mock-pool.d.ts","../../../node_modules/undici-types/mock-errors.d.ts","../../../node_modules/undici-types/proxy-agent.d.ts","../../../node_modules/undici-types/env-http-proxy-agent.d.ts","../../../node_modules/undici-types/retry-handler.d.ts","../../../node_modules/undici-types/retry-agent.d.ts","../../../node_modules/undici-types/api.d.ts","../../../node_modules/undici-types/interceptors.d.ts","../../../node_modules/undici-types/util.d.ts","../../../node_modules/undici-types/cookies.d.ts","../../../node_modules/undici-types/patch.d.ts","../../../node_modules/undici-types/websocket.d.ts","../../../node_modules/undici-types/eventsource.d.ts","../../../node_modules/undici-types/filereader.d.ts","../../../node_modules/undici-types/diagnostics-channel.d.ts","../../../node_modules/undici-types/content-type.d.ts","../../../node_modules/undici-types/cache.d.ts","../../../node_modules/undici-types/index.d.ts","../../../node_modules/@types/node/web-globals/fetch.d.ts","../../../node_modules/@types/node/web-globals/navigator.d.ts","../../../node_modules/@types/node/web-globals/storage.d.ts","../../../node_modules/@types/node/assert.d.ts","../../../node_modules/@types/node/assert/strict.d.ts","../../../node_modules/@types/node/async_hooks.d.ts","../../../node_modules/@types/node/buffer.d.ts","../../../node_modules/@types/node/child_process.d.ts","../../../node_modules/@types/node/cluster.d.ts","../../../node_modules/@types/node/console.d.ts","../../../node_modules/@types/node/constants.d.ts","../../../node_modules/@types/node/crypto.d.ts","../../../node_modules/@types/node/dgram.d.ts","../../../node_modules/@types/node/diagnostics_channel.d.ts","../../../node_modules/@types/node/dns.d.ts","../../../node_modules/@types/node/dns/promises.d.ts","../../../node_modules/@types/node/domain.d.ts","../../../node_modules/@types/node/events.d.ts","../../../node_modules/@types/node/fs.d.ts","../../../node_modules/@types/node/fs/promises.d.ts","../../../node_modules/@types/node/http.d.ts","../../../node_modules/@types/node/http2.d.ts","../../../node_modules/@types/node/https.d.ts","../../../node_modules/@types/node/inspector.d.ts","../../../node_modules/@types/node/inspector.generated.d.ts","../../../node_modules/@types/node/module.d.ts","../../../node_modules/@types/node/net.d.ts","../../../node_modules/@types/node/os.d.ts","../../../node_modules/@types/node/path.d.ts","../../../node_modules/@types/node/perf_hooks.d.ts","../../../node_modules/@types/node/process.d.ts","../../../node_modules/@types/node/punycode.d.ts","../../../node_modules/@types/node/querystring.d.ts","../../../node_modules/@types/node/readline.d.ts","../../../node_modules/@types/node/readline/promises.d.ts","../../../node_modules/@types/node/repl.d.ts","../../../node_modules/@types/node/sea.d.ts","../../../node_modules/@types/node/sqlite.d.ts","../../../node_modules/@types/node/stream.d.ts","../../../node_modules/@types/node/stream/promises.d.ts","../../../node_modules/@types/node/stream/consumers.d.ts","../../../node_modules/@types/node/stream/web.d.ts","../../../node_modules/@types/node/string_decoder.d.ts","../../../node_modules/@types/node/test.d.ts","../../../node_modules/@types/node/timers.d.ts","../../../node_modules/@types/node/timers/promises.d.ts","../../../node_modules/@types/node/tls.d.ts","../../../node_modules/@types/node/trace_events.d.ts","../../../node_modules/@types/node/tty.d.ts","../../../node_modules/@types/node/url.d.ts","../../../node_modules/@types/node/util.d.ts","../../../node_modules/@types/node/v8.d.ts","../../../node_modules/@types/node/vm.d.ts","../../../node_modules/@types/node/wasi.d.ts","../../../node_modules/@types/node/worker_threads.d.ts","../../../node_modules/@types/node/zlib.d.ts","../../../node_modules/@types/node/index.d.ts","../../../node_modules/@types/ws/index.d.mts","../src/relay-server.ts","../src/relay-main.ts"],"fileIdsList":[[73,118,119,121,138,139],[73,120,121,138,139],[121,138,139],[73,121,126,138,139,156],[73,121,122,127,132,138,139,141,153,164],[73,121,122,123,132,138,139,141],[73,121,138,139],[68,69,70,73,121,138,139],[73,121,124,138,139,165],[73,121,125,126,133,138,139,142],[73,121,126,138,139,153,161],[73,121,127,129,132,138,139,141],[73,120,121,128,138,139],[73,121,129,130,138,139],[73,121,131,132,138,139],[73,120,121,132,138,139],[73,121,132,133,134,138,139,153,164],[73,121,132,133,134,138,139,148,153,156],[73,114,121,129,132,135,138,139,141,153,164],[73,121,132,133,135,136,138,139,141,153,161,164],[73,121,135,137,138,139,153,161,164],[71,72,73,74,75,76,77,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170],[73,121,132,138,139],[73,121,138,139,140,164],[73,121,129,132,138,139,141,153],[73,121,138,139,142],[73,121,138,139,143],[73,120,121,138,139,144],[73,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170],[73,121,138,139,146],[73,121,138,139,147],[73,121,132,138,139,148,149],[73,121,138,139,148,150,165,167],[73,121,133,138,139],[73,121,132,138,139,153,154,156],[73,121,138,139,155,156],[73,121,138,139,153,154],[73,121,138,139,156],[73,121,138,139,157],[73,118,121,138,139,153,158,164],[73,121,132,138,139,159,160],[73,121,138,139,159,160],[73,121,126,138,139,141,153,161],[73,121,138,139,162],[73,121,138,139,141,163],[73,121,135,138,139,147,164],[73,121,126,138,139,165],[73,121,138,139,153,166],[73,121,138,139,140,167],[73,121,138,139,168],[73,114,121,138,139],[73,114,121,132,134,138,139,144,153,156,164,166,167,169],[73,121,138,139,153,170],[73,121,132,135,137,138,139,141,153,161,164,170,171],[73,86,90,121,138,139,164],[73,86,121,138,139,153,164],[73,81,121,138,139],[73,83,86,121,138,139,161,164],[73,121,138,139,141,161],[73,121,138,139,171],[73,81,121,138,139,171],[73,83,86,121,138,139,141,164],[73,78,79,82,85,121,132,138,139,153,164],[73,86,93,121,138,139],[73,78,84,121,138,139],[73,86,107,108,121,138,139],[73,82,86,121,138,139,156,164,171],[73,107,121,138,139,171],[73,80,81,121,138,139,171],[73,86,121,138,139],[73,80,81,82,83,84,85,86,87,88,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,108,109,110,111,112,113,121,138,139],[73,86,101,121,138,139],[73,86,93,94,121,138,139],[73,84,86,94,95,121,138,139],[73,85,121,138,139],[73,78,81,86,121,138,139],[73,86,90,94,95,121,138,139],[73,90,121,138,139],[73,84,86,89,121,138,139,164],[73,78,83,86,93,121,138,139],[73,121,138,139,153],[73,81,86,107,121,138,139,169,171],[63,73,121,138,139],[62,65,73,121,138,139],[62,63,64,66,73,121,138,139],[73,121,138,139,173],[63,73,121,135,138,139,172]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"27bdc30a0e32783366a5abeda841bc22757c1797de8681bbe81fbc735eeb1c10","impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cdf8847677ac7d20486e54dd3fcf09eda95812ac8ace44b4418da1bbbab6eb8","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"df83c2a6c73228b625b0beb6669c7ee2a09c914637e2d35170723ad49c0f5cd4","affectsGlobalScope":true,"impliedFormat":1},{"version":"436aaf437562f276ec2ddbee2f2cdedac7664c1e4c1d2c36839ddd582eeb3d0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e3c06ea092138bf9fa5e874a1fdbc9d54805d074bee1de31b99a11e2fec239d","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"93d79f12c401be264bcb23d89f4e74c1e72a5605fcc42fbeefc0f404a51a545f","signature":"fdc8d72f90b3ac131587d78463fc03c479edc4ea623455ad17c72dadcc955299"},{"version":"70cd1ae64dac1d01603caad64f2f9b3dc1b5b39a021a640346dbbd69532746f4","signature":"69ee6c9e1da9cea7c05b53aba10a74ec8c56214d95563dd93a106f78db0e18a8"},{"version":"ecf8251ec9dd047961cac4d6da5574fa9ea5e7f095c7c0f777654ff364cb8041","signature":"ce3dc2e2dd5757bac8ac7629f26e0e241301fa2a17b2b50bee4283d651f0abe4"},{"version":"60592f5ae1b739c9607a99895d4a3ad5c865b16903e4180e50b256e360a4a104","impliedFormat":1},{"version":"a9dbb24cf673eafcae19f9ca4e897016408548a4e67a1fac55494520ed2a755e","signature":"a850bcf01aa5683c7c881619122e748159a3623a7c7f27fe41277bdee5c34d4e"},{"version":"c01e05998877dfac8ae25ddab219c902e9b6bb04145a134e0e0adc960c9dc842","signature":"5594a4bf850fcede314d66496e8d6411d67be1df7a4f8cbac4754c0e65591f10"},{"version":"6c7176368037af28cb72f2392010fa1cef295d6d6744bca8cfb54985f3a18c3e","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"437e20f2ba32abaeb7985e0afe0002de1917bc74e949ba585e49feba65da6ca1","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"98cffbf06d6bab333473c70a893770dbe990783904002c4f1a960447b4b53dca","affectsGlobalScope":true,"impliedFormat":1},{"version":"3af97acf03cc97de58a3a4bc91f8f616408099bc4233f6d0852e72a8ffb91ac9","affectsGlobalScope":true,"impliedFormat":1},{"version":"808069bba06b6768b62fd22429b53362e7af342da4a236ed2d2e1c89fcca3b4a","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"b52476feb4a0cbcb25e5931b930fc73cb6643fb1a5060bf8a3dda0eeae5b4b68","affectsGlobalScope":true,"impliedFormat":1},{"version":"f9501cc13ce624c72b61f12b3963e84fad210fbdf0ffbc4590e08460a3f04eba","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0fa06ada475b910e2106c98c68b10483dc8811d0c14a8a8dd36efb2672485b29","impliedFormat":1},{"version":"33e5e9aba62c3193d10d1d33ae1fa75c46a1171cf76fef750777377d53b0303f","impliedFormat":1},{"version":"2b06b93fd01bcd49d1a6bd1f9b65ddcae6480b9a86e9061634d6f8e354c1468f","impliedFormat":1},{"version":"6a0cd27e5dc2cfbe039e731cf879d12b0e2dded06d1b1dedad07f7712de0d7f4","affectsGlobalScope":true,"impliedFormat":1},{"version":"13f5c844119c43e51ce777c509267f14d6aaf31eafb2c2b002ca35584cd13b29","impliedFormat":1},{"version":"e60477649d6ad21542bd2dc7e3d9ff6853d0797ba9f689ba2f6653818999c264","impliedFormat":1},{"version":"c2510f124c0293ab80b1777c44d80f812b75612f297b9857406468c0f4dafe29","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"4c829ab315f57c5442c6667b53769975acbf92003a66aef19bce151987675bd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"b2ade7657e2db96d18315694789eff2ddd3d8aea7215b181f8a0b303277cc579","impliedFormat":1},{"version":"9855e02d837744303391e5623a531734443a5f8e6e8755e018c41d63ad797db2","impliedFormat":1},{"version":"4d631b81fa2f07a0e63a9a143d6a82c25c5f051298651a9b69176ba28930756d","impliedFormat":1},{"version":"836a356aae992ff3c28a0212e3eabcb76dd4b0cc06bcb9607aeef560661b860d","impliedFormat":1},{"version":"1e0d1f8b0adfa0b0330e028c7941b5a98c08b600efe7f14d2d2a00854fb2f393","impliedFormat":1},{"version":"41670ee38943d9cbb4924e436f56fc19ee94232bc96108562de1a734af20dc2c","affectsGlobalScope":true,"impliedFormat":1},{"version":"c906fb15bd2aabc9ed1e3f44eb6a8661199d6c320b3aa196b826121552cb3695","impliedFormat":1},{"version":"22295e8103f1d6d8ea4b5d6211e43421fe4564e34d0dd8e09e520e452d89e659","impliedFormat":1},{"version":"58647d85d0f722a1ce9de50955df60a7489f0593bf1a7015521efe901c06d770","impliedFormat":1},{"version":"9018e9493596e2d041fc531f5101a0d05f9d2e1311f4ae3c74345b1766158c08","impliedFormat":1},{"version":"a10f0e1854f3316d7ee437b79649e5a6ae3ae14ffe6322b02d4987071a95362e","impliedFormat":1},{"version":"e208f73ef6a980104304b0d2ca5f6bf1b85de6009d2c7e404028b875020fa8f2","impliedFormat":1},{"version":"d163b6bc2372b4f07260747cbc6c0a6405ab3fbcea3852305e98ac43ca59f5bc","impliedFormat":1},{"version":"e6fa9ad47c5f71ff733744a029d1dc472c618de53804eae08ffc243b936f87ff","affectsGlobalScope":true,"impliedFormat":1},{"version":"a6f137d651076822d4fe884287e68fd61785a0d3d1fdb250a5059b691fa897db","impliedFormat":1},{"version":"24826ed94a78d5c64bd857570fdbd96229ad41b5cb654c08d75a9845e3ab7dde","impliedFormat":1},{"version":"8b479a130ccb62e98f11f136d3ac80f2984fdc07616516d29881f3061f2dd472","impliedFormat":1},{"version":"928af3d90454bf656a52a48679f199f64c1435247d6189d1caf4c68f2eaf921f","affectsGlobalScope":true,"impliedFormat":1},{"version":"bceb58df66ab8fb00170df20cd813978c5ab84be1d285710c4eb005d8e9d8efb","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f16a7e4deafa527ed9995a772bb380eb7d3c2c0fd4ae178c5263ed18394db2c","impliedFormat":1},{"version":"933921f0bb0ec12ef45d1062a1fc0f27635318f4d294e4d99de9a5493e618ca2","impliedFormat":1},{"version":"71a0f3ad612c123b57239a7749770017ecfe6b66411488000aba83e4546fde25","impliedFormat":1},{"version":"77fbe5eecb6fac4b6242bbf6eebfc43e98ce5ccba8fa44e0ef6a95c945ff4d98","impliedFormat":1},{"version":"4f9d8ca0c417b67b69eeb54c7ca1bedd7b56034bb9bfd27c5d4f3bc4692daca7","impliedFormat":1},{"version":"814118df420c4e38fe5ae1b9a3bafb6e9c2aa40838e528cde908381867be6466","impliedFormat":1},{"version":"a3fc63c0d7b031693f665f5494412ba4b551fe644ededccc0ab5922401079c95","impliedFormat":1},{"version":"80523c00b8544a2000ae0143e4a90a00b47f99823eb7926c1e03c494216fc363","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"746911b62b329587939560deb5c036aca48aece03147b021fa680223255d5183","affectsGlobalScope":true,"impliedFormat":1},{"version":"18fd40412d102c5564136f29735e5d1c3b455b8a37f920da79561f1fde068208","impliedFormat":1},{"version":"c8d3e5a18ba35629954e48c4cc8f11dc88224650067a172685c736b27a34a4dc","impliedFormat":1},{"version":"f0be1b8078cd549d91f37c30c222c2a187ac1cf981d994fb476a1adc61387b14","affectsGlobalScope":true,"impliedFormat":1},{"version":"0aaed1d72199b01234152f7a60046bc947f1f37d78d182e9ae09c4289e06a592","impliedFormat":1},{"version":"2b55d426ff2b9087485e52ac4bc7cfafe1dc420fc76dad926cd46526567c501a","impliedFormat":1},{"version":"66ba1b2c3e3a3644a1011cd530fb444a96b1b2dfe2f5e837a002d41a1a799e60","impliedFormat":1},{"version":"7e514f5b852fdbc166b539fdd1f4e9114f29911592a5eb10a94bb3a13ccac3c4","impliedFormat":1},{"version":"5b7aa3c4c1a5d81b411e8cb302b45507fea9358d3569196b27eb1a27ae3a90ef","affectsGlobalScope":true,"impliedFormat":1},{"version":"5987a903da92c7462e0b35704ce7da94d7fdc4b89a984871c0e2b87a8aae9e69","affectsGlobalScope":true,"impliedFormat":1},{"version":"ea08a0345023ade2b47fbff5a76d0d0ed8bff10bc9d22b83f40858a8e941501c","impliedFormat":1},{"version":"47613031a5a31510831304405af561b0ffaedb734437c595256bb61a90f9311b","impliedFormat":1},{"version":"ae062ce7d9510060c5d7e7952ae379224fb3f8f2dd74e88959878af2057c143b","impliedFormat":1},{"version":"8a1a0d0a4a06a8d278947fcb66bf684f117bf147f89b06e50662d79a53be3e9f","affectsGlobalScope":true,"impliedFormat":1},{"version":"358765d5ea8afd285d4fd1532e78b88273f18cb3f87403a9b16fef61ac9fdcfe","impliedFormat":1},{"version":"9f55299850d4f0921e79b6bf344b47c420ce0f507b9dcf593e532b09ea7eeea1","impliedFormat":1},{"version":"316f1486e15cbf7896425f0a16dfe12d447dd57cfb3244b8b119c77df870858f","impliedFormat":99},{"version":"62a40d6f94d252e271a6e32be95b2833567a7364131479d63d3e21d6cdba4df5","signature":"f163cf33de4138cc5a2fa805ba2735bd08ba856a3cc93df24c521dda33a4a75c"},{"version":"c08677db7683bf1dd549578103d0ed35030a1c807a84a782765529c61d89fdd2","signature":"43e818adf60173644896298637f47b01d5819b17eda46eaa32d0c7d64724d012"}],"root":[[62,64],66,67,173,174],"options":{"composite":true,"declaration":true,"declarationMap":true,"esModuleInterop":true,"exactOptionalPropertyTypes":false,"module":99,"noFallthroughCasesInSwitch":true,"noImplicitOverride":true,"noUncheckedIndexedAccess":true,"outDir":"./","rootDir":"../src","skipLibCheck":true,"sourceMap":true,"strict":true,"target":9,"tsBuildInfoFile":"./.tsbuildinfo","verbatimModuleSyntax":true},"referencedMap":[[118,1],[119,1],[120,2],[73,3],[121,4],[122,5],[123,6],[68,7],[71,8],[69,7],[70,7],[124,9],[125,10],[126,11],[127,12],[128,13],[129,14],[130,14],[131,15],[132,16],[133,17],[134,18],[74,7],[72,7],[135,19],[136,20],[137,21],[171,22],[138,23],[139,7],[140,24],[141,25],[142,26],[143,27],[144,28],[145,29],[146,30],[147,31],[148,32],[149,32],[150,33],[151,7],[152,34],[153,35],[155,36],[154,37],[156,38],[157,39],[158,40],[159,41],[160,42],[161,43],[162,44],[163,45],[164,46],[165,47],[166,48],[167,49],[168,50],[75,7],[76,7],[77,7],[115,51],[116,7],[117,7],[169,52],[170,53],[172,54],[65,7],[60,7],[61,7],[12,7],[11,7],[2,7],[13,7],[14,7],[15,7],[16,7],[17,7],[18,7],[19,7],[20,7],[3,7],[21,7],[22,7],[4,7],[23,7],[27,7],[24,7],[25,7],[26,7],[28,7],[29,7],[30,7],[5,7],[31,7],[32,7],[33,7],[34,7],[6,7],[38,7],[35,7],[36,7],[37,7],[39,7],[7,7],[40,7],[45,7],[46,7],[41,7],[42,7],[43,7],[44,7],[8,7],[50,7],[47,7],[48,7],[49,7],[51,7],[9,7],[52,7],[53,7],[54,7],[56,7],[55,7],[57,7],[58,7],[10,7],[59,7],[1,7],[93,55],[103,56],[92,55],[113,57],[84,58],[83,59],[112,60],[106,61],[111,62],[86,63],[100,64],[85,65],[109,66],[81,67],[80,60],[110,68],[82,69],[87,70],[88,7],[91,70],[78,7],[114,71],[104,72],[95,73],[96,74],[98,75],[94,76],[97,77],[107,60],[89,78],[90,79],[99,80],[79,81],[102,72],[101,70],[105,7],[108,82],[62,7],[64,83],[66,84],[67,85],[174,86],[173,87],[63,7]],"latestChangedDtsFile":"./relay-main.d.ts","version":"5.9.3"}
1
+ {"fileNames":["../../../node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/typescript/lib/lib.es2021.d.ts","../../../node_modules/typescript/lib/lib.es2022.d.ts","../../../node_modules/typescript/lib/lib.es2023.d.ts","../../../node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../node_modules/typescript/lib/lib.es2017.date.d.ts","../../../node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/typescript/lib/lib.es2021.promise.d.ts","../../../node_modules/typescript/lib/lib.es2021.string.d.ts","../../../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../../node_modules/typescript/lib/lib.es2021.intl.d.ts","../../../node_modules/typescript/lib/lib.es2022.array.d.ts","../../../node_modules/typescript/lib/lib.es2022.error.d.ts","../../../node_modules/typescript/lib/lib.es2022.intl.d.ts","../../../node_modules/typescript/lib/lib.es2022.object.d.ts","../../../node_modules/typescript/lib/lib.es2022.string.d.ts","../../../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../../node_modules/typescript/lib/lib.es2023.array.d.ts","../../../node_modules/typescript/lib/lib.es2023.collection.d.ts","../../../node_modules/typescript/lib/lib.es2023.intl.d.ts","../../../node_modules/typescript/lib/lib.decorators.d.ts","../../../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../src/base64.ts","../src/session-bridge.ts","../src/cf-adapter.ts","../../../node_modules/tweetnacl/nacl.d.ts","../src/channel.ts","../src/session-id.ts","../src/index.ts","../../../node_modules/@types/node/compatibility/disposable.d.ts","../../../node_modules/@types/node/compatibility/indexable.d.ts","../../../node_modules/@types/node/compatibility/iterators.d.ts","../../../node_modules/@types/node/compatibility/index.d.ts","../../../node_modules/@types/node/globals.typedarray.d.ts","../../../node_modules/@types/node/buffer.buffer.d.ts","../../../node_modules/@types/node/globals.d.ts","../../../node_modules/@types/node/web-globals/abortcontroller.d.ts","../../../node_modules/@types/node/web-globals/domexception.d.ts","../../../node_modules/@types/node/web-globals/events.d.ts","../../../node_modules/undici-types/header.d.ts","../../../node_modules/undici-types/readable.d.ts","../../../node_modules/undici-types/file.d.ts","../../../node_modules/undici-types/fetch.d.ts","../../../node_modules/undici-types/formdata.d.ts","../../../node_modules/undici-types/connector.d.ts","../../../node_modules/undici-types/client.d.ts","../../../node_modules/undici-types/errors.d.ts","../../../node_modules/undici-types/dispatcher.d.ts","../../../node_modules/undici-types/global-dispatcher.d.ts","../../../node_modules/undici-types/global-origin.d.ts","../../../node_modules/undici-types/pool-stats.d.ts","../../../node_modules/undici-types/pool.d.ts","../../../node_modules/undici-types/handlers.d.ts","../../../node_modules/undici-types/balanced-pool.d.ts","../../../node_modules/undici-types/agent.d.ts","../../../node_modules/undici-types/mock-interceptor.d.ts","../../../node_modules/undici-types/mock-agent.d.ts","../../../node_modules/undici-types/mock-client.d.ts","../../../node_modules/undici-types/mock-pool.d.ts","../../../node_modules/undici-types/mock-errors.d.ts","../../../node_modules/undici-types/proxy-agent.d.ts","../../../node_modules/undici-types/env-http-proxy-agent.d.ts","../../../node_modules/undici-types/retry-handler.d.ts","../../../node_modules/undici-types/retry-agent.d.ts","../../../node_modules/undici-types/api.d.ts","../../../node_modules/undici-types/interceptors.d.ts","../../../node_modules/undici-types/util.d.ts","../../../node_modules/undici-types/cookies.d.ts","../../../node_modules/undici-types/patch.d.ts","../../../node_modules/undici-types/websocket.d.ts","../../../node_modules/undici-types/eventsource.d.ts","../../../node_modules/undici-types/filereader.d.ts","../../../node_modules/undici-types/diagnostics-channel.d.ts","../../../node_modules/undici-types/content-type.d.ts","../../../node_modules/undici-types/cache.d.ts","../../../node_modules/undici-types/index.d.ts","../../../node_modules/@types/node/web-globals/fetch.d.ts","../../../node_modules/@types/node/web-globals/navigator.d.ts","../../../node_modules/@types/node/web-globals/storage.d.ts","../../../node_modules/@types/node/assert.d.ts","../../../node_modules/@types/node/assert/strict.d.ts","../../../node_modules/@types/node/async_hooks.d.ts","../../../node_modules/@types/node/buffer.d.ts","../../../node_modules/@types/node/child_process.d.ts","../../../node_modules/@types/node/cluster.d.ts","../../../node_modules/@types/node/console.d.ts","../../../node_modules/@types/node/constants.d.ts","../../../node_modules/@types/node/crypto.d.ts","../../../node_modules/@types/node/dgram.d.ts","../../../node_modules/@types/node/diagnostics_channel.d.ts","../../../node_modules/@types/node/dns.d.ts","../../../node_modules/@types/node/dns/promises.d.ts","../../../node_modules/@types/node/domain.d.ts","../../../node_modules/@types/node/events.d.ts","../../../node_modules/@types/node/fs.d.ts","../../../node_modules/@types/node/fs/promises.d.ts","../../../node_modules/@types/node/http.d.ts","../../../node_modules/@types/node/http2.d.ts","../../../node_modules/@types/node/https.d.ts","../../../node_modules/@types/node/inspector.d.ts","../../../node_modules/@types/node/inspector.generated.d.ts","../../../node_modules/@types/node/module.d.ts","../../../node_modules/@types/node/net.d.ts","../../../node_modules/@types/node/os.d.ts","../../../node_modules/@types/node/path.d.ts","../../../node_modules/@types/node/perf_hooks.d.ts","../../../node_modules/@types/node/process.d.ts","../../../node_modules/@types/node/punycode.d.ts","../../../node_modules/@types/node/querystring.d.ts","../../../node_modules/@types/node/readline.d.ts","../../../node_modules/@types/node/readline/promises.d.ts","../../../node_modules/@types/node/repl.d.ts","../../../node_modules/@types/node/sea.d.ts","../../../node_modules/@types/node/sqlite.d.ts","../../../node_modules/@types/node/stream.d.ts","../../../node_modules/@types/node/stream/promises.d.ts","../../../node_modules/@types/node/stream/consumers.d.ts","../../../node_modules/@types/node/stream/web.d.ts","../../../node_modules/@types/node/string_decoder.d.ts","../../../node_modules/@types/node/test.d.ts","../../../node_modules/@types/node/timers.d.ts","../../../node_modules/@types/node/timers/promises.d.ts","../../../node_modules/@types/node/tls.d.ts","../../../node_modules/@types/node/trace_events.d.ts","../../../node_modules/@types/node/tty.d.ts","../../../node_modules/@types/node/url.d.ts","../../../node_modules/@types/node/util.d.ts","../../../node_modules/@types/node/v8.d.ts","../../../node_modules/@types/node/vm.d.ts","../../../node_modules/@types/node/wasi.d.ts","../../../node_modules/@types/node/worker_threads.d.ts","../../../node_modules/@types/node/zlib.d.ts","../../../node_modules/@types/node/index.d.ts","../../../node_modules/pino-std-serializers/index.d.ts","../../../node_modules/sonic-boom/types/index.d.ts","../../../node_modules/thread-stream/index.d.ts","../../../node_modules/pino/pino.d.ts","../../../node_modules/pino-abstract-transport/index.d.ts","../../../node_modules/colorette/index.d.ts","../../../node_modules/pino-pretty/index.d.ts","../../../node_modules/rotating-file-stream/dist/types/index.d.ts","../src/relay-logger.ts","../../../node_modules/@types/ws/index.d.mts","../src/relay-server.ts","../src/relay-main.ts"],"fileIdsList":[[74,119,120,122,139,140],[74,121,122,139,140],[122,139,140],[74,122,127,139,140,157],[74,122,123,128,133,139,140,142,154,165],[74,122,123,124,133,139,140,142],[74,122,139,140],[69,70,71,74,122,139,140],[74,122,125,139,140,166],[74,122,126,127,134,139,140,143],[74,122,127,139,140,154,162],[74,122,128,130,133,139,140,142],[74,121,122,129,139,140],[74,122,130,131,139,140],[74,122,132,133,139,140],[74,121,122,133,139,140],[74,122,133,134,135,139,140,154,165],[74,122,133,134,135,139,140,149,154,157],[74,115,122,130,133,136,139,140,142,154,165],[74,122,133,134,136,137,139,140,142,154,162,165],[74,122,136,138,139,140,154,162,165],[72,73,74,75,76,77,78,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171],[74,122,133,139,140],[74,122,139,140,141,165],[74,122,130,133,139,140,142,154],[74,122,139,140,143],[74,122,139,140,144],[74,121,122,139,140,145],[74,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171],[74,122,139,140,147],[74,122,139,140,148],[74,122,133,139,140,149,150],[74,122,139,140,149,151,166,168],[74,122,134,139,140],[74,122,133,139,140,154,155,157],[74,122,139,140,156,157],[74,122,139,140,154,155],[74,122,139,140,157],[74,122,139,140,158],[74,119,122,139,140,154,159,165],[74,122,133,139,140,160,161],[74,122,139,140,160,161],[74,122,127,139,140,142,154,162],[74,122,139,140,163],[74,122,139,140,142,164],[74,122,136,139,140,148,165],[74,122,127,139,140,166],[74,122,139,140,154,167],[74,122,139,140,141,168],[74,122,139,140,169],[74,115,122,139,140],[74,115,122,133,135,139,140,145,154,157,165,167,168,170],[74,122,139,140,154,171],[74,122,133,136,138,139,140,142,154,162,165,171,172],[74,122,139,140,154,172],[74,122,139,140,154,172,176,177,178],[74,122,136,139,140,172],[74,122,133,139,140,170,173,174,175],[74,122,139,140,154],[74,122,133,139,140,172],[74,122,133,139,140,170],[74,87,91,122,139,140,165],[74,87,122,139,140,154,165],[74,82,122,139,140],[74,84,87,122,139,140,162,165],[74,122,139,140,142,162],[74,122,139,140,172],[74,82,122,139,140,172],[74,84,87,122,139,140,142,165],[74,79,80,83,86,122,133,139,140,154,165],[74,87,94,122,139,140],[74,79,85,122,139,140],[74,87,108,109,122,139,140],[74,83,87,122,139,140,157,165,172],[74,108,122,139,140,172],[74,81,82,122,139,140,172],[74,87,122,139,140],[74,81,82,83,84,85,86,87,88,89,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,109,110,111,112,113,114,122,139,140],[74,87,102,122,139,140],[74,87,94,95,122,139,140],[74,85,87,95,96,122,139,140],[74,86,122,139,140],[74,79,82,87,122,139,140],[74,87,91,95,96,122,139,140],[74,91,122,139,140],[74,85,87,90,122,139,140,165],[74,79,84,87,94,122,139,140],[74,82,87,108,122,139,140,170,172],[63,74,122,139,140],[62,65,74,122,139,140],[62,63,64,66,67,74,122,139,140],[74,122,134,139,140,176,179,180],[74,122,139,140,181,183],[63,74,122,127,136,139,140,181,182],[65,74,122,139,140]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"27bdc30a0e32783366a5abeda841bc22757c1797de8681bbe81fbc735eeb1c10","impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cdf8847677ac7d20486e54dd3fcf09eda95812ac8ace44b4418da1bbbab6eb8","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"df83c2a6c73228b625b0beb6669c7ee2a09c914637e2d35170723ad49c0f5cd4","affectsGlobalScope":true,"impliedFormat":1},{"version":"436aaf437562f276ec2ddbee2f2cdedac7664c1e4c1d2c36839ddd582eeb3d0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e3c06ea092138bf9fa5e874a1fdbc9d54805d074bee1de31b99a11e2fec239d","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"93d79f12c401be264bcb23d89f4e74c1e72a5605fcc42fbeefc0f404a51a545f","signature":"fdc8d72f90b3ac131587d78463fc03c479edc4ea623455ad17c72dadcc955299"},{"version":"3e8bae2f330caaa8719a8e85eb3c01c5c0241b6ada6a0127224351a08c3d8900","signature":"ecf8e91d58670bc78270e6758c6e77854f2d6aef117f40b2ba603e6f50e995e2"},{"version":"ecf8251ec9dd047961cac4d6da5574fa9ea5e7f095c7c0f777654ff364cb8041","signature":"ce3dc2e2dd5757bac8ac7629f26e0e241301fa2a17b2b50bee4283d651f0abe4"},{"version":"60592f5ae1b739c9607a99895d4a3ad5c865b16903e4180e50b256e360a4a104","impliedFormat":1},{"version":"a70121b727280bbf4c967362afdfcd77cbfa88992c7a1e376756c146705e16bd","signature":"bcd5c0fae5ea5c81407b139a70177eea554ff0c710c48c853e2b8f6733ae8545"},{"version":"20d6b112e4eacc51938ecc17251c3593b02da550bebf7197d6dd91dbbe7ecea7","signature":"5bdfe06830e16dec56b82724ae3d5780e3de52694594845a6b04a955f9084640"},{"version":"689a8e62e6bb834078e3dccd2e48b0747a1ae61f825492f752745de723a8f79c","signature":"4f83d9e566c1dca290eed97eaf97be11b8eaec0dc22397e2bbc5240c81aff4e0"},{"version":"6c7176368037af28cb72f2392010fa1cef295d6d6744bca8cfb54985f3a18c3e","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"437e20f2ba32abaeb7985e0afe0002de1917bc74e949ba585e49feba65da6ca1","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"98cffbf06d6bab333473c70a893770dbe990783904002c4f1a960447b4b53dca","affectsGlobalScope":true,"impliedFormat":1},{"version":"3af97acf03cc97de58a3a4bc91f8f616408099bc4233f6d0852e72a8ffb91ac9","affectsGlobalScope":true,"impliedFormat":1},{"version":"808069bba06b6768b62fd22429b53362e7af342da4a236ed2d2e1c89fcca3b4a","affectsGlobalScope":true,"impliedFormat":1},{"version":"1db0b7dca579049ca4193d034d835f6bfe73096c73663e5ef9a0b5779939f3d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"9798340ffb0d067d69b1ae5b32faa17ab31b82466a3fc00d8f2f2df0c8554aaa","affectsGlobalScope":true,"impliedFormat":1},{"version":"f26b11d8d8e4b8028f1c7d618b22274c892e4b0ef5b3678a8ccbad85419aef43","affectsGlobalScope":true,"impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"763fe0f42b3d79b440a9b6e51e9ba3f3f91352469c1e4b3b67bfa4ff6352f3f4","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"c464d66b20788266e5353b48dc4aa6bc0dc4a707276df1e7152ab0c9ae21fad8","impliedFormat":1},{"version":"78d0d27c130d35c60b5e5566c9f1e5be77caf39804636bc1a40133919a949f21","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"1d6e127068ea8e104a912e42fc0a110e2aa5a66a356a917a163e8cf9a65e4a75","impliedFormat":1},{"version":"5ded6427296cdf3b9542de4471d2aa8d3983671d4cac0f4bf9c637208d1ced43","impliedFormat":1},{"version":"7f182617db458e98fc18dfb272d40aa2fff3a353c44a89b2c0ccb3937709bfb5","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"0b8a9268adaf4da35e7fa830c8981cfa22adbbe5b3f6f5ab91f6658899e657a7","impliedFormat":1},{"version":"11396ed8a44c02ab9798b7dca436009f866e8dae3c9c25e8c1fbc396880bf1bb","impliedFormat":1},{"version":"ba7bc87d01492633cb5a0e5da8a4a42a1c86270e7b3d2dea5d156828a84e4882","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"c21dc52e277bcfc75fac0436ccb75c204f9e1b3fa5e12729670910639f27343e","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"ea0148f897b45a76544ae179784c95af1bd6721b8610af9ffa467a518a086a43","impliedFormat":1},{"version":"24c6a117721e606c9984335f71711877293a9651e44f59f3d21c1ea0856f9cc9","impliedFormat":1},{"version":"dd3273ead9fbde62a72949c97dbec2247ea08e0c6952e701a483d74ef92d6a17","impliedFormat":1},{"version":"405822be75ad3e4d162e07439bac80c6bcc6dbae1929e179cf467ec0b9ee4e2e","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"e61be3f894b41b7baa1fbd6a66893f2579bfad01d208b4ff61daef21493ef0a8","impliedFormat":1},{"version":"bd0532fd6556073727d28da0edfd1736417a3f9f394877b6d5ef6ad88fba1d1a","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"615ba88d0128ed16bf83ef8ccbb6aff05c3ee2db1cc0f89ab50a4939bfc1943f","impliedFormat":1},{"version":"a4d551dbf8746780194d550c88f26cf937caf8d56f102969a110cfaed4b06656","impliedFormat":1},{"version":"8bd86b8e8f6a6aa6c49b71e14c4ffe1211a0e97c80f08d2c8cc98838006e4b88","impliedFormat":1},{"version":"317e63deeb21ac07f3992f5b50cdca8338f10acd4fbb7257ebf56735bf52ab00","impliedFormat":1},{"version":"4732aec92b20fb28c5fe9ad99521fb59974289ed1e45aecb282616202184064f","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"bf67d53d168abc1298888693338cb82854bdb2e69ef83f8a0092093c2d562107","impliedFormat":1},{"version":"b52476feb4a0cbcb25e5931b930fc73cb6643fb1a5060bf8a3dda0eeae5b4b68","affectsGlobalScope":true,"impliedFormat":1},{"version":"f9501cc13ce624c72b61f12b3963e84fad210fbdf0ffbc4590e08460a3f04eba","affectsGlobalScope":true,"impliedFormat":1},{"version":"e7721c4f69f93c91360c26a0a84ee885997d748237ef78ef665b153e622b36c1","affectsGlobalScope":true,"impliedFormat":1},{"version":"0fa06ada475b910e2106c98c68b10483dc8811d0c14a8a8dd36efb2672485b29","impliedFormat":1},{"version":"33e5e9aba62c3193d10d1d33ae1fa75c46a1171cf76fef750777377d53b0303f","impliedFormat":1},{"version":"2b06b93fd01bcd49d1a6bd1f9b65ddcae6480b9a86e9061634d6f8e354c1468f","impliedFormat":1},{"version":"6a0cd27e5dc2cfbe039e731cf879d12b0e2dded06d1b1dedad07f7712de0d7f4","affectsGlobalScope":true,"impliedFormat":1},{"version":"13f5c844119c43e51ce777c509267f14d6aaf31eafb2c2b002ca35584cd13b29","impliedFormat":1},{"version":"e60477649d6ad21542bd2dc7e3d9ff6853d0797ba9f689ba2f6653818999c264","impliedFormat":1},{"version":"c2510f124c0293ab80b1777c44d80f812b75612f297b9857406468c0f4dafe29","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"4c829ab315f57c5442c6667b53769975acbf92003a66aef19bce151987675bd1","affectsGlobalScope":true,"impliedFormat":1},{"version":"b2ade7657e2db96d18315694789eff2ddd3d8aea7215b181f8a0b303277cc579","impliedFormat":1},{"version":"9855e02d837744303391e5623a531734443a5f8e6e8755e018c41d63ad797db2","impliedFormat":1},{"version":"4d631b81fa2f07a0e63a9a143d6a82c25c5f051298651a9b69176ba28930756d","impliedFormat":1},{"version":"836a356aae992ff3c28a0212e3eabcb76dd4b0cc06bcb9607aeef560661b860d","impliedFormat":1},{"version":"1e0d1f8b0adfa0b0330e028c7941b5a98c08b600efe7f14d2d2a00854fb2f393","impliedFormat":1},{"version":"41670ee38943d9cbb4924e436f56fc19ee94232bc96108562de1a734af20dc2c","affectsGlobalScope":true,"impliedFormat":1},{"version":"c906fb15bd2aabc9ed1e3f44eb6a8661199d6c320b3aa196b826121552cb3695","impliedFormat":1},{"version":"22295e8103f1d6d8ea4b5d6211e43421fe4564e34d0dd8e09e520e452d89e659","impliedFormat":1},{"version":"58647d85d0f722a1ce9de50955df60a7489f0593bf1a7015521efe901c06d770","impliedFormat":1},{"version":"9018e9493596e2d041fc531f5101a0d05f9d2e1311f4ae3c74345b1766158c08","impliedFormat":1},{"version":"a10f0e1854f3316d7ee437b79649e5a6ae3ae14ffe6322b02d4987071a95362e","impliedFormat":1},{"version":"e208f73ef6a980104304b0d2ca5f6bf1b85de6009d2c7e404028b875020fa8f2","impliedFormat":1},{"version":"d163b6bc2372b4f07260747cbc6c0a6405ab3fbcea3852305e98ac43ca59f5bc","impliedFormat":1},{"version":"e6fa9ad47c5f71ff733744a029d1dc472c618de53804eae08ffc243b936f87ff","affectsGlobalScope":true,"impliedFormat":1},{"version":"a6f137d651076822d4fe884287e68fd61785a0d3d1fdb250a5059b691fa897db","impliedFormat":1},{"version":"24826ed94a78d5c64bd857570fdbd96229ad41b5cb654c08d75a9845e3ab7dde","impliedFormat":1},{"version":"8b479a130ccb62e98f11f136d3ac80f2984fdc07616516d29881f3061f2dd472","impliedFormat":1},{"version":"928af3d90454bf656a52a48679f199f64c1435247d6189d1caf4c68f2eaf921f","affectsGlobalScope":true,"impliedFormat":1},{"version":"bceb58df66ab8fb00170df20cd813978c5ab84be1d285710c4eb005d8e9d8efb","affectsGlobalScope":true,"impliedFormat":1},{"version":"3f16a7e4deafa527ed9995a772bb380eb7d3c2c0fd4ae178c5263ed18394db2c","impliedFormat":1},{"version":"933921f0bb0ec12ef45d1062a1fc0f27635318f4d294e4d99de9a5493e618ca2","impliedFormat":1},{"version":"71a0f3ad612c123b57239a7749770017ecfe6b66411488000aba83e4546fde25","impliedFormat":1},{"version":"77fbe5eecb6fac4b6242bbf6eebfc43e98ce5ccba8fa44e0ef6a95c945ff4d98","impliedFormat":1},{"version":"4f9d8ca0c417b67b69eeb54c7ca1bedd7b56034bb9bfd27c5d4f3bc4692daca7","impliedFormat":1},{"version":"814118df420c4e38fe5ae1b9a3bafb6e9c2aa40838e528cde908381867be6466","impliedFormat":1},{"version":"a3fc63c0d7b031693f665f5494412ba4b551fe644ededccc0ab5922401079c95","impliedFormat":1},{"version":"80523c00b8544a2000ae0143e4a90a00b47f99823eb7926c1e03c494216fc363","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"45650f47bfb376c8a8ed39d4bcda5902ab899a3150029684ee4c10676d9fbaee","impliedFormat":1},{"version":"746911b62b329587939560deb5c036aca48aece03147b021fa680223255d5183","affectsGlobalScope":true,"impliedFormat":1},{"version":"18fd40412d102c5564136f29735e5d1c3b455b8a37f920da79561f1fde068208","impliedFormat":1},{"version":"c8d3e5a18ba35629954e48c4cc8f11dc88224650067a172685c736b27a34a4dc","impliedFormat":1},{"version":"f0be1b8078cd549d91f37c30c222c2a187ac1cf981d994fb476a1adc61387b14","affectsGlobalScope":true,"impliedFormat":1},{"version":"0aaed1d72199b01234152f7a60046bc947f1f37d78d182e9ae09c4289e06a592","impliedFormat":1},{"version":"2b55d426ff2b9087485e52ac4bc7cfafe1dc420fc76dad926cd46526567c501a","impliedFormat":1},{"version":"66ba1b2c3e3a3644a1011cd530fb444a96b1b2dfe2f5e837a002d41a1a799e60","impliedFormat":1},{"version":"7e514f5b852fdbc166b539fdd1f4e9114f29911592a5eb10a94bb3a13ccac3c4","impliedFormat":1},{"version":"5b7aa3c4c1a5d81b411e8cb302b45507fea9358d3569196b27eb1a27ae3a90ef","affectsGlobalScope":true,"impliedFormat":1},{"version":"5987a903da92c7462e0b35704ce7da94d7fdc4b89a984871c0e2b87a8aae9e69","affectsGlobalScope":true,"impliedFormat":1},{"version":"ea08a0345023ade2b47fbff5a76d0d0ed8bff10bc9d22b83f40858a8e941501c","impliedFormat":1},{"version":"47613031a5a31510831304405af561b0ffaedb734437c595256bb61a90f9311b","impliedFormat":1},{"version":"ae062ce7d9510060c5d7e7952ae379224fb3f8f2dd74e88959878af2057c143b","impliedFormat":1},{"version":"8a1a0d0a4a06a8d278947fcb66bf684f117bf147f89b06e50662d79a53be3e9f","affectsGlobalScope":true,"impliedFormat":1},{"version":"358765d5ea8afd285d4fd1532e78b88273f18cb3f87403a9b16fef61ac9fdcfe","impliedFormat":1},{"version":"9f55299850d4f0921e79b6bf344b47c420ce0f507b9dcf593e532b09ea7eeea1","impliedFormat":1},{"version":"4fe80f12b1d5189384a219095c2eabadbb389c2d3703aae7c5376dbaa56061df","impliedFormat":1},{"version":"9eb1d2dceae65d1c82fc6be7e9b6b19cf3ca93c364678611107362b6ad4d2d41","impliedFormat":1},{"version":"eb81f582c0e1ae21f004b39c268c68ad13222cd7e72f45080d6cdf9b994dfecf","impliedFormat":1},{"version":"e40f9840e4686053a5d42b39fddfd6774172a3d12fa61c1edb8c35b452a5e74a","impliedFormat":1},{"version":"89bf59c1d834a4b01c7d9b5b4cfa64ffed09e59580d27bbadf1acdd69706c200","impliedFormat":1},{"version":"c8adda9f45d2f7ec9fb28c59859db32da6c2835f1fec96433e2729e5805fa46f","impliedFormat":99},{"version":"f5a1b2ccbcb26cea8b577af7882ff2a9294f4df6a45de84592edb5d076e748fe","impliedFormat":1},{"version":"d61602e258728a87ce5cfa48339e76433ecf3606b088099d1b2ffeade5e82697","impliedFormat":99},{"version":"41ea04a2d2bc32f97f147cac9d91a2fd92f7934cb729ac5535ba0f6865fc3b45","signature":"7c3ebfda16b99a75767688cd8083fe3575b9375b1a300def8aa2a43674d018c0"},{"version":"316f1486e15cbf7896425f0a16dfe12d447dd57cfb3244b8b119c77df870858f","impliedFormat":99},{"version":"642af7857461c4dfea9fad81329297b83e7d58e903fafe092a018e9b4d55d985","signature":"bfdc6d9373a35f1f169167bdeac3117644cbadb29e1efba52e50f56ed474cc7d"},{"version":"fff8778302897b575b7183cae10b0aa79015726ef59145ca4671505b9e07f369","signature":"43e818adf60173644896298637f47b01d5819b17eda46eaa32d0c7d64724d012"}],"root":[[62,64],[66,68],181,183,184],"options":{"composite":true,"declaration":true,"declarationMap":true,"esModuleInterop":true,"exactOptionalPropertyTypes":false,"module":99,"noFallthroughCasesInSwitch":true,"noImplicitOverride":true,"noUncheckedIndexedAccess":true,"outDir":"./","rootDir":"../src","skipLibCheck":true,"sourceMap":true,"strict":true,"target":9,"tsBuildInfoFile":"./.tsbuildinfo","verbatimModuleSyntax":true},"referencedMap":[[119,1],[120,1],[121,2],[74,3],[122,4],[123,5],[124,6],[69,7],[72,8],[70,7],[71,7],[125,9],[126,10],[127,11],[128,12],[129,13],[130,14],[131,14],[132,15],[133,16],[134,17],[135,18],[75,7],[73,7],[136,19],[137,20],[138,21],[172,22],[139,23],[140,7],[141,24],[142,25],[143,26],[144,27],[145,28],[146,29],[147,30],[148,31],[149,32],[150,32],[151,33],[152,7],[153,34],[154,35],[156,36],[155,37],[157,38],[158,39],[159,40],[160,41],[161,42],[162,43],[163,44],[164,45],[165,46],[166,47],[167,48],[168,49],[169,50],[76,7],[77,7],[78,7],[116,51],[117,7],[118,7],[170,52],[171,53],[182,54],[178,7],[177,55],[179,56],[173,57],[176,58],[180,59],[174,60],[175,61],[65,7],[60,7],[61,7],[12,7],[11,7],[2,7],[13,7],[14,7],[15,7],[16,7],[17,7],[18,7],[19,7],[20,7],[3,7],[21,7],[22,7],[4,7],[23,7],[27,7],[24,7],[25,7],[26,7],[28,7],[29,7],[30,7],[5,7],[31,7],[32,7],[33,7],[34,7],[6,7],[38,7],[35,7],[36,7],[37,7],[39,7],[7,7],[40,7],[45,7],[46,7],[41,7],[42,7],[43,7],[44,7],[8,7],[50,7],[47,7],[48,7],[49,7],[51,7],[9,7],[52,7],[53,7],[54,7],[56,7],[55,7],[57,7],[58,7],[10,7],[59,7],[1,7],[94,62],[104,63],[93,62],[114,64],[85,65],[84,66],[113,67],[107,68],[112,69],[87,70],[101,71],[86,72],[110,73],[82,74],[81,67],[111,75],[83,76],[88,77],[89,7],[92,77],[79,7],[115,78],[105,79],[96,80],[97,81],[99,82],[95,83],[98,84],[108,67],[90,85],[91,86],[100,87],[80,59],[103,79],[102,77],[106,7],[109,88],[62,7],[64,89],[66,90],[68,91],[181,92],[184,93],[183,94],[63,7],[67,95]],"latestChangedDtsFile":"./relay-main.d.ts","version":"5.9.3"}
package/dist/channel.d.ts CHANGED
@@ -11,11 +11,18 @@ export interface Transport {
11
11
  export interface EncryptedChannelEvents {
12
12
  /** Fired once the E2EE handshake completes and app messages may flow. */
13
13
  onReady?: () => void;
14
- /** Fired for each successfully decrypted+authenticated app message. */
14
+ /** Fired for each successfully decrypted+authenticated text app message. */
15
15
  onMessage?: (plaintext: string) => void;
16
+ /**
17
+ * Fired for each successfully decrypted+authenticated BINARY app message (terminal I/O,
18
+ * file-transfer chunks). Carried as a distinct wire frame type (`e2ee_bin`) from text `e2ee_app`
19
+ * messages, but otherwise identical: same handshake gate, same ECDH shared key, same
20
+ * auth-failure-drops-silently behavior — see `sendBinary`/`openBytes` below.
21
+ */
22
+ onBinaryMessage?: (bytes: Uint8Array) => void;
16
23
  /** Fired when the underlying transport closes. */
17
24
  onClose?: (reason?: string) => void;
18
- /** Fired when a received frame fails authentication (tampered/corrupt) — the message is dropped. */
25
+ /** Fired when a received frame (text or binary) fails authentication (tampered/corrupt) — the message is dropped. */
19
26
  onAuthError?: (error: unknown) => void;
20
27
  }
21
28
  /** Opaque attachment describing which relay session a channel is bound to. */
@@ -25,10 +32,20 @@ export interface RelaySessionAttachment {
25
32
  export interface EncryptedChannel {
26
33
  readonly role: ConnectionRole;
27
34
  readonly attachment: RelaySessionAttachment;
28
- /** True once the handshake has completed and `send` will actually transmit. */
35
+ /** True once the handshake has completed and `send`/`sendBinary` will actually transmit. */
29
36
  readonly ready: boolean;
30
- /** Encrypt + send an application message. Throws if called before the handshake completes. */
37
+ /** Encrypt + send a text application message. Throws if called before the handshake completes. */
31
38
  send(plaintext: string): void;
39
+ /**
40
+ * Encrypt + send a BINARY application message (terminal I/O, file-transfer chunks). Wire format
41
+ * is a sibling of `send()`'s — same crypto, same nonce/ciphertext framing, just fed raw bytes
42
+ * instead of UTF-8 text and tagged `e2ee_bin` instead of `e2ee_app` so the receiver dispatches
43
+ * to `onBinaryMessage` instead of `onMessage`. Still travels as a JSON-wrapped base64 STRING
44
+ * over the relay's text-frame-only wire (architecture/relay-e2ee.md § Behavior) — no raw binary
45
+ * WebSocket frames are involved, so the relay bridge (`session-bridge.ts`) needs no changes.
46
+ * Throws if called before the handshake completes.
47
+ */
48
+ sendBinary(bytes: Uint8Array): void;
32
49
  close(): void;
33
50
  }
34
51
  export interface CreateDaemonChannelOptions {
@@ -1 +1 @@
1
- {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAsBA,mDAAmD;AACnD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEjD,gGAAgG;AAChG,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACjD,OAAO,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAClD,KAAK,IAAI,IAAI,CAAC;CACf;AAED,uDAAuD;AACvD,MAAM,WAAW,sBAAsB;IACrC,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,uEAAuE;IACvE,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,kDAAkD;IAClD,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,oGAAoG;IACpG,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED,8EAA8E;AAC9E,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,sBAAsB,CAAC;IAC5C,+EAA+E;IAC/E,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,8FAA8F;IAC9F,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,KAAK,IAAI,IAAI,CAAC;CACf;AA+FD,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,sBAAsB,CAAC;IACnC;;;;;;OAMG;IACH,aAAa,EAAE;QAAE,SAAS,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,UAAU,CAAA;KAAE,CAAC;IAChE,MAAM,CAAC,EAAE,sBAAsB,CAAC;CACjC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,gBAAgB,CAkDtF;AAED,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,sBAAsB,CAAC;IACnC,iGAAiG;IACjG,eAAe,EAAE,UAAU,CAAC;IAC5B,MAAM,CAAC,EAAE,sBAAsB,CAAC;CACjC;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,gBAAgB,CAkDtF"}
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAsBA,mDAAmD;AACnD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEjD,gGAAgG;AAChG,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACjD,OAAO,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAClD,KAAK,IAAI,IAAI,CAAC;CACf;AAED,uDAAuD;AACvD,MAAM,WAAW,sBAAsB;IACrC,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;;;OAKG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IAC9C,kDAAkD;IAClD,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,qHAAqH;IACrH,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED,8EAA8E;AAC9E,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,sBAAsB,CAAC;IAC5C,4FAA4F;IAC5F,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,kGAAkG;IAClG,IAAI,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B;;;;;;;;OAQG;IACH,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IACpC,KAAK,IAAI,IAAI,CAAC;CACf;AAoID,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,sBAAsB,CAAC;IACnC;;;;;;OAMG;IACH,aAAa,EAAE;QAAE,SAAS,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,UAAU,CAAA;KAAE,CAAC;IAChE,MAAM,CAAC,EAAE,sBAAsB,CAAC;CACjC;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,gBAAgB,CA8DtF;AAED,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,sBAAsB,CAAC;IACnC,iGAAiG;IACjG,eAAe,EAAE,UAAU,CAAC;IAC5B,MAAM,CAAC,EAAE,sBAAsB,CAAC;CACjC;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,0BAA0B,GAAG,gBAAgB,CAwDtF"}
package/dist/channel.js CHANGED
@@ -31,18 +31,17 @@ function parseFrame(data) {
31
31
  }
32
32
  }
33
33
  const NONCE_LENGTH = 24; // XSalsa20-Poly1305 nonce size (nacl.box.nonceLength)
34
- /** Encrypt `plaintext` under `sharedKey`, producing the wire frame `base64(nonce ++ ciphertext)`. */
35
- function seal(plaintext, sharedKey) {
34
+ /** Encrypt raw `message` bytes under `sharedKey`, producing the wire frame `base64(nonce ++ ciphertext)`. */
35
+ function sealBytes(message, sharedKey) {
36
36
  const nonce = nacl.randomBytes(NONCE_LENGTH);
37
- const message = new TextEncoder().encode(plaintext);
38
37
  const ciphertext = nacl.box.after(message, nonce, sharedKey);
39
38
  const combined = new Uint8Array(nonce.length + ciphertext.length);
40
39
  combined.set(nonce, 0);
41
40
  combined.set(ciphertext, nonce.length);
42
41
  return encodeBase64(combined);
43
42
  }
44
- /** Decrypt a `base64(nonce ++ ciphertext)` wire frame under `sharedKey`, or return `null` on auth failure. */
45
- function open(frame, sharedKey) {
43
+ /** Decrypt a `base64(nonce ++ ciphertext)` wire frame under `sharedKey` to raw bytes, or `null` on auth failure. */
44
+ function openBytes(frame, sharedKey) {
46
45
  let combined;
47
46
  try {
48
47
  combined = decodeBase64(frame);
@@ -54,7 +53,15 @@ function open(frame, sharedKey) {
54
53
  return null;
55
54
  const nonce = combined.slice(0, NONCE_LENGTH);
56
55
  const ciphertext = combined.slice(NONCE_LENGTH);
57
- const opened = nacl.box.open.after(ciphertext, nonce, sharedKey);
56
+ return nacl.box.open.after(ciphertext, nonce, sharedKey);
57
+ }
58
+ /** Encrypt `plaintext` under `sharedKey`, producing the wire frame `base64(nonce ++ ciphertext)`. */
59
+ function seal(plaintext, sharedKey) {
60
+ return sealBytes(new TextEncoder().encode(plaintext), sharedKey);
61
+ }
62
+ /** Decrypt a `base64(nonce ++ ciphertext)` wire frame under `sharedKey`, or return `null` on auth failure. */
63
+ function open(frame, sharedKey) {
64
+ const opened = openBytes(frame, sharedKey);
58
65
  return opened ? new TextDecoder().decode(opened) : null;
59
66
  }
60
67
  /** Shared app-frame plumbing once both sides agree on `sharedKey` — identical for client/daemon. */
@@ -78,6 +85,19 @@ function wireAppMessages(role, attachment, transport, events, getSharedKey, isRe
78
85
  }
79
86
  events.onMessage?.(plaintext);
80
87
  },
88
+ handleBinaryFrame(frame) {
89
+ if (closed)
90
+ return;
91
+ const sharedKey = getSharedKey();
92
+ if (!isReady() || !sharedKey)
93
+ return; // refuse ANY app message before handshake completes
94
+ const bytes = openBytes(frame.frame, sharedKey);
95
+ if (bytes === null) {
96
+ events.onAuthError?.(new Error(`relay ${role} channel: binary message failed authentication`));
97
+ return;
98
+ }
99
+ events.onBinaryMessage?.(bytes);
100
+ },
81
101
  send(plaintext) {
82
102
  if (closed)
83
103
  throw new Error(`relay ${role} channel: cannot send after close()`);
@@ -87,6 +107,15 @@ function wireAppMessages(role, attachment, transport, events, getSharedKey, isRe
87
107
  }
88
108
  transport.send(JSON.stringify({ type: "e2ee_app", frame: seal(plaintext, sharedKey) }));
89
109
  },
110
+ sendBinary(bytes) {
111
+ if (closed)
112
+ throw new Error(`relay ${role} channel: cannot send after close()`);
113
+ const sharedKey = getSharedKey();
114
+ if (!isReady() || !sharedKey) {
115
+ throw new Error(`relay ${role} channel: cannot send before the E2EE handshake completes`);
116
+ }
117
+ transport.send(JSON.stringify({ type: "e2ee_bin", frame: sealBytes(bytes, sharedKey) }));
118
+ },
90
119
  close() {
91
120
  if (closed)
92
121
  return;
@@ -112,8 +141,13 @@ export function createDaemonChannel(opts) {
112
141
  if (!frame)
113
142
  return; // ignore anything the relay/peer sends that isn't a recognized frame
114
143
  if (frame.type === "e2ee_hello") {
115
- if (ready)
116
- return; // handshake already completed for this channel; ignore replays
144
+ // Re-run the handshake on EVERY e2ee_hello rather than ignoring it once `ready`. The relay
145
+ // multiplexes one deterministic session id across however many client sockets attach over
146
+ // the daemon's lifetime (browser reload, second tab, reconnect) — each is a legitimate NEW
147
+ // peer presenting a fresh ephemeral key, not a replay of the first one. Re-deriving simply
148
+ // re-arms the channel for whichever peer is currently attached ("last hello wins"); a truly
149
+ // identical replayed frame just re-derives the same shared key, so this is idempotent for
150
+ // an actual replay and correct for a new peer.
117
151
  let remotePublicKey;
118
152
  try {
119
153
  remotePublicKey = decodeBase64(frame.ephemeralPublicKey);
@@ -129,6 +163,10 @@ export function createDaemonChannel(opts) {
129
163
  }
130
164
  if (frame.type === "e2ee_app") {
131
165
  plumbing.handleAppFrame(frame);
166
+ return;
167
+ }
168
+ if (frame.type === "e2ee_bin") {
169
+ plumbing.handleBinaryFrame(frame);
132
170
  }
133
171
  // `e2ee_ready` is never sent to a daemon channel; ignore if it arrives.
134
172
  });
@@ -139,6 +177,7 @@ export function createDaemonChannel(opts) {
139
177
  return ready;
140
178
  },
141
179
  send: plumbing.send,
180
+ sendBinary: plumbing.sendBinary,
142
181
  close: plumbing.close,
143
182
  };
144
183
  }
@@ -169,6 +208,10 @@ export function createClientChannel(opts) {
169
208
  }
170
209
  if (frame.type === "e2ee_app") {
171
210
  plumbing.handleAppFrame(frame);
211
+ return;
212
+ }
213
+ if (frame.type === "e2ee_bin") {
214
+ plumbing.handleBinaryFrame(frame);
172
215
  }
173
216
  // `e2ee_hello` is never sent to a client channel; ignore if it arrives.
174
217
  });
@@ -183,6 +226,7 @@ export function createClientChannel(opts) {
183
226
  return ready;
184
227
  },
185
228
  send: plumbing.send,
229
+ sendBinary: plumbing.sendBinary,
186
230
  close: plumbing.close,
187
231
  };
188
232
  }
@@ -1 +1 @@
1
- {"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from "./channel.js";
2
2
  export * from "./base64.js";
3
+ export * from "./session-id.js";
3
4
  export * from "./session-bridge.js";
4
5
  export * from "./cf-adapter.js";
5
6
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  // Browser/RN/Node-safe: pure crypto + logic, no platform-specific runtime imports.
2
2
  export * from "./channel.js";
3
3
  export * from "./base64.js";
4
+ export * from "./session-id.js";
4
5
  export * from "./session-bridge.js";
5
6
  export * from "./cf-adapter.js";
6
7
  // `./relay-server.js` (Node-only: `node:http`, `ws`) is deliberately NOT re-exported here — it
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAEhC,+FAA+F;AAC/F,+FAA+F;AAC/F,kGAAkG;AAClG,qFAAqF"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mFAAmF;AACnF,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAEhC,+FAA+F;AAC/F,+FAA+F;AAC/F,kGAAkG;AAClG,qFAAqF"}
@@ -0,0 +1,24 @@
1
+ import { type Logger as PinoLogger } from "pino";
2
+ export type RelayLogLevel = "trace" | "debug" | "info" | "warn" | "error" | "fatal" | "silent";
3
+ /** The structural logger the relay passes around (pino-shaped, console-compatible subset). */
4
+ export type RelayLogger = Pick<PinoLogger, "trace" | "debug" | "info" | "warn" | "error" | "fatal">;
5
+ export interface CreateRelayLoggerOptions {
6
+ /** Defaults to `PI_STUDIO_RELAY_LOG_LEVEL`, then "info". */
7
+ level?: RelayLogLevel;
8
+ /** Force pretty output on/off; defaults to stdout TTY detection. */
9
+ pretty?: boolean;
10
+ /**
11
+ * Additionally write structured NDJSON to a rotating file in this directory (stdout keeps
12
+ * receiving logs too). Defaults to `PI_STUDIO_RELAY_LOG_DIR` (unset = stdout only).
13
+ */
14
+ logDir?: string;
15
+ /** Rotating-file size threshold (default "10M"). */
16
+ rotateSize?: string;
17
+ /** Rotating-file retention count (default 5). */
18
+ rotateMaxFiles?: number;
19
+ /** Override the stdout stream (tests). Defaults to `process.stdout`. */
20
+ stdoutStream?: NodeJS.WritableStream;
21
+ }
22
+ /** Build the relay logger. Pure/synchronous; safe to call in tests. */
23
+ export declare function createRelayLogger(options?: CreateRelayLoggerOptions): RelayLogger;
24
+ //# sourceMappingURL=relay-logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay-logger.d.ts","sourceRoot":"","sources":["../src/relay-logger.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAqB,KAAK,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AAIpE,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE/F,8FAA8F;AAC9F,MAAM,MAAM,WAAW,GAAG,IAAI,CAC5B,UAAU,EACV,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CACxD,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACvC,4DAA4D;IAC5D,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,oEAAoE;IACpE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;CACtC;AASD,uEAAuE;AACvE,wBAAgB,iBAAiB,CAAC,OAAO,GAAE,wBAA6B,GAAG,WAAW,CA6BrF"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Operational logging for the self-hosted relay server. Node-only (imports `node:fs`,
3
+ * `rotating-file-stream`) — imported only from `relay-server.ts`/`relay-main.ts`, which live
4
+ * behind the `"./server"` package export subpath, so it never reaches a browser bundle that
5
+ * transitively imports this package's main barrel.
6
+ *
7
+ * Mirrors the daemon's logging stack (`packages/server/src/logging/logger.ts`): pino everywhere,
8
+ * pretty/colorized on a TTY, structured NDJSON otherwise. Differences, intentional for a small
9
+ * stateless edge process:
10
+ *
11
+ * - **stdout is ALWAYS written** (container/PM2/journald-friendly — `docker logs` just works);
12
+ * a rotating file under `logDir` is ADDITIONALLY written when configured, via pino multistream.
13
+ * - No worker-thread transport: `pino-pretty` is used as a direct sonic-boom-compatible stream,
14
+ * same rationale as the daemon (Vitest-friendliness, no shutdown latency).
15
+ *
16
+ * Logs metadata only (connection ids, remote addresses, session ids, frame sizes, durations) —
17
+ * never relayed payloads, which the relay structurally cannot read anyway.
18
+ */
19
+ import { mkdirSync } from "node:fs";
20
+ import { pino, multistream } from "pino";
21
+ import pinoPretty from "pino-pretty";
22
+ import { createStream as createRotatingStream } from "rotating-file-stream";
23
+ const LEVELS = new Set(["trace", "debug", "info", "warn", "error", "fatal", "silent"]);
24
+ function resolveLevel(level) {
25
+ const raw = (level ?? process.env.PI_STUDIO_RELAY_LOG_LEVEL ?? "info").toLowerCase();
26
+ return (LEVELS.has(raw) ? raw : "info");
27
+ }
28
+ /** Build the relay logger. Pure/synchronous; safe to call in tests. */
29
+ export function createRelayLogger(options = {}) {
30
+ const level = resolveLevel(options.level);
31
+ if (level === "silent")
32
+ return pino({ level: "silent" });
33
+ const base = { name: "pi-studio-relay" };
34
+ const streams = [];
35
+ // stdout: pretty on a TTY, raw NDJSON otherwise (docker logs / journald / PM2).
36
+ const pretty = options.pretty ?? Boolean(process.stdout.isTTY);
37
+ streams.push({
38
+ stream: pretty
39
+ ? pinoPretty({ colorize: true, translateTime: "SYS:HH:MM:ss.l", ignore: "pid,hostname" })
40
+ : (options.stdoutStream ?? process.stdout),
41
+ });
42
+ // Optional rotating file — in addition to stdout, never instead of it.
43
+ const logDir = options.logDir ?? process.env.PI_STUDIO_RELAY_LOG_DIR;
44
+ if (logDir) {
45
+ mkdirSync(logDir, { recursive: true });
46
+ streams.push({
47
+ stream: createRotatingStream("pi-studio-relay.log", {
48
+ path: logDir,
49
+ size: options.rotateSize ?? "10M",
50
+ maxFiles: options.rotateMaxFiles ?? 5,
51
+ }),
52
+ });
53
+ }
54
+ return pino({ level, base }, multistream(streams));
55
+ }
56
+ //# sourceMappingURL=relay-logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"relay-logger.js","sourceRoot":"","sources":["../src/relay-logger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,IAAI,EAAE,WAAW,EAA6B,MAAM,MAAM,CAAC;AACpE,OAAO,UAAU,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,YAAY,IAAI,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AA4B5E,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AAEvF,SAAS,YAAY,CAAC,KAAc;IAClC,MAAM,GAAG,GAAG,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IACrF,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAkB,CAAC;AAC3D,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,iBAAiB,CAAC,UAAoC,EAAE;IACtE,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1C,IAAI,KAAK,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAEzD,MAAM,IAAI,GAAG,EAAE,IAAI,EAAE,iBAAiB,EAAE,CAAC;IACzC,MAAM,OAAO,GAA6C,EAAE,CAAC;IAE7D,gFAAgF;IAChF,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/D,OAAO,CAAC,IAAI,CAAC;QACX,MAAM,EAAE,MAAM;YACZ,CAAC,CAAC,UAAU,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC;YACzF,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;KAC7C,CAAC,CAAC;IAEH,uEAAuE;IACvE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IACrE,IAAI,MAAM,EAAE,CAAC;QACX,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC;YACX,MAAM,EAAE,oBAAoB,CAAC,qBAAqB,EAAE;gBAClD,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,OAAO,CAAC,UAAU,IAAI,KAAK;gBACjC,QAAQ,EAAE,OAAO,CAAC,cAAc,IAAI,CAAC;aACtC,CAAC;SACH,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;AACrD,CAAC"}
@@ -5,8 +5,14 @@
5
5
  * `startRelayServer`, logs the bound address + health endpoint, and shuts down cleanly on
6
6
  * `SIGINT`/`SIGTERM`. This is what `pi-studio relay start` (packages/cli) spawns as a detached
7
7
  * child process, and what `npx @av-pi-studio/relay` runs directly for a foreground/manual deploy.
8
+ *
9
+ * Logging: structured pino to stdout always (pretty on a TTY, NDJSON otherwise — so `docker logs`
10
+ * works out of the box); `PI_STUDIO_RELAY_LOG_LEVEL` sets the level (default `info`),
11
+ * `PI_STUDIO_RELAY_LOG_DIR` additionally writes a rotating NDJSON file. Metadata only — the relay
12
+ * never sees message contents, so nothing sensitive can be logged.
8
13
  */
9
14
  import { startRelayServer } from "./relay-server.js";
15
+ import { createRelayLogger } from "./relay-logger.js";
10
16
  const DEFAULT_LISTEN = "0.0.0.0:7000";
11
17
  function parseListen(value) {
12
18
  const idx = value.lastIndexOf(":");
@@ -27,17 +33,18 @@ function resolveListen(argv) {
27
33
  }
28
34
  async function main() {
29
35
  const { host, port } = parseListen(resolveListen(process.argv.slice(2)));
30
- const handle = await startRelayServer({ host, port });
31
- console.log(`[pi-studio-relay] listening on ws://${handle.host}:${handle.port} (health: /health)`);
36
+ const log = createRelayLogger();
37
+ const handle = await startRelayServer({ host, port, logger: log });
38
+ log.info({ host: handle.host, port: handle.port }, `listening on ws://${handle.host}:${handle.port} (health: /health)`);
32
39
  const shutdown = () => {
33
- console.log("[pi-studio-relay] shutting down");
40
+ log.info("shutting down");
34
41
  void handle.close().then(() => process.exit(0));
35
42
  };
36
43
  process.on("SIGINT", shutdown);
37
44
  process.on("SIGTERM", shutdown);
38
45
  }
39
46
  main().catch((err) => {
40
- console.error(`[pi-studio-relay] fatal: ${err?.message ?? String(err)}`);
47
+ createRelayLogger().fatal({ err: err?.message ?? String(err) }, "fatal");
41
48
  process.exit(1);
42
49
  });
43
50
  //# sourceMappingURL=relay-main.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"relay-main.js","sourceRoot":"","sources":["../src/relay-main.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,cAAc,GAAG,cAAc,CAAC;AAEtC,SAAS,WAAW,CAAC,KAAa;IAChC,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,GAAG,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACvG,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC;AAED,SAAS,aAAa,CAAC,IAAc;IACnC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC,SAAS,GAAG,CAAC,CAAE,CAAC;IACzE,OAAO,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,cAAc,CAAC;AAC9D,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAEtD,OAAO,CAAC,GAAG,CAAC,uCAAuC,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,oBAAoB,CAAC,CAAC;IAEnG,MAAM,QAAQ,GAAG,GAAS,EAAE;QAC1B,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;QAC/C,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,OAAO,CAAC,KAAK,CAAC,4BAA6B,GAAa,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
1
+ {"version":3,"file":"relay-main.js","sourceRoot":"","sources":["../src/relay-main.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,cAAc,GAAG,cAAc,CAAC;AAEtC,SAAS,WAAW,CAAC,KAAa;IAChC,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACnC,IAAI,GAAG,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;IACvG,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CAAC,mCAAmC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAC9E,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC;AAED,SAAS,aAAa,CAAC,IAAc;IACnC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAC3C,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,IAAI,CAAC,SAAS,GAAG,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC,SAAS,GAAG,CAAC,CAAE,CAAC;IACzE,OAAO,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,cAAc,CAAC;AAC9D,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,WAAW,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,MAAM,GAAG,GAAG,iBAAiB,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;IAEnE,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,qBAAqB,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,oBAAoB,CAAC,CAAC;IAExH,MAAM,QAAQ,GAAG,GAAS,EAAE;QAC1B,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC1B,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IAC5B,iBAAiB,EAAE,CAAC,KAAK,CAAC,EAAE,GAAG,EAAG,GAAa,EAAE,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;IACpF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -1,9 +1,14 @@
1
1
  import { RelaySessionBridge } from "./session-bridge.js";
2
+ import { type RelayLogger } from "./relay-logger.js";
3
+ export { createRelayLogger, type RelayLogger, type CreateRelayLoggerOptions, type RelayLogLevel } from "./relay-logger.js";
2
4
  export interface RelayServerOptions {
3
5
  /** Interface to bind. Defaults to all interfaces (`0.0.0.0`) since the relay must accept
4
6
  * connections dialed in from other hosts — unlike the daemon, which defaults to localhost. */
5
7
  host?: string;
6
8
  port: number;
9
+ /** Operational logger; defaults to a silent logger (tests, embedded use). `relay-main.ts`
10
+ * passes a real stdout logger. */
11
+ logger?: RelayLogger;
7
12
  }
8
13
  export interface RelayServerHandle {
9
14
  readonly host: string;
@@ -1 +1 @@
1
- {"version":3,"file":"relay-server.d.ts","sourceRoot":"","sources":["../src/relay-server.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAE,kBAAkB,EAAoB,MAAM,qBAAqB,CAAC;AAE3E,MAAM,WAAW,kBAAkB;IACjC;mGAC+F;IAC/F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAmBD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAgCrF"}
1
+ {"version":3,"file":"relay-server.d.ts","sourceRoot":"","sources":["../src/relay-server.ts"],"names":[],"mappings":"AAkBA,OAAO,EAAE,kBAAkB,EAAoB,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKxE,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,KAAK,wBAAwB,EAAE,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAE3H,MAAM,WAAW,kBAAkB;IACjC;mGAC+F;IAC/F,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb;uCACmC;IACnC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAmCD;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAmFrF"}
@@ -13,20 +13,31 @@
13
13
  * public key in the `e2ee_hello` handshake frame.
14
14
  */
15
15
  import { createServer } from "node:http";
16
+ import { randomUUID } from "node:crypto";
16
17
  import { WebSocketServer } from "ws";
17
18
  import { RelaySessionBridge } from "./session-bridge.js";
19
+ import { createRelayLogger } from "./relay-logger.js";
20
+ // The logger is re-exported from this Node-only subpath so embedders spawning the server inline
21
+ // (packages/cli's relay-control.ts) can construct one from the same module URL they resolve for
22
+ // startRelayServer — without a second import.meta.resolve.
23
+ export { createRelayLogger } from "./relay-logger.js";
18
24
  const DEFAULT_RELAY_HOST = "0.0.0.0";
19
- function wrapWsSocket(ws) {
25
+ function wrapWsSocket(ws, meta) {
20
26
  const messageHandlers = [];
21
27
  ws.on("message", (data, isBinary) => {
22
- if (!isBinary)
23
- for (const h of messageHandlers)
24
- h(data.toString("utf8"));
28
+ if (isBinary)
29
+ return;
30
+ const text = data.toString("utf8");
31
+ meta.bytesIn += text.length;
32
+ for (const h of messageHandlers)
33
+ h(text);
25
34
  });
26
35
  return {
27
36
  send: (data) => {
28
- if (ws.readyState === ws.OPEN)
37
+ if (ws.readyState === ws.OPEN) {
38
+ meta.bytesOut += data.length;
29
39
  ws.send(data);
40
+ }
30
41
  },
31
42
  onMessage: (h) => messageHandlers.push(h),
32
43
  onClose: (h) => ws.on("close", (code, reasonBuf) => h(reasonBuf.toString("utf8") || `code ${code}`)),
@@ -41,7 +52,28 @@ function wrapWsSocket(ws) {
41
52
  */
42
53
  export function startRelayServer(opts) {
43
54
  const host = opts.host ?? DEFAULT_RELAY_HOST;
44
- const bridge = new RelaySessionBridge();
55
+ const log = opts.logger ?? createRelayLogger({ level: "silent" });
56
+ // Connection metadata keyed by the bridged socket, so bridge lifecycle hooks can log with
57
+ // connection context (id + remote address) without the bridge knowing anything about transports.
58
+ const metas = new WeakMap();
59
+ const metaOf = (s) => metas.get(s);
60
+ const bridge = new RelaySessionBridge({
61
+ onRegisterRejected: (socket) => {
62
+ const m = metaOf(socket);
63
+ log.warn({ conn: m?.conn, remoteAddress: m?.remoteAddress }, "ignored frame before registration (first frame must be relay_register)");
64
+ },
65
+ onRegister: (socket, sessionId, peers) => {
66
+ const m = metaOf(socket);
67
+ log.info({ conn: m?.conn, remoteAddress: m?.remoteAddress, sessionId, peers }, peers === 2 ? "session registered — both peers attached" : "session registered");
68
+ },
69
+ onForward: (sessionId, bytes) => {
70
+ log.trace({ sessionId, bytes }, "frame forwarded");
71
+ },
72
+ onUnregister: (socket, sessionId, peers) => {
73
+ const m = metaOf(socket);
74
+ log.info({ conn: m?.conn, sessionId, peers }, peers === 0 ? "peer detached — session idle" : "peer detached");
75
+ },
76
+ });
45
77
  const httpServer = createServer((req, res) => {
46
78
  if (req.method === "GET" && req.url === "/health") {
47
79
  res.writeHead(200, { "content-type": "text/plain; charset=utf-8" }).end("ok");
@@ -50,7 +82,32 @@ export function startRelayServer(opts) {
50
82
  res.writeHead(404).end();
51
83
  });
52
84
  const wss = new WebSocketServer({ server: httpServer });
53
- wss.on("connection", (ws) => bridge.attach(wrapWsSocket(ws)));
85
+ wss.on("connection", (ws, req) => {
86
+ const meta = {
87
+ conn: randomUUID().slice(0, 8),
88
+ remoteAddress: req.socket.remoteAddress ?? "unknown",
89
+ connectedAt: Date.now(),
90
+ bytesIn: 0,
91
+ bytesOut: 0,
92
+ };
93
+ log.info({ conn: meta.conn, remoteAddress: meta.remoteAddress }, "connection open");
94
+ ws.on("error", (err) => {
95
+ log.error({ conn: meta.conn, remoteAddress: meta.remoteAddress, err: err.message }, "socket error");
96
+ });
97
+ ws.on("close", (code) => {
98
+ log.info({
99
+ conn: meta.conn,
100
+ remoteAddress: meta.remoteAddress,
101
+ code,
102
+ durationMs: Date.now() - meta.connectedAt,
103
+ bytesIn: meta.bytesIn,
104
+ bytesOut: meta.bytesOut,
105
+ }, "connection closed");
106
+ });
107
+ const socket = wrapWsSocket(ws, meta);
108
+ metas.set(socket, meta);
109
+ bridge.attach(socket);
110
+ });
54
111
  return new Promise((resolve, reject) => {
55
112
  httpServer.on("error", reject);
56
113
  httpServer.listen(opts.port, host, () => {
@@ -1 +1 @@
1
- {"version":3,"file":"relay-server.js","sourceRoot":"","sources":["../src/relay-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"relay-server.js","sourceRoot":"","sources":["../src/relay-server.ts"],"names":[],"mappings":"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"}
@@ -20,13 +20,31 @@ export interface RelaySocket {
20
20
  onClose(handler: (reason?: string) => void): void;
21
21
  close(code?: number, reason?: string): void;
22
22
  }
23
+ /**
24
+ * Metadata-only lifecycle hooks a relay host (e.g. `relay-server.ts`) can subscribe to for
25
+ * operational logging. Every callback receives ONLY metadata the relay already legitimately sees
26
+ * (session ids, peer counts, frame sizes) — never frame contents. Firing these hooks does not
27
+ * weaken the zero-knowledge property: the bridge still parses nothing past the registration frame.
28
+ */
29
+ export interface RelayBridgeEvents {
30
+ /** A socket failed to present a valid registration frame as its first frame (silently ignored). */
31
+ onRegisterRejected?(socket: RelaySocket): void;
32
+ /** A socket registered under `sessionId`; `peers` is the session's socket count after adding. */
33
+ onRegister?(socket: RelaySocket, sessionId: string, peers: number): void;
34
+ /** A frame of `bytes` UTF-8 bytes was forwarded from one socket to a peer in `sessionId`. */
35
+ onForward?(sessionId: string, bytes: number): void;
36
+ /** A registered socket detached; `peers` is the session's socket count after removal. */
37
+ onUnregister?(socket: RelaySocket, sessionId: string, peers: number): void;
38
+ }
23
39
  /**
24
40
  * Pairs relay-attached sockets by session id and forwards non-registration frames verbatim between
25
41
  * every OTHER socket sharing that session id. One bridge instance serves an entire relay server
26
42
  * (or Cloudflare Durable Object instance); `attach()` is called once per newly accepted connection.
27
43
  */
28
44
  export declare class RelaySessionBridge {
45
+ private readonly events;
29
46
  private readonly sessions;
47
+ constructor(events?: RelayBridgeEvents);
30
48
  /**
31
49
  * Attach a raw socket. Its first frame MUST be a registration frame or it is silently ignored
32
50
  * (never forwarded, never crashes the bridge) — an unregistered socket receives nothing and
@@ -1 +1 @@
1
- {"version":3,"file":"session-bridge.d.ts","sourceRoot":"","sources":["../src/session-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,kGAAkG;AAClG,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACjD,OAAO,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAClD,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7C;AAcD;;;;GAIG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAEhE;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IA6BjC,8FAA8F;IAC9F,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;CAGrC"}
1
+ {"version":3,"file":"session-bridge.d.ts","sourceRoot":"","sources":["../src/session-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,kGAAkG;AAClG,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACjD,OAAO,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IAClD,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7C;AAED;;;;;GAKG;AACH,MAAM,WAAW,iBAAiB;IAChC,mGAAmG;IACnG,kBAAkB,CAAC,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAAC;IAC/C,iGAAiG;IACjG,UAAU,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACzE,6FAA6F;IAC7F,SAAS,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACnD,yFAAyF;IACzF,YAAY,CAAC,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5E;AAcD;;;;GAIG;AACH,qBAAa,kBAAkB;IAGjB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAFnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;gBAEnC,MAAM,GAAE,iBAAsB;IAE3D;;;;OAIG;IACH,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAqCjC,8FAA8F;IAC9F,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;CAGrC"}
@@ -31,7 +31,11 @@ function tryParseSessionId(data) {
31
31
  * (or Cloudflare Durable Object instance); `attach()` is called once per newly accepted connection.
32
32
  */
33
33
  export class RelaySessionBridge {
34
+ events;
34
35
  sessions = new Map();
36
+ constructor(events = {}) {
37
+ this.events = events;
38
+ }
35
39
  /**
36
40
  * Attach a raw socket. Its first frame MUST be a registration frame or it is silently ignored
37
41
  * (never forwarded, never crashes the bridge) — an unregistered socket receives nothing and
@@ -42,19 +46,25 @@ export class RelaySessionBridge {
42
46
  socket.onMessage((data) => {
43
47
  if (sessionId === null) {
44
48
  const parsedSessionId = tryParseSessionId(data);
45
- if (!parsedSessionId)
46
- return; // not a registration frame; ignore malformed/unexpected input
49
+ if (!parsedSessionId) {
50
+ // not a registration frame; ignore malformed/unexpected input
51
+ this.events.onRegisterRejected?.(socket);
52
+ return;
53
+ }
47
54
  sessionId = parsedSessionId;
48
55
  const peers = this.sessions.get(sessionId) ?? new Set();
49
56
  peers.add(socket);
50
57
  this.sessions.set(sessionId, peers);
58
+ this.events.onRegister?.(socket, sessionId, peers.size);
51
59
  return;
52
60
  }
53
61
  // Forward verbatim to every OTHER socket sharing this session id. No JSON.parse, no
54
62
  // inspection — this frame may be the E2EE handshake or opaque ciphertext.
55
63
  for (const peer of this.sessions.get(sessionId) ?? []) {
56
- if (peer !== socket)
57
- peer.send(data);
64
+ if (peer === socket)
65
+ continue;
66
+ peer.send(data);
67
+ this.events.onForward?.(sessionId, data.length);
58
68
  }
59
69
  });
60
70
  socket.onClose(() => {
@@ -66,6 +76,7 @@ export class RelaySessionBridge {
66
76
  peers.delete(socket);
67
77
  if (peers.size === 0)
68
78
  this.sessions.delete(sessionId);
79
+ this.events.onUnregister?.(socket, sessionId, peers.size);
69
80
  });
70
81
  }
71
82
  /** Number of sockets currently registered under `sessionId` (observability / test helper). */
@@ -1 +1 @@
1
- {"version":3,"file":"session-bridge.js","sourceRoot":"","sources":["../src/session-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAUH,SAAS,iBAAiB,CAAC,IAAY;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4C,CAAC;QAC3E,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACjG,OAAO,MAAM,CAAC,SAAS,CAAC;QAC1B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,kBAAkB;IACZ,QAAQ,GAAG,IAAI,GAAG,EAA4B,CAAC;IAEhE;;;;OAIG;IACH,MAAM,CAAC,MAAmB;QACxB,IAAI,SAAS,GAAkB,IAAI,CAAC;QAEpC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE;YACxB,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;gBACvB,MAAM,eAAe,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBAChD,IAAI,CAAC,eAAe;oBAAE,OAAO,CAAC,8DAA8D;gBAC5F,SAAS,GAAG,eAAe,CAAC;gBAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,GAAG,EAAe,CAAC;gBACrE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAClB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBACpC,OAAO;YACT,CAAC;YACD,oFAAoF;YACpF,0EAA0E;YAC1E,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;gBACtD,IAAI,IAAI,KAAK,MAAM;oBAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACvC,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE;YAClB,IAAI,SAAS,KAAK,IAAI;gBAAE,OAAO;YAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC3C,IAAI,CAAC,KAAK;gBAAE,OAAO;YACnB,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACrB,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC;gBAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;IACL,CAAC;IAED,8FAA8F;IAC9F,SAAS,CAAC,SAAiB;QACzB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC;IACjD,CAAC;CACF"}
1
+ {"version":3,"file":"session-bridge.js","sourceRoot":"","sources":["../src/session-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AA2BH,SAAS,iBAAiB,CAAC,IAAY;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4C,CAAC;QAC3E,IAAI,MAAM,CAAC,IAAI,KAAK,gBAAgB,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACjG,OAAO,MAAM,CAAC,SAAS,CAAC;QAC1B,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,OAAO,kBAAkB;IAGA;IAFZ,QAAQ,GAAG,IAAI,GAAG,EAA4B,CAAC;IAEhE,YAA6B,SAA4B,EAAE;QAA9B,WAAM,GAAN,MAAM,CAAwB;IAAG,CAAC;IAE/D;;;;OAIG;IACH,MAAM,CAAC,MAAmB;QACxB,IAAI,SAAS,GAAkB,IAAI,CAAC;QAEpC,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE;YACxB,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;gBACvB,MAAM,eAAe,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC;gBAChD,IAAI,CAAC,eAAe,EAAE,CAAC;oBACrB,8DAA8D;oBAC9D,IAAI,CAAC,MAAM,CAAC,kBAAkB,EAAE,CAAC,MAAM,CAAC,CAAC;oBACzC,OAAO;gBACT,CAAC;gBACD,SAAS,GAAG,eAAe,CAAC;gBAC5B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,GAAG,EAAe,CAAC;gBACrE,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAClB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;gBACpC,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBACxD,OAAO;YACT,CAAC;YACD,oFAAoF;YACpF,0EAA0E;YAC1E,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC;gBACtD,IAAI,IAAI,KAAK,MAAM;oBAAE,SAAS;gBAC9B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAChB,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;YAClD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,MAAM,CAAC,OAAO,CAAC,GAAG,EAAE;YAClB,IAAI,SAAS,KAAK,IAAI;gBAAE,OAAO;YAC/B,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;YAC3C,IAAI,CAAC,KAAK;gBAAE,OAAO;YACnB,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACrB,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC;gBAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACtD,IAAI,CAAC,MAAM,CAAC,YAAY,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC;IAED,8FAA8F;IAC9F,SAAS,CAAC,SAAiB;QACzB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC;IACjD,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ /** Derive the relay session id for a daemon identified by `publicKey` (its persistent Curve25519 public key). */
2
+ export declare function deriveRelaySessionId(publicKey: Uint8Array): string;
3
+ //# sourceMappingURL=session-id.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-id.d.ts","sourceRoot":"","sources":["../src/session-id.ts"],"names":[],"mappings":"AAoBA,iHAAiH;AACjH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM,CAOlE"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Deterministic relay session id derivation (architecture/relay-e2ee.md § Pairing).
3
+ *
4
+ * The relay's rendezvous `sessionId` (the `{ type: "relay_register", sessionId }` frame) must be
5
+ * something both sides can compute independently from data the pairing link already carries — the
6
+ * daemon's persistent public key — so a pairing link keeps working across relay reconnects
7
+ * (each of which previously minted a fresh random session id, silently invalidating any link
8
+ * printed before the next drop).
9
+ *
10
+ * This derivation adds no new secret: the pairing link already carries the daemon's public key
11
+ * and is documented as "the trust anchor, treat it like a password" (relay-e2ee.md § Pairing). A
12
+ * session id computed from that same public value reveals nothing an attacker didn't already have
13
+ * once they held the link. What it changes is durability — the daemon and any pairing-link holder
14
+ * now agree on the same session id forever (until the keypair itself is regenerated), instead of a
15
+ * fresh id being renegotiated implicitly on every reconnect.
16
+ */
17
+ import nacl from "tweetnacl";
18
+ const SESSION_ID_BYTES = 16; // 32 hex chars — plenty of entropy for a rendezvous label, not a secret.
19
+ /** Derive the relay session id for a daemon identified by `publicKey` (its persistent Curve25519 public key). */
20
+ export function deriveRelaySessionId(publicKey) {
21
+ const digest = nacl.hash(publicKey); // SHA-512, 64 bytes
22
+ let hex = "";
23
+ for (let i = 0; i < SESSION_ID_BYTES; i++) {
24
+ hex += digest[i].toString(16).padStart(2, "0");
25
+ }
26
+ return hex;
27
+ }
28
+ //# sourceMappingURL=session-id.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-id.js","sourceRoot":"","sources":["../src/session-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,gBAAgB,GAAG,EAAE,CAAC,CAAC,yEAAyE;AAEtG,iHAAiH;AACjH,MAAM,UAAU,oBAAoB,CAAC,SAAqB;IACxD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,oBAAoB;IACzD,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,gBAAgB,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1C,GAAG,IAAK,MAAM,CAAC,CAAC,CAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC7D,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@av-pi-studio/relay",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -25,6 +25,9 @@
25
25
  "clean": "rm -rf dist *.tsbuildinfo"
26
26
  },
27
27
  "dependencies": {
28
+ "pino": "^10.2.0",
29
+ "pino-pretty": "^13.1.3",
30
+ "rotating-file-stream": "^3.2.9",
28
31
  "tweetnacl": "^1.0.3",
29
32
  "ws": "^8.21.0"
30
33
  },