heliumts 0.4.4 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,19 @@
1
+ import type { RpcStats } from "../runtime/protocol.js";
2
+ /**
3
+ * Custom error class for RPC failures.
4
+ *
5
+ * Thrown when a server-side method throws an error. This ensures that
6
+ * errors from the backend propagate as real `Error` instances on the
7
+ * frontend, so they surface in `try / catch`, React error boundaries,
8
+ * and developer tools.
9
+ *
10
+ * Properties:
11
+ * - `message` – the error message sent by the server.
12
+ * - `stats` – rate-limit / request stats returned alongside the error.
13
+ */
14
+ export declare class RpcError extends Error {
15
+ /** Rate-limit / request stats returned alongside the error. */
16
+ readonly stats: RpcStats | null;
17
+ constructor(message: string, stats?: RpcStats | null);
18
+ }
19
+ //# sourceMappingURL=RpcError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RpcError.d.ts","sourceRoot":"","sources":["../../src/client/RpcError.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEvD;;;;;;;;;;;GAWG;AACH,qBAAa,QAAS,SAAQ,KAAK;IAC/B,+DAA+D;IAC/D,SAAgB,KAAK,EAAE,QAAQ,GAAG,IAAI,CAAC;gBAE3B,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,QAAQ,GAAG,IAAI;CAKvD"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Custom error class for RPC failures.
3
+ *
4
+ * Thrown when a server-side method throws an error. This ensures that
5
+ * errors from the backend propagate as real `Error` instances on the
6
+ * frontend, so they surface in `try / catch`, React error boundaries,
7
+ * and developer tools.
8
+ *
9
+ * Properties:
10
+ * - `message` – the error message sent by the server.
11
+ * - `stats` – rate-limit / request stats returned alongside the error.
12
+ */
13
+ export class RpcError extends Error {
14
+ constructor(message, stats) {
15
+ super(message);
16
+ this.name = "RpcError";
17
+ this.stats = stats ?? null;
18
+ }
19
+ }
20
+ //# sourceMappingURL=RpcError.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RpcError.js","sourceRoot":"","sources":["../../src/client/RpcError.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;GAWG;AACH,MAAM,OAAO,QAAS,SAAQ,KAAK;IAI/B,YAAY,OAAe,EAAE,KAAuB;QAChD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,KAAK,GAAG,KAAK,IAAI,IAAI,CAAC;IAC/B,CAAC;CACJ","sourcesContent":["import type { RpcStats } from \"../runtime/protocol.js\";\n\n/**\n * Custom error class for RPC failures.\n *\n * Thrown when a server-side method throws an error. This ensures that\n * errors from the backend propagate as real `Error` instances on the\n * frontend, so they surface in `try / catch`, React error boundaries,\n * and developer tools.\n *\n * Properties:\n * - `message` – the error message sent by the server.\n * - `stats` – rate-limit / request stats returned alongside the error.\n */\nexport class RpcError extends Error {\n /** Rate-limit / request stats returned alongside the error. */\n public readonly stats: RpcStats | null;\n\n constructor(message: string, stats?: RpcStats | null) {\n super(message);\n this.name = \"RpcError\";\n this.stats = stats ?? null;\n }\n}\n"]}
@@ -4,6 +4,7 @@ export type { LayoutProps } from "./routerManifest.js";
4
4
  export type { PageTransitionProps } from "./transitions.js";
5
5
  export * from "./useCall.js";
6
6
  export * from "./useFetch.js";
7
+ export { RpcError } from "./RpcError.js";
7
8
  export type { RpcTransport } from "./rpcClient.js";
8
9
  export { getRpcTransport, isAutoHttpOnMobileEnabled, preconnect } from "./rpcClient.js";
9
10
  export * from "./types.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClF,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAG5D,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAG9B,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGxF,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AACA,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AACrF,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClF,YAAY,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIvD,YAAY,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAG5D,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAG9B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAGxF,cAAc,YAAY,CAAC"}
@@ -2,6 +2,8 @@ export { AppRouter, Link, Redirect, RouterContext, useRouter } from "./Router.js
2
2
  // RPC hooks for data fetching and mutations
3
3
  export * from "./useCall.js";
4
4
  export * from "./useFetch.js";
5
+ // RPC error type
6
+ export { RpcError } from "./RpcError.js";
5
7
  export { getRpcTransport, isAutoHttpOnMobileEnabled, preconnect } from "./rpcClient.js";
6
8
  // Type definitions
7
9
  export * from "./types.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAOlF,4CAA4C;AAC5C,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAI9B,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAExF,mBAAmB;AACnB,cAAc,YAAY,CAAC;AAE3B,yEAAyE","sourcesContent":["// Router components and hooks\nexport type { AppShellProps, LinkProps, RouterNavigationOptions } from \"./Router.js\";\nexport { AppRouter, Link, Redirect, RouterContext, useRouter } from \"./Router.js\";\nexport type { LayoutProps } from \"./routerManifest.js\";\n\n// React 18+ page transitions (separate module for better tree-shaking)\n// Import from \"heliumts/client/transitions\" to ensure they're only bundled when used\nexport type { PageTransitionProps } from \"./transitions.js\";\n\n// RPC hooks for data fetching and mutations\nexport * from \"./useCall.js\";\nexport * from \"./useFetch.js\";\n\n// RPC transport info (configured via helium.config.js)\nexport type { RpcTransport } from \"./rpcClient.js\";\nexport { getRpcTransport, isAutoHttpOnMobileEnabled, preconnect } from \"./rpcClient.js\";\n\n// Type definitions\nexport * from \"./types.js\";\n\n// Internal - rpcClient and cache are used by hooks, not exposed to users\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAOlF,4CAA4C;AAC5C,cAAc,cAAc,CAAC;AAC7B,cAAc,eAAe,CAAC;AAE9B,iBAAiB;AACjB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAIzC,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAExF,mBAAmB;AACnB,cAAc,YAAY,CAAC;AAE3B,yEAAyE","sourcesContent":["// Router components and hooks\nexport type { AppShellProps, LinkProps, RouterNavigationOptions } from \"./Router.js\";\nexport { AppRouter, Link, Redirect, RouterContext, useRouter } from \"./Router.js\";\nexport type { LayoutProps } from \"./routerManifest.js\";\n\n// React 18+ page transitions (separate module for better tree-shaking)\n// Import from \"heliumts/client/transitions\" to ensure they're only bundled when used\nexport type { PageTransitionProps } from \"./transitions.js\";\n\n// RPC hooks for data fetching and mutations\nexport * from \"./useCall.js\";\nexport * from \"./useFetch.js\";\n\n// RPC error type\nexport { RpcError } from \"./RpcError.js\";\n\n// RPC transport info (configured via helium.config.js)\nexport type { RpcTransport } from \"./rpcClient.js\";\nexport { getRpcTransport, isAutoHttpOnMobileEnabled, preconnect } from \"./rpcClient.js\";\n\n// Type definitions\nexport * from \"./types.js\";\n\n// Internal - rpcClient and cache are used by hooks, not exposed to users\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"rpcClient.d.ts","sourceRoot":"","sources":["../../src/client/rpcClient.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA2B,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAEhF,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACvB,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,QAAQ,CAAC;CACnB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;AAUzD;;GAEG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAE9C;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,OAAO,CAEnD;AA4XD;;;GAGG;AACH,wBAAsB,OAAO,CAAC,OAAO,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAY7H;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAYjC"}
1
+ {"version":3,"file":"rpcClient.d.ts","sourceRoot":"","sources":["../../src/client/rpcClient.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAA2B,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGhF,MAAM,MAAM,SAAS,CAAC,CAAC,IAAI;IACvB,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,EAAE,QAAQ,CAAC;CACnB,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,CAAC;AAUzD;;GAEG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAE9C;AAED;;GAEG;AACH,wBAAgB,yBAAyB,IAAI,OAAO,CAEnD;AA4XD;;;GAGG;AACH,wBAAsB,OAAO,CAAC,OAAO,GAAG,OAAO,EAAE,KAAK,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAY7H;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,IAAI,CAYjC"}
@@ -1,4 +1,5 @@
1
1
  import { decode as msgpackDecode, encode as msgpackEncode } from "@msgpack/msgpack";
2
+ import { RpcError } from "./RpcError.js";
2
3
  // Read build-time config with fallback defaults
3
4
  const configuredTransport = typeof __HELIUM_RPC_TRANSPORT__ !== "undefined" ? __HELIUM_RPC_TRANSPORT__ : "websocket";
4
5
  const configuredAutoHttpOnMobile = typeof __HELIUM_RPC_AUTO_HTTP_ON_MOBILE__ !== "undefined" ? __HELIUM_RPC_AUTO_HTTP_ON_MOBILE__ : false;
@@ -97,11 +98,11 @@ async function sendBatchHttp(batch) {
97
98
  item.resolve({ data: res.result, stats: res.stats });
98
99
  }
99
100
  else {
100
- item.reject({ error: res.error, stats: res.stats });
101
+ item.reject(new RpcError(res.error, res.stats));
101
102
  }
102
103
  }
103
104
  else {
104
- item.reject(new Error("No response for request"));
105
+ item.reject(new RpcError("No response for request"));
105
106
  }
106
107
  }
107
108
  }
@@ -210,7 +211,7 @@ async function createSocket() {
210
211
  entry.resolve({ data: res.result, stats: res.stats });
211
212
  }
212
213
  else {
213
- entry.reject({ error: res.error, stats: res.stats });
214
+ entry.reject(new RpcError(res.error, res.stats));
214
215
  }
215
216
  };
216
217
  if (Array.isArray(msg)) {
@@ -1 +1 @@
1
- {"version":3,"file":"rpcClient.js","sourceRoot":"","sources":["../../src/client/rpcClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAqBpF,gDAAgD;AAChD,MAAM,mBAAmB,GAAiB,OAAO,wBAAwB,KAAK,WAAW,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,WAAW,CAAC;AACnI,MAAM,0BAA0B,GAAY,OAAO,kCAAkC,KAAK,WAAW,CAAC,CAAC,CAAC,kCAAkC,CAAC,CAAC,CAAC,KAAK,CAAC;AAEnJ;;GAEG;AACH,MAAM,UAAU,eAAe;IAC3B,OAAO,mBAAmB,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB;IACrC,OAAO,0BAA0B,CAAC;AACtC,CAAC;AAED,mEAAmE;AACnE,SAAS,sBAAsB;IAC3B,IAAI,mBAAmB,KAAK,MAAM,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,IAAI,mBAAmB,KAAK,WAAW,EAAE,CAAC;QACtC,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,0DAA0D;IAC1D,IAAI,CAAC,0BAA0B,EAAE,CAAC;QAC9B,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,yCAAyC;IACzC,IAAI,OAAO,SAAS,KAAK,WAAW,EAAE,CAAC;QACnC,MAAM,IAAI,GAAI,SAAqC,CAAC,UAAU,CAAC;QAC/D,IAAI,IAAI,EAAE,CAAC;YACP,4DAA4D;YAC5D,MAAM,SAAS,GAAG,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAC1C,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC;gBAC7F,OAAO,IAAI,CAAC;YAChB,CAAC;QACL,CAAC;IACL,CAAC;IAED,OAAO,KAAK,CAAC;AACjB,CAAC;AAqBD,IAAI,YAAY,GAAqB,EAAE,CAAC;AACxC,IAAI,gBAAgB,GAAG,KAAK,CAAC;AAE7B,SAAS,aAAa;IAClB,IAAI,gBAAgB,EAAE,CAAC;QACnB,OAAO;IACX,CAAC;IACD,gBAAgB,GAAG,IAAI,CAAC;IACxB,cAAc,CAAC,GAAG,EAAE;QAChB,gBAAgB,GAAG,KAAK,CAAC;QACzB,UAAU,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;AACP,CAAC;AAED,KAAK,UAAU,UAAU;IACrB,MAAM,KAAK,GAAG,YAAY,CAAC;IAC3B,YAAY,GAAG,EAAE,CAAC;IAElB,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO;IACX,CAAC;IAED,IAAI,CAAC;QACD,IAAI,sBAAsB,EAAE,EAAE,CAAC;YAC3B,MAAM,aAAa,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;aAAM,CAAC;YACJ,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,4BAA4B;QAC5B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACvB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;IACL,CAAC;AACL,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,KAAuB;IAChD,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAExC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,iBAAiB,EAAE;QAC5C,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACL,cAAc,EAAE,qBAAqB;YACrC,MAAM,EAAE,qBAAqB;SAChC;QACD,IAAI,EAAE,OAA8B;KACvC,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,oBAAoB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,cAAc,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAC;IACpD,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,UAAU,CAAC,cAAc,CAAC,CAAgC,CAAC;IAEzF,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACnD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACvB,MAAM,GAAG,GAAG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACzC,IAAI,GAAG,EAAE,CAAC;YACN,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACT,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;YACzD,CAAC;iBAAM,CAAC;gBACJ,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;YACxD,CAAC;QACL,CAAC;aAAM,CAAC;YACJ,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC,CAAC;QACtD,CAAC;IACL,CAAC;AACL,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,KAAuB;IACrD,MAAM,EAAE,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACrC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAEzC,4BAA4B;IAC5B,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACnB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE;YACrB,OAAO,EAAE,CAAC,CAAU,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAmB,CAAC;YAC1D,MAAM,EAAE,IAAI,CAAC,MAAM;SACtB,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC;QACD,8BAA8B;QAC9B,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QACxC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACrB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACX,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACnB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC5B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC,CAAC,CAAC;IACP,CAAC;AACL,CAAC;AAED,+EAA+E;AAC/E,gDAAgD;AAChD,+EAA+E;AAE/E,IAAI,MAAM,GAAqB,IAAI,CAAC;AACpC,IAAI,iBAAiB,GAA8B,IAAI,CAAC;AAExD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAoF,CAAC;AAE5G,gEAAgE;AAChE,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;IAClB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE;QACzB,IAAI,MAAM,EAAE,CAAC;YACT,8BAA8B;YAC9B,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,IAAI,CAAC;YACd,iBAAiB,GAAG,IAAI,CAAC;QAC7B,CAAC;QACD,8BAA8B;QAC9B,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE;YACtB,KAAK,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,KAAK,EAAE,CAAC;IACpB,CAAC,CAAC,CAAC;AACP,CAAC;AAED,IAAI,KAAK,GAAG,CAAC,CAAC;AACd,SAAS,MAAM;IACX,OAAO,KAAK,EAAE,CAAC;AACnB,CAAC;AAED,KAAK,UAAU,eAAe;IAC1B,IAAI,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC1D,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,8BAA8B,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;YAC9D,OAAO,SAAS,CAAC;QACrB,CAAC;QACD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,OAAO,IAAI,CAAC,KAAK,CAAC;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;QACnD,OAAO,SAAS,CAAC;IACrB,CAAC;AACL,CAAC;AAED,KAAK,UAAU,YAAY;IACvB,+DAA+D;IAC/D,MAAM,KAAK,GAAG,MAAM,eAAe,EAAE,CAAC;IAEtC,+DAA+D;IAC/D,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IACxE,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,6BAA6B;IAChE,MAAM,GAAG,GAAG,GAAG,QAAQ,KAAK,IAAI,OAAO,KAAK,CAAC,CAAC,CAAC,UAAU,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACxE,MAAM,EAAE,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;IAC9B,EAAE,CAAC,UAAU,GAAG,aAAa,CAAC;IAE9B,EAAE,CAAC,SAAS,GAAG,KAAK,EAAE,KAAK,EAAE,EAAE;QAC3B,IAAI,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,IAAmB,CAAC,CAAC;QAErD,kEAAkE;QAClE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC1D,IAAI,CAAC;gBACD,gFAAgF;gBAChF,IAAI,OAAO,mBAAmB,KAAK,WAAW,EAAE,CAAC;oBAC7C,MAAM,EAAE,GAAG,IAAI,mBAAmB,CAAC,MAAM,CAAC,CAAC;oBAC3C,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;oBACvC,IAAI,MAAM,EAAE,CAAC;wBACT,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;wBAC5C,MAAM,MAAM,GAAG,MAAM,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC,WAAW,EAAE,CAAC;wBAC9D,IAAI,GAAG,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC;oBAClC,CAAC;gBACL,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,OAAO,CAAC,KAAK,CAAC,yCAAyC,EAAE,GAAG,CAAC,CAAC;gBAC9D,OAAO;YACX,CAAC;QACL,CAAC;QAED,mCAAmC;QACnC,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAgC,CAAC;QAE/D,MAAM,cAAc,GAAG,CAAC,GAAgB,EAAE,EAAE;YACxC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAClC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACT,OAAO;YACX,CAAC;YACD,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACvB,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC;gBACT,KAAK,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;YAC1D,CAAC;iBAAM,CAAC;gBACJ,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;YACzD,CAAC;QACL,CAAC,CAAC;QAEF,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAChC,CAAC;aAAM,CAAC;YACJ,cAAc,CAAC,GAAG,CAAC,CAAC;QACxB,CAAC;IACL,CAAC,CAAC;IAEF,EAAE,CAAC,OAAO,GAAG,GAAG,EAAE;QACd,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;YAChB,MAAM,GAAG,IAAI,CAAC;YACd,iBAAiB,GAAG,IAAI,CAAC;QAC7B,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,EAAE,CAAC;AACd,CAAC;AAED,KAAK,UAAU,iBAAiB;IAC5B,mDAAmD;IACnD,IAAI,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;QACjD,OAAO,MAAM,CAAC;IAClB,CAAC;IAED,0DAA0D;IAC1D,IAAI,iBAAiB,EAAE,CAAC;QACpB,OAAO,iBAAiB,CAAC;IAC7B,CAAC;IAED,qDAAqD;IACrD,IAAI,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,UAAU,EAAE,CAAC;QACvD,iBAAiB,GAAG,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAChD,MAAM,OAAO,GAAG,GAAG,EAAE;gBACjB,MAAO,CAAC,mBAAmB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;gBAChD,MAAO,CAAC,mBAAmB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;gBAClD,MAAO,CAAC,mBAAmB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YACtD,CAAC,CAAC;YACF,MAAM,UAAU,GAAG,GAAG,EAAE;gBACpB,OAAO,EAAE,CAAC;gBACV,iBAAiB,GAAG,IAAI,CAAC;gBACzB,OAAO,CAAC,MAAO,CAAC,CAAC;YACrB,CAAC,CAAC;YACF,MAAM,WAAW,GAAG,GAAG,EAAE;gBACrB,OAAO,EAAE,CAAC;gBACV,MAAM,GAAG,IAAI,CAAC;gBACd,iBAAiB,GAAG,IAAI,CAAC;gBACzB,MAAM,CAAC,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;YACrD,CAAC,CAAC;YACF,MAAM,WAAW,GAAG,GAAG,EAAE;gBACrB,OAAO,EAAE,CAAC;gBACV,MAAM,GAAG,IAAI,CAAC;gBACd,iBAAiB,GAAG,IAAI,CAAC;gBACzB,MAAM,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;YACzD,CAAC,CAAC;YAEF,MAAO,CAAC,gBAAgB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAC7C,MAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YAC/C,MAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QACH,OAAO,iBAAiB,CAAC;IAC7B,CAAC;IAED,6CAA6C;IAC7C,iBAAiB,GAAG,CAAC,KAAK,IAAI,EAAE;QAC5B,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;QAC9B,OAAO,IAAI,OAAO,CAAY,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC9C,MAAM,OAAO,GAAG,GAAG,EAAE;gBACjB,MAAO,CAAC,mBAAmB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;gBAChD,MAAO,CAAC,mBAAmB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;gBAClD,MAAO,CAAC,mBAAmB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YACtD,CAAC,CAAC;YACF,MAAM,UAAU,GAAG,GAAG,EAAE;gBACpB,OAAO,EAAE,CAAC;gBACV,iBAAiB,GAAG,IAAI,CAAC;gBACzB,OAAO,CAAC,MAAO,CAAC,CAAC;YACrB,CAAC,CAAC;YACF,MAAM,WAAW,GAAG,GAAG,EAAE;gBACrB,OAAO,EAAE,CAAC;gBACV,MAAM,GAAG,IAAI,CAAC;gBACd,iBAAiB,GAAG,IAAI,CAAC;gBACzB,MAAM,CAAC,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;YACrD,CAAC,CAAC;YACF,MAAM,WAAW,GAAG,GAAG,EAAE;gBACrB,OAAO,EAAE,CAAC;gBACV,MAAM,GAAG,IAAI,CAAC;gBACd,iBAAiB,GAAG,IAAI,CAAC;gBACzB,MAAM,CAAC,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;YACzD,CAAC,CAAC;YAEF,MAAO,CAAC,gBAAgB,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;YAC7C,MAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YAC/C,MAAO,CAAC,gBAAgB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,EAAE,CAAC;IAEL,OAAO,iBAAiB,CAAC;AAC7B,CAAC;AAED,KAAK,UAAU,gBAAgB,CAAiB,QAAgB,EAAE,IAAY;IAC1E,qHAAqH;IACrH,IAAI,MAAM,IAAI,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;QACjD,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;QACpB,MAAM,GAAG,GAAe,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QACvD,OAAO,IAAI,OAAO,CAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACvD,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE;gBACZ,OAAO,EAAE,CAAC,CAAU,EAAE,EAAE,CAAC,OAAO,CAAC,CAAuB,CAAC;gBACzD,MAAM;aACT,CAAC,CAAC;YACH,IAAI,CAAC;gBACD,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;gBACnC,MAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC1B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBACnB,MAAM,CAAC,GAAG,CAAC,CAAC;YAChB,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC;IAED,MAAM,EAAE,GAAG,MAAM,iBAAiB,EAAE,CAAC;IACrC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;IAEpB,MAAM,GAAG,GAAe,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAEvD,OAAO,IAAI,OAAO,CAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACvD,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE;YACZ,OAAO,EAAE,CAAC,CAAU,EAAE,EAAE,CAAC,OAAO,CAAC,CAAuB,CAAC;YACzD,MAAM;SACT,CAAC,CAAC;QACH,IAAI,CAAC;YACD,8BAA8B;YAC9B,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;YACnC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACrB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACnB,MAAM,CAAC,GAAG,CAAC,CAAC;QAChB,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAqC,QAAgB,EAAE,IAAY;IAC5F,IAAI,sBAAsB,EAAE,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC;QACpB,MAAM,GAAG,GAAe,EAAE,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QAEvD,OAAO,IAAI,OAAO,CAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACvD,YAAY,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,OAAc,EAAE,MAAM,EAAE,CAAC,CAAC;YAC5D,aAAa,EAAE,CAAC;QACpB,CAAC,CAAC,CAAC;IACP,CAAC;IAED,OAAO,gBAAgB,CAAiB,QAAQ,EAAE,IAAI,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU;IACtB,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAChC,OAAO;IACX,CAAC;IACD,qDAAqD;IACrD,IAAI,sBAAsB,EAAE,EAAE,CAAC;QAC3B,OAAO;IACX,CAAC;IACD,yDAAyD;IACzD,iBAAiB,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;QAC3B,iEAAiE;IACrE,CAAC,CAAC,CAAC;AACP,CAAC;AAED,iFAAiF;AACjF,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;IACnE,6DAA6D;IAC7D,MAAM,kBAAkB,GAAG,MAAM,CAAC,mBAAmB,IAAI,CAAC,CAAC,EAAc,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IACjG,kBAAkB,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC;AAC3C,CAAC","sourcesContent":["import { decode as msgpackDecode, encode as msgpackEncode } from \"@msgpack/msgpack\";\n\nimport type { RpcRequest, RpcResponse, RpcStats } from \"../runtime/protocol.js\";\n\nexport type RpcResult<T> = {\n data: T;\n stats: RpcStats;\n};\n\n/**\n * Transport mode for RPC calls.\n * - \"http\": Uses HTTP POST requests (faster on mobile/high-latency networks, benefits from HTTP/2)\n * - \"websocket\": Uses persistent WebSocket connection (lower latency on desktop/low-latency networks)\n * - \"auto\": Automatically selects based on connection type\n */\nexport type RpcTransport = \"http\" | \"websocket\" | \"auto\";\n\n// Build-time configuration injected by Vite plugin from helium.config.js\ndeclare const __HELIUM_RPC_TRANSPORT__: RpcTransport;\ndeclare const __HELIUM_RPC_AUTO_HTTP_ON_MOBILE__: boolean;\n\n// Read build-time config with fallback defaults\nconst configuredTransport: RpcTransport = typeof __HELIUM_RPC_TRANSPORT__ !== \"undefined\" ? __HELIUM_RPC_TRANSPORT__ : \"websocket\";\nconst configuredAutoHttpOnMobile: boolean = typeof __HELIUM_RPC_AUTO_HTTP_ON_MOBILE__ !== \"undefined\" ? __HELIUM_RPC_AUTO_HTTP_ON_MOBILE__ : false;\n\n/**\n * Get the configured RPC transport mode (from helium.config.js).\n */\nexport function getRpcTransport(): RpcTransport {\n return configuredTransport;\n}\n\n/**\n * Check if auto HTTP on mobile is enabled (from helium.config.js).\n */\nexport function isAutoHttpOnMobileEnabled(): boolean {\n return configuredAutoHttpOnMobile;\n}\n\n// Detect if we should prefer HTTP transport (mobile/slow networks)\nfunction shouldUseHttpTransport(): boolean {\n if (configuredTransport === \"http\") {\n return true;\n }\n if (configuredTransport === \"websocket\") {\n return false;\n }\n\n // Auto mode: check if mobile HTTP optimization is enabled\n if (!configuredAutoHttpOnMobile) {\n return false;\n }\n\n // Prefer HTTP on mobile/slow connections\n if (typeof navigator !== \"undefined\") {\n const conn = (navigator as NavigatorWithConnection).connection;\n if (conn) {\n // Use HTTP for cellular connections or slow effective types\n const slowTypes = [\"slow-2g\", \"2g\", \"3g\"];\n if (conn.type === \"cellular\" || (conn.effectiveType && slowTypes.includes(conn.effectiveType))) {\n return true;\n }\n }\n }\n\n return false;\n}\n\ninterface NetworkInformation {\n type?: string;\n effectiveType?: string;\n}\n\ninterface NavigatorWithConnection extends Navigator {\n connection?: NetworkInformation;\n}\n\n// ============================================================================\n// Batching Logic\n// ============================================================================\n\ntype PendingRequest = {\n req: RpcRequest;\n resolve: (value: RpcResult<any>) => void;\n reject: (reason?: any) => void;\n};\n\nlet pendingBatch: PendingRequest[] = [];\nlet isBatchScheduled = false;\n\nfunction scheduleBatch() {\n if (isBatchScheduled) {\n return;\n }\n isBatchScheduled = true;\n queueMicrotask(() => {\n isBatchScheduled = false;\n flushBatch();\n });\n}\n\nasync function flushBatch() {\n const batch = pendingBatch;\n pendingBatch = [];\n\n if (batch.length === 0) {\n return;\n }\n\n try {\n if (shouldUseHttpTransport()) {\n await sendBatchHttp(batch);\n } else {\n await sendBatchWebSocket(batch);\n }\n } catch (err) {\n // Transport error, fail all\n for (const item of batch) {\n item.reject(err);\n }\n }\n}\n\nasync function sendBatchHttp(batch: PendingRequest[]) {\n const requests = batch.map((b) => b.req);\n const encoded = msgpackEncode(requests);\n\n const response = await fetch(\"/__helium__/rpc\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/msgpack\",\n Accept: \"application/msgpack\",\n },\n body: encoded as unknown as BodyInit,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP RPC failed: ${response.status}`);\n }\n\n const responseBuffer = await response.arrayBuffer();\n const msg = msgpackDecode(new Uint8Array(responseBuffer)) as RpcResponse | RpcResponse[];\n\n const responses = Array.isArray(msg) ? msg : [msg];\n const responseMap = new Map(responses.map((r) => [r.id, r]));\n\n for (const item of batch) {\n const res = responseMap.get(item.req.id);\n if (res) {\n if (res.ok) {\n item.resolve({ data: res.result, stats: res.stats });\n } else {\n item.reject({ error: res.error, stats: res.stats });\n }\n } else {\n item.reject(new Error(\"No response for request\"));\n }\n }\n}\n\nasync function sendBatchWebSocket(batch: PendingRequest[]) {\n const ws = await ensureSocketReady();\n const requests = batch.map((b) => b.req);\n\n // Register pending promises\n batch.forEach((item) => {\n pending.set(item.req.id, {\n resolve: (v: unknown) => item.resolve(v as RpcResult<any>),\n reject: item.reject,\n });\n });\n\n try {\n // Always use msgpack encoding\n const encoded = msgpackEncode(requests);\n ws.send(encoded);\n } catch (err) {\n batch.forEach((item) => {\n pending.delete(item.req.id);\n item.reject(err);\n });\n }\n}\n\n// ============================================================================\n// WebSocket Transport (original implementation)\n// ============================================================================\n\nlet socket: WebSocket | null = null;\nlet connectionPromise: Promise<WebSocket> | null = null;\n\nconst pending = new Map<string | number, { resolve: (v: unknown) => void; reject: (e: unknown) => void }>();\n\n// Clean up WebSocket connection on HMR (Hot Module Replacement)\nif (import.meta.hot) {\n import.meta.hot.dispose(() => {\n if (socket) {\n // Close the socket gracefully\n socket.close();\n socket = null;\n connectionPromise = null;\n }\n // Reject all pending requests\n pending.forEach((entry) => {\n entry.reject(new Error(\"Module reloaded\"));\n });\n pending.clear();\n });\n}\n\nlet msgId = 0;\nfunction nextId() {\n return msgId++;\n}\n\nasync function fetchFreshToken(): Promise<string | undefined> {\n try {\n const response = await fetch(\"/__helium__/refresh-token\");\n if (!response.ok) {\n console.warn(\"Failed to fetch fresh token:\", response.status);\n return undefined;\n }\n const data = await response.json();\n return data.token;\n } catch (error) {\n console.warn(\"Error fetching fresh token:\", error);\n return undefined;\n }\n}\n\nasync function createSocket(): Promise<WebSocket> {\n // Fetch a fresh token before creating the WebSocket connection\n const token = await fetchFreshToken();\n\n // Use the same protocol, hostname and port as the current page\n const protocol = window.location.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n const host = window.location.host; // includes hostname and port\n const url = `${protocol}//${host}/rpc${token ? `?token=${token}` : \"\"}`;\n const ws = new WebSocket(url);\n ws.binaryType = \"arraybuffer\";\n\n ws.onmessage = async (event) => {\n let data = new Uint8Array(event.data as ArrayBuffer);\n\n // Check for Gzip header (0x1f 0x8b) to detect compressed messages\n if (data.length > 2 && data[0] === 0x1f && data[1] === 0x8b) {\n try {\n // Use DecompressionStream if available (Chrome 80+, Firefox 113+, Safari 16.4+)\n if (typeof DecompressionStream !== \"undefined\") {\n const ds = new DecompressionStream(\"gzip\");\n const stream = new Response(data).body;\n if (stream) {\n const decompressed = stream.pipeThrough(ds);\n const buffer = await new Response(decompressed).arrayBuffer();\n data = new Uint8Array(buffer);\n }\n }\n } catch (err) {\n console.error(\"Failed to decompress WebSocket message:\", err);\n return;\n }\n }\n\n // Always expect binary MessagePack\n const msg = msgpackDecode(data) as RpcResponse | RpcResponse[];\n\n const handleResponse = (res: RpcResponse) => {\n const entry = pending.get(res.id);\n if (!entry) {\n return;\n }\n pending.delete(res.id);\n if (res.ok) {\n entry.resolve({ data: res.result, stats: res.stats });\n } else {\n entry.reject({ error: res.error, stats: res.stats });\n }\n };\n\n if (Array.isArray(msg)) {\n msg.forEach(handleResponse);\n } else {\n handleResponse(msg);\n }\n };\n\n ws.onclose = () => {\n if (socket === ws) {\n socket = null;\n connectionPromise = null;\n }\n };\n\n return ws;\n}\n\nasync function ensureSocketReady(): Promise<WebSocket> {\n // If we have an open socket, return it immediately\n if (socket && socket.readyState === WebSocket.OPEN) {\n return socket;\n }\n\n // If we have a connection in progress, reuse that promise\n if (connectionPromise) {\n return connectionPromise;\n }\n\n // If we have a socket that's connecting, wait for it\n if (socket && socket.readyState === WebSocket.CONNECTING) {\n connectionPromise = new Promise((resolve, reject) => {\n const cleanup = () => {\n socket!.removeEventListener(\"open\", handleOpen);\n socket!.removeEventListener(\"error\", handleError);\n socket!.removeEventListener(\"close\", handleClose);\n };\n const handleOpen = () => {\n cleanup();\n connectionPromise = null;\n resolve(socket!);\n };\n const handleError = () => {\n cleanup();\n socket = null;\n connectionPromise = null;\n reject(new Error(\"WebSocket connection failed\"));\n };\n const handleClose = () => {\n cleanup();\n socket = null;\n connectionPromise = null;\n reject(new Error(\"WebSocket closed before opening\"));\n };\n\n socket!.addEventListener(\"open\", handleOpen);\n socket!.addEventListener(\"error\", handleError);\n socket!.addEventListener(\"close\", handleClose);\n });\n return connectionPromise;\n }\n\n // Create a new socket and connection promise\n connectionPromise = (async () => {\n socket = await createSocket();\n return new Promise<WebSocket>((resolve, reject) => {\n const cleanup = () => {\n socket!.removeEventListener(\"open\", handleOpen);\n socket!.removeEventListener(\"error\", handleError);\n socket!.removeEventListener(\"close\", handleClose);\n };\n const handleOpen = () => {\n cleanup();\n connectionPromise = null;\n resolve(socket!);\n };\n const handleError = () => {\n cleanup();\n socket = null;\n connectionPromise = null;\n reject(new Error(\"WebSocket connection failed\"));\n };\n const handleClose = () => {\n cleanup();\n socket = null;\n connectionPromise = null;\n reject(new Error(\"WebSocket closed before opening\"));\n };\n\n socket!.addEventListener(\"open\", handleOpen);\n socket!.addEventListener(\"error\", handleError);\n socket!.addEventListener(\"close\", handleClose);\n });\n })();\n\n return connectionPromise;\n}\n\nasync function rpcCallWebSocket<TResult, TArgs>(methodId: string, args?: TArgs): Promise<RpcResult<TResult>> {\n // Optimization: If socket is open, send immediately without awaiting ensureSocketReady (which adds a microtask tick)\n if (socket && socket.readyState === WebSocket.OPEN) {\n const id = nextId();\n const req: RpcRequest = { id, method: methodId, args };\n return new Promise<RpcResult<TResult>>((resolve, reject) => {\n pending.set(id, {\n resolve: (v: unknown) => resolve(v as RpcResult<TResult>),\n reject,\n });\n try {\n const encoded = msgpackEncode(req);\n socket!.send(encoded);\n } catch (err) {\n pending.delete(id);\n reject(err);\n }\n });\n }\n\n const ws = await ensureSocketReady();\n const id = nextId();\n\n const req: RpcRequest = { id, method: methodId, args };\n\n return new Promise<RpcResult<TResult>>((resolve, reject) => {\n pending.set(id, {\n resolve: (v: unknown) => resolve(v as RpcResult<TResult>),\n reject,\n });\n try {\n // Always use msgpack encoding\n const encoded = msgpackEncode(req);\n ws.send(encoded);\n } catch (err) {\n pending.delete(id);\n reject(err);\n }\n });\n}\n\n/**\n * Make an RPC call using the appropriate transport.\n * Automatically selects HTTP or WebSocket based on network conditions and configuration.\n */\nexport async function rpcCall<TResult = unknown, TArgs = unknown>(methodId: string, args?: TArgs): Promise<RpcResult<TResult>> {\n if (shouldUseHttpTransport()) {\n const id = nextId();\n const req: RpcRequest = { id, method: methodId, args };\n\n return new Promise<RpcResult<TResult>>((resolve, reject) => {\n pendingBatch.push({ req, resolve: resolve as any, reject });\n scheduleBatch();\n });\n }\n\n return rpcCallWebSocket<TResult, TArgs>(methodId, args);\n}\n\n/**\n * Pre-establishes the WebSocket connection.\n * Call this early (e.g., on page load) to avoid connection latency on first RPC call.\n * This is especially beneficial on high-latency networks like mobile LTE.\n * Note: Only effective when using WebSocket transport (not HTTP transport).\n */\nexport function preconnect(): void {\n if (typeof window === \"undefined\") {\n return;\n }\n // Only preconnect if we're using WebSocket transport\n if (shouldUseHttpTransport()) {\n return;\n }\n // Fire and forget - establishes connection in background\n ensureSocketReady().catch(() => {\n // Silently ignore preconnect failures, will retry on actual call\n });\n}\n\n// Auto-preconnect when the module loads (browser only, WebSocket transport only)\nif (typeof window !== \"undefined\" && typeof document !== \"undefined\") {\n // Use requestIdleCallback if available, otherwise setTimeout\n const schedulePreconnect = window.requestIdleCallback || ((cb: () => void) => setTimeout(cb, 1));\n schedulePreconnect(() => preconnect());\n}\n"]}
1
+ {"version":3,"file":"rpcClient.js","sourceRoot":"","sources":["../../src/client/rpcClient.ts"],"names":[],"mappings":"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","sourcesContent":["import { decode as msgpackDecode, encode as msgpackEncode } from \"@msgpack/msgpack\";\n\nimport type { RpcRequest, RpcResponse, RpcStats } from \"../runtime/protocol.js\";\nimport { RpcError } from \"./RpcError.js\";\n\nexport type RpcResult<T> = {\n data: T;\n stats: RpcStats;\n};\n\n/**\n * Transport mode for RPC calls.\n * - \"http\": Uses HTTP POST requests (faster on mobile/high-latency networks, benefits from HTTP/2)\n * - \"websocket\": Uses persistent WebSocket connection (lower latency on desktop/low-latency networks)\n * - \"auto\": Automatically selects based on connection type\n */\nexport type RpcTransport = \"http\" | \"websocket\" | \"auto\";\n\n// Build-time configuration injected by Vite plugin from helium.config.js\ndeclare const __HELIUM_RPC_TRANSPORT__: RpcTransport;\ndeclare const __HELIUM_RPC_AUTO_HTTP_ON_MOBILE__: boolean;\n\n// Read build-time config with fallback defaults\nconst configuredTransport: RpcTransport = typeof __HELIUM_RPC_TRANSPORT__ !== \"undefined\" ? __HELIUM_RPC_TRANSPORT__ : \"websocket\";\nconst configuredAutoHttpOnMobile: boolean = typeof __HELIUM_RPC_AUTO_HTTP_ON_MOBILE__ !== \"undefined\" ? __HELIUM_RPC_AUTO_HTTP_ON_MOBILE__ : false;\n\n/**\n * Get the configured RPC transport mode (from helium.config.js).\n */\nexport function getRpcTransport(): RpcTransport {\n return configuredTransport;\n}\n\n/**\n * Check if auto HTTP on mobile is enabled (from helium.config.js).\n */\nexport function isAutoHttpOnMobileEnabled(): boolean {\n return configuredAutoHttpOnMobile;\n}\n\n// Detect if we should prefer HTTP transport (mobile/slow networks)\nfunction shouldUseHttpTransport(): boolean {\n if (configuredTransport === \"http\") {\n return true;\n }\n if (configuredTransport === \"websocket\") {\n return false;\n }\n\n // Auto mode: check if mobile HTTP optimization is enabled\n if (!configuredAutoHttpOnMobile) {\n return false;\n }\n\n // Prefer HTTP on mobile/slow connections\n if (typeof navigator !== \"undefined\") {\n const conn = (navigator as NavigatorWithConnection).connection;\n if (conn) {\n // Use HTTP for cellular connections or slow effective types\n const slowTypes = [\"slow-2g\", \"2g\", \"3g\"];\n if (conn.type === \"cellular\" || (conn.effectiveType && slowTypes.includes(conn.effectiveType))) {\n return true;\n }\n }\n }\n\n return false;\n}\n\ninterface NetworkInformation {\n type?: string;\n effectiveType?: string;\n}\n\ninterface NavigatorWithConnection extends Navigator {\n connection?: NetworkInformation;\n}\n\n// ============================================================================\n// Batching Logic\n// ============================================================================\n\ntype PendingRequest = {\n req: RpcRequest;\n resolve: (value: RpcResult<any>) => void;\n reject: (reason?: any) => void;\n};\n\nlet pendingBatch: PendingRequest[] = [];\nlet isBatchScheduled = false;\n\nfunction scheduleBatch() {\n if (isBatchScheduled) {\n return;\n }\n isBatchScheduled = true;\n queueMicrotask(() => {\n isBatchScheduled = false;\n flushBatch();\n });\n}\n\nasync function flushBatch() {\n const batch = pendingBatch;\n pendingBatch = [];\n\n if (batch.length === 0) {\n return;\n }\n\n try {\n if (shouldUseHttpTransport()) {\n await sendBatchHttp(batch);\n } else {\n await sendBatchWebSocket(batch);\n }\n } catch (err) {\n // Transport error, fail all\n for (const item of batch) {\n item.reject(err);\n }\n }\n}\n\nasync function sendBatchHttp(batch: PendingRequest[]) {\n const requests = batch.map((b) => b.req);\n const encoded = msgpackEncode(requests);\n\n const response = await fetch(\"/__helium__/rpc\", {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/msgpack\",\n Accept: \"application/msgpack\",\n },\n body: encoded as unknown as BodyInit,\n });\n\n if (!response.ok) {\n throw new Error(`HTTP RPC failed: ${response.status}`);\n }\n\n const responseBuffer = await response.arrayBuffer();\n const msg = msgpackDecode(new Uint8Array(responseBuffer)) as RpcResponse | RpcResponse[];\n\n const responses = Array.isArray(msg) ? msg : [msg];\n const responseMap = new Map(responses.map((r) => [r.id, r]));\n\n for (const item of batch) {\n const res = responseMap.get(item.req.id);\n if (res) {\n if (res.ok) {\n item.resolve({ data: res.result, stats: res.stats });\n } else {\n item.reject(new RpcError(res.error, res.stats));\n }\n } else {\n item.reject(new RpcError(\"No response for request\"));\n }\n }\n}\n\nasync function sendBatchWebSocket(batch: PendingRequest[]) {\n const ws = await ensureSocketReady();\n const requests = batch.map((b) => b.req);\n\n // Register pending promises\n batch.forEach((item) => {\n pending.set(item.req.id, {\n resolve: (v: unknown) => item.resolve(v as RpcResult<any>),\n reject: item.reject,\n });\n });\n\n try {\n // Always use msgpack encoding\n const encoded = msgpackEncode(requests);\n ws.send(encoded);\n } catch (err) {\n batch.forEach((item) => {\n pending.delete(item.req.id);\n item.reject(err);\n });\n }\n}\n\n// ============================================================================\n// WebSocket Transport (original implementation)\n// ============================================================================\n\nlet socket: WebSocket | null = null;\nlet connectionPromise: Promise<WebSocket> | null = null;\n\nconst pending = new Map<string | number, { resolve: (v: unknown) => void; reject: (e: unknown) => void }>();\n\n// Clean up WebSocket connection on HMR (Hot Module Replacement)\nif (import.meta.hot) {\n import.meta.hot.dispose(() => {\n if (socket) {\n // Close the socket gracefully\n socket.close();\n socket = null;\n connectionPromise = null;\n }\n // Reject all pending requests\n pending.forEach((entry) => {\n entry.reject(new Error(\"Module reloaded\"));\n });\n pending.clear();\n });\n}\n\nlet msgId = 0;\nfunction nextId() {\n return msgId++;\n}\n\nasync function fetchFreshToken(): Promise<string | undefined> {\n try {\n const response = await fetch(\"/__helium__/refresh-token\");\n if (!response.ok) {\n console.warn(\"Failed to fetch fresh token:\", response.status);\n return undefined;\n }\n const data = await response.json();\n return data.token;\n } catch (error) {\n console.warn(\"Error fetching fresh token:\", error);\n return undefined;\n }\n}\n\nasync function createSocket(): Promise<WebSocket> {\n // Fetch a fresh token before creating the WebSocket connection\n const token = await fetchFreshToken();\n\n // Use the same protocol, hostname and port as the current page\n const protocol = window.location.protocol === \"https:\" ? \"wss:\" : \"ws:\";\n const host = window.location.host; // includes hostname and port\n const url = `${protocol}//${host}/rpc${token ? `?token=${token}` : \"\"}`;\n const ws = new WebSocket(url);\n ws.binaryType = \"arraybuffer\";\n\n ws.onmessage = async (event) => {\n let data = new Uint8Array(event.data as ArrayBuffer);\n\n // Check for Gzip header (0x1f 0x8b) to detect compressed messages\n if (data.length > 2 && data[0] === 0x1f && data[1] === 0x8b) {\n try {\n // Use DecompressionStream if available (Chrome 80+, Firefox 113+, Safari 16.4+)\n if (typeof DecompressionStream !== \"undefined\") {\n const ds = new DecompressionStream(\"gzip\");\n const stream = new Response(data).body;\n if (stream) {\n const decompressed = stream.pipeThrough(ds);\n const buffer = await new Response(decompressed).arrayBuffer();\n data = new Uint8Array(buffer);\n }\n }\n } catch (err) {\n console.error(\"Failed to decompress WebSocket message:\", err);\n return;\n }\n }\n\n // Always expect binary MessagePack\n const msg = msgpackDecode(data) as RpcResponse | RpcResponse[];\n\n const handleResponse = (res: RpcResponse) => {\n const entry = pending.get(res.id);\n if (!entry) {\n return;\n }\n pending.delete(res.id);\n if (res.ok) {\n entry.resolve({ data: res.result, stats: res.stats });\n } else {\n entry.reject(new RpcError(res.error, res.stats));\n }\n };\n\n if (Array.isArray(msg)) {\n msg.forEach(handleResponse);\n } else {\n handleResponse(msg);\n }\n };\n\n ws.onclose = () => {\n if (socket === ws) {\n socket = null;\n connectionPromise = null;\n }\n };\n\n return ws;\n}\n\nasync function ensureSocketReady(): Promise<WebSocket> {\n // If we have an open socket, return it immediately\n if (socket && socket.readyState === WebSocket.OPEN) {\n return socket;\n }\n\n // If we have a connection in progress, reuse that promise\n if (connectionPromise) {\n return connectionPromise;\n }\n\n // If we have a socket that's connecting, wait for it\n if (socket && socket.readyState === WebSocket.CONNECTING) {\n connectionPromise = new Promise((resolve, reject) => {\n const cleanup = () => {\n socket!.removeEventListener(\"open\", handleOpen);\n socket!.removeEventListener(\"error\", handleError);\n socket!.removeEventListener(\"close\", handleClose);\n };\n const handleOpen = () => {\n cleanup();\n connectionPromise = null;\n resolve(socket!);\n };\n const handleError = () => {\n cleanup();\n socket = null;\n connectionPromise = null;\n reject(new Error(\"WebSocket connection failed\"));\n };\n const handleClose = () => {\n cleanup();\n socket = null;\n connectionPromise = null;\n reject(new Error(\"WebSocket closed before opening\"));\n };\n\n socket!.addEventListener(\"open\", handleOpen);\n socket!.addEventListener(\"error\", handleError);\n socket!.addEventListener(\"close\", handleClose);\n });\n return connectionPromise;\n }\n\n // Create a new socket and connection promise\n connectionPromise = (async () => {\n socket = await createSocket();\n return new Promise<WebSocket>((resolve, reject) => {\n const cleanup = () => {\n socket!.removeEventListener(\"open\", handleOpen);\n socket!.removeEventListener(\"error\", handleError);\n socket!.removeEventListener(\"close\", handleClose);\n };\n const handleOpen = () => {\n cleanup();\n connectionPromise = null;\n resolve(socket!);\n };\n const handleError = () => {\n cleanup();\n socket = null;\n connectionPromise = null;\n reject(new Error(\"WebSocket connection failed\"));\n };\n const handleClose = () => {\n cleanup();\n socket = null;\n connectionPromise = null;\n reject(new Error(\"WebSocket closed before opening\"));\n };\n\n socket!.addEventListener(\"open\", handleOpen);\n socket!.addEventListener(\"error\", handleError);\n socket!.addEventListener(\"close\", handleClose);\n });\n })();\n\n return connectionPromise;\n}\n\nasync function rpcCallWebSocket<TResult, TArgs>(methodId: string, args?: TArgs): Promise<RpcResult<TResult>> {\n // Optimization: If socket is open, send immediately without awaiting ensureSocketReady (which adds a microtask tick)\n if (socket && socket.readyState === WebSocket.OPEN) {\n const id = nextId();\n const req: RpcRequest = { id, method: methodId, args };\n return new Promise<RpcResult<TResult>>((resolve, reject) => {\n pending.set(id, {\n resolve: (v: unknown) => resolve(v as RpcResult<TResult>),\n reject,\n });\n try {\n const encoded = msgpackEncode(req);\n socket!.send(encoded);\n } catch (err) {\n pending.delete(id);\n reject(err);\n }\n });\n }\n\n const ws = await ensureSocketReady();\n const id = nextId();\n\n const req: RpcRequest = { id, method: methodId, args };\n\n return new Promise<RpcResult<TResult>>((resolve, reject) => {\n pending.set(id, {\n resolve: (v: unknown) => resolve(v as RpcResult<TResult>),\n reject,\n });\n try {\n // Always use msgpack encoding\n const encoded = msgpackEncode(req);\n ws.send(encoded);\n } catch (err) {\n pending.delete(id);\n reject(err);\n }\n });\n}\n\n/**\n * Make an RPC call using the appropriate transport.\n * Automatically selects HTTP or WebSocket based on network conditions and configuration.\n */\nexport async function rpcCall<TResult = unknown, TArgs = unknown>(methodId: string, args?: TArgs): Promise<RpcResult<TResult>> {\n if (shouldUseHttpTransport()) {\n const id = nextId();\n const req: RpcRequest = { id, method: methodId, args };\n\n return new Promise<RpcResult<TResult>>((resolve, reject) => {\n pendingBatch.push({ req, resolve: resolve as any, reject });\n scheduleBatch();\n });\n }\n\n return rpcCallWebSocket<TResult, TArgs>(methodId, args);\n}\n\n/**\n * Pre-establishes the WebSocket connection.\n * Call this early (e.g., on page load) to avoid connection latency on first RPC call.\n * This is especially beneficial on high-latency networks like mobile LTE.\n * Note: Only effective when using WebSocket transport (not HTTP transport).\n */\nexport function preconnect(): void {\n if (typeof window === \"undefined\") {\n return;\n }\n // Only preconnect if we're using WebSocket transport\n if (shouldUseHttpTransport()) {\n return;\n }\n // Fire and forget - establishes connection in background\n ensureSocketReady().catch(() => {\n // Silently ignore preconnect failures, will retry on actual call\n });\n}\n\n// Auto-preconnect when the module loads (browser only, WebSocket transport only)\nif (typeof window !== \"undefined\" && typeof document !== \"undefined\") {\n // Use requestIdleCallback if available, otherwise setTimeout\n const schedulePreconnect = window.requestIdleCallback || ((cb: () => void) => setTimeout(cb, 1));\n schedulePreconnect(() => preconnect());\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"useCall.d.ts","sourceRoot":"","sources":["../../src/client/useCall.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;GAMG;AACH,KAAK,cAAc,GAAG;IAClB,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CACzC,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO,GAAE,cAAmB;;iBAe9D,KAAK,KAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;;;;EAqB7E"}
1
+ {"version":3,"file":"useCall.d.ts","sourceRoot":"","sources":["../../src/client/useCall.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAIvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;GAMG;AACH,KAAK,cAAc,GAAG;IAClB,UAAU,CAAC,EAAE,UAAU,EAAE,CAAC;IAC1B,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,IAAI,CAAC;CACzC,CAAC;AAEF;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,OAAO,GAAE,cAAmB;;iBAe9D,KAAK,KAAG,OAAO,CAAC,OAAO,GAAG,SAAS,CAAC;;;;EAqB7E"}
@@ -1,5 +1,6 @@
1
1
  import { useCallback, useRef, useState } from "react";
2
2
  import { invalidateByMethod } from "./cache.js";
3
+ import { RpcError } from "./RpcError.js";
3
4
  import { rpcCall } from "./rpcClient.js";
4
5
  /**
5
6
  * React hook for imperative RPC calls (commonly used for mutations).
@@ -34,10 +35,10 @@ export function useCall(method, options = {}) {
34
35
  return result.data;
35
36
  }
36
37
  catch (err) {
37
- const errorObj = err;
38
- setError(errorObj.error ?? "Unknown error");
39
- setStats(errorObj.stats ?? null);
40
- return undefined;
38
+ const rpcError = err instanceof RpcError ? err : new RpcError(err instanceof Error ? err.message : "Unknown error");
39
+ setError(rpcError.message);
40
+ setStats(rpcError.stats);
41
+ throw rpcError;
41
42
  }
42
43
  finally {
43
44
  setCalling(false);
@@ -1 +1 @@
1
- {"version":3,"file":"useCall.js","sourceRoot":"","sources":["../../src/client/useCall.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAezC;;;;;;;;GAQG;AACH,MAAM,UAAU,OAAO,CAAiB,MAAkC,EAAE,UAA0B,EAAE;IACpG,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAsB,SAAS,CAAC,CAAC;IACjE,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAkB,IAAI,CAAC,CAAC;IAE1D,sEAAsE;IACtE,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAEnC,6BAA6B;IAC7B,WAAW,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC;IAClC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAE7B,2DAA2D;IAC3D,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,IAAW,EAAgC,EAAE;QACzE,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAiB,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACxE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACrB,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvB,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAC1E,UAAU,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC5C,OAAO,MAAM,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACpB,MAAM,QAAQ,GAAG,GAA2C,CAAC;YAC7D,QAAQ,CAAC,QAAQ,CAAC,KAAK,IAAI,eAAe,CAAC,CAAC;YAC5C,QAAQ,CAAC,QAAQ,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;YACjC,OAAO,SAAS,CAAC;QACrB,CAAC;gBAAS,CAAC;YACP,UAAU,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,2CAA2C;IAEnD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AACnD,CAAC","sourcesContent":["import { useCallback, useRef, useState } from \"react\";\n\nimport type { RpcStats } from \"../runtime/protocol.js\";\nimport { invalidateByMethod } from \"./cache.js\";\nimport { rpcCall } from \"./rpcClient.js\";\nimport type { MethodStub } from \"./types.js\";\n\n/**\n * Options passed to `useCall`.\n *\n * - invalidate: array of MethodStubs whose cache entries will be invalidated\n * when this call completes successfully (useful to refresh related reads).\n * - onSuccess: optional callback that receives the result on success.\n */\ntype UseCallOptions = {\n invalidate?: MethodStub[];\n onSuccess?: (result: unknown) => void;\n};\n\n/**\n * React hook for imperative RPC calls (commonly used for mutations).\n *\n * @template TArgs - argument type for the method\n * @template TResult - expected result type\n * @param method - MethodStub identifying the server method to call\n * @param options - UseCallOptions to control invalidation / callbacks\n * @returns { data, call, isCalling, error, stats } where `call(args)` triggers the RPC and returns the result\n */\nexport function useCall<TArgs, TResult>(method: MethodStub<TArgs, TResult>, options: UseCallOptions = {}) {\n const [data, setData] = useState<TResult | undefined>(undefined);\n const [isCalling, setCalling] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [stats, setStats] = useState<RpcStats | null>(null);\n\n // Use refs to store latest values without causing callback recreation\n const methodIdRef = useRef(method.__id);\n const optionsRef = useRef(options);\n\n // Update refs on each render\n methodIdRef.current = method.__id;\n optionsRef.current = options;\n\n // Memoized call function - stable reference across renders\n const call = useCallback(async (args: TArgs): Promise<TResult | undefined> => {\n setCalling(true);\n setError(null);\n try {\n const result = await rpcCall<TResult, TArgs>(methodIdRef.current, args);\n setData(result.data);\n setStats(result.stats);\n optionsRef.current.invalidate?.forEach((m) => invalidateByMethod(m.__id));\n optionsRef.current.onSuccess?.(result.data);\n return result.data;\n } catch (err: unknown) {\n const errorObj = err as { error?: string; stats?: RpcStats };\n setError(errorObj.error ?? \"Unknown error\");\n setStats(errorObj.stats ?? null);\n return undefined;\n } finally {\n setCalling(false);\n }\n }, []); // Empty deps - uses refs for latest values\n\n return { data, call, isCalling, error, stats };\n}\n"]}
1
+ {"version":3,"file":"useCall.js","sourceRoot":"","sources":["../../src/client/useCall.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAezC;;;;;;;;GAQG;AACH,MAAM,UAAU,OAAO,CAAiB,MAAkC,EAAE,UAA0B,EAAE;IACpG,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAsB,SAAS,CAAC,CAAC;IACjE,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAkB,IAAI,CAAC,CAAC;IAE1D,sEAAsE;IACtE,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAEnC,6BAA6B;IAC7B,WAAW,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC;IAClC,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAE7B,2DAA2D;IAC3D,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,IAAW,EAAgC,EAAE;QACzE,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,QAAQ,CAAC,IAAI,CAAC,CAAC;QACf,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAiB,WAAW,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YACxE,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACrB,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvB,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAC1E,UAAU,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAC5C,OAAO,MAAM,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACpB,MAAM,QAAQ,GAAG,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;YACpH,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC3B,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YACzB,MAAM,QAAQ,CAAC;QACnB,CAAC;gBAAS,CAAC;YACP,UAAU,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,2CAA2C;IAEnD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AACnD,CAAC","sourcesContent":["import { useCallback, useRef, useState } from \"react\";\n\nimport type { RpcStats } from \"../runtime/protocol.js\";\nimport { invalidateByMethod } from \"./cache.js\";\nimport { RpcError } from \"./RpcError.js\";\nimport { rpcCall } from \"./rpcClient.js\";\nimport type { MethodStub } from \"./types.js\";\n\n/**\n * Options passed to `useCall`.\n *\n * - invalidate: array of MethodStubs whose cache entries will be invalidated\n * when this call completes successfully (useful to refresh related reads).\n * - onSuccess: optional callback that receives the result on success.\n */\ntype UseCallOptions = {\n invalidate?: MethodStub[];\n onSuccess?: (result: unknown) => void;\n};\n\n/**\n * React hook for imperative RPC calls (commonly used for mutations).\n *\n * @template TArgs - argument type for the method\n * @template TResult - expected result type\n * @param method - MethodStub identifying the server method to call\n * @param options - UseCallOptions to control invalidation / callbacks\n * @returns { data, call, isCalling, error, stats } where `call(args)` triggers the RPC and returns the result\n */\nexport function useCall<TArgs, TResult>(method: MethodStub<TArgs, TResult>, options: UseCallOptions = {}) {\n const [data, setData] = useState<TResult | undefined>(undefined);\n const [isCalling, setCalling] = useState(false);\n const [error, setError] = useState<string | null>(null);\n const [stats, setStats] = useState<RpcStats | null>(null);\n\n // Use refs to store latest values without causing callback recreation\n const methodIdRef = useRef(method.__id);\n const optionsRef = useRef(options);\n\n // Update refs on each render\n methodIdRef.current = method.__id;\n optionsRef.current = options;\n\n // Memoized call function - stable reference across renders\n const call = useCallback(async (args: TArgs): Promise<TResult | undefined> => {\n setCalling(true);\n setError(null);\n try {\n const result = await rpcCall<TResult, TArgs>(methodIdRef.current, args);\n setData(result.data);\n setStats(result.stats);\n optionsRef.current.invalidate?.forEach((m) => invalidateByMethod(m.__id));\n optionsRef.current.onSuccess?.(result.data);\n return result.data;\n } catch (err: unknown) {\n const rpcError = err instanceof RpcError ? err : new RpcError(err instanceof Error ? err.message : \"Unknown error\");\n setError(rpcError.message);\n setStats(rpcError.stats);\n throw rpcError;\n } finally {\n setCalling(false);\n }\n }, []); // Empty deps - uses refs for latest values\n\n return { data, call, isCalling, error, stats };\n}\n"]}
@@ -8,6 +8,8 @@ import type { MethodStub } from "./types.js";
8
8
  * window focus/visibility change and re-run the fetch.
9
9
  * - showLoaderOnRefocus: when false (default), refetches triggered by window
10
10
  * focus/visibility will update data silently without showing the loading state.
11
+ * - showLoaderOnInvalidate: when false (default), refetches triggered by cache
12
+ * invalidation will update data silently without showing the loading state.
11
13
  * - enabled: disable automatic fetching (defaults to true) — useful when
12
14
  * you only want to fetch when a required value (e.g. id) is present.
13
15
  */
@@ -15,6 +17,7 @@ export interface UseFetchOptions {
15
17
  ttl?: number;
16
18
  refetchOnWindowFocus?: boolean;
17
19
  showLoaderOnRefocus?: boolean;
20
+ showLoaderOnInvalidate?: boolean;
18
21
  enabled?: boolean;
19
22
  }
20
23
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"useFetch.d.ts","sourceRoot":"","sources":["../../src/client/useFetch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAGvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;GAUG;AACH,MAAM,WAAW,eAAe;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAsED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,eAAe;;;;;2BA0OvE,OAAO;EAGnD"}
1
+ {"version":3,"file":"useFetch.d.ts","sourceRoot":"","sources":["../../src/client/useFetch.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAIvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,eAAe;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,OAAO,CAAC,EAAE,OAAO,CAAC;CACrB;AAsED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,EAAE,eAAe;;;;;2BA4OvE,OAAO;EAGnD"}
@@ -1,6 +1,7 @@
1
1
  import { useCallback, useEffect, useRef, useState } from "react";
2
2
  import { cacheKey, get, getPendingFetch, has, isPending, set, setPendingFetch, subscribeInvalidations } from "./cache.js";
3
3
  import { rpcCall } from "./rpcClient.js";
4
+ import { RpcError } from "./RpcError.js";
4
5
  function getFocusCallbacksSet() {
5
6
  if (typeof window === "undefined") {
6
7
  return new Set();
@@ -68,7 +69,7 @@ function setupFocusListeners() {
68
69
  export function useFetch(method, args, options) {
69
70
  // Compute cache key
70
71
  const key = cacheKey(method.__id, args);
71
- const { ttl, refetchOnWindowFocus = true, showLoaderOnRefocus = false, enabled = true } = options ?? {};
72
+ const { ttl, refetchOnWindowFocus = true, showLoaderOnRefocus = false, showLoaderOnInvalidate = false, enabled = true } = options ?? {};
72
73
  // Use refs to store latest values without causing effect re-runs
73
74
  const methodIdRef = useRef(method.__id);
74
75
  const argsRef = useRef(args);
@@ -76,6 +77,7 @@ export function useFetch(method, args, options) {
76
77
  const ttlRef = useRef(ttl);
77
78
  const enabledRef = useRef(enabled);
78
79
  const showLoaderOnRefocusRef = useRef(showLoaderOnRefocus);
80
+ const showLoaderOnInvalidateRef = useRef(showLoaderOnInvalidate);
79
81
  // Update refs on each render
80
82
  methodIdRef.current = method.__id;
81
83
  argsRef.current = args;
@@ -83,6 +85,7 @@ export function useFetch(method, args, options) {
83
85
  ttlRef.current = ttl;
84
86
  enabledRef.current = enabled;
85
87
  showLoaderOnRefocusRef.current = showLoaderOnRefocus;
88
+ showLoaderOnInvalidateRef.current = showLoaderOnInvalidate;
86
89
  // Track if component is mounted
87
90
  const isMountedRef = useRef(true);
88
91
  const [data, setData] = useState(() => (has(key) ? get(key) : undefined));
@@ -114,9 +117,9 @@ export function useFetch(method, args, options) {
114
117
  }
115
118
  catch (err) {
116
119
  if (isMountedRef.current) {
117
- const errorObj = err;
118
- setError(errorObj.error ?? "Unknown error");
119
- setStats(errorObj.stats ?? null);
120
+ const rpcError = err instanceof RpcError ? err : new RpcError(err instanceof Error ? err.message : "Unknown error");
121
+ setError(rpcError.message);
122
+ setStats(rpcError.stats);
120
123
  }
121
124
  return undefined;
122
125
  }
@@ -147,9 +150,9 @@ export function useFetch(method, args, options) {
147
150
  if (!isMountedRef.current) {
148
151
  return undefined;
149
152
  }
150
- const errorObj = err;
151
- setError(errorObj.error ?? "Unknown error");
152
- setStats(errorObj.stats ?? null);
153
+ const rpcError = err instanceof RpcError ? err : new RpcError(err instanceof Error ? err.message : "Unknown error");
154
+ setError(rpcError.message);
155
+ setStats(rpcError.stats);
153
156
  return undefined;
154
157
  }
155
158
  finally {
@@ -200,9 +203,9 @@ export function useFetch(method, args, options) {
200
203
  })
201
204
  .catch((err) => {
202
205
  if (isMountedRef.current) {
203
- const errorObj = err;
204
- setError(errorObj.error ?? "Unknown error");
205
- setStats(errorObj.stats ?? null);
206
+ const rpcError = err instanceof RpcError ? err : new RpcError(err instanceof Error ? err.message : "Unknown error");
207
+ setError(rpcError.message);
208
+ setStats(rpcError.stats);
206
209
  }
207
210
  })
208
211
  .finally(() => {
@@ -237,7 +240,7 @@ export function useFetch(method, args, options) {
237
240
  useEffect(() => {
238
241
  const unsubscribe = subscribeInvalidations((methodId) => {
239
242
  if (methodId === methodIdRef.current && enabledRef.current && isMountedRef.current && !isPending(keyRef.current)) {
240
- doFetch(true);
243
+ doFetch(showLoaderOnInvalidateRef.current);
241
244
  }
242
245
  });
243
246
  return unsubscribe;
@@ -1 +1 @@
1
- {"version":3,"file":"useFetch.js","sourceRoot":"","sources":["../../src/client/useFetch.ts"],"names":[],"mappings":"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","sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport type { RpcStats } from \"../runtime/protocol.js\";\nimport { cacheKey, get, getPendingFetch, has, isPending, set, setPendingFetch, subscribeInvalidations } from \"./cache.js\";\nimport { rpcCall } from \"./rpcClient.js\";\nimport type { MethodStub } from \"./types.js\";\n\n/**\n * Options controlling `useFetch` behaviour.\n *\n * - ttl: optional time-to-live for the cached response (milliseconds).\n * - refetchOnWindowFocus: when true the hook will invalidate cache on\n * window focus/visibility change and re-run the fetch.\n * - showLoaderOnRefocus: when false (default), refetches triggered by window\n * focus/visibility will update data silently without showing the loading state.\n * - enabled: disable automatic fetching (defaults to true) — useful when\n * you only want to fetch when a required value (e.g. id) is present.\n */\nexport interface UseFetchOptions {\n ttl?: number; // TTL in milliseconds\n refetchOnWindowFocus?: boolean; // Whether to refetch when tab becomes visible\n showLoaderOnRefocus?: boolean; // Whether to show loader when refetching on focus (defaults to false)\n enabled?: boolean; // Whether to fetch data. Defaults to true. Useful for conditional fetching (e.g., only fetch when an ID exists)\n}\n\n// Store focus refetch callbacks globally (survives HMR)\ntype FocusCallback = (showLoader: boolean) => void;\n\nfunction getFocusCallbacksSet(): Set<FocusCallback> {\n if (typeof window === \"undefined\") {\n return new Set();\n }\n const win = window as typeof window & {\n __heliumFocusCallbacks?: Set<FocusCallback>;\n };\n if (!win.__heliumFocusCallbacks) {\n win.__heliumFocusCallbacks = new Set();\n }\n return win.__heliumFocusCallbacks;\n}\n\nfunction getVisibilityState(): { registered: boolean; lastTrigger: number } {\n if (typeof window === \"undefined\") {\n return { registered: false, lastTrigger: 0 };\n }\n const win = window as typeof window & {\n __heliumVisibilityState?: { registered: boolean; lastTrigger: number };\n };\n if (!win.__heliumVisibilityState) {\n win.__heliumVisibilityState = { registered: false, lastTrigger: 0 };\n }\n return win.__heliumVisibilityState;\n}\n\n// Minimum time between focus-triggered refetches (debounce)\nconst FOCUS_DEBOUNCE_MS = 2000;\n\nfunction setupFocusListeners() {\n const state = getVisibilityState();\n if (state.registered || typeof document === \"undefined\") {\n return;\n }\n state.registered = true;\n\n const triggerRefetch = () => {\n const now = Date.now();\n // Debounce to prevent rapid refetches during HMR\n if (now - state.lastTrigger < FOCUS_DEBOUNCE_MS) {\n return;\n }\n state.lastTrigger = now;\n\n // Get all registered callbacks and call them\n const callbacks = getFocusCallbacksSet();\n callbacks.forEach((cb) => {\n try {\n cb(false); // Silent refetch on focus\n } catch {\n // Ignore errors from stale callbacks\n }\n });\n };\n\n const handleVisibilityChange = () => {\n if (!document.hidden) {\n triggerRefetch();\n }\n };\n\n document.addEventListener(\"visibilitychange\", handleVisibilityChange, { passive: true });\n window.addEventListener(\"focus\", triggerRefetch, { passive: true });\n}\n\n/**\n * React hook for fetching and caching the result of a server method.\n *\n * @template TArgs - method argument type\n * @template TResult - expected return type\n * @param method - a MethodStub representing the server method to call\n * @param args - optional argument object passed to the server method\n * @param options - controls caching and refetch behavior (see UseFetchOptions)\n * @returns { data, isLoading, error, stats, refetch } — `data` is the cached or latest value; `refetch` triggers an immediate request\n */\nexport function useFetch<TArgs, TResult>(method: MethodStub<TArgs, TResult>, args?: TArgs, options?: UseFetchOptions) {\n // Compute cache key\n const key = cacheKey(method.__id, args);\n\n const { ttl, refetchOnWindowFocus = true, showLoaderOnRefocus = false, enabled = true } = options ?? {};\n\n // Use refs to store latest values without causing effect re-runs\n const methodIdRef = useRef(method.__id);\n const argsRef = useRef(args);\n const keyRef = useRef(key);\n const ttlRef = useRef(ttl);\n const enabledRef = useRef(enabled);\n const showLoaderOnRefocusRef = useRef(showLoaderOnRefocus);\n\n // Update refs on each render\n methodIdRef.current = method.__id;\n argsRef.current = args;\n keyRef.current = key;\n ttlRef.current = ttl;\n enabledRef.current = enabled;\n showLoaderOnRefocusRef.current = showLoaderOnRefocus;\n\n // Track if component is mounted\n const isMountedRef = useRef(true);\n\n const [data, setData] = useState<TResult | undefined>(() => (has(key) ? get<TResult>(key) : undefined));\n const [isLoading, setLoading] = useState(!has(key) && enabled);\n const [error, setError] = useState<string | null>(null);\n const [stats, setStats] = useState<RpcStats | null>(null);\n\n // Core fetch function using refs (stable reference)\n // Uses global deduplication to prevent multiple fetches for the same key\n const doFetch = useCallback(async (showLoader: boolean = true): Promise<TResult | undefined> => {\n if (!isMountedRef.current) {\n return undefined;\n }\n\n const currentKey = keyRef.current;\n\n // Check if there's already a pending fetch for this key (global deduplication)\n const existingFetch = getPendingFetch<{ data: TResult; stats: RpcStats }>(currentKey);\n if (existingFetch) {\n // Wait for the existing fetch and use its result\n if (showLoader) {\n setLoading(true);\n }\n try {\n const result = await existingFetch;\n if (isMountedRef.current) {\n setData(result.data);\n setStats(result.stats);\n setError(null);\n }\n return result.data;\n } catch (err: unknown) {\n if (isMountedRef.current) {\n const errorObj = err as { error?: string; stats?: RpcStats };\n setError(errorObj.error ?? \"Unknown error\");\n setStats(errorObj.stats ?? null);\n }\n return undefined;\n } finally {\n if (isMountedRef.current && showLoader) {\n setLoading(false);\n }\n }\n }\n\n if (showLoader) {\n setLoading(true);\n }\n setError(null);\n\n // Create the fetch promise and register it globally\n const fetchPromise = rpcCall<TResult, TArgs>(methodIdRef.current, argsRef.current as TArgs);\n const dedupedPromise = setPendingFetch(currentKey, fetchPromise);\n\n try {\n const result = await dedupedPromise;\n if (!isMountedRef.current) {\n return undefined;\n }\n set(currentKey, result.data, ttlRef.current);\n setData(result.data);\n setStats(result.stats);\n return result.data;\n } catch (err: unknown) {\n if (!isMountedRef.current) {\n return undefined;\n }\n const errorObj = err as { error?: string; stats?: RpcStats };\n setError(errorObj.error ?? \"Unknown error\");\n setStats(errorObj.stats ?? null);\n return undefined;\n } finally {\n if (isMountedRef.current && showLoader) {\n setLoading(false);\n }\n }\n }, []); // No dependencies - uses refs\n\n // Track mounted state\n useEffect(() => {\n isMountedRef.current = true;\n return () => {\n isMountedRef.current = false;\n };\n }, []);\n\n // Sync data from cache when key changes\n useEffect(() => {\n if (has(key)) {\n const cachedData = get<TResult>(key);\n if (cachedData !== undefined) {\n setData(cachedData);\n setLoading(false);\n }\n }\n }, [key]);\n\n // Initial fetch on mount or when key/enabled changes\n useEffect(() => {\n if (!enabled) {\n setLoading(false);\n return;\n }\n\n // Only fetch if not in cache and not already pending globally\n if (!has(key) && !isPending(key)) {\n doFetch(true);\n } else if (isPending(key)) {\n // There's a pending fetch - wait for it\n setLoading(true);\n const pendingFetch = getPendingFetch<{ data: TResult; stats: RpcStats }>(key);\n if (pendingFetch) {\n pendingFetch\n .then((result) => {\n if (isMountedRef.current) {\n setData(result.data);\n setStats(result.stats);\n setError(null);\n }\n })\n .catch((err: unknown) => {\n if (isMountedRef.current) {\n const errorObj = err as { error?: string; stats?: RpcStats };\n setError(errorObj.error ?? \"Unknown error\");\n setStats(errorObj.stats ?? null);\n }\n })\n .finally(() => {\n if (isMountedRef.current) {\n setLoading(false);\n }\n });\n }\n }\n }, [key, enabled, doFetch]);\n\n // Register for focus/visibility refetch\n useEffect(() => {\n if (!refetchOnWindowFocus) {\n return;\n }\n\n // Setup global focus listeners once\n setupFocusListeners();\n\n // Create a stable callback for this hook instance\n const focusCallback: FocusCallback = (showLoader: boolean) => {\n if (enabledRef.current && isMountedRef.current && !isPending(keyRef.current)) {\n doFetch(showLoaderOnRefocusRef.current || showLoader);\n }\n };\n\n // Register this callback\n const callbacks = getFocusCallbacksSet();\n callbacks.add(focusCallback);\n\n return () => {\n callbacks.delete(focusCallback);\n };\n }, [refetchOnWindowFocus, doFetch]);\n\n // Subscribe to cache invalidations (from useCall or manual invalidation)\n useEffect(() => {\n const unsubscribe = subscribeInvalidations((methodId) => {\n if (methodId === methodIdRef.current && enabledRef.current && isMountedRef.current && !isPending(keyRef.current)) {\n doFetch(true);\n }\n });\n\n return unsubscribe;\n }, [doFetch]);\n\n // TTL-based auto-refetch\n useEffect(() => {\n if (!enabled || !ttl) {\n return;\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let isActive = true;\n\n const scheduleRefetch = () => {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n\n timeoutId = setTimeout(async () => {\n if (!isActive || !enabledRef.current || !isMountedRef.current) {\n return;\n }\n await doFetch(false); // Silent refetch for TTL\n if (isActive) {\n scheduleRefetch();\n }\n }, ttl);\n };\n\n // Only schedule if data is already cached\n if (has(key)) {\n scheduleRefetch();\n }\n\n return () => {\n isActive = false;\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n };\n }, [key, ttl, enabled, doFetch]);\n\n // Public refetch function\n const refetch = useCallback((showLoader: boolean = true) => doFetch(showLoader), [doFetch]);\n\n return { data, isLoading, error, stats, refetch };\n}\n"]}
1
+ {"version":3,"file":"useFetch.js","sourceRoot":"","sources":["../../src/client/useFetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGjE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAC1H,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AA2BzC,SAAS,oBAAoB;IACzB,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAChC,OAAO,IAAI,GAAG,EAAE,CAAC;IACrB,CAAC;IACD,MAAM,GAAG,GAAG,MAEX,CAAC;IACF,IAAI,CAAC,GAAG,CAAC,sBAAsB,EAAE,CAAC;QAC9B,GAAG,CAAC,sBAAsB,GAAG,IAAI,GAAG,EAAE,CAAC;IAC3C,CAAC;IACD,OAAO,GAAG,CAAC,sBAAsB,CAAC;AACtC,CAAC;AAED,SAAS,kBAAkB;IACvB,IAAI,OAAO,MAAM,KAAK,WAAW,EAAE,CAAC;QAChC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IACjD,CAAC;IACD,MAAM,GAAG,GAAG,MAEX,CAAC;IACF,IAAI,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC;QAC/B,GAAG,CAAC,uBAAuB,GAAG,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;IACxE,CAAC;IACD,OAAO,GAAG,CAAC,uBAAuB,CAAC;AACvC,CAAC;AAED,4DAA4D;AAC5D,MAAM,iBAAiB,GAAG,IAAI,CAAC;AAE/B,SAAS,mBAAmB;IACxB,MAAM,KAAK,GAAG,kBAAkB,EAAE,CAAC;IACnC,IAAI,KAAK,CAAC,UAAU,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;QACtD,OAAO;IACX,CAAC;IACD,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;IAExB,MAAM,cAAc,GAAG,GAAG,EAAE;QACxB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,iDAAiD;QACjD,IAAI,GAAG,GAAG,KAAK,CAAC,WAAW,GAAG,iBAAiB,EAAE,CAAC;YAC9C,OAAO;QACX,CAAC;QACD,KAAK,CAAC,WAAW,GAAG,GAAG,CAAC;QAExB,6CAA6C;QAC7C,MAAM,SAAS,GAAG,oBAAoB,EAAE,CAAC;QACzC,SAAS,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;YACrB,IAAI,CAAC;gBACD,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,0BAA0B;YACzC,CAAC;YAAC,MAAM,CAAC;gBACL,qCAAqC;YACzC,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IAEF,MAAM,sBAAsB,GAAG,GAAG,EAAE;QAChC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC;YACnB,cAAc,EAAE,CAAC;QACrB,CAAC;IACL,CAAC,CAAC;IAEF,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,sBAAsB,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IACzF,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;AACxE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,QAAQ,CAAiB,MAAkC,EAAE,IAAY,EAAE,OAAyB;IAChH,oBAAoB;IACpB,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAExC,MAAM,EAAE,GAAG,EAAE,oBAAoB,GAAG,IAAI,EAAE,mBAAmB,GAAG,KAAK,EAAE,sBAAsB,GAAG,KAAK,EAAE,OAAO,GAAG,IAAI,EAAE,GAAG,OAAO,IAAI,EAAE,CAAC;IAExI,iEAAiE;IACjE,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IACnC,MAAM,sBAAsB,GAAG,MAAM,CAAC,mBAAmB,CAAC,CAAC;IAC3D,MAAM,yBAAyB,GAAG,MAAM,CAAC,sBAAsB,CAAC,CAAC;IAEjE,6BAA6B;IAC7B,WAAW,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC;IAClC,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IACvB,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC;IACrB,MAAM,CAAC,OAAO,GAAG,GAAG,CAAC;IACrB,UAAU,CAAC,OAAO,GAAG,OAAO,CAAC;IAC7B,sBAAsB,CAAC,OAAO,GAAG,mBAAmB,CAAC;IACrD,yBAAyB,CAAC,OAAO,GAAG,sBAAsB,CAAC;IAE3D,gCAAgC;IAChC,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAElC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAsB,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAU,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;IACxG,MAAM,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,CAAC;IAC/D,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IACxD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAkB,IAAI,CAAC,CAAC;IAE1D,oDAAoD;IACpD,yEAAyE;IACzE,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,aAAsB,IAAI,EAAgC,EAAE;QAC3F,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;YACxB,OAAO,SAAS,CAAC;QACrB,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,CAAC;QAElC,+EAA+E;QAC/E,MAAM,aAAa,GAAG,eAAe,CAAqC,UAAU,CAAC,CAAC;QACtF,IAAI,aAAa,EAAE,CAAC;YAChB,iDAAiD;YACjD,IAAI,UAAU,EAAE,CAAC;gBACb,UAAU,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC;YACD,IAAI,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;gBACnC,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;oBACvB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;oBACrB,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;oBACvB,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACnB,CAAC;gBACD,OAAO,MAAM,CAAC,IAAI,CAAC;YACvB,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACpB,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;oBACvB,MAAM,QAAQ,GAAG,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;oBACpH,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;oBAC3B,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;gBAC7B,CAAC;gBACD,OAAO,SAAS,CAAC;YACrB,CAAC;oBAAS,CAAC;gBACP,IAAI,YAAY,CAAC,OAAO,IAAI,UAAU,EAAE,CAAC;oBACrC,UAAU,CAAC,KAAK,CAAC,CAAC;gBACtB,CAAC;YACL,CAAC;QACL,CAAC;QAED,IAAI,UAAU,EAAE,CAAC;YACb,UAAU,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;QACD,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEf,oDAAoD;QACpD,MAAM,YAAY,GAAG,OAAO,CAAiB,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,OAAgB,CAAC,CAAC;QAC5F,MAAM,cAAc,GAAG,eAAe,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QAEjE,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC;YACpC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;gBACxB,OAAO,SAAS,CAAC;YACrB,CAAC;YACD,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC;YAC7C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACrB,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvB,OAAO,MAAM,CAAC,IAAI,CAAC;QACvB,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACpB,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;gBACxB,OAAO,SAAS,CAAC;YACrB,CAAC;YACD,MAAM,QAAQ,GAAG,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;YACpH,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC3B,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;YACzB,OAAO,SAAS,CAAC;QACrB,CAAC;gBAAS,CAAC;YACP,IAAI,YAAY,CAAC,OAAO,IAAI,UAAU,EAAE,CAAC;gBACrC,UAAU,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;QACL,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,8BAA8B;IAEtC,sBAAsB;IACtB,SAAS,CAAC,GAAG,EAAE;QACX,YAAY,CAAC,OAAO,GAAG,IAAI,CAAC;QAC5B,OAAO,GAAG,EAAE;YACR,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;QACjC,CAAC,CAAC;IACN,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,wCAAwC;IACxC,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACX,MAAM,UAAU,GAAG,GAAG,CAAU,GAAG,CAAC,CAAC;YACrC,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;gBAC3B,OAAO,CAAC,UAAU,CAAC,CAAC;gBACpB,UAAU,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;QACL,CAAC;IACL,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAEV,qDAAqD;IACrD,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,OAAO,EAAE,CAAC;YACX,UAAU,CAAC,KAAK,CAAC,CAAC;YAClB,OAAO;QACX,CAAC;QAED,8DAA8D;QAC9D,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;aAAM,IAAI,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,wCAAwC;YACxC,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,MAAM,YAAY,GAAG,eAAe,CAAqC,GAAG,CAAC,CAAC;YAC9E,IAAI,YAAY,EAAE,CAAC;gBACf,YAAY;qBACP,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE;oBACb,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;wBACvB,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;wBACrB,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;wBACvB,QAAQ,CAAC,IAAI,CAAC,CAAC;oBACnB,CAAC;gBACL,CAAC,CAAC;qBACD,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;oBACpB,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;wBACvB,MAAM,QAAQ,GAAG,GAAG,YAAY,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;wBACpH,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;wBAC3B,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;oBAC7B,CAAC;gBACL,CAAC,CAAC;qBACD,OAAO,CAAC,GAAG,EAAE;oBACV,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;wBACvB,UAAU,CAAC,KAAK,CAAC,CAAC;oBACtB,CAAC;gBACL,CAAC,CAAC,CAAC;YACX,CAAC;QACL,CAAC;IACL,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAE5B,wCAAwC;IACxC,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACxB,OAAO;QACX,CAAC;QAED,oCAAoC;QACpC,mBAAmB,EAAE,CAAC;QAEtB,kDAAkD;QAClD,MAAM,aAAa,GAAkB,CAAC,UAAmB,EAAE,EAAE;YACzD,IAAI,UAAU,CAAC,OAAO,IAAI,YAAY,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3E,OAAO,CAAC,sBAAsB,CAAC,OAAO,IAAI,UAAU,CAAC,CAAC;YAC1D,CAAC;QACL,CAAC,CAAC;QAEF,yBAAyB;QACzB,MAAM,SAAS,GAAG,oBAAoB,EAAE,CAAC;QACzC,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAE7B,OAAO,GAAG,EAAE;YACR,SAAS,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QACpC,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,oBAAoB,EAAE,OAAO,CAAC,CAAC,CAAC;IAEpC,yEAAyE;IACzE,SAAS,CAAC,GAAG,EAAE;QACX,MAAM,WAAW,GAAG,sBAAsB,CAAC,CAAC,QAAQ,EAAE,EAAE;YACpD,IAAI,QAAQ,KAAK,WAAW,CAAC,OAAO,IAAI,UAAU,CAAC,OAAO,IAAI,YAAY,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/G,OAAO,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;YAC/C,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,WAAW,CAAC;IACvB,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,yBAAyB;IACzB,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,CAAC,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;YACnB,OAAO;QACX,CAAC;QAED,IAAI,SAAoD,CAAC;QACzD,IAAI,QAAQ,GAAG,IAAI,CAAC;QAEpB,MAAM,eAAe,GAAG,GAAG,EAAE;YACzB,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC1B,YAAY,CAAC,SAAS,CAAC,CAAC;YAC5B,CAAC;YAED,SAAS,GAAG,UAAU,CAAC,KAAK,IAAI,EAAE;gBAC9B,IAAI,CAAC,QAAQ,IAAI,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;oBAC5D,OAAO;gBACX,CAAC;gBACD,MAAM,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,yBAAyB;gBAC/C,IAAI,QAAQ,EAAE,CAAC;oBACX,eAAe,EAAE,CAAC;gBACtB,CAAC;YACL,CAAC,EAAE,GAAG,CAAC,CAAC;QACZ,CAAC,CAAC;QAEF,0CAA0C;QAC1C,IAAI,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACX,eAAe,EAAE,CAAC;QACtB,CAAC;QAED,OAAO,GAAG,EAAE;YACR,QAAQ,GAAG,KAAK,CAAC;YACjB,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC1B,YAAY,CAAC,SAAS,CAAC,CAAC;YAC5B,CAAC;QACL,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;IAEjC,0BAA0B;IAC1B,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,aAAsB,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAE5F,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AACtD,CAAC","sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\";\n\nimport type { RpcStats } from \"../runtime/protocol.js\";\nimport { cacheKey, get, getPendingFetch, has, isPending, set, setPendingFetch, subscribeInvalidations } from \"./cache.js\";\nimport { rpcCall } from \"./rpcClient.js\";\nimport { RpcError } from \"./RpcError.js\";\nimport type { MethodStub } from \"./types.js\";\n\n/**\n * Options controlling `useFetch` behaviour.\n *\n * - ttl: optional time-to-live for the cached response (milliseconds).\n * - refetchOnWindowFocus: when true the hook will invalidate cache on\n * window focus/visibility change and re-run the fetch.\n * - showLoaderOnRefocus: when false (default), refetches triggered by window\n * focus/visibility will update data silently without showing the loading state.\n * - showLoaderOnInvalidate: when false (default), refetches triggered by cache\n * invalidation will update data silently without showing the loading state.\n * - enabled: disable automatic fetching (defaults to true) — useful when\n * you only want to fetch when a required value (e.g. id) is present.\n */\nexport interface UseFetchOptions {\n ttl?: number; // TTL in milliseconds\n refetchOnWindowFocus?: boolean; // Whether to refetch when tab becomes visible\n showLoaderOnRefocus?: boolean; // Whether to show loader when refetching on focus (defaults to false)\n showLoaderOnInvalidate?: boolean; // Whether to show loader when refetching on cache invalidation (defaults to false)\n enabled?: boolean; // Whether to fetch data. Defaults to true. Useful for conditional fetching (e.g., only fetch when an ID exists)\n}\n\n// Store focus refetch callbacks globally (survives HMR)\ntype FocusCallback = (showLoader: boolean) => void;\n\nfunction getFocusCallbacksSet(): Set<FocusCallback> {\n if (typeof window === \"undefined\") {\n return new Set();\n }\n const win = window as typeof window & {\n __heliumFocusCallbacks?: Set<FocusCallback>;\n };\n if (!win.__heliumFocusCallbacks) {\n win.__heliumFocusCallbacks = new Set();\n }\n return win.__heliumFocusCallbacks;\n}\n\nfunction getVisibilityState(): { registered: boolean; lastTrigger: number } {\n if (typeof window === \"undefined\") {\n return { registered: false, lastTrigger: 0 };\n }\n const win = window as typeof window & {\n __heliumVisibilityState?: { registered: boolean; lastTrigger: number };\n };\n if (!win.__heliumVisibilityState) {\n win.__heliumVisibilityState = { registered: false, lastTrigger: 0 };\n }\n return win.__heliumVisibilityState;\n}\n\n// Minimum time between focus-triggered refetches (debounce)\nconst FOCUS_DEBOUNCE_MS = 2000;\n\nfunction setupFocusListeners() {\n const state = getVisibilityState();\n if (state.registered || typeof document === \"undefined\") {\n return;\n }\n state.registered = true;\n\n const triggerRefetch = () => {\n const now = Date.now();\n // Debounce to prevent rapid refetches during HMR\n if (now - state.lastTrigger < FOCUS_DEBOUNCE_MS) {\n return;\n }\n state.lastTrigger = now;\n\n // Get all registered callbacks and call them\n const callbacks = getFocusCallbacksSet();\n callbacks.forEach((cb) => {\n try {\n cb(false); // Silent refetch on focus\n } catch {\n // Ignore errors from stale callbacks\n }\n });\n };\n\n const handleVisibilityChange = () => {\n if (!document.hidden) {\n triggerRefetch();\n }\n };\n\n document.addEventListener(\"visibilitychange\", handleVisibilityChange, { passive: true });\n window.addEventListener(\"focus\", triggerRefetch, { passive: true });\n}\n\n/**\n * React hook for fetching and caching the result of a server method.\n *\n * @template TArgs - method argument type\n * @template TResult - expected return type\n * @param method - a MethodStub representing the server method to call\n * @param args - optional argument object passed to the server method\n * @param options - controls caching and refetch behavior (see UseFetchOptions)\n * @returns { data, isLoading, error, stats, refetch } — `data` is the cached or latest value; `refetch` triggers an immediate request\n */\nexport function useFetch<TArgs, TResult>(method: MethodStub<TArgs, TResult>, args?: TArgs, options?: UseFetchOptions) {\n // Compute cache key\n const key = cacheKey(method.__id, args);\n\n const { ttl, refetchOnWindowFocus = true, showLoaderOnRefocus = false, showLoaderOnInvalidate = false, enabled = true } = options ?? {};\n\n // Use refs to store latest values without causing effect re-runs\n const methodIdRef = useRef(method.__id);\n const argsRef = useRef(args);\n const keyRef = useRef(key);\n const ttlRef = useRef(ttl);\n const enabledRef = useRef(enabled);\n const showLoaderOnRefocusRef = useRef(showLoaderOnRefocus);\n const showLoaderOnInvalidateRef = useRef(showLoaderOnInvalidate);\n\n // Update refs on each render\n methodIdRef.current = method.__id;\n argsRef.current = args;\n keyRef.current = key;\n ttlRef.current = ttl;\n enabledRef.current = enabled;\n showLoaderOnRefocusRef.current = showLoaderOnRefocus;\n showLoaderOnInvalidateRef.current = showLoaderOnInvalidate;\n\n // Track if component is mounted\n const isMountedRef = useRef(true);\n\n const [data, setData] = useState<TResult | undefined>(() => (has(key) ? get<TResult>(key) : undefined));\n const [isLoading, setLoading] = useState(!has(key) && enabled);\n const [error, setError] = useState<string | null>(null);\n const [stats, setStats] = useState<RpcStats | null>(null);\n\n // Core fetch function using refs (stable reference)\n // Uses global deduplication to prevent multiple fetches for the same key\n const doFetch = useCallback(async (showLoader: boolean = true): Promise<TResult | undefined> => {\n if (!isMountedRef.current) {\n return undefined;\n }\n\n const currentKey = keyRef.current;\n\n // Check if there's already a pending fetch for this key (global deduplication)\n const existingFetch = getPendingFetch<{ data: TResult; stats: RpcStats }>(currentKey);\n if (existingFetch) {\n // Wait for the existing fetch and use its result\n if (showLoader) {\n setLoading(true);\n }\n try {\n const result = await existingFetch;\n if (isMountedRef.current) {\n setData(result.data);\n setStats(result.stats);\n setError(null);\n }\n return result.data;\n } catch (err: unknown) {\n if (isMountedRef.current) {\n const rpcError = err instanceof RpcError ? err : new RpcError(err instanceof Error ? err.message : \"Unknown error\");\n setError(rpcError.message);\n setStats(rpcError.stats);\n }\n return undefined;\n } finally {\n if (isMountedRef.current && showLoader) {\n setLoading(false);\n }\n }\n }\n\n if (showLoader) {\n setLoading(true);\n }\n setError(null);\n\n // Create the fetch promise and register it globally\n const fetchPromise = rpcCall<TResult, TArgs>(methodIdRef.current, argsRef.current as TArgs);\n const dedupedPromise = setPendingFetch(currentKey, fetchPromise);\n\n try {\n const result = await dedupedPromise;\n if (!isMountedRef.current) {\n return undefined;\n }\n set(currentKey, result.data, ttlRef.current);\n setData(result.data);\n setStats(result.stats);\n return result.data;\n } catch (err: unknown) {\n if (!isMountedRef.current) {\n return undefined;\n }\n const rpcError = err instanceof RpcError ? err : new RpcError(err instanceof Error ? err.message : \"Unknown error\");\n setError(rpcError.message);\n setStats(rpcError.stats);\n return undefined;\n } finally {\n if (isMountedRef.current && showLoader) {\n setLoading(false);\n }\n }\n }, []); // No dependencies - uses refs\n\n // Track mounted state\n useEffect(() => {\n isMountedRef.current = true;\n return () => {\n isMountedRef.current = false;\n };\n }, []);\n\n // Sync data from cache when key changes\n useEffect(() => {\n if (has(key)) {\n const cachedData = get<TResult>(key);\n if (cachedData !== undefined) {\n setData(cachedData);\n setLoading(false);\n }\n }\n }, [key]);\n\n // Initial fetch on mount or when key/enabled changes\n useEffect(() => {\n if (!enabled) {\n setLoading(false);\n return;\n }\n\n // Only fetch if not in cache and not already pending globally\n if (!has(key) && !isPending(key)) {\n doFetch(true);\n } else if (isPending(key)) {\n // There's a pending fetch - wait for it\n setLoading(true);\n const pendingFetch = getPendingFetch<{ data: TResult; stats: RpcStats }>(key);\n if (pendingFetch) {\n pendingFetch\n .then((result) => {\n if (isMountedRef.current) {\n setData(result.data);\n setStats(result.stats);\n setError(null);\n }\n })\n .catch((err: unknown) => {\n if (isMountedRef.current) {\n const rpcError = err instanceof RpcError ? err : new RpcError(err instanceof Error ? err.message : \"Unknown error\");\n setError(rpcError.message);\n setStats(rpcError.stats);\n }\n })\n .finally(() => {\n if (isMountedRef.current) {\n setLoading(false);\n }\n });\n }\n }\n }, [key, enabled, doFetch]);\n\n // Register for focus/visibility refetch\n useEffect(() => {\n if (!refetchOnWindowFocus) {\n return;\n }\n\n // Setup global focus listeners once\n setupFocusListeners();\n\n // Create a stable callback for this hook instance\n const focusCallback: FocusCallback = (showLoader: boolean) => {\n if (enabledRef.current && isMountedRef.current && !isPending(keyRef.current)) {\n doFetch(showLoaderOnRefocusRef.current || showLoader);\n }\n };\n\n // Register this callback\n const callbacks = getFocusCallbacksSet();\n callbacks.add(focusCallback);\n\n return () => {\n callbacks.delete(focusCallback);\n };\n }, [refetchOnWindowFocus, doFetch]);\n\n // Subscribe to cache invalidations (from useCall or manual invalidation)\n useEffect(() => {\n const unsubscribe = subscribeInvalidations((methodId) => {\n if (methodId === methodIdRef.current && enabledRef.current && isMountedRef.current && !isPending(keyRef.current)) {\n doFetch(showLoaderOnInvalidateRef.current);\n }\n });\n\n return unsubscribe;\n }, [doFetch]);\n\n // TTL-based auto-refetch\n useEffect(() => {\n if (!enabled || !ttl) {\n return;\n }\n\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n let isActive = true;\n\n const scheduleRefetch = () => {\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n\n timeoutId = setTimeout(async () => {\n if (!isActive || !enabledRef.current || !isMountedRef.current) {\n return;\n }\n await doFetch(false); // Silent refetch for TTL\n if (isActive) {\n scheduleRefetch();\n }\n }, ttl);\n };\n\n // Only schedule if data is already cached\n if (has(key)) {\n scheduleRefetch();\n }\n\n return () => {\n isActive = false;\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n };\n }, [key, ttl, enabled, doFetch]);\n\n // Public refetch function\n const refetch = useCallback((showLoader: boolean = true) => doFetch(showLoader), [doFetch]);\n\n return { data, isLoading, error, stats, refetch };\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"httpRouter.d.ts","sourceRoot":"","sources":["../../src/server/httpRouter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAM5D,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC;CAC1B;AAED,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CAKN;IACR,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,eAAe,CAAa;IAEpC,kBAAkB,CAAC,KAAK,EAAE,MAAM;IAIhC,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE;IAalC,aAAa,CAAC,UAAU,EAAE,gBAAgB;IAIpC,aAAa,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CAwGlG"}
1
+ {"version":3,"file":"httpRouter.d.ts","sourceRoot":"","sources":["../../src/server/httpRouter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,MAAM,CAAC;AAM5D,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,wBAAwB,CAAC;AACzE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAExD,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,aAAa,CAAC;CAC1B;AAED,qBAAa,UAAU;IACnB,OAAO,CAAC,MAAM,CAKN;IACR,OAAO,CAAC,UAAU,CAAiC;IACnD,OAAO,CAAC,eAAe,CAAa;IAEpC,kBAAkB,CAAC,KAAK,EAAE,MAAM;IAIhC,cAAc,CAAC,MAAM,EAAE,SAAS,EAAE;IAalC,aAAa,CAAC,UAAU,EAAE,gBAAgB;IAIpC,aAAa,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;CAsGlG"}
@@ -88,16 +88,14 @@ export class HTTPRouter {
88
88
  // No middleware, execute handler directly
89
89
  result = await route.handler.handler(httpRequest, httpCtx);
90
90
  }
91
- if (result instanceof Response) {
91
+ if (isWebResponse(result)) {
92
92
  res.statusCode = result.status;
93
93
  result.headers.forEach((value, key) => {
94
94
  res.setHeader(key, value);
95
95
  });
96
96
  if (result.body) {
97
- const { Readable } = await import("stream");
98
- // @ts-ignore
99
- const nodeStream = Readable.fromWeb(result.body);
100
- nodeStream.pipe(res);
97
+ const arrayBuf = await result.arrayBuffer();
98
+ res.end(Buffer.from(arrayBuf));
101
99
  }
102
100
  else {
103
101
  res.end();
@@ -224,4 +222,32 @@ function parseCookies(cookieHeader) {
224
222
  }
225
223
  return cookies;
226
224
  }
225
+ /**
226
+ * Detect a Web `Response` object using duck-typing instead of `instanceof`.
227
+ *
228
+ * In Vite's SSR environment the handler code runs inside a separate module
229
+ * context (`ssrLoadModule`), so the `Response` constructor available there
230
+ * may be a *different reference* than the global `Response` that
231
+ * `httpRouter.ts` sees. The classic `instanceof Response` check therefore
232
+ * fails, causing the framework to fall through to `JSON.stringify(result)`
233
+ * which serialises a Response into a tiny broken payload (~126 bytes).
234
+ *
235
+ * By checking for the characteristic properties (`status`, `headers` as a
236
+ * `Headers`-like object, and `arrayBuffer` method) we reliably detect
237
+ * Response objects regardless of which realm they were created in.
238
+ */
239
+ function isWebResponse(value) {
240
+ if (value instanceof Response) {
241
+ return true;
242
+ }
243
+ if (typeof value !== "object" || value === null) {
244
+ return false;
245
+ }
246
+ const candidate = value;
247
+ return (typeof candidate.status === "number" &&
248
+ typeof candidate.arrayBuffer === "function" &&
249
+ typeof candidate.headers === "object" &&
250
+ candidate.headers !== null &&
251
+ typeof candidate.headers.forEach === "function");
252
+ }
227
253
  //# sourceMappingURL=httpRouter.js.map