@floegence/flowersec-core 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client-connect/connectCore.js +71 -10
- package/dist/client.d.ts +3 -1
- package/dist/framing/index.d.ts +1 -0
- package/dist/framing/index.js +1 -0
- package/dist/framing/jsonframe.d.ts +14 -0
- package/dist/{rpc/framing.js → framing/jsonframe.js} +14 -6
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/rpc/client.js +2 -2
- package/dist/rpc/index.d.ts +0 -1
- package/dist/rpc/index.js +0 -1
- package/dist/rpc/server.js +2 -2
- package/dist/streamhello/streamHello.js +1 -1
- package/dist/streamio/index.d.ts +15 -0
- package/dist/streamio/index.js +58 -0
- package/dist/yamux/byteReader.js +2 -1
- package/dist/yamux/errors.d.ts +4 -0
- package/dist/yamux/errors.js +10 -0
- package/dist/yamux/index.d.ts +1 -0
- package/dist/yamux/index.js +1 -0
- package/dist/yamux/stream.d.ts +1 -1
- package/dist/yamux/stream.js +2 -2
- package/package.json +9 -1
- package/dist/rpc/framing.d.ts +0 -4
|
@@ -5,7 +5,7 @@ import { RpcClient } from "../rpc/client.js";
|
|
|
5
5
|
import { writeStreamHello } from "../streamhello/streamHello.js";
|
|
6
6
|
import { normalizeObserver, nowSeconds } from "../observability/observer.js";
|
|
7
7
|
import { base64urlDecode } from "../utils/base64url.js";
|
|
8
|
-
import { FlowersecError, throwIfAborted } from "../utils/errors.js";
|
|
8
|
+
import { AbortError, FlowersecError, throwIfAborted } from "../utils/errors.js";
|
|
9
9
|
import { WebSocketBinaryTransport, WsCloseError } from "../ws-client/binaryTransport.js";
|
|
10
10
|
import { OriginMismatchError, WsFactoryRequiredError, classifyConnectError, classifyHandshakeError, createWebSocket, waitOpen, withAbortAndTimeout, } from "./common.js";
|
|
11
11
|
import { isTunnelAttachCloseReason } from "./tunnelAttachCloseReason.js";
|
|
@@ -177,14 +177,7 @@ export async function connectCore(args) {
|
|
|
177
177
|
secure.close();
|
|
178
178
|
throw new FlowersecError({ path: args.path, stage: "yamux", code: "open_stream_failed", message: "open rpc stream failed", cause: e });
|
|
179
179
|
}
|
|
180
|
-
const reader = new ByteReader(
|
|
181
|
-
try {
|
|
182
|
-
return await rpcStream.read();
|
|
183
|
-
}
|
|
184
|
-
catch {
|
|
185
|
-
return null;
|
|
186
|
-
}
|
|
187
|
-
});
|
|
180
|
+
const reader = new ByteReader(() => rpcStream.read());
|
|
188
181
|
const readExactly = (n) => reader.readExactly(n);
|
|
189
182
|
const write = (b) => rpcStream.write(b);
|
|
190
183
|
try {
|
|
@@ -252,9 +245,28 @@ export async function connectCore(args) {
|
|
|
252
245
|
mux,
|
|
253
246
|
rpc,
|
|
254
247
|
ping,
|
|
255
|
-
openStream: async (kind) => {
|
|
248
|
+
openStream: async (kind, opts = {}) => {
|
|
256
249
|
if (kind == null || kind === "")
|
|
257
250
|
throw new FlowersecError({ path: args.path, stage: "validate", code: "missing_stream_kind", message: "missing stream kind" });
|
|
251
|
+
if (opts.signal?.aborted) {
|
|
252
|
+
throw new FlowersecError({
|
|
253
|
+
path: args.path,
|
|
254
|
+
stage: "yamux",
|
|
255
|
+
code: "canceled",
|
|
256
|
+
message: "open stream aborted",
|
|
257
|
+
cause: opts.signal.reason,
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
const abortReason = (signal) => {
|
|
261
|
+
const r = signal.reason;
|
|
262
|
+
if (r instanceof Error)
|
|
263
|
+
return r;
|
|
264
|
+
if (typeof r === "string" && r !== "")
|
|
265
|
+
return new AbortError(r);
|
|
266
|
+
return new AbortError("aborted");
|
|
267
|
+
};
|
|
268
|
+
const signal = opts.signal;
|
|
269
|
+
let abortListener;
|
|
258
270
|
let s;
|
|
259
271
|
try {
|
|
260
272
|
s = await mux.openStream();
|
|
@@ -262,10 +274,59 @@ export async function connectCore(args) {
|
|
|
262
274
|
catch (e) {
|
|
263
275
|
throw new FlowersecError({ path: args.path, stage: "yamux", code: "open_stream_failed", message: "open stream failed", cause: e });
|
|
264
276
|
}
|
|
277
|
+
if (signal != null) {
|
|
278
|
+
abortListener = () => {
|
|
279
|
+
try {
|
|
280
|
+
s.reset(abortReason(signal));
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
// ignore
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
signal.addEventListener("abort", abortListener, { once: true });
|
|
287
|
+
if (signal.aborted)
|
|
288
|
+
abortListener();
|
|
289
|
+
}
|
|
290
|
+
if (signal?.aborted) {
|
|
291
|
+
if (abortListener != null)
|
|
292
|
+
signal.removeEventListener("abort", abortListener);
|
|
293
|
+
try {
|
|
294
|
+
await s.close();
|
|
295
|
+
}
|
|
296
|
+
catch {
|
|
297
|
+
// ignore
|
|
298
|
+
}
|
|
299
|
+
throw new FlowersecError({
|
|
300
|
+
path: args.path,
|
|
301
|
+
stage: "yamux",
|
|
302
|
+
code: "canceled",
|
|
303
|
+
message: "open stream aborted",
|
|
304
|
+
cause: signal.reason,
|
|
305
|
+
});
|
|
306
|
+
}
|
|
265
307
|
try {
|
|
266
308
|
await writeStreamHello((b) => s.write(b), kind);
|
|
267
309
|
}
|
|
268
310
|
catch (err) {
|
|
311
|
+
if (signal?.aborted) {
|
|
312
|
+
if (abortListener != null)
|
|
313
|
+
signal.removeEventListener("abort", abortListener);
|
|
314
|
+
try {
|
|
315
|
+
await s.close();
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
// ignore
|
|
319
|
+
}
|
|
320
|
+
throw new FlowersecError({
|
|
321
|
+
path: args.path,
|
|
322
|
+
stage: "yamux",
|
|
323
|
+
code: "canceled",
|
|
324
|
+
message: "open stream aborted",
|
|
325
|
+
cause: signal.reason,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
if (signal != null && abortListener != null)
|
|
329
|
+
signal.removeEventListener("abort", abortListener);
|
|
269
330
|
try {
|
|
270
331
|
await s.close();
|
|
271
332
|
}
|
package/dist/client.d.ts
CHANGED
|
@@ -7,7 +7,9 @@ export type Client = Readonly<{
|
|
|
7
7
|
path: ClientPath;
|
|
8
8
|
endpointInstanceId?: string;
|
|
9
9
|
rpc: RpcClient;
|
|
10
|
-
openStream: (kind: string
|
|
10
|
+
openStream: (kind: string, opts?: Readonly<{
|
|
11
|
+
signal?: AbortSignal;
|
|
12
|
+
}>) => Promise<YamuxStream>;
|
|
11
13
|
ping: () => Promise<void>;
|
|
12
14
|
close: () => void;
|
|
13
15
|
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./jsonframe.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./jsonframe.js";
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export declare const DEFAULT_MAX_JSON_FRAME_BYTES: number;
|
|
2
|
+
export declare class JsonFramingError extends Error {
|
|
3
|
+
}
|
|
4
|
+
type WriteFn = (b: Uint8Array) => Promise<void>;
|
|
5
|
+
type WriteLike = Readonly<{
|
|
6
|
+
write: (b: Uint8Array) => Promise<void>;
|
|
7
|
+
}>;
|
|
8
|
+
type ReadExactlyFn = (n: number) => Promise<Uint8Array>;
|
|
9
|
+
type ReadExactlyLike = Readonly<{
|
|
10
|
+
readExactly: (n: number) => Promise<Uint8Array>;
|
|
11
|
+
}>;
|
|
12
|
+
export declare function writeJsonFrame(write: WriteFn | WriteLike, v: unknown): Promise<void>;
|
|
13
|
+
export declare function readJsonFrame(readExactly: ReadExactlyFn | ReadExactlyLike, maxBytes: number): Promise<unknown>;
|
|
14
|
+
export {};
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { readU32be, u32be } from "../utils/bin.js";
|
|
2
|
+
export const DEFAULT_MAX_JSON_FRAME_BYTES = 1 << 20;
|
|
2
3
|
const te = new TextEncoder();
|
|
3
4
|
const td = new TextDecoder();
|
|
4
|
-
//
|
|
5
|
-
export class
|
|
5
|
+
// JsonFramingError marks malformed or oversized frames.
|
|
6
|
+
export class JsonFramingError extends Error {
|
|
7
|
+
}
|
|
8
|
+
function normalizeWrite(write) {
|
|
9
|
+
return typeof write === "function" ? write : (b) => write.write(b);
|
|
10
|
+
}
|
|
11
|
+
function normalizeReadExactly(readExactly) {
|
|
12
|
+
return typeof readExactly === "function" ? readExactly : (n) => readExactly.readExactly(n);
|
|
6
13
|
}
|
|
7
14
|
// writeJsonFrame encodes a JSON payload with a 4-byte length prefix.
|
|
8
15
|
export async function writeJsonFrame(write, v) {
|
|
@@ -11,14 +18,15 @@ export async function writeJsonFrame(write, v) {
|
|
|
11
18
|
const out = new Uint8Array(4 + json.length);
|
|
12
19
|
out.set(hdr, 0);
|
|
13
20
|
out.set(json, 4);
|
|
14
|
-
await write(out);
|
|
21
|
+
await normalizeWrite(write)(out);
|
|
15
22
|
}
|
|
16
23
|
// readJsonFrame reads and parses a length-prefixed JSON payload.
|
|
17
24
|
export async function readJsonFrame(readExactly, maxBytes) {
|
|
18
|
-
const
|
|
25
|
+
const read = normalizeReadExactly(readExactly);
|
|
26
|
+
const hdr = await read(4);
|
|
19
27
|
const n = readU32be(hdr, 0);
|
|
20
28
|
if (maxBytes > 0 && n > maxBytes)
|
|
21
|
-
throw new
|
|
22
|
-
const payload = await
|
|
29
|
+
throw new JsonFramingError("frame too large");
|
|
30
|
+
const payload = await read(n);
|
|
23
31
|
return JSON.parse(td.decode(payload));
|
|
24
32
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from "./utils/base64url.js";
|
|
2
2
|
export * from "./utils/bin.js";
|
|
3
3
|
export * from "./utils/errors.js";
|
|
4
|
+
export * from "./framing/index.js";
|
|
5
|
+
export * from "./streamio/index.js";
|
|
4
6
|
export * from "./e2ee/constants.js";
|
|
5
7
|
export * from "./e2ee/framing.js";
|
|
6
8
|
export * from "./e2ee/transcript.js";
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export * from "./utils/base64url.js";
|
|
2
2
|
export * from "./utils/bin.js";
|
|
3
3
|
export * from "./utils/errors.js";
|
|
4
|
+
export * from "./framing/index.js";
|
|
5
|
+
export * from "./streamio/index.js";
|
|
4
6
|
export * from "./e2ee/constants.js";
|
|
5
7
|
export * from "./e2ee/framing.js";
|
|
6
8
|
export * from "./e2ee/transcript.js";
|
package/dist/rpc/client.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { normalizeObserver, nowSeconds } from "../observability/observer.js";
|
|
2
|
-
import { readJsonFrame, writeJsonFrame } from "
|
|
2
|
+
import { DEFAULT_MAX_JSON_FRAME_BYTES, readJsonFrame, writeJsonFrame } from "../framing/jsonframe.js";
|
|
3
3
|
import { assertRpcEnvelope } from "./validate.js";
|
|
4
4
|
// Guard against precision loss when encoding request IDs as numbers.
|
|
5
5
|
const MAX_SAFE_REQUEST_ID = BigInt(Number.MAX_SAFE_INTEGER);
|
|
@@ -108,7 +108,7 @@ export class RpcClient {
|
|
|
108
108
|
async readLoop() {
|
|
109
109
|
try {
|
|
110
110
|
while (!this.closed) {
|
|
111
|
-
const v = assertRpcEnvelope(await readJsonFrame(this.readExactly,
|
|
111
|
+
const v = assertRpcEnvelope(await readJsonFrame(this.readExactly, DEFAULT_MAX_JSON_FRAME_BYTES));
|
|
112
112
|
if (v.response_to === 0) {
|
|
113
113
|
// Notification: response_to=0 and request_id=0.
|
|
114
114
|
if (v.request_id === 0) {
|
package/dist/rpc/index.d.ts
CHANGED
package/dist/rpc/index.js
CHANGED
package/dist/rpc/server.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readJsonFrame, writeJsonFrame } from "
|
|
1
|
+
import { DEFAULT_MAX_JSON_FRAME_BYTES, readJsonFrame, writeJsonFrame } from "../framing/jsonframe.js";
|
|
2
2
|
import { assertRpcEnvelope } from "./validate.js";
|
|
3
3
|
// RpcServer dispatches request envelopes to registered handlers.
|
|
4
4
|
export class RpcServer {
|
|
@@ -21,7 +21,7 @@ export class RpcServer {
|
|
|
21
21
|
while (!this.closed) {
|
|
22
22
|
if (signal?.aborted)
|
|
23
23
|
throw signal.reason ?? new Error("aborted");
|
|
24
|
-
const v = assertRpcEnvelope(await readJsonFrame(this.readExactly,
|
|
24
|
+
const v = assertRpcEnvelope(await readJsonFrame(this.readExactly, DEFAULT_MAX_JSON_FRAME_BYTES));
|
|
25
25
|
if (v.response_to !== 0)
|
|
26
26
|
continue;
|
|
27
27
|
if (v.request_id === 0) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readJsonFrame, writeJsonFrame } from "../
|
|
1
|
+
import { readJsonFrame, writeJsonFrame } from "../framing/jsonframe.js";
|
|
2
2
|
// writeStreamHello sends the initial stream greeting.
|
|
3
3
|
export async function writeStreamHello(write, kind) {
|
|
4
4
|
const h = { kind, v: 1 };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ByteReader } from "../yamux/byteReader.js";
|
|
2
|
+
import type { YamuxStream } from "../yamux/stream.js";
|
|
3
|
+
export declare function readMaybe(stream: YamuxStream): Promise<Uint8Array | null>;
|
|
4
|
+
export declare function createByteReader(stream: YamuxStream, opts?: Readonly<{
|
|
5
|
+
signal?: AbortSignal;
|
|
6
|
+
}>): ByteReader;
|
|
7
|
+
export declare function readExactly(reader: ByteReader, n: number, opts?: Readonly<{
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
}>): Promise<Uint8Array>;
|
|
10
|
+
export type ReadNBytesOptions = Readonly<{
|
|
11
|
+
chunkSize?: number;
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
onProgress?: (read: number) => void;
|
|
14
|
+
}>;
|
|
15
|
+
export declare function readNBytes(reader: ByteReader, n: number, opts?: ReadNBytesOptions): Promise<Uint8Array>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { AbortError, throwIfAborted } from "../utils/errors.js";
|
|
2
|
+
import { ByteReader } from "../yamux/byteReader.js";
|
|
3
|
+
function abortReasonToError(signal) {
|
|
4
|
+
const r = signal.reason;
|
|
5
|
+
if (r instanceof Error)
|
|
6
|
+
return r;
|
|
7
|
+
if (typeof r === "string" && r !== "")
|
|
8
|
+
return new AbortError(r);
|
|
9
|
+
return new AbortError("aborted");
|
|
10
|
+
}
|
|
11
|
+
function bindAbortToStream(stream, signal) {
|
|
12
|
+
const onAbort = () => {
|
|
13
|
+
try {
|
|
14
|
+
stream.reset(abortReasonToError(signal));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Best-effort cancel.
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
if (signal.aborted) {
|
|
21
|
+
onAbort();
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
25
|
+
}
|
|
26
|
+
// readMaybe reads the next chunk or null on EOF.
|
|
27
|
+
export async function readMaybe(stream) {
|
|
28
|
+
return await stream.read();
|
|
29
|
+
}
|
|
30
|
+
// createByteReader adapts a YamuxStream to a ByteReader (EOF is handled by YamuxStream.read()).
|
|
31
|
+
export function createByteReader(stream, opts = {}) {
|
|
32
|
+
if (opts.signal != null)
|
|
33
|
+
bindAbortToStream(stream, opts.signal);
|
|
34
|
+
return new ByteReader(() => stream.read());
|
|
35
|
+
}
|
|
36
|
+
// readExactly reads n bytes (or throws on EOF/error). If signal aborts, the caller is expected to reset/close the stream.
|
|
37
|
+
export async function readExactly(reader, n, opts = {}) {
|
|
38
|
+
throwIfAborted(opts.signal, "read aborted");
|
|
39
|
+
return await reader.readExactly(n);
|
|
40
|
+
}
|
|
41
|
+
// readNBytes reads exactly n bytes and returns them as a single contiguous buffer.
|
|
42
|
+
export async function readNBytes(reader, n, opts = {}) {
|
|
43
|
+
const total = Math.max(0, Math.floor(n));
|
|
44
|
+
const out = new Uint8Array(total);
|
|
45
|
+
if (total === 0)
|
|
46
|
+
return out;
|
|
47
|
+
const chunkSize = Math.max(1, Math.floor(opts.chunkSize ?? 64 * 1024));
|
|
48
|
+
let off = 0;
|
|
49
|
+
while (off < total) {
|
|
50
|
+
throwIfAborted(opts.signal, "read aborted");
|
|
51
|
+
const take = Math.min(chunkSize, total - off);
|
|
52
|
+
const chunk = await reader.readExactly(take);
|
|
53
|
+
out.set(chunk, off);
|
|
54
|
+
off += chunk.length;
|
|
55
|
+
opts.onProgress?.(off);
|
|
56
|
+
}
|
|
57
|
+
return out;
|
|
58
|
+
}
|
package/dist/yamux/byteReader.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { StreamEOFError } from "./errors.js";
|
|
1
2
|
// ByteReader buffers incoming chunks and supports exact reads.
|
|
2
3
|
export class ByteReader {
|
|
3
4
|
readChunk;
|
|
@@ -15,7 +16,7 @@ export class ByteReader {
|
|
|
15
16
|
while (this.buffered < n) {
|
|
16
17
|
const chunk = await this.readChunk();
|
|
17
18
|
if (chunk == null)
|
|
18
|
-
throw new
|
|
19
|
+
throw new StreamEOFError();
|
|
19
20
|
if (chunk.length === 0)
|
|
20
21
|
continue;
|
|
21
22
|
this.chunks.push(chunk);
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// StreamEOFError marks end-of-stream for yamux reads.
|
|
2
|
+
export class StreamEOFError extends Error {
|
|
3
|
+
constructor(message = "eof") {
|
|
4
|
+
super(message);
|
|
5
|
+
this.name = "StreamEOFError";
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
export function isStreamEOFError(e) {
|
|
9
|
+
return e instanceof StreamEOFError;
|
|
10
|
+
}
|
package/dist/yamux/index.d.ts
CHANGED
package/dist/yamux/index.js
CHANGED
package/dist/yamux/stream.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare class YamuxStream {
|
|
|
15
15
|
open(): Promise<void>;
|
|
16
16
|
onData(data: Uint8Array, flags: number): void;
|
|
17
17
|
onWindowUpdate(delta: number, flags: number): void;
|
|
18
|
-
read(): Promise<Uint8Array>;
|
|
18
|
+
read(): Promise<Uint8Array | null>;
|
|
19
19
|
write(data: Uint8Array): Promise<void>;
|
|
20
20
|
close(): Promise<void>;
|
|
21
21
|
reset(err: Error): void;
|
package/dist/yamux/stream.js
CHANGED
|
@@ -54,7 +54,7 @@ export class YamuxStream {
|
|
|
54
54
|
this.sendWindow += delta >>> 0;
|
|
55
55
|
this.session.notifySendWindow(this.id);
|
|
56
56
|
}
|
|
57
|
-
// read resolves with the next data chunk or throws on
|
|
57
|
+
// read resolves with the next data chunk, null on EOF, or throws on reset/errors.
|
|
58
58
|
async read() {
|
|
59
59
|
while (true) {
|
|
60
60
|
if (this.error != null)
|
|
@@ -66,7 +66,7 @@ export class YamuxStream {
|
|
|
66
66
|
return b;
|
|
67
67
|
}
|
|
68
68
|
if (this.state === "closed" || this.state === "remoteClose")
|
|
69
|
-
|
|
69
|
+
return null;
|
|
70
70
|
await new Promise((resolve) => this.readWaiters.push(resolve));
|
|
71
71
|
}
|
|
72
72
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@floegence/flowersec-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Flowersec core TypeScript library (browser-friendly E2EE + multiplexing over WebSocket).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -36,6 +36,14 @@
|
|
|
36
36
|
"types": "./dist/browser/index.d.ts",
|
|
37
37
|
"default": "./dist/browser/index.js"
|
|
38
38
|
},
|
|
39
|
+
"./framing": {
|
|
40
|
+
"types": "./dist/framing/index.d.ts",
|
|
41
|
+
"default": "./dist/framing/index.js"
|
|
42
|
+
},
|
|
43
|
+
"./streamio": {
|
|
44
|
+
"types": "./dist/streamio/index.d.ts",
|
|
45
|
+
"default": "./dist/streamio/index.js"
|
|
46
|
+
},
|
|
39
47
|
"./rpc": {
|
|
40
48
|
"types": "./dist/rpc/index.d.ts",
|
|
41
49
|
"default": "./dist/rpc/index.js"
|
package/dist/rpc/framing.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
export declare class RpcFramingError extends Error {
|
|
2
|
-
}
|
|
3
|
-
export declare function writeJsonFrame(write: (b: Uint8Array) => Promise<void>, v: unknown): Promise<void>;
|
|
4
|
-
export declare function readJsonFrame(readExactly: (n: number) => Promise<Uint8Array>, maxBytes: number): Promise<unknown>;
|