@floegence/flowersec-core 0.3.2 → 0.4.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.
@@ -2,12 +2,40 @@ import { connectDirect } from "../direct-client/connect.js";
2
2
  import { connectTunnel } from "../tunnel-client/connect.js";
3
3
  import { connect } from "../facade.js";
4
4
  import { createNodeWsFactory } from "./wsFactory.js";
5
+ const defaultMaxHandshakePayload = 8 * 1024;
6
+ const defaultMaxRecordBytes = 1 << 20;
7
+ const handshakeFrameOverheadBytes = 4 + 1 + 1 + 4;
8
+ const wsMaxPayloadSlackBytes = 64;
9
+ function defaultWsMaxPayload(opts) {
10
+ const maxHandshakePayload = opts.maxHandshakePayload ?? 0;
11
+ const maxRecordBytes = opts.maxRecordBytes ?? 0;
12
+ const hp = Number.isSafeInteger(maxHandshakePayload) && maxHandshakePayload > 0 ? maxHandshakePayload : defaultMaxHandshakePayload;
13
+ const rb = Number.isSafeInteger(maxRecordBytes) && maxRecordBytes > 0 ? maxRecordBytes : defaultMaxRecordBytes;
14
+ const handshakeMax = Math.min(Number.MAX_SAFE_INTEGER, hp + handshakeFrameOverheadBytes);
15
+ const max = Math.max(rb, handshakeMax);
16
+ return Math.min(Number.MAX_SAFE_INTEGER, max + wsMaxPayloadSlackBytes);
17
+ }
5
18
  export async function connectNode(input, opts) {
6
- return await connect(input, { ...opts, wsFactory: opts.wsFactory ?? createNodeWsFactory() });
19
+ const wsFactory = opts.wsFactory ??
20
+ createNodeWsFactory({
21
+ maxPayload: defaultWsMaxPayload(opts),
22
+ perMessageDeflate: false,
23
+ });
24
+ return await connect(input, { ...opts, wsFactory });
7
25
  }
8
26
  export async function connectTunnelNode(grant, opts) {
9
- return await connectTunnel(grant, { ...opts, wsFactory: opts.wsFactory ?? createNodeWsFactory() });
27
+ const wsFactory = opts.wsFactory ??
28
+ createNodeWsFactory({
29
+ maxPayload: defaultWsMaxPayload(opts),
30
+ perMessageDeflate: false,
31
+ });
32
+ return await connectTunnel(grant, { ...opts, wsFactory });
10
33
  }
11
34
  export async function connectDirectNode(info, opts) {
12
- return await connectDirect(info, { ...opts, wsFactory: opts.wsFactory ?? createNodeWsFactory() });
35
+ const wsFactory = opts.wsFactory ??
36
+ createNodeWsFactory({
37
+ maxPayload: defaultWsMaxPayload(opts),
38
+ perMessageDeflate: false,
39
+ });
40
+ return await connectDirect(info, { ...opts, wsFactory });
13
41
  }
@@ -1,2 +1,6 @@
1
1
  import type { WebSocketLike } from "../ws-client/binaryTransport.js";
2
- export declare function createNodeWsFactory(): (url: string, origin: string) => WebSocketLike;
2
+ export type NodeWsFactoryOptions = Readonly<{
3
+ maxPayload?: number;
4
+ perMessageDeflate?: boolean;
5
+ }>;
6
+ export declare function createNodeWsFactory(opts?: NodeWsFactoryOptions): (url: string, origin: string) => WebSocketLike;
@@ -2,12 +2,21 @@ import { createRequire } from "node:module";
2
2
  // createNodeWsFactory returns a wsFactory compatible with connectTunnel/connectDirect in Node.js.
3
3
  //
4
4
  // It uses the "ws" package to set the Origin header explicitly (browsers set Origin automatically).
5
- export function createNodeWsFactory() {
5
+ export function createNodeWsFactory(opts = {}) {
6
6
  const require = createRequire(import.meta.url);
7
7
  const wsMod = require("ws");
8
8
  const WebSocketCtor = wsMod?.WebSocket ?? wsMod;
9
+ const maxPayload = opts.maxPayload;
10
+ if (maxPayload !== undefined && (!Number.isSafeInteger(maxPayload) || maxPayload <= 0)) {
11
+ throw new Error("maxPayload must be a positive integer");
12
+ }
13
+ const perMessageDeflate = opts.perMessageDeflate ?? false;
9
14
  return (url, origin) => {
10
- const raw = new WebSocketCtor(url, { headers: { Origin: origin } });
15
+ const raw = new WebSocketCtor(url, {
16
+ headers: { Origin: origin },
17
+ ...(maxPayload !== undefined ? { maxPayload } : {}),
18
+ perMessageDeflate,
19
+ });
11
20
  // Map (type -> user listener -> wrapped listener) so removeEventListener works.
12
21
  const listeners = new Map();
13
22
  const addEventListener = (type, listener) => {
@@ -6,7 +6,7 @@ export declare class AbortError extends Error {
6
6
  }
7
7
  export type FlowersecPath = "auto" | "tunnel" | "direct";
8
8
  export type FlowersecStage = "validate" | "connect" | "attach" | "handshake" | "secure" | "yamux" | "rpc" | "close";
9
- export type FlowersecErrorCode = "timeout" | "canceled" | "invalid_version" | "invalid_input" | "invalid_option" | "invalid_endpoint_instance_id" | "invalid_psk" | "invalid_suite" | "missing_grant" | "missing_connect_info" | "missing_conn" | "missing_handler" | "missing_stream_kind" | "role_mismatch" | "missing_tunnel_url" | "missing_ws_url" | "missing_origin" | "missing_channel_id" | "missing_token" | "missing_init_exp" | "timestamp_after_init_exp" | "timestamp_out_of_skew" | "auth_tag_mismatch" | "resolve_failed" | "random_failed" | "upgrade_failed" | "dial_failed" | "attach_failed" | "too_many_connections" | "expected_attach" | "invalid_attach" | "invalid_token" | "channel_mismatch" | "init_exp_mismatch" | "idle_timeout_mismatch" | "token_replay" | "replace_rate_limited" | "handshake_failed" | "ping_failed" | "mux_failed" | "accept_stream_failed" | "open_stream_failed" | "stream_hello_failed" | "not_connected";
9
+ export type FlowersecErrorCode = "timeout" | "canceled" | "invalid_version" | "invalid_input" | "invalid_option" | "invalid_endpoint_instance_id" | "invalid_psk" | "invalid_suite" | "missing_grant" | "missing_connect_info" | "missing_conn" | "missing_handler" | "missing_stream_kind" | "role_mismatch" | "missing_tunnel_url" | "missing_ws_url" | "missing_origin" | "missing_channel_id" | "missing_token" | "missing_init_exp" | "timestamp_after_init_exp" | "timestamp_out_of_skew" | "auth_tag_mismatch" | "resolve_failed" | "random_failed" | "upgrade_failed" | "dial_failed" | "attach_failed" | "too_many_connections" | "expected_attach" | "invalid_attach" | "invalid_token" | "channel_mismatch" | "init_exp_mismatch" | "idle_timeout_mismatch" | "token_replay" | "replace_rate_limited" | "handshake_failed" | "ping_failed" | "mux_failed" | "accept_stream_failed" | "open_stream_failed" | "stream_hello_failed" | "rpc_failed" | "not_connected";
10
10
  export declare class FlowersecError extends Error {
11
11
  readonly code: FlowersecErrorCode;
12
12
  readonly stage: FlowersecStage;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floegence/flowersec-core",
3
- "version": "0.3.2",
3
+ "version": "0.4.0",
4
4
  "description": "Flowersec core TypeScript library (browser-friendly E2EE + multiplexing over WebSocket).",
5
5
  "license": "MIT",
6
6
  "repository": {