@debros/network-ts-sdk 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,11 +1,45 @@
1
1
  import WebSocket from 'isomorphic-ws';
2
2
 
3
+ declare class SDKError extends Error {
4
+ readonly httpStatus: number;
5
+ readonly code: string;
6
+ readonly details: Record<string, any>;
7
+ constructor(message: string, httpStatus?: number, code?: string, details?: Record<string, any>);
8
+ static fromResponse(status: number, body: any, message?: string): SDKError;
9
+ toJSON(): {
10
+ name: string;
11
+ message: string;
12
+ httpStatus: number;
13
+ code: string;
14
+ details: Record<string, any>;
15
+ };
16
+ }
17
+
18
+ /**
19
+ * Context provided to the onNetworkError callback
20
+ */
21
+ interface NetworkErrorContext {
22
+ method: "GET" | "POST" | "PUT" | "DELETE" | "WS";
23
+ path: string;
24
+ isRetry: boolean;
25
+ attempt: number;
26
+ }
27
+ /**
28
+ * Callback invoked when a network error occurs.
29
+ * Use this to trigger gateway failover or other error handling.
30
+ */
31
+ type NetworkErrorCallback = (error: SDKError, context: NetworkErrorContext) => void;
3
32
  interface HttpClientConfig {
4
33
  baseURL: string;
5
34
  timeout?: number;
6
35
  maxRetries?: number;
7
36
  retryDelayMs?: number;
8
37
  fetch?: typeof fetch;
38
+ /**
39
+ * Callback invoked on network errors (after all retries exhausted).
40
+ * Use this to trigger gateway failover at the application layer.
41
+ */
42
+ onNetworkError?: NetworkErrorCallback;
9
43
  }
10
44
  declare class HttpClient {
11
45
  private baseURL;
@@ -15,7 +49,12 @@ declare class HttpClient {
15
49
  private fetch;
16
50
  private apiKey?;
17
51
  private jwt?;
52
+ private onNetworkError?;
18
53
  constructor(config: HttpClientConfig);
54
+ /**
55
+ * Set the network error callback
56
+ */
57
+ setOnNetworkError(callback: NetworkErrorCallback | undefined): void;
19
58
  setApiKey(apiKey?: string): void;
20
59
  setJwt(jwt?: string): void;
21
60
  private getAuthHeaders;
@@ -287,6 +326,11 @@ interface WSClientConfig {
287
326
  timeout?: number;
288
327
  authToken?: string;
289
328
  WebSocket?: typeof WebSocket;
329
+ /**
330
+ * Callback invoked on WebSocket errors.
331
+ * Use this to trigger gateway failover at the application layer.
332
+ */
333
+ onNetworkError?: NetworkErrorCallback;
290
334
  }
291
335
  type WSMessageHandler = (data: string) => void;
292
336
  type WSErrorHandler = (error: Error) => void;
@@ -302,6 +346,7 @@ declare class WSClient {
302
346
  private timeout;
303
347
  private authToken?;
304
348
  private WebSocketClass;
349
+ private onNetworkError?;
305
350
  private ws?;
306
351
  private messageHandlers;
307
352
  private errorHandlers;
@@ -309,6 +354,10 @@ declare class WSClient {
309
354
  private openHandlers;
310
355
  private isClosed;
311
356
  constructor(config: WSClientConfig);
357
+ /**
358
+ * Set the network error callback
359
+ */
360
+ setOnNetworkError(callback: NetworkErrorCallback | undefined): void;
312
361
  /**
313
362
  * Get the current WebSocket URL
314
363
  */
@@ -769,21 +818,6 @@ declare class FunctionsClient {
769
818
  invoke<TInput = any, TOutput = any>(functionName: string, input: TInput): Promise<TOutput>;
770
819
  }
771
820
 
772
- declare class SDKError extends Error {
773
- readonly httpStatus: number;
774
- readonly code: string;
775
- readonly details: Record<string, any>;
776
- constructor(message: string, httpStatus?: number, code?: string, details?: Record<string, any>);
777
- static fromResponse(status: number, body: any, message?: string): SDKError;
778
- toJSON(): {
779
- name: string;
780
- message: string;
781
- httpStatus: number;
782
- code: string;
783
- details: Record<string, any>;
784
- };
785
- }
786
-
787
821
  /**
788
822
  * Serverless Functions Types
789
823
  * Type definitions for calling serverless functions on the Orama Network
@@ -811,6 +845,11 @@ interface ClientConfig extends Omit<HttpClientConfig, "fetch"> {
811
845
  wsConfig?: Partial<Omit<WSClientConfig, "wsURL">>;
812
846
  functionsConfig?: FunctionsClientConfig;
813
847
  fetch?: typeof fetch;
848
+ /**
849
+ * Callback invoked on network errors (HTTP and WebSocket).
850
+ * Use this to trigger gateway failover at the application layer.
851
+ */
852
+ onNetworkError?: NetworkErrorCallback;
814
853
  }
815
854
  interface Client {
816
855
  auth: AuthClient;
@@ -823,4 +862,4 @@ interface Client {
823
862
  }
824
863
  declare function createClient(config: ClientConfig): Client;
825
864
 
826
- export { AuthClient, type AuthConfig, CacheClient, type CacheDeleteRequest, type CacheDeleteResponse, type CacheGetRequest, type CacheGetResponse, type CacheHealthResponse, type CacheMultiGetRequest, type CacheMultiGetResponse, type CachePutRequest, type CachePutResponse, type CacheScanRequest, type CacheScanResponse, type Client, type ClientConfig, type CloseHandler, type ColumnDefinition, DBClient, type Entity, type ErrorHandler, type FindOptions, type FunctionResponse, FunctionsClient, type FunctionsClientConfig, HttpClient, LocalStorageAdapter, MemoryStorage, type MessageHandler, NetworkClient, type NetworkStatus, type PeerInfo, type PresenceMember, type PresenceOptions, type PresenceResponse, type ProxyRequest, type ProxyResponse, PubSubClient, type PubSubMessage, QueryBuilder, type QueryResponse, Repository, SDKError, type SelectOptions, type StorageAdapter, StorageClient, type StoragePinRequest, type StoragePinResponse, type StorageStatus, type StorageUploadResponse, type SubscribeOptions, Subscription, type SuccessResponse, type TransactionOp, type TransactionRequest, WSClient, type WhoAmI, createClient, extractPrimaryKey, extractTableName };
865
+ export { AuthClient, type AuthConfig, CacheClient, type CacheDeleteRequest, type CacheDeleteResponse, type CacheGetRequest, type CacheGetResponse, type CacheHealthResponse, type CacheMultiGetRequest, type CacheMultiGetResponse, type CachePutRequest, type CachePutResponse, type CacheScanRequest, type CacheScanResponse, type Client, type ClientConfig, type CloseHandler, type ColumnDefinition, DBClient, type Entity, type ErrorHandler, type FindOptions, type FunctionResponse, FunctionsClient, type FunctionsClientConfig, HttpClient, LocalStorageAdapter, MemoryStorage, type MessageHandler, NetworkClient, type NetworkErrorCallback, type NetworkErrorContext, type NetworkStatus, type PeerInfo, type PresenceMember, type PresenceOptions, type PresenceResponse, type ProxyRequest, type ProxyResponse, PubSubClient, type PubSubMessage, QueryBuilder, type QueryResponse, Repository, SDKError, type SelectOptions, type StorageAdapter, StorageClient, type StoragePinRequest, type StoragePinResponse, type StorageStatus, type StorageUploadResponse, type SubscribeOptions, Subscription, type SuccessResponse, type TransactionOp, type TransactionRequest, WSClient, type WhoAmI, createClient, extractPrimaryKey, extractTableName };
package/dist/index.js CHANGED
@@ -40,6 +40,13 @@ var HttpClient = class {
40
40
  this.maxRetries = config.maxRetries ?? 3;
41
41
  this.retryDelayMs = config.retryDelayMs ?? 1e3;
42
42
  this.fetch = config.fetch ?? createFetchWithTLSConfig();
43
+ this.onNetworkError = config.onNetworkError;
44
+ }
45
+ /**
46
+ * Set the network error callback
47
+ */
48
+ setOnNetworkError(callback) {
49
+ this.onNetworkError = callback;
43
50
  }
44
51
  setApiKey(apiKey) {
45
52
  this.apiKey = apiKey;
@@ -195,6 +202,21 @@ var HttpClient = class {
195
202
  }
196
203
  }
197
204
  }
205
+ if (this.onNetworkError) {
206
+ const sdkError = error instanceof SDKError ? error : new SDKError(
207
+ error instanceof Error ? error.message : String(error),
208
+ 0,
209
+ // httpStatus 0 indicates network-level failure
210
+ "NETWORK_ERROR"
211
+ );
212
+ this.onNetworkError(sdkError, {
213
+ method,
214
+ path,
215
+ isRetry: false,
216
+ attempt: this.maxRetries
217
+ // All retries exhausted
218
+ });
219
+ }
198
220
  throw error;
199
221
  } finally {
200
222
  clearTimeout(timeoutId);
@@ -291,6 +313,19 @@ var HttpClient = class {
291
313
  error
292
314
  );
293
315
  }
316
+ if (this.onNetworkError) {
317
+ const sdkError = error instanceof SDKError ? error : new SDKError(
318
+ error instanceof Error ? error.message : String(error),
319
+ 0,
320
+ "NETWORK_ERROR"
321
+ );
322
+ this.onNetworkError(sdkError, {
323
+ method: "POST",
324
+ path,
325
+ isRetry: false,
326
+ attempt: this.maxRetries
327
+ });
328
+ }
294
329
  throw error;
295
330
  } finally {
296
331
  clearTimeout(timeoutId);
@@ -315,16 +350,26 @@ var HttpClient = class {
315
350
  const response = await this.fetch(url.toString(), fetchOptions);
316
351
  if (!response.ok) {
317
352
  clearTimeout(timeoutId);
318
- const error = await response.json().catch(() => ({
353
+ const errorBody = await response.json().catch(() => ({
319
354
  error: response.statusText
320
355
  }));
321
- throw SDKError.fromResponse(response.status, error);
356
+ throw SDKError.fromResponse(response.status, errorBody);
322
357
  }
323
358
  return response;
324
359
  } catch (error) {
325
360
  clearTimeout(timeoutId);
326
- if (error instanceof SDKError) {
327
- throw error;
361
+ if (this.onNetworkError) {
362
+ const sdkError = error instanceof SDKError ? error : new SDKError(
363
+ error instanceof Error ? error.message : String(error),
364
+ 0,
365
+ "NETWORK_ERROR"
366
+ );
367
+ this.onNetworkError(sdkError, {
368
+ method: "GET",
369
+ path,
370
+ isRetry: false,
371
+ attempt: 0
372
+ });
328
373
  }
329
374
  throw error;
330
375
  }
@@ -814,6 +859,13 @@ var WSClient = class {
814
859
  this.timeout = config.timeout ?? 3e4;
815
860
  this.authToken = config.authToken;
816
861
  this.WebSocketClass = config.WebSocket ?? WebSocket;
862
+ this.onNetworkError = config.onNetworkError;
863
+ }
864
+ /**
865
+ * Set the network error callback
866
+ */
867
+ setOnNetworkError(callback) {
868
+ this.onNetworkError = callback;
817
869
  }
818
870
  /**
819
871
  * Get the current WebSocket URL
@@ -832,9 +884,16 @@ var WSClient = class {
832
884
  this.isClosed = false;
833
885
  const timeout = setTimeout(() => {
834
886
  this.ws?.close();
835
- reject(
836
- new SDKError("WebSocket connection timeout", 408, "WS_TIMEOUT")
837
- );
887
+ const error = new SDKError("WebSocket connection timeout", 408, "WS_TIMEOUT");
888
+ if (this.onNetworkError) {
889
+ this.onNetworkError(error, {
890
+ method: "WS",
891
+ path: this.wsURL,
892
+ isRetry: false,
893
+ attempt: 0
894
+ });
895
+ }
896
+ reject(error);
838
897
  }, this.timeout);
839
898
  this.ws.addEventListener("open", () => {
840
899
  clearTimeout(timeout);
@@ -850,6 +909,14 @@ var WSClient = class {
850
909
  console.error("[WSClient] WebSocket error:", event);
851
910
  clearTimeout(timeout);
852
911
  const error = new SDKError("WebSocket error", 500, "WS_ERROR", event);
912
+ if (this.onNetworkError) {
913
+ this.onNetworkError(error, {
914
+ method: "WS",
915
+ path: this.wsURL,
916
+ isRetry: false,
917
+ attempt: 0
918
+ });
919
+ }
853
920
  this.errorHandlers.forEach((handler) => handler(error));
854
921
  reject(error);
855
922
  });
@@ -1627,7 +1694,8 @@ function createClient(config) {
1627
1694
  timeout: config.timeout,
1628
1695
  maxRetries: config.maxRetries,
1629
1696
  retryDelayMs: config.retryDelayMs,
1630
- fetch: config.fetch
1697
+ fetch: config.fetch,
1698
+ onNetworkError: config.onNetworkError
1631
1699
  });
1632
1700
  const auth = new AuthClient({
1633
1701
  httpClient,
@@ -1639,7 +1707,8 @@ function createClient(config) {
1639
1707
  const db = new DBClient(httpClient);
1640
1708
  const pubsub = new PubSubClient(httpClient, {
1641
1709
  ...config.wsConfig,
1642
- wsURL
1710
+ wsURL,
1711
+ onNetworkError: config.onNetworkError
1643
1712
  });
1644
1713
  const network = new NetworkClient(httpClient);
1645
1714
  const cache = new CacheClient(httpClient);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/core/http.ts","../src/auth/types.ts","../src/auth/client.ts","../src/db/qb.ts","../src/db/repository.ts","../src/db/client.ts","../src/core/ws.ts","../src/pubsub/client.ts","../src/network/client.ts","../src/cache/client.ts","../src/storage/client.ts","../src/functions/client.ts","../src/index.ts"],"sourcesContent":["export class SDKError extends Error {\n public readonly httpStatus: number;\n public readonly code: string;\n public readonly details: Record<string, any>;\n\n constructor(\n message: string,\n httpStatus: number = 500,\n code: string = \"SDK_ERROR\",\n details: Record<string, any> = {}\n ) {\n super(message);\n this.name = \"SDKError\";\n this.httpStatus = httpStatus;\n this.code = code;\n this.details = details;\n }\n\n static fromResponse(\n status: number,\n body: any,\n message?: string\n ): SDKError {\n const errorMsg = message || body?.error || `HTTP ${status}`;\n const code = body?.code || `HTTP_${status}`;\n return new SDKError(errorMsg, status, code, body);\n }\n\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n httpStatus: this.httpStatus,\n code: this.code,\n details: this.details,\n };\n }\n}\n","import { SDKError } from \"../errors\";\n\nexport interface HttpClientConfig {\n baseURL: string;\n timeout?: number;\n maxRetries?: number;\n retryDelayMs?: number;\n fetch?: typeof fetch;\n}\n\n/**\n * Create a fetch function with proper TLS configuration for staging certificates\n * In Node.js, we need to configure TLS to accept Let's Encrypt staging certificates\n */\nfunction createFetchWithTLSConfig(): typeof fetch {\n // Check if we're in a Node.js environment\n if (typeof process !== \"undefined\" && process.versions?.node) {\n // For testing/staging/development: allow staging certificates\n // Let's Encrypt staging certificates are self-signed and not trusted by default\n const isDevelopmentOrStaging =\n process.env.NODE_ENV !== \"production\" ||\n process.env.DEBROS_ALLOW_STAGING_CERTS === \"true\" ||\n process.env.DEBROS_USE_HTTPS === \"true\";\n\n if (isDevelopmentOrStaging) {\n // Allow self-signed/staging certificates\n // WARNING: Only use this in development/testing environments\n process.env.NODE_TLS_REJECT_UNAUTHORIZED = \"0\";\n }\n }\n return globalThis.fetch;\n}\n\nexport class HttpClient {\n private baseURL: string;\n private timeout: number;\n private maxRetries: number;\n private retryDelayMs: number;\n private fetch: typeof fetch;\n private apiKey?: string;\n private jwt?: string;\n\n constructor(config: HttpClientConfig) {\n this.baseURL = config.baseURL.replace(/\\/$/, \"\");\n this.timeout = config.timeout ?? 60000;\n this.maxRetries = config.maxRetries ?? 3;\n this.retryDelayMs = config.retryDelayMs ?? 1000;\n // Use provided fetch or create one with proper TLS configuration for staging certificates\n this.fetch = config.fetch ?? createFetchWithTLSConfig();\n }\n\n setApiKey(apiKey?: string) {\n this.apiKey = apiKey;\n // Don't clear JWT - allow both to coexist\n }\n\n setJwt(jwt?: string) {\n this.jwt = jwt;\n // Don't clear API key - allow both to coexist\n if (typeof console !== \"undefined\") {\n console.log(\n \"[HttpClient] JWT set:\",\n !!jwt,\n \"API key still present:\",\n !!this.apiKey\n );\n }\n }\n\n private getAuthHeaders(path: string): Record<string, string> {\n const headers: Record<string, string> = {};\n\n // For database, pubsub, proxy, and cache operations, ONLY use API key to avoid JWT user context\n // interfering with namespace-level authorization\n const isDbOperation = path.includes(\"/v1/rqlite/\");\n const isPubSubOperation = path.includes(\"/v1/pubsub/\");\n const isProxyOperation = path.includes(\"/v1/proxy/\");\n const isCacheOperation = path.includes(\"/v1/cache/\");\n\n // For auth operations, prefer API key over JWT to ensure proper authentication\n const isAuthOperation = path.includes(\"/v1/auth/\");\n\n if (\n isDbOperation ||\n isPubSubOperation ||\n isProxyOperation ||\n isCacheOperation\n ) {\n // For database/pubsub/proxy/cache operations: use only API key (preferred for namespace operations)\n if (this.apiKey) {\n headers[\"X-API-Key\"] = this.apiKey;\n } else if (this.jwt) {\n // Fallback to JWT if no API key\n headers[\"Authorization\"] = `Bearer ${this.jwt}`;\n }\n } else if (isAuthOperation) {\n // For auth operations: prefer API key over JWT (auth endpoints should use explicit API key)\n if (this.apiKey) {\n headers[\"X-API-Key\"] = this.apiKey;\n }\n if (this.jwt) {\n headers[\"Authorization\"] = `Bearer ${this.jwt}`;\n }\n } else {\n // For other operations: send both JWT and API key\n if (this.jwt) {\n headers[\"Authorization\"] = `Bearer ${this.jwt}`;\n }\n if (this.apiKey) {\n headers[\"X-API-Key\"] = this.apiKey;\n }\n }\n return headers;\n }\n\n private getAuthToken(): string | undefined {\n return this.jwt || this.apiKey;\n }\n\n getApiKey(): string | undefined {\n return this.apiKey;\n }\n\n /**\n * Get the base URL\n */\n getBaseURL(): string {\n return this.baseURL;\n }\n\n async request<T = any>(\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n path: string,\n options: {\n body?: any;\n headers?: Record<string, string>;\n query?: Record<string, string | number | boolean>;\n timeout?: number; // Per-request timeout override\n } = {}\n ): Promise<T> {\n const startTime = performance.now(); // Track request start time\n const url = new URL(this.baseURL + path);\n if (options.query) {\n Object.entries(options.query).forEach(([key, value]) => {\n url.searchParams.append(key, String(value));\n });\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...this.getAuthHeaders(path),\n ...options.headers,\n };\n\n const controller = new AbortController();\n const requestTimeout = options.timeout ?? this.timeout; // Use override or default\n const timeoutId = setTimeout(() => controller.abort(), requestTimeout);\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n signal: controller.signal,\n };\n\n if (options.body !== undefined) {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n // Extract and log SQL query details for rqlite operations\n const isRqliteOperation = path.includes(\"/v1/rqlite/\");\n let queryDetails: string | null = null;\n if (isRqliteOperation && options.body) {\n try {\n const body =\n typeof options.body === \"string\"\n ? JSON.parse(options.body)\n : options.body;\n\n if (body.sql) {\n // Direct SQL query (query/exec endpoints)\n queryDetails = `SQL: ${body.sql}`;\n if (body.args && body.args.length > 0) {\n queryDetails += ` | Args: [${body.args\n .map((a: any) => (typeof a === \"string\" ? `\"${a}\"` : a))\n .join(\", \")}]`;\n }\n } else if (body.table) {\n // Table-based query (find/find-one/select endpoints)\n queryDetails = `Table: ${body.table}`;\n if (body.criteria && Object.keys(body.criteria).length > 0) {\n queryDetails += ` | Criteria: ${JSON.stringify(body.criteria)}`;\n }\n if (body.options) {\n queryDetails += ` | Options: ${JSON.stringify(body.options)}`;\n }\n if (body.select) {\n queryDetails += ` | Select: ${JSON.stringify(body.select)}`;\n }\n if (body.where) {\n queryDetails += ` | Where: ${JSON.stringify(body.where)}`;\n }\n if (body.limit) {\n queryDetails += ` | Limit: ${body.limit}`;\n }\n if (body.offset) {\n queryDetails += ` | Offset: ${body.offset}`;\n }\n }\n } catch (e) {\n // Failed to parse body, ignore\n }\n }\n\n try {\n const result = await this.requestWithRetry(\n url.toString(),\n fetchOptions,\n 0,\n startTime\n );\n const duration = performance.now() - startTime;\n if (typeof console !== \"undefined\") {\n const logMessage = `[HttpClient] ${method} ${path} completed in ${duration.toFixed(\n 2\n )}ms`;\n if (queryDetails) {\n console.log(logMessage);\n console.log(`[HttpClient] ${queryDetails}`);\n } else {\n console.log(logMessage);\n }\n }\n return result;\n } catch (error) {\n const duration = performance.now() - startTime;\n if (typeof console !== \"undefined\") {\n // For 404 errors on find-one calls, log at warn level (not error) since \"not found\" is expected\n // Application layer handles these cases in try-catch blocks\n const is404FindOne =\n path === \"/v1/rqlite/find-one\" &&\n error instanceof SDKError &&\n error.httpStatus === 404;\n\n if (is404FindOne) {\n // Log as warning for visibility, but not as error since it's expected behavior\n console.warn(\n `[HttpClient] ${method} ${path} returned 404 after ${duration.toFixed(\n 2\n )}ms (expected for optional lookups)`\n );\n } else {\n const errorMessage = `[HttpClient] ${method} ${path} failed after ${duration.toFixed(\n 2\n )}ms:`;\n console.error(errorMessage, error);\n if (queryDetails) {\n console.error(`[HttpClient] ${queryDetails}`);\n }\n }\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private async requestWithRetry(\n url: string,\n options: RequestInit,\n attempt: number = 0,\n startTime?: number // Track start time for timing across retries\n ): Promise<any> {\n try {\n const response = await this.fetch(url, options);\n\n if (!response.ok) {\n let body: any;\n try {\n body = await response.json();\n } catch {\n body = { error: response.statusText };\n }\n throw SDKError.fromResponse(response.status, body);\n }\n\n // Request succeeded - return response\n const contentType = response.headers.get(\"content-type\");\n if (contentType?.includes(\"application/json\")) {\n return response.json();\n }\n return response.text();\n } catch (error) {\n const isRetryableError =\n error instanceof SDKError &&\n [408, 429, 500, 502, 503, 504].includes(error.httpStatus);\n\n // Retry on same gateway for retryable HTTP errors\n if (isRetryableError && attempt < this.maxRetries) {\n if (typeof console !== \"undefined\") {\n console.warn(\n `[HttpClient] Retrying request (attempt ${attempt + 1}/${this.maxRetries})`\n );\n }\n await new Promise((resolve) =>\n setTimeout(resolve, this.retryDelayMs * (attempt + 1))\n );\n return this.requestWithRetry(url, options, attempt + 1, startTime);\n }\n\n // All retries exhausted - throw error for app to handle\n throw error;\n }\n }\n\n async get<T = any>(\n path: string,\n options?: Omit<Parameters<typeof this.request>[2], \"body\">\n ): Promise<T> {\n return this.request<T>(\"GET\", path, options);\n }\n\n async post<T = any>(\n path: string,\n body?: any,\n options?: Omit<Parameters<typeof this.request>[2], \"body\">\n ): Promise<T> {\n return this.request<T>(\"POST\", path, { ...options, body });\n }\n\n async put<T = any>(\n path: string,\n body?: any,\n options?: Omit<Parameters<typeof this.request>[2], \"body\">\n ): Promise<T> {\n return this.request<T>(\"PUT\", path, { ...options, body });\n }\n\n async delete<T = any>(\n path: string,\n options?: Omit<Parameters<typeof this.request>[2], \"body\">\n ): Promise<T> {\n return this.request<T>(\"DELETE\", path, options);\n }\n\n /**\n * Upload a file using multipart/form-data\n * This is a special method for file uploads that bypasses JSON serialization\n */\n async uploadFile<T = any>(\n path: string,\n formData: FormData,\n options?: {\n timeout?: number;\n }\n ): Promise<T> {\n const startTime = performance.now(); // Track upload start time\n const url = new URL(this.baseURL + path);\n const headers: Record<string, string> = {\n ...this.getAuthHeaders(path),\n // Don't set Content-Type - browser will set it with boundary\n };\n\n const controller = new AbortController();\n const requestTimeout = options?.timeout ?? this.timeout * 5; // 5x timeout for uploads\n const timeoutId = setTimeout(() => controller.abort(), requestTimeout);\n\n const fetchOptions: RequestInit = {\n method: \"POST\",\n headers,\n body: formData,\n signal: controller.signal,\n };\n\n try {\n const result = await this.requestWithRetry(\n url.toString(),\n fetchOptions,\n 0,\n startTime\n );\n const duration = performance.now() - startTime;\n if (typeof console !== \"undefined\") {\n console.log(\n `[HttpClient] POST ${path} (upload) completed in ${duration.toFixed(\n 2\n )}ms`\n );\n }\n return result;\n } catch (error) {\n const duration = performance.now() - startTime;\n if (typeof console !== \"undefined\") {\n console.error(\n `[HttpClient] POST ${path} (upload) failed after ${duration.toFixed(\n 2\n )}ms:`,\n error\n );\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Get a binary response (returns Response object for streaming)\n */\n async getBinary(path: string): Promise<Response> {\n const url = new URL(this.baseURL + path);\n const headers: Record<string, string> = {\n ...this.getAuthHeaders(path),\n };\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout * 5); // 5x timeout for downloads\n\n const fetchOptions: RequestInit = {\n method: \"GET\",\n headers,\n signal: controller.signal,\n };\n\n try {\n const response = await this.fetch(url.toString(), fetchOptions);\n if (!response.ok) {\n clearTimeout(timeoutId);\n const error = await response.json().catch(() => ({\n error: response.statusText,\n }));\n throw SDKError.fromResponse(response.status, error);\n }\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n if (error instanceof SDKError) {\n throw error;\n }\n throw error;\n }\n }\n\n getToken(): string | undefined {\n return this.getAuthToken();\n }\n}\n","export interface AuthConfig {\n apiKey?: string;\n jwt?: string;\n}\n\nexport interface WhoAmI {\n address?: string;\n namespace?: string;\n authenticated: boolean;\n}\n\nexport interface StorageAdapter {\n get(key: string): Promise<string | null>;\n set(key: string, value: string): Promise<void>;\n clear(): Promise<void>;\n}\n\nexport class MemoryStorage implements StorageAdapter {\n private storage: Map<string, string> = new Map();\n\n async get(key: string): Promise<string | null> {\n return this.storage.get(key) ?? null;\n }\n\n async set(key: string, value: string): Promise<void> {\n this.storage.set(key, value);\n }\n\n async clear(): Promise<void> {\n this.storage.clear();\n }\n}\n\nexport class LocalStorageAdapter implements StorageAdapter {\n private prefix = \"@network/sdk:\";\n\n async get(key: string): Promise<string | null> {\n if (typeof globalThis !== \"undefined\" && globalThis.localStorage) {\n return globalThis.localStorage.getItem(this.prefix + key);\n }\n return null;\n }\n\n async set(key: string, value: string): Promise<void> {\n if (typeof globalThis !== \"undefined\" && globalThis.localStorage) {\n globalThis.localStorage.setItem(this.prefix + key, value);\n }\n }\n\n async clear(): Promise<void> {\n if (typeof globalThis !== \"undefined\" && globalThis.localStorage) {\n const keysToDelete: string[] = [];\n for (let i = 0; i < globalThis.localStorage.length; i++) {\n const key = globalThis.localStorage.key(i);\n if (key?.startsWith(this.prefix)) {\n keysToDelete.push(key);\n }\n }\n keysToDelete.forEach((key) => globalThis.localStorage.removeItem(key));\n }\n }\n}\n","import { HttpClient } from \"../core/http\";\nimport { AuthConfig, WhoAmI, StorageAdapter, MemoryStorage } from \"./types\";\n\nexport class AuthClient {\n private httpClient: HttpClient;\n private storage: StorageAdapter;\n private currentApiKey?: string;\n private currentJwt?: string;\n\n constructor(config: {\n httpClient: HttpClient;\n storage?: StorageAdapter;\n apiKey?: string;\n jwt?: string;\n }) {\n this.httpClient = config.httpClient;\n this.storage = config.storage ?? new MemoryStorage();\n this.currentApiKey = config.apiKey;\n this.currentJwt = config.jwt;\n\n if (this.currentApiKey) {\n this.httpClient.setApiKey(this.currentApiKey);\n }\n if (this.currentJwt) {\n this.httpClient.setJwt(this.currentJwt);\n }\n }\n\n setApiKey(apiKey: string) {\n this.currentApiKey = apiKey;\n // Don't clear JWT - it will be cleared explicitly on logout\n this.httpClient.setApiKey(apiKey);\n this.storage.set(\"apiKey\", apiKey);\n }\n\n setJwt(jwt: string) {\n this.currentJwt = jwt;\n // Don't clear API key - keep it as fallback for after logout\n this.httpClient.setJwt(jwt);\n this.storage.set(\"jwt\", jwt);\n }\n\n getToken(): string | undefined {\n return this.httpClient.getToken();\n }\n\n async whoami(): Promise<WhoAmI> {\n try {\n const response = await this.httpClient.get<WhoAmI>(\"/v1/auth/whoami\");\n return response;\n } catch {\n return { authenticated: false };\n }\n }\n\n async refresh(): Promise<string> {\n const response = await this.httpClient.post<{ token: string }>(\n \"/v1/auth/refresh\"\n );\n const token = response.token;\n this.setJwt(token);\n return token;\n }\n\n /**\n * Logout user and clear JWT, but preserve API key\n * Use this for user logout in apps where API key is app-level credential\n */\n async logoutUser(): Promise<void> {\n // Attempt server-side logout if using JWT\n if (this.currentJwt) {\n try {\n await this.httpClient.post(\"/v1/auth/logout\", { all: true });\n } catch (error) {\n // Log warning but don't fail - local cleanup is more important\n console.warn(\n \"Server-side logout failed, continuing with local cleanup:\",\n error\n );\n }\n }\n\n // Clear JWT only, preserve API key\n this.currentJwt = undefined;\n this.httpClient.setJwt(undefined);\n await this.storage.set(\"jwt\", \"\"); // Clear JWT from storage\n\n // Ensure API key is loaded and set as active auth method\n if (!this.currentApiKey) {\n // Try to load from storage\n const storedApiKey = await this.storage.get(\"apiKey\");\n if (storedApiKey) {\n this.currentApiKey = storedApiKey;\n }\n }\n\n // Restore API key as the active auth method\n if (this.currentApiKey) {\n this.httpClient.setApiKey(this.currentApiKey);\n console.log(\"[Auth] API key restored after user logout\");\n } else {\n console.warn(\"[Auth] No API key available after logout\");\n }\n }\n\n /**\n * Full logout - clears both JWT and API key\n * Use this to completely reset authentication state\n */\n async logout(): Promise<void> {\n // Only attempt server-side logout if using JWT\n // API keys don't support server-side logout with all=true\n if (this.currentJwt) {\n try {\n await this.httpClient.post(\"/v1/auth/logout\", { all: true });\n } catch (error) {\n // Log warning but don't fail - local cleanup is more important\n console.warn(\n \"Server-side logout failed, continuing with local cleanup:\",\n error\n );\n }\n }\n\n // Always clear local state\n this.currentApiKey = undefined;\n this.currentJwt = undefined;\n this.httpClient.setApiKey(undefined);\n this.httpClient.setJwt(undefined);\n await this.storage.clear();\n }\n\n async clear(): Promise<void> {\n this.currentApiKey = undefined;\n this.currentJwt = undefined;\n this.httpClient.setApiKey(undefined);\n this.httpClient.setJwt(undefined);\n await this.storage.clear();\n }\n\n /**\n * Request a challenge nonce for wallet authentication\n */\n async challenge(params: {\n wallet: string;\n purpose?: string;\n namespace?: string;\n }): Promise<{\n nonce: string;\n wallet: string;\n namespace: string;\n expires_at: string;\n }> {\n const response = await this.httpClient.post(\"/v1/auth/challenge\", {\n wallet: params.wallet,\n purpose: params.purpose || \"authentication\",\n namespace: params.namespace || \"default\",\n });\n return response;\n }\n\n /**\n * Verify wallet signature and get JWT token\n */\n async verify(params: {\n wallet: string;\n nonce: string;\n signature: string;\n namespace?: string;\n chain_type?: \"ETH\" | \"SOL\";\n }): Promise<{\n access_token: string;\n refresh_token?: string;\n subject: string;\n namespace: string;\n api_key?: string;\n expires_in?: number;\n token_type?: string;\n }> {\n const response = await this.httpClient.post(\"/v1/auth/verify\", {\n wallet: params.wallet,\n nonce: params.nonce,\n signature: params.signature,\n namespace: params.namespace || \"default\",\n chain_type: params.chain_type || \"ETH\",\n });\n\n // Persist JWT\n this.setJwt(response.access_token);\n\n // Persist API key if server provided it (created in verifyHandler)\n if ((response as any).api_key) {\n this.setApiKey((response as any).api_key);\n }\n\n // Persist refresh token if present (optional, for silent renewal)\n if ((response as any).refresh_token) {\n await this.storage.set(\"refreshToken\", (response as any).refresh_token);\n }\n\n return response as any;\n }\n\n /**\n * Get API key for wallet (creates namespace ownership)\n */\n async getApiKey(params: {\n wallet: string;\n nonce: string;\n signature: string;\n namespace?: string;\n chain_type?: \"ETH\" | \"SOL\";\n }): Promise<{\n api_key: string;\n namespace: string;\n wallet: string;\n }> {\n const response = await this.httpClient.post(\"/v1/auth/api-key\", {\n wallet: params.wallet,\n nonce: params.nonce,\n signature: params.signature,\n namespace: params.namespace || \"default\",\n chain_type: params.chain_type || \"ETH\",\n });\n\n // Automatically set the API key\n this.setApiKey(response.api_key);\n\n return response;\n }\n}\n","import { HttpClient } from \"../core/http\";\nimport { SelectOptions, QueryResponse } from \"./types\";\n\nexport class QueryBuilder {\n private httpClient: HttpClient;\n private table: string;\n private options: SelectOptions = {};\n\n constructor(httpClient: HttpClient, table: string) {\n this.httpClient = httpClient;\n this.table = table;\n }\n\n select(...columns: string[]): this {\n this.options.select = columns;\n return this;\n }\n\n innerJoin(table: string, on: string): this {\n if (!this.options.joins) this.options.joins = [];\n this.options.joins.push({ kind: \"INNER\", table, on });\n return this;\n }\n\n leftJoin(table: string, on: string): this {\n if (!this.options.joins) this.options.joins = [];\n this.options.joins.push({ kind: \"LEFT\", table, on });\n return this;\n }\n\n rightJoin(table: string, on: string): this {\n if (!this.options.joins) this.options.joins = [];\n this.options.joins.push({ kind: \"RIGHT\", table, on });\n return this;\n }\n\n where(expr: string, args?: any[]): this {\n if (!this.options.where) this.options.where = [];\n this.options.where.push({ conj: \"AND\", expr, args });\n return this;\n }\n\n andWhere(expr: string, args?: any[]): this {\n return this.where(expr, args);\n }\n\n orWhere(expr: string, args?: any[]): this {\n if (!this.options.where) this.options.where = [];\n this.options.where.push({ conj: \"OR\", expr, args });\n return this;\n }\n\n groupBy(...columns: string[]): this {\n this.options.group_by = columns;\n return this;\n }\n\n orderBy(...columns: string[]): this {\n this.options.order_by = columns;\n return this;\n }\n\n limit(n: number): this {\n this.options.limit = n;\n return this;\n }\n\n offset(n: number): this {\n this.options.offset = n;\n return this;\n }\n\n async getMany<T = any>(ctx?: any): Promise<T[]> {\n const response = await this.httpClient.post<QueryResponse>(\n \"/v1/rqlite/select\",\n {\n table: this.table,\n ...this.options,\n }\n );\n return response.items || [];\n }\n\n async getOne<T = any>(ctx?: any): Promise<T | null> {\n const response = await this.httpClient.post<QueryResponse>(\n \"/v1/rqlite/select\",\n {\n table: this.table,\n ...this.options,\n one: true,\n limit: 1,\n }\n );\n const items = response.items || [];\n return items.length > 0 ? items[0] : null;\n }\n\n async count(): Promise<number> {\n const response = await this.httpClient.post<QueryResponse>(\n \"/v1/rqlite/select\",\n {\n table: this.table,\n select: [\"COUNT(*) AS count\"],\n where: this.options.where,\n one: true,\n }\n );\n const items = response.items || [];\n return items.length > 0 ? items[0].count : 0;\n }\n}\n","import { HttpClient } from \"../core/http\";\nimport { QueryBuilder } from \"./qb\";\nimport { QueryResponse, FindOptions } from \"./types\";\nimport { SDKError } from \"../errors\";\n\nexport class Repository<T extends Record<string, any>> {\n private httpClient: HttpClient;\n private tableName: string;\n private primaryKey: string;\n\n constructor(httpClient: HttpClient, tableName: string, primaryKey = \"id\") {\n this.httpClient = httpClient;\n this.tableName = tableName;\n this.primaryKey = primaryKey;\n }\n\n createQueryBuilder(): QueryBuilder {\n return new QueryBuilder(this.httpClient, this.tableName);\n }\n\n async find(\n criteria: Record<string, any> = {},\n options: FindOptions = {}\n ): Promise<T[]> {\n const response = await this.httpClient.post<QueryResponse>(\n \"/v1/rqlite/find\",\n {\n table: this.tableName,\n criteria,\n options,\n }\n );\n return response.items || [];\n }\n\n async findOne(criteria: Record<string, any>): Promise<T | null> {\n try {\n const response = await this.httpClient.post<T | null>(\n \"/v1/rqlite/find-one\",\n {\n table: this.tableName,\n criteria,\n }\n );\n return response;\n } catch (error) {\n // Return null if not found instead of throwing\n if (error instanceof SDKError && error.httpStatus === 404) {\n return null;\n }\n throw error;\n }\n }\n\n async save(entity: T): Promise<T> {\n const pkValue = entity[this.primaryKey];\n\n if (!pkValue) {\n // INSERT\n const response = await this.httpClient.post<{\n rows_affected: number;\n last_insert_id: number;\n }>(\"/v1/rqlite/exec\", {\n sql: this.buildInsertSql(entity),\n args: this.buildInsertArgs(entity),\n });\n\n if (response.last_insert_id) {\n (entity as any)[this.primaryKey] = response.last_insert_id;\n }\n return entity;\n } else {\n // UPDATE\n await this.httpClient.post(\"/v1/rqlite/exec\", {\n sql: this.buildUpdateSql(entity),\n args: this.buildUpdateArgs(entity),\n });\n return entity;\n }\n }\n\n async remove(entity: T | Record<string, any>): Promise<void> {\n const pkValue = entity[this.primaryKey];\n if (!pkValue) {\n throw new SDKError(\n `Primary key \"${this.primaryKey}\" is required for remove`,\n 400,\n \"MISSING_PK\"\n );\n }\n\n await this.httpClient.post(\"/v1/rqlite/exec\", {\n sql: `DELETE FROM ${this.tableName} WHERE ${this.primaryKey} = ?`,\n args: [pkValue],\n });\n }\n\n private buildInsertSql(entity: T): string {\n const columns = Object.keys(entity).filter((k) => entity[k] !== undefined);\n const placeholders = columns.map(() => \"?\").join(\", \");\n return `INSERT INTO ${this.tableName} (${columns.join(\n \", \"\n )}) VALUES (${placeholders})`;\n }\n\n private buildInsertArgs(entity: T): any[] {\n return Object.entries(entity)\n .filter(([, v]) => v !== undefined)\n .map(([, v]) => v);\n }\n\n private buildUpdateSql(entity: T): string {\n const columns = Object.keys(entity)\n .filter((k) => entity[k] !== undefined && k !== this.primaryKey)\n .map((k) => `${k} = ?`);\n return `UPDATE ${this.tableName} SET ${columns.join(\", \")} WHERE ${\n this.primaryKey\n } = ?`;\n }\n\n private buildUpdateArgs(entity: T): any[] {\n const args = Object.entries(entity)\n .filter(([k, v]) => v !== undefined && k !== this.primaryKey)\n .map(([, v]) => v);\n args.push(entity[this.primaryKey]);\n return args;\n }\n}\n","import { HttpClient } from \"../core/http\";\nimport { QueryBuilder } from \"./qb\";\nimport { Repository } from \"./repository\";\nimport {\n QueryResponse,\n TransactionOp,\n TransactionRequest,\n Entity,\n FindOptions,\n} from \"./types\";\n\nexport class DBClient {\n private httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n /**\n * Execute a write/DDL SQL statement.\n */\n async exec(\n sql: string,\n args: any[] = []\n ): Promise<{ rows_affected: number; last_insert_id?: number }> {\n return this.httpClient.post(\"/v1/rqlite/exec\", { sql, args });\n }\n\n /**\n * Execute a SELECT query.\n */\n async query<T = any>(sql: string, args: any[] = []): Promise<T[]> {\n const response = await this.httpClient.post<QueryResponse>(\n \"/v1/rqlite/query\",\n { sql, args }\n );\n return response.items || [];\n }\n\n /**\n * Find rows with map-based criteria.\n */\n async find<T = any>(\n table: string,\n criteria: Record<string, any> = {},\n options: FindOptions = {}\n ): Promise<T[]> {\n const response = await this.httpClient.post<QueryResponse>(\n \"/v1/rqlite/find\",\n {\n table,\n criteria,\n options,\n }\n );\n return response.items || [];\n }\n\n /**\n * Find a single row with map-based criteria.\n */\n async findOne<T = any>(\n table: string,\n criteria: Record<string, any>\n ): Promise<T | null> {\n return this.httpClient.post<T | null>(\"/v1/rqlite/find-one\", {\n table,\n criteria,\n });\n }\n\n /**\n * Create a fluent QueryBuilder for complex SELECT queries.\n */\n createQueryBuilder(table: string): QueryBuilder {\n return new QueryBuilder(this.httpClient, table);\n }\n\n /**\n * Create a Repository for entity-based operations.\n */\n repository<T extends Record<string, any>>(\n tableName: string,\n primaryKey = \"id\"\n ): Repository<T> {\n return new Repository(this.httpClient, tableName, primaryKey);\n }\n\n /**\n * Execute multiple operations atomically.\n */\n async transaction(\n ops: TransactionOp[],\n returnResults = true\n ): Promise<any[]> {\n const response = await this.httpClient.post<{ results?: any[] }>(\n \"/v1/rqlite/transaction\",\n {\n ops,\n return_results: returnResults,\n }\n );\n return response.results || [];\n }\n\n /**\n * Create a table from DDL SQL.\n */\n async createTable(schema: string): Promise<void> {\n await this.httpClient.post(\"/v1/rqlite/create-table\", { schema });\n }\n\n /**\n * Drop a table.\n */\n async dropTable(table: string): Promise<void> {\n await this.httpClient.post(\"/v1/rqlite/drop-table\", { table });\n }\n\n /**\n * Get current database schema.\n */\n async getSchema(): Promise<any> {\n return this.httpClient.get(\"/v1/rqlite/schema\");\n }\n}\n","import WebSocket from \"isomorphic-ws\";\nimport { SDKError } from \"../errors\";\n\nexport interface WSClientConfig {\n wsURL: string;\n timeout?: number;\n authToken?: string;\n WebSocket?: typeof WebSocket;\n}\n\nexport type WSMessageHandler = (data: string) => void;\nexport type WSErrorHandler = (error: Error) => void;\nexport type WSCloseHandler = () => void;\nexport type WSOpenHandler = () => void;\n\n/**\n * Simple WebSocket client with minimal abstractions\n * No complex reconnection, no failover - keep it simple\n * Gateway failover is handled at the application layer\n */\nexport class WSClient {\n private wsURL: string;\n private timeout: number;\n private authToken?: string;\n private WebSocketClass: typeof WebSocket;\n\n private ws?: WebSocket;\n private messageHandlers: Set<WSMessageHandler> = new Set();\n private errorHandlers: Set<WSErrorHandler> = new Set();\n private closeHandlers: Set<WSCloseHandler> = new Set();\n private openHandlers: Set<WSOpenHandler> = new Set();\n private isClosed = false;\n\n constructor(config: WSClientConfig) {\n this.wsURL = config.wsURL;\n this.timeout = config.timeout ?? 30000;\n this.authToken = config.authToken;\n this.WebSocketClass = config.WebSocket ?? WebSocket;\n }\n\n /**\n * Get the current WebSocket URL\n */\n get url(): string {\n return this.wsURL;\n }\n\n /**\n * Connect to WebSocket server\n */\n connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n const wsUrl = this.buildWSUrl();\n this.ws = new this.WebSocketClass(wsUrl);\n this.isClosed = false;\n\n const timeout = setTimeout(() => {\n this.ws?.close();\n reject(\n new SDKError(\"WebSocket connection timeout\", 408, \"WS_TIMEOUT\")\n );\n }, this.timeout);\n\n this.ws.addEventListener(\"open\", () => {\n clearTimeout(timeout);\n console.log(\"[WSClient] Connected to\", this.wsURL);\n this.openHandlers.forEach((handler) => handler());\n resolve();\n });\n\n this.ws.addEventListener(\"message\", (event: Event) => {\n const msgEvent = event as MessageEvent;\n this.messageHandlers.forEach((handler) => handler(msgEvent.data));\n });\n\n this.ws.addEventListener(\"error\", (event: Event) => {\n console.error(\"[WSClient] WebSocket error:\", event);\n clearTimeout(timeout);\n const error = new SDKError(\"WebSocket error\", 500, \"WS_ERROR\", event);\n this.errorHandlers.forEach((handler) => handler(error));\n reject(error);\n });\n\n this.ws.addEventListener(\"close\", () => {\n clearTimeout(timeout);\n console.log(\"[WSClient] Connection closed\");\n this.closeHandlers.forEach((handler) => handler());\n });\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Build WebSocket URL with auth token\n */\n private buildWSUrl(): string {\n let url = this.wsURL;\n\n if (this.authToken) {\n const separator = url.includes(\"?\") ? \"&\" : \"?\";\n const paramName = this.authToken.startsWith(\"ak_\") ? \"api_key\" : \"token\";\n url += `${separator}${paramName}=${encodeURIComponent(this.authToken)}`;\n }\n\n return url;\n }\n\n /**\n * Register message handler\n */\n onMessage(handler: WSMessageHandler): () => void {\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n /**\n * Unregister message handler\n */\n offMessage(handler: WSMessageHandler): void {\n this.messageHandlers.delete(handler);\n }\n\n /**\n * Register error handler\n */\n onError(handler: WSErrorHandler): () => void {\n this.errorHandlers.add(handler);\n return () => this.errorHandlers.delete(handler);\n }\n\n /**\n * Unregister error handler\n */\n offError(handler: WSErrorHandler): void {\n this.errorHandlers.delete(handler);\n }\n\n /**\n * Register close handler\n */\n onClose(handler: WSCloseHandler): () => void {\n this.closeHandlers.add(handler);\n return () => this.closeHandlers.delete(handler);\n }\n\n /**\n * Unregister close handler\n */\n offClose(handler: WSCloseHandler): void {\n this.closeHandlers.delete(handler);\n }\n\n /**\n * Register open handler\n */\n onOpen(handler: WSOpenHandler): () => void {\n this.openHandlers.add(handler);\n return () => this.openHandlers.delete(handler);\n }\n\n /**\n * Send data through WebSocket\n */\n send(data: string): void {\n if (this.ws?.readyState !== WebSocket.OPEN) {\n throw new SDKError(\"WebSocket is not connected\", 500, \"WS_NOT_CONNECTED\");\n }\n this.ws.send(data);\n }\n\n /**\n * Close WebSocket connection\n */\n close(): void {\n if (this.isClosed) {\n return;\n }\n this.isClosed = true;\n this.ws?.close();\n }\n\n /**\n * Check if WebSocket is connected\n */\n isConnected(): boolean {\n return !this.isClosed && this.ws?.readyState === WebSocket.OPEN;\n }\n\n /**\n * Update auth token\n */\n setAuthToken(token?: string): void {\n this.authToken = token;\n }\n}\n","import { HttpClient } from \"../core/http\";\nimport { WSClient, WSClientConfig } from \"../core/ws\";\nimport {\n PubSubMessage,\n RawEnvelope,\n MessageHandler,\n ErrorHandler,\n CloseHandler,\n SubscribeOptions,\n PresenceResponse,\n PresenceMember,\n PresenceOptions,\n} from \"./types\";\n\n// Cross-platform base64 encoding/decoding utilities\nfunction base64Encode(str: string): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(str).toString(\"base64\");\n } else if (typeof btoa !== \"undefined\") {\n return btoa(\n encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) =>\n String.fromCharCode(parseInt(p1, 16))\n )\n );\n }\n throw new Error(\"No base64 encoding method available\");\n}\n\nfunction base64EncodeBytes(bytes: Uint8Array): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(bytes).toString(\"base64\");\n } else if (typeof btoa !== \"undefined\") {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n throw new Error(\"No base64 encoding method available\");\n}\n\nfunction base64Decode(b64: string): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(b64, \"base64\").toString(\"utf-8\");\n } else if (typeof atob !== \"undefined\") {\n const binary = atob(b64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return new TextDecoder().decode(bytes);\n }\n throw new Error(\"No base64 decoding method available\");\n}\n\n/**\n * Simple PubSub client - one WebSocket connection per topic\n * Gateway failover is handled at the application layer\n */\nexport class PubSubClient {\n private httpClient: HttpClient;\n private wsConfig: Partial<WSClientConfig>;\n\n constructor(httpClient: HttpClient, wsConfig: Partial<WSClientConfig> = {}) {\n this.httpClient = httpClient;\n this.wsConfig = wsConfig;\n }\n\n /**\n * Publish a message to a topic via HTTP\n */\n async publish(topic: string, data: string | Uint8Array): Promise<void> {\n let dataBase64: string;\n if (typeof data === \"string\") {\n dataBase64 = base64Encode(data);\n } else {\n dataBase64 = base64EncodeBytes(data);\n }\n\n await this.httpClient.post(\n \"/v1/pubsub/publish\",\n {\n topic,\n data_base64: dataBase64,\n },\n {\n timeout: 30000,\n }\n );\n }\n\n /**\n * List active topics in the current namespace\n */\n async topics(): Promise<string[]> {\n const response = await this.httpClient.get<{ topics: string[] }>(\n \"/v1/pubsub/topics\"\n );\n return response.topics || [];\n }\n\n /**\n * Get current presence for a topic without subscribing\n */\n async getPresence(topic: string): Promise<PresenceResponse> {\n const response = await this.httpClient.get<PresenceResponse>(\n `/v1/pubsub/presence?topic=${encodeURIComponent(topic)}`\n );\n return response;\n }\n\n /**\n * Subscribe to a topic via WebSocket\n * Creates one WebSocket connection per topic\n */\n async subscribe(\n topic: string,\n options: SubscribeOptions = {}\n ): Promise<Subscription> {\n // Build WebSocket URL for this topic\n const wsUrl = new URL(this.wsConfig.wsURL || \"ws://127.0.0.1:6001\");\n wsUrl.pathname = \"/v1/pubsub/ws\";\n wsUrl.searchParams.set(\"topic\", topic);\n\n // Handle presence options\n let presence: PresenceOptions | undefined;\n if (options.presence?.enabled) {\n presence = options.presence;\n wsUrl.searchParams.set(\"presence\", \"true\");\n wsUrl.searchParams.set(\"member_id\", presence.memberId);\n if (presence.meta) {\n wsUrl.searchParams.set(\"member_meta\", JSON.stringify(presence.meta));\n }\n }\n\n const authToken = this.httpClient.getApiKey() ?? this.httpClient.getToken();\n\n // Create WebSocket client\n const wsClient = new WSClient({\n ...this.wsConfig,\n wsURL: wsUrl.toString(),\n authToken,\n });\n\n await wsClient.connect();\n\n // Create subscription wrapper\n const subscription = new Subscription(wsClient, topic, presence, () =>\n this.getPresence(topic)\n );\n\n if (options.onMessage) {\n subscription.onMessage(options.onMessage);\n }\n if (options.onError) {\n subscription.onError(options.onError);\n }\n if (options.onClose) {\n subscription.onClose(options.onClose);\n }\n\n return subscription;\n }\n}\n\n/**\n * Subscription represents an active WebSocket subscription to a topic\n */\nexport class Subscription {\n private wsClient: WSClient;\n private topic: string;\n private presenceOptions?: PresenceOptions;\n private messageHandlers: Set<MessageHandler> = new Set();\n private errorHandlers: Set<ErrorHandler> = new Set();\n private closeHandlers: Set<CloseHandler> = new Set();\n private isClosed = false;\n private wsMessageHandler: ((data: string) => void) | null = null;\n private wsErrorHandler: ((error: Error) => void) | null = null;\n private wsCloseHandler: (() => void) | null = null;\n private getPresenceFn: () => Promise<PresenceResponse>;\n\n constructor(\n wsClient: WSClient,\n topic: string,\n presenceOptions: PresenceOptions | undefined,\n getPresenceFn: () => Promise<PresenceResponse>\n ) {\n this.wsClient = wsClient;\n this.topic = topic;\n this.presenceOptions = presenceOptions;\n this.getPresenceFn = getPresenceFn;\n\n // Register message handler\n this.wsMessageHandler = (data) => {\n try {\n // Parse gateway JSON envelope: {data: base64String, timestamp, topic}\n const envelope: RawEnvelope = JSON.parse(data);\n\n // Validate envelope structure\n if (!envelope || typeof envelope !== \"object\") {\n throw new Error(\"Invalid envelope: not an object\");\n }\n\n // Handle presence events\n if (\n envelope.type === \"presence.join\" ||\n envelope.type === \"presence.leave\"\n ) {\n if (!envelope.member_id) {\n console.warn(\"[Subscription] Presence event missing member_id\");\n return;\n }\n\n const presenceMember: PresenceMember = {\n memberId: envelope.member_id,\n joinedAt: envelope.timestamp,\n meta: envelope.meta,\n };\n\n if (\n envelope.type === \"presence.join\" &&\n this.presenceOptions?.onJoin\n ) {\n this.presenceOptions.onJoin(presenceMember);\n } else if (\n envelope.type === \"presence.leave\" &&\n this.presenceOptions?.onLeave\n ) {\n this.presenceOptions.onLeave(presenceMember);\n }\n return; // Don't call regular onMessage for presence events\n }\n\n if (!envelope.data || typeof envelope.data !== \"string\") {\n throw new Error(\"Invalid envelope: missing or invalid data field\");\n }\n if (!envelope.topic || typeof envelope.topic !== \"string\") {\n throw new Error(\"Invalid envelope: missing or invalid topic field\");\n }\n if (typeof envelope.timestamp !== \"number\") {\n throw new Error(\n \"Invalid envelope: missing or invalid timestamp field\"\n );\n }\n\n // Decode base64 data\n const messageData = base64Decode(envelope.data);\n\n const message: PubSubMessage = {\n topic: envelope.topic,\n data: messageData,\n timestamp: envelope.timestamp,\n };\n\n console.log(\"[Subscription] Received message on topic:\", this.topic);\n this.messageHandlers.forEach((handler) => handler(message));\n } catch (error) {\n console.error(\"[Subscription] Error processing message:\", error);\n this.errorHandlers.forEach((handler) =>\n handler(error instanceof Error ? error : new Error(String(error)))\n );\n }\n };\n\n this.wsClient.onMessage(this.wsMessageHandler);\n\n // Register error handler\n this.wsErrorHandler = (error) => {\n this.errorHandlers.forEach((handler) => handler(error));\n };\n this.wsClient.onError(this.wsErrorHandler);\n\n // Register close handler\n this.wsCloseHandler = () => {\n this.closeHandlers.forEach((handler) => handler());\n };\n this.wsClient.onClose(this.wsCloseHandler);\n }\n\n /**\n * Get current presence (requires presence.enabled on subscribe)\n */\n async getPresence(): Promise<PresenceMember[]> {\n if (!this.presenceOptions?.enabled) {\n throw new Error(\"Presence is not enabled for this subscription\");\n }\n\n const response = await this.getPresenceFn();\n return response.members;\n }\n\n /**\n * Check if presence is enabled for this subscription\n */\n hasPresence(): boolean {\n return !!this.presenceOptions?.enabled;\n }\n\n /**\n * Register message handler\n */\n onMessage(handler: MessageHandler): () => void {\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n /**\n * Register error handler\n */\n onError(handler: ErrorHandler): () => void {\n this.errorHandlers.add(handler);\n return () => this.errorHandlers.delete(handler);\n }\n\n /**\n * Register close handler\n */\n onClose(handler: CloseHandler): () => void {\n this.closeHandlers.add(handler);\n return () => this.closeHandlers.delete(handler);\n }\n\n /**\n * Close subscription and underlying WebSocket\n */\n close(): void {\n if (this.isClosed) {\n return;\n }\n this.isClosed = true;\n\n // Remove handlers from WSClient\n if (this.wsMessageHandler) {\n this.wsClient.offMessage(this.wsMessageHandler);\n this.wsMessageHandler = null;\n }\n if (this.wsErrorHandler) {\n this.wsClient.offError(this.wsErrorHandler);\n this.wsErrorHandler = null;\n }\n if (this.wsCloseHandler) {\n this.wsClient.offClose(this.wsCloseHandler);\n this.wsCloseHandler = null;\n }\n\n // Clear all local handlers\n this.messageHandlers.clear();\n this.errorHandlers.clear();\n this.closeHandlers.clear();\n\n // Close WebSocket connection\n this.wsClient.close();\n }\n\n /**\n * Check if subscription is active\n */\n isConnected(): boolean {\n return !this.isClosed && this.wsClient.isConnected();\n }\n}\n","import { HttpClient } from \"../core/http\";\n\nexport interface PeerInfo {\n id: string;\n addresses: string[];\n lastSeen?: string;\n}\n\nexport interface NetworkStatus {\n node_id: string;\n connected: boolean;\n peer_count: number;\n database_size: number;\n uptime: number;\n}\n\nexport interface ProxyRequest {\n url: string;\n method: string;\n headers?: Record<string, string>;\n body?: string;\n}\n\nexport interface ProxyResponse {\n status_code: number;\n headers: Record<string, string>;\n body: string;\n error?: string;\n}\n\nexport class NetworkClient {\n private httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n /**\n * Check gateway health.\n */\n async health(): Promise<boolean> {\n try {\n await this.httpClient.get(\"/v1/health\");\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Get network status.\n */\n async status(): Promise<NetworkStatus> {\n const response = await this.httpClient.get<NetworkStatus>(\n \"/v1/network/status\"\n );\n return response;\n }\n\n /**\n * Get connected peers.\n */\n async peers(): Promise<PeerInfo[]> {\n const response = await this.httpClient.get<{ peers: PeerInfo[] }>(\n \"/v1/network/peers\"\n );\n return response.peers || [];\n }\n\n /**\n * Connect to a peer.\n */\n async connect(peerAddr: string): Promise<void> {\n await this.httpClient.post(\"/v1/network/connect\", { peer_addr: peerAddr });\n }\n\n /**\n * Disconnect from a peer.\n */\n async disconnect(peerId: string): Promise<void> {\n await this.httpClient.post(\"/v1/network/disconnect\", { peer_id: peerId });\n }\n\n /**\n * Proxy an HTTP request through the Anyone network.\n * Requires authentication (API key or JWT).\n *\n * @param request - The proxy request configuration\n * @returns The proxied response\n * @throws {SDKError} If the Anyone proxy is not available or the request fails\n *\n * @example\n * ```ts\n * const response = await client.network.proxyAnon({\n * url: 'https://api.example.com/data',\n * method: 'GET',\n * headers: {\n * 'Accept': 'application/json'\n * }\n * });\n *\n * console.log(response.status_code); // 200\n * console.log(response.body); // Response data\n * ```\n */\n async proxyAnon(request: ProxyRequest): Promise<ProxyResponse> {\n const response = await this.httpClient.post<ProxyResponse>(\n \"/v1/proxy/anon\",\n request\n );\n\n // Check if the response contains an error\n if (response.error) {\n throw new Error(`Proxy request failed: ${response.error}`);\n }\n\n return response;\n }\n}\n","import { HttpClient } from \"../core/http\";\nimport { SDKError } from \"../errors\";\n\nexport interface CacheGetRequest {\n dmap: string;\n key: string;\n}\n\nexport interface CacheGetResponse {\n key: string;\n value: any;\n dmap: string;\n}\n\nexport interface CachePutRequest {\n dmap: string;\n key: string;\n value: any;\n ttl?: string; // Duration string like \"1h\", \"30m\"\n}\n\nexport interface CachePutResponse {\n status: string;\n key: string;\n dmap: string;\n}\n\nexport interface CacheDeleteRequest {\n dmap: string;\n key: string;\n}\n\nexport interface CacheDeleteResponse {\n status: string;\n key: string;\n dmap: string;\n}\n\nexport interface CacheMultiGetRequest {\n dmap: string;\n keys: string[];\n}\n\nexport interface CacheMultiGetResponse {\n results: Array<{\n key: string;\n value: any;\n }>;\n dmap: string;\n}\n\nexport interface CacheScanRequest {\n dmap: string;\n match?: string; // Optional regex pattern\n}\n\nexport interface CacheScanResponse {\n keys: string[];\n count: number;\n dmap: string;\n}\n\nexport interface CacheHealthResponse {\n status: string;\n service: string;\n}\n\nexport class CacheClient {\n private httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n /**\n * Check cache service health\n */\n async health(): Promise<CacheHealthResponse> {\n return this.httpClient.get(\"/v1/cache/health\");\n }\n\n /**\n * Get a value from cache\n * Returns null if the key is not found (cache miss/expired), which is normal behavior\n */\n async get(dmap: string, key: string): Promise<CacheGetResponse | null> {\n try {\n return await this.httpClient.post<CacheGetResponse>(\"/v1/cache/get\", {\n dmap,\n key,\n });\n } catch (error) {\n // Cache misses (404 or \"key not found\" messages) are normal behavior - return null instead of throwing\n if (\n error instanceof SDKError &&\n (error.httpStatus === 404 ||\n (error.httpStatus === 500 &&\n error.message?.toLowerCase().includes(\"key not found\")))\n ) {\n return null;\n }\n // Re-throw other errors (network issues, server errors, etc.)\n throw error;\n }\n }\n\n /**\n * Put a value into cache\n */\n async put(\n dmap: string,\n key: string,\n value: any,\n ttl?: string\n ): Promise<CachePutResponse> {\n return this.httpClient.post<CachePutResponse>(\"/v1/cache/put\", {\n dmap,\n key,\n value,\n ttl,\n });\n }\n\n /**\n * Delete a value from cache\n */\n async delete(dmap: string, key: string): Promise<CacheDeleteResponse> {\n return this.httpClient.post<CacheDeleteResponse>(\"/v1/cache/delete\", {\n dmap,\n key,\n });\n }\n\n /**\n * Get multiple values from cache in a single request\n * Returns a map of key -> value (or null if not found)\n * Gracefully handles 404 errors (endpoint not implemented) by returning empty results\n */\n async multiGet(\n dmap: string,\n keys: string[]\n ): Promise<Map<string, any | null>> {\n try {\n if (keys.length === 0) {\n return new Map();\n }\n\n const response = await this.httpClient.post<CacheMultiGetResponse>(\n \"/v1/cache/mget\",\n {\n dmap,\n keys,\n }\n );\n\n // Convert array to Map\n const resultMap = new Map<string, any | null>();\n\n // First, mark all keys as null (cache miss)\n keys.forEach((key) => {\n resultMap.set(key, null);\n });\n\n // Then, update with found values\n if (response.results) {\n response.results.forEach(({ key, value }) => {\n resultMap.set(key, value);\n });\n }\n\n return resultMap;\n } catch (error) {\n // Handle 404 errors silently (endpoint not implemented on backend)\n // This is expected behavior when the backend doesn't support multiGet yet\n if (error instanceof SDKError && error.httpStatus === 404) {\n // Return map with all nulls silently - caller can fall back to individual gets\n const resultMap = new Map<string, any | null>();\n keys.forEach((key) => {\n resultMap.set(key, null);\n });\n return resultMap;\n }\n\n // Log and return empty results for other errors\n const resultMap = new Map<string, any | null>();\n keys.forEach((key) => {\n resultMap.set(key, null);\n });\n console.error(`[CacheClient] Error in multiGet for ${dmap}:`, error);\n return resultMap;\n }\n }\n\n /**\n * Scan keys in a distributed map, optionally matching a regex pattern\n */\n async scan(dmap: string, match?: string): Promise<CacheScanResponse> {\n return this.httpClient.post<CacheScanResponse>(\"/v1/cache/scan\", {\n dmap,\n match,\n });\n }\n}\n","import { HttpClient } from \"../core/http\";\n\nexport interface StorageUploadResponse {\n cid: string;\n name: string;\n size: number;\n}\n\nexport interface StoragePinRequest {\n cid: string;\n name?: string;\n}\n\nexport interface StoragePinResponse {\n cid: string;\n name: string;\n}\n\nexport interface StorageStatus {\n cid: string;\n name: string;\n status: string; // \"pinned\", \"pinning\", \"queued\", \"unpinned\", \"error\"\n replication_min: number;\n replication_max: number;\n replication_factor: number;\n peers: string[];\n error?: string;\n}\n\nexport class StorageClient {\n private httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n /**\n * Upload content to IPFS and optionally pin it.\n * Supports both File objects (browser) and Buffer/ReadableStream (Node.js).\n *\n * @param file - File to upload (File, Blob, or Buffer)\n * @param name - Optional filename\n * @param options - Optional upload options\n * @param options.pin - Whether to pin the content (default: true). Pinning happens asynchronously on the backend.\n * @returns Upload result with CID\n *\n * @example\n * ```ts\n * // Browser\n * const fileInput = document.querySelector('input[type=\"file\"]');\n * const file = fileInput.files[0];\n * const result = await client.storage.upload(file, file.name);\n * console.log(result.cid);\n *\n * // Node.js\n * const fs = require('fs');\n * const fileBuffer = fs.readFileSync('image.jpg');\n * const result = await client.storage.upload(fileBuffer, 'image.jpg', { pin: true });\n * ```\n */\n async upload(\n file: File | Blob | ArrayBuffer | Uint8Array | ReadableStream<Uint8Array>,\n name?: string,\n options?: {\n pin?: boolean;\n }\n ): Promise<StorageUploadResponse> {\n // Create FormData for multipart upload\n const formData = new FormData();\n\n // Handle different input types\n if (file instanceof File) {\n formData.append(\"file\", file);\n } else if (file instanceof Blob) {\n formData.append(\"file\", file, name);\n } else if (file instanceof ArrayBuffer) {\n const blob = new Blob([file]);\n formData.append(\"file\", blob, name);\n } else if (file instanceof Uint8Array) {\n // Convert Uint8Array to ArrayBuffer for Blob constructor\n const buffer = file.buffer.slice(\n file.byteOffset,\n file.byteOffset + file.byteLength\n ) as ArrayBuffer;\n const blob = new Blob([buffer], { type: \"application/octet-stream\" });\n formData.append(\"file\", blob, name);\n } else if (file instanceof ReadableStream) {\n // For ReadableStream, we need to read it into a blob first\n // This is a limitation - in practice, pass File/Blob/Buffer\n const chunks: ArrayBuffer[] = [];\n const reader = file.getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n const buffer = value.buffer.slice(\n value.byteOffset,\n value.byteOffset + value.byteLength\n ) as ArrayBuffer;\n chunks.push(buffer);\n }\n const blob = new Blob(chunks);\n formData.append(\"file\", blob, name);\n } else {\n throw new Error(\n \"Unsupported file type. Use File, Blob, ArrayBuffer, Uint8Array, or ReadableStream.\"\n );\n }\n\n // Add pin flag (default: true)\n const shouldPin = options?.pin !== false; // Default to true\n formData.append(\"pin\", shouldPin ? \"true\" : \"false\");\n\n return this.httpClient.uploadFile<StorageUploadResponse>(\n \"/v1/storage/upload\",\n formData,\n { timeout: 300000 } // 5 minute timeout for large files\n );\n }\n\n /**\n * Pin an existing CID\n *\n * @param cid - Content ID to pin\n * @param name - Optional name for the pin\n * @returns Pin result\n */\n async pin(cid: string, name?: string): Promise<StoragePinResponse> {\n return this.httpClient.post<StoragePinResponse>(\"/v1/storage/pin\", {\n cid,\n name,\n });\n }\n\n /**\n * Get the pin status for a CID\n *\n * @param cid - Content ID to check\n * @returns Pin status information\n */\n async status(cid: string): Promise<StorageStatus> {\n return this.httpClient.get<StorageStatus>(`/v1/storage/status/${cid}`);\n }\n\n /**\n * Retrieve content from IPFS by CID\n *\n * @param cid - Content ID to retrieve\n * @returns ReadableStream of the content\n *\n * @example\n * ```ts\n * const stream = await client.storage.get(cid);\n * const reader = stream.getReader();\n * while (true) {\n * const { done, value } = await reader.read();\n * if (done) break;\n * // Process chunk\n * }\n * ```\n */\n async get(cid: string): Promise<ReadableStream<Uint8Array>> {\n // Retry logic for content retrieval - content may not be immediately available\n // after upload due to eventual consistency in IPFS Cluster\n // IPFS Cluster pins can take 2-3+ seconds to complete across all nodes\n const maxAttempts = 8;\n let lastError: Error | null = null;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const response = await this.httpClient.getBinary(\n `/v1/storage/get/${cid}`\n );\n\n if (!response.body) {\n throw new Error(\"Response body is null\");\n }\n\n return response.body;\n } catch (error: any) {\n lastError = error;\n\n // Check if this is a 404 error (content not found)\n const isNotFound =\n error?.httpStatus === 404 ||\n error?.message?.includes(\"not found\") ||\n error?.message?.includes(\"404\");\n\n // If it's not a 404 error, or this is the last attempt, give up\n if (!isNotFound || attempt === maxAttempts) {\n throw error;\n }\n\n // Wait before retrying (exponential backoff: 400ms, 800ms, 1200ms, etc.)\n // This gives up to ~12 seconds total wait time, covering typical pin completion\n const backoffMs = attempt * 2500;\n await new Promise((resolve) => setTimeout(resolve, backoffMs));\n }\n }\n\n // This should never be reached, but TypeScript needs it\n throw lastError || new Error(\"Failed to retrieve content\");\n }\n\n /**\n * Retrieve content from IPFS by CID and return the full Response object\n * Useful when you need access to response headers (e.g., content-length)\n *\n * @param cid - Content ID to retrieve\n * @returns Response object with body stream and headers\n *\n * @example\n * ```ts\n * const response = await client.storage.getBinary(cid);\n * const contentLength = response.headers.get('content-length');\n * const reader = response.body.getReader();\n * // ... read stream\n * ```\n */\n async getBinary(cid: string): Promise<Response> {\n // Retry logic for content retrieval - content may not be immediately available\n // after upload due to eventual consistency in IPFS Cluster\n // IPFS Cluster pins can take 2-3+ seconds to complete across all nodes\n const maxAttempts = 8;\n let lastError: Error | null = null;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const response = await this.httpClient.getBinary(\n `/v1/storage/get/${cid}`\n );\n\n if (!response) {\n throw new Error(\"Response is null\");\n }\n\n return response;\n } catch (error: any) {\n lastError = error;\n\n // Check if this is a 404 error (content not found)\n const isNotFound =\n error?.httpStatus === 404 ||\n error?.message?.includes(\"not found\") ||\n error?.message?.includes(\"404\");\n\n // If it's not a 404 error, or this is the last attempt, give up\n if (!isNotFound || attempt === maxAttempts) {\n throw error;\n }\n\n // Wait before retrying (exponential backoff: 400ms, 800ms, 1200ms, etc.)\n // This gives up to ~12 seconds total wait time, covering typical pin completion\n const backoffMs = attempt * 2500;\n await new Promise((resolve) => setTimeout(resolve, backoffMs));\n }\n }\n\n // This should never be reached, but TypeScript needs it\n throw lastError || new Error(\"Failed to retrieve content\");\n }\n\n /**\n * Unpin a CID\n *\n * @param cid - Content ID to unpin\n */\n async unpin(cid: string): Promise<void> {\n await this.httpClient.delete(`/v1/storage/unpin/${cid}`);\n }\n}\n","/**\n * Functions Client\n * Client for calling serverless functions on the Orama Network\n */\n\nimport { HttpClient } from \"../core/http\";\nimport { SDKError } from \"../errors\";\n\nexport interface FunctionsClientConfig {\n /**\n * Base URL for the functions gateway\n * Defaults to using the same baseURL as the HTTP client\n */\n gatewayURL?: string;\n \n /**\n * Namespace for the functions\n */\n namespace: string;\n}\n\nexport class FunctionsClient {\n private httpClient: HttpClient;\n private gatewayURL?: string;\n private namespace: string;\n\n constructor(httpClient: HttpClient, config?: FunctionsClientConfig) {\n this.httpClient = httpClient;\n this.gatewayURL = config?.gatewayURL;\n this.namespace = config?.namespace ?? \"default\";\n }\n\n /**\n * Invoke a serverless function by name\n * \n * @param functionName - Name of the function to invoke\n * @param input - Input payload for the function\n * @returns The function response\n */\n async invoke<TInput = any, TOutput = any>(\n functionName: string,\n input: TInput\n ): Promise<TOutput> {\n const url = this.gatewayURL\n ? `${this.gatewayURL}/v1/invoke/${this.namespace}/${functionName}`\n : `/v1/invoke/${this.namespace}/${functionName}`;\n\n try {\n const response = await this.httpClient.post<TOutput>(url, input);\n return response;\n } catch (error) {\n if (error instanceof SDKError) {\n throw error;\n }\n throw new SDKError(\n `Function ${functionName} failed`,\n 500,\n error instanceof Error ? error.message : String(error)\n );\n }\n }\n}\n","import { HttpClient, HttpClientConfig } from \"./core/http\";\nimport { AuthClient } from \"./auth/client\";\nimport { DBClient } from \"./db/client\";\nimport { PubSubClient } from \"./pubsub/client\";\nimport { NetworkClient } from \"./network/client\";\nimport { CacheClient } from \"./cache/client\";\nimport { StorageClient } from \"./storage/client\";\nimport { FunctionsClient, FunctionsClientConfig } from \"./functions/client\";\nimport { WSClientConfig } from \"./core/ws\";\nimport {\n StorageAdapter,\n MemoryStorage,\n LocalStorageAdapter,\n} from \"./auth/types\";\n\nexport interface ClientConfig extends Omit<HttpClientConfig, \"fetch\"> {\n apiKey?: string;\n jwt?: string;\n storage?: StorageAdapter;\n wsConfig?: Partial<Omit<WSClientConfig, \"wsURL\">>;\n functionsConfig?: FunctionsClientConfig;\n fetch?: typeof fetch;\n}\n\nexport interface Client {\n auth: AuthClient;\n db: DBClient;\n pubsub: PubSubClient;\n network: NetworkClient;\n cache: CacheClient;\n storage: StorageClient;\n functions: FunctionsClient;\n}\n\nexport function createClient(config: ClientConfig): Client {\n const httpClient = new HttpClient({\n baseURL: config.baseURL,\n timeout: config.timeout,\n maxRetries: config.maxRetries,\n retryDelayMs: config.retryDelayMs,\n fetch: config.fetch,\n });\n\n const auth = new AuthClient({\n httpClient,\n storage: config.storage,\n apiKey: config.apiKey,\n jwt: config.jwt,\n });\n\n // Derive WebSocket URL from baseURL\n const wsURL = config.baseURL.replace(/^http/, \"ws\").replace(/\\/$/, \"\");\n\n const db = new DBClient(httpClient);\n const pubsub = new PubSubClient(httpClient, {\n ...config.wsConfig,\n wsURL,\n });\n const network = new NetworkClient(httpClient);\n const cache = new CacheClient(httpClient);\n const storage = new StorageClient(httpClient);\n const functions = new FunctionsClient(httpClient, config.functionsConfig);\n\n return {\n auth,\n db,\n pubsub,\n network,\n cache,\n storage,\n functions,\n };\n}\n\nexport { HttpClient } from \"./core/http\";\nexport { WSClient } from \"./core/ws\";\nexport { AuthClient } from \"./auth/client\";\nexport { DBClient } from \"./db/client\";\nexport { QueryBuilder } from \"./db/qb\";\nexport { Repository } from \"./db/repository\";\nexport { PubSubClient, Subscription } from \"./pubsub/client\";\nexport { NetworkClient } from \"./network/client\";\nexport { CacheClient } from \"./cache/client\";\nexport { StorageClient } from \"./storage/client\";\nexport { FunctionsClient } from \"./functions/client\";\nexport { SDKError } from \"./errors\";\nexport { MemoryStorage, LocalStorageAdapter } from \"./auth/types\";\nexport type { StorageAdapter, AuthConfig, WhoAmI } from \"./auth/types\";\nexport type * from \"./db/types\";\nexport type {\n MessageHandler,\n ErrorHandler,\n CloseHandler,\n PresenceMember,\n PresenceResponse,\n PresenceOptions,\n SubscribeOptions,\n} from \"./pubsub/types\";\nexport { type PubSubMessage } from \"./pubsub/types\";\nexport type {\n PeerInfo,\n NetworkStatus,\n ProxyRequest,\n ProxyResponse,\n} from \"./network/client\";\nexport type {\n CacheGetRequest,\n CacheGetResponse,\n CachePutRequest,\n CachePutResponse,\n CacheDeleteRequest,\n CacheDeleteResponse,\n CacheMultiGetRequest,\n CacheMultiGetResponse,\n CacheScanRequest,\n CacheScanResponse,\n CacheHealthResponse,\n} from \"./cache/client\";\nexport type {\n StorageUploadResponse,\n StoragePinRequest,\n StoragePinResponse,\n StorageStatus,\n} from \"./storage/client\";\nexport type { FunctionsClientConfig } from \"./functions/client\";\nexport type * from \"./functions/types\";\n"],"mappings":"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","names":["resultMap"]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/core/http.ts","../src/auth/types.ts","../src/auth/client.ts","../src/db/qb.ts","../src/db/repository.ts","../src/db/client.ts","../src/core/ws.ts","../src/pubsub/client.ts","../src/network/client.ts","../src/cache/client.ts","../src/storage/client.ts","../src/functions/client.ts","../src/index.ts"],"sourcesContent":["export class SDKError extends Error {\n public readonly httpStatus: number;\n public readonly code: string;\n public readonly details: Record<string, any>;\n\n constructor(\n message: string,\n httpStatus: number = 500,\n code: string = \"SDK_ERROR\",\n details: Record<string, any> = {}\n ) {\n super(message);\n this.name = \"SDKError\";\n this.httpStatus = httpStatus;\n this.code = code;\n this.details = details;\n }\n\n static fromResponse(\n status: number,\n body: any,\n message?: string\n ): SDKError {\n const errorMsg = message || body?.error || `HTTP ${status}`;\n const code = body?.code || `HTTP_${status}`;\n return new SDKError(errorMsg, status, code, body);\n }\n\n toJSON() {\n return {\n name: this.name,\n message: this.message,\n httpStatus: this.httpStatus,\n code: this.code,\n details: this.details,\n };\n }\n}\n","import { SDKError } from \"../errors\";\n\n/**\n * Context provided to the onNetworkError callback\n */\nexport interface NetworkErrorContext {\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\" | \"WS\";\n path: string;\n isRetry: boolean;\n attempt: number;\n}\n\n/**\n * Callback invoked when a network error occurs.\n * Use this to trigger gateway failover or other error handling.\n */\nexport type NetworkErrorCallback = (\n error: SDKError,\n context: NetworkErrorContext\n) => void;\n\nexport interface HttpClientConfig {\n baseURL: string;\n timeout?: number;\n maxRetries?: number;\n retryDelayMs?: number;\n fetch?: typeof fetch;\n /**\n * Callback invoked on network errors (after all retries exhausted).\n * Use this to trigger gateway failover at the application layer.\n */\n onNetworkError?: NetworkErrorCallback;\n}\n\n/**\n * Create a fetch function with proper TLS configuration for staging certificates\n * In Node.js, we need to configure TLS to accept Let's Encrypt staging certificates\n */\nfunction createFetchWithTLSConfig(): typeof fetch {\n // Check if we're in a Node.js environment\n if (typeof process !== \"undefined\" && process.versions?.node) {\n // For testing/staging/development: allow staging certificates\n // Let's Encrypt staging certificates are self-signed and not trusted by default\n const isDevelopmentOrStaging =\n process.env.NODE_ENV !== \"production\" ||\n process.env.DEBROS_ALLOW_STAGING_CERTS === \"true\" ||\n process.env.DEBROS_USE_HTTPS === \"true\";\n\n if (isDevelopmentOrStaging) {\n // Allow self-signed/staging certificates\n // WARNING: Only use this in development/testing environments\n process.env.NODE_TLS_REJECT_UNAUTHORIZED = \"0\";\n }\n }\n return globalThis.fetch;\n}\n\nexport class HttpClient {\n private baseURL: string;\n private timeout: number;\n private maxRetries: number;\n private retryDelayMs: number;\n private fetch: typeof fetch;\n private apiKey?: string;\n private jwt?: string;\n private onNetworkError?: NetworkErrorCallback;\n\n constructor(config: HttpClientConfig) {\n this.baseURL = config.baseURL.replace(/\\/$/, \"\");\n this.timeout = config.timeout ?? 60000;\n this.maxRetries = config.maxRetries ?? 3;\n this.retryDelayMs = config.retryDelayMs ?? 1000;\n // Use provided fetch or create one with proper TLS configuration for staging certificates\n this.fetch = config.fetch ?? createFetchWithTLSConfig();\n this.onNetworkError = config.onNetworkError;\n }\n\n /**\n * Set the network error callback\n */\n setOnNetworkError(callback: NetworkErrorCallback | undefined): void {\n this.onNetworkError = callback;\n }\n\n setApiKey(apiKey?: string) {\n this.apiKey = apiKey;\n // Don't clear JWT - allow both to coexist\n }\n\n setJwt(jwt?: string) {\n this.jwt = jwt;\n // Don't clear API key - allow both to coexist\n if (typeof console !== \"undefined\") {\n console.log(\n \"[HttpClient] JWT set:\",\n !!jwt,\n \"API key still present:\",\n !!this.apiKey\n );\n }\n }\n\n private getAuthHeaders(path: string): Record<string, string> {\n const headers: Record<string, string> = {};\n\n // For database, pubsub, proxy, and cache operations, ONLY use API key to avoid JWT user context\n // interfering with namespace-level authorization\n const isDbOperation = path.includes(\"/v1/rqlite/\");\n const isPubSubOperation = path.includes(\"/v1/pubsub/\");\n const isProxyOperation = path.includes(\"/v1/proxy/\");\n const isCacheOperation = path.includes(\"/v1/cache/\");\n\n // For auth operations, prefer API key over JWT to ensure proper authentication\n const isAuthOperation = path.includes(\"/v1/auth/\");\n\n if (\n isDbOperation ||\n isPubSubOperation ||\n isProxyOperation ||\n isCacheOperation\n ) {\n // For database/pubsub/proxy/cache operations: use only API key (preferred for namespace operations)\n if (this.apiKey) {\n headers[\"X-API-Key\"] = this.apiKey;\n } else if (this.jwt) {\n // Fallback to JWT if no API key\n headers[\"Authorization\"] = `Bearer ${this.jwt}`;\n }\n } else if (isAuthOperation) {\n // For auth operations: prefer API key over JWT (auth endpoints should use explicit API key)\n if (this.apiKey) {\n headers[\"X-API-Key\"] = this.apiKey;\n }\n if (this.jwt) {\n headers[\"Authorization\"] = `Bearer ${this.jwt}`;\n }\n } else {\n // For other operations: send both JWT and API key\n if (this.jwt) {\n headers[\"Authorization\"] = `Bearer ${this.jwt}`;\n }\n if (this.apiKey) {\n headers[\"X-API-Key\"] = this.apiKey;\n }\n }\n return headers;\n }\n\n private getAuthToken(): string | undefined {\n return this.jwt || this.apiKey;\n }\n\n getApiKey(): string | undefined {\n return this.apiKey;\n }\n\n /**\n * Get the base URL\n */\n getBaseURL(): string {\n return this.baseURL;\n }\n\n async request<T = any>(\n method: \"GET\" | \"POST\" | \"PUT\" | \"DELETE\",\n path: string,\n options: {\n body?: any;\n headers?: Record<string, string>;\n query?: Record<string, string | number | boolean>;\n timeout?: number; // Per-request timeout override\n } = {}\n ): Promise<T> {\n const startTime = performance.now(); // Track request start time\n const url = new URL(this.baseURL + path);\n if (options.query) {\n Object.entries(options.query).forEach(([key, value]) => {\n url.searchParams.append(key, String(value));\n });\n }\n\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...this.getAuthHeaders(path),\n ...options.headers,\n };\n\n const controller = new AbortController();\n const requestTimeout = options.timeout ?? this.timeout; // Use override or default\n const timeoutId = setTimeout(() => controller.abort(), requestTimeout);\n\n const fetchOptions: RequestInit = {\n method,\n headers,\n signal: controller.signal,\n };\n\n if (options.body !== undefined) {\n fetchOptions.body = JSON.stringify(options.body);\n }\n\n // Extract and log SQL query details for rqlite operations\n const isRqliteOperation = path.includes(\"/v1/rqlite/\");\n let queryDetails: string | null = null;\n if (isRqliteOperation && options.body) {\n try {\n const body =\n typeof options.body === \"string\"\n ? JSON.parse(options.body)\n : options.body;\n\n if (body.sql) {\n // Direct SQL query (query/exec endpoints)\n queryDetails = `SQL: ${body.sql}`;\n if (body.args && body.args.length > 0) {\n queryDetails += ` | Args: [${body.args\n .map((a: any) => (typeof a === \"string\" ? `\"${a}\"` : a))\n .join(\", \")}]`;\n }\n } else if (body.table) {\n // Table-based query (find/find-one/select endpoints)\n queryDetails = `Table: ${body.table}`;\n if (body.criteria && Object.keys(body.criteria).length > 0) {\n queryDetails += ` | Criteria: ${JSON.stringify(body.criteria)}`;\n }\n if (body.options) {\n queryDetails += ` | Options: ${JSON.stringify(body.options)}`;\n }\n if (body.select) {\n queryDetails += ` | Select: ${JSON.stringify(body.select)}`;\n }\n if (body.where) {\n queryDetails += ` | Where: ${JSON.stringify(body.where)}`;\n }\n if (body.limit) {\n queryDetails += ` | Limit: ${body.limit}`;\n }\n if (body.offset) {\n queryDetails += ` | Offset: ${body.offset}`;\n }\n }\n } catch (e) {\n // Failed to parse body, ignore\n }\n }\n\n try {\n const result = await this.requestWithRetry(\n url.toString(),\n fetchOptions,\n 0,\n startTime\n );\n const duration = performance.now() - startTime;\n if (typeof console !== \"undefined\") {\n const logMessage = `[HttpClient] ${method} ${path} completed in ${duration.toFixed(\n 2\n )}ms`;\n if (queryDetails) {\n console.log(logMessage);\n console.log(`[HttpClient] ${queryDetails}`);\n } else {\n console.log(logMessage);\n }\n }\n return result;\n } catch (error) {\n const duration = performance.now() - startTime;\n if (typeof console !== \"undefined\") {\n // For 404 errors on find-one calls, log at warn level (not error) since \"not found\" is expected\n // Application layer handles these cases in try-catch blocks\n const is404FindOne =\n path === \"/v1/rqlite/find-one\" &&\n error instanceof SDKError &&\n error.httpStatus === 404;\n\n if (is404FindOne) {\n // Log as warning for visibility, but not as error since it's expected behavior\n console.warn(\n `[HttpClient] ${method} ${path} returned 404 after ${duration.toFixed(\n 2\n )}ms (expected for optional lookups)`\n );\n } else {\n const errorMessage = `[HttpClient] ${method} ${path} failed after ${duration.toFixed(\n 2\n )}ms:`;\n console.error(errorMessage, error);\n if (queryDetails) {\n console.error(`[HttpClient] ${queryDetails}`);\n }\n }\n }\n\n // Call the network error callback if configured\n // This allows the app to trigger gateway failover\n if (this.onNetworkError) {\n // Convert native errors (TypeError, AbortError) to SDKError for the callback\n const sdkError =\n error instanceof SDKError\n ? error\n : new SDKError(\n error instanceof Error ? error.message : String(error),\n 0, // httpStatus 0 indicates network-level failure\n \"NETWORK_ERROR\"\n );\n this.onNetworkError(sdkError, {\n method,\n path,\n isRetry: false,\n attempt: this.maxRetries, // All retries exhausted\n });\n }\n\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private async requestWithRetry(\n url: string,\n options: RequestInit,\n attempt: number = 0,\n startTime?: number // Track start time for timing across retries\n ): Promise<any> {\n try {\n const response = await this.fetch(url, options);\n\n if (!response.ok) {\n let body: any;\n try {\n body = await response.json();\n } catch {\n body = { error: response.statusText };\n }\n throw SDKError.fromResponse(response.status, body);\n }\n\n // Request succeeded - return response\n const contentType = response.headers.get(\"content-type\");\n if (contentType?.includes(\"application/json\")) {\n return response.json();\n }\n return response.text();\n } catch (error) {\n const isRetryableError =\n error instanceof SDKError &&\n [408, 429, 500, 502, 503, 504].includes(error.httpStatus);\n\n // Retry on same gateway for retryable HTTP errors\n if (isRetryableError && attempt < this.maxRetries) {\n if (typeof console !== \"undefined\") {\n console.warn(\n `[HttpClient] Retrying request (attempt ${attempt + 1}/${this.maxRetries})`\n );\n }\n await new Promise((resolve) =>\n setTimeout(resolve, this.retryDelayMs * (attempt + 1))\n );\n return this.requestWithRetry(url, options, attempt + 1, startTime);\n }\n\n // All retries exhausted - throw error for app to handle\n throw error;\n }\n }\n\n async get<T = any>(\n path: string,\n options?: Omit<Parameters<typeof this.request>[2], \"body\">\n ): Promise<T> {\n return this.request<T>(\"GET\", path, options);\n }\n\n async post<T = any>(\n path: string,\n body?: any,\n options?: Omit<Parameters<typeof this.request>[2], \"body\">\n ): Promise<T> {\n return this.request<T>(\"POST\", path, { ...options, body });\n }\n\n async put<T = any>(\n path: string,\n body?: any,\n options?: Omit<Parameters<typeof this.request>[2], \"body\">\n ): Promise<T> {\n return this.request<T>(\"PUT\", path, { ...options, body });\n }\n\n async delete<T = any>(\n path: string,\n options?: Omit<Parameters<typeof this.request>[2], \"body\">\n ): Promise<T> {\n return this.request<T>(\"DELETE\", path, options);\n }\n\n /**\n * Upload a file using multipart/form-data\n * This is a special method for file uploads that bypasses JSON serialization\n */\n async uploadFile<T = any>(\n path: string,\n formData: FormData,\n options?: {\n timeout?: number;\n }\n ): Promise<T> {\n const startTime = performance.now(); // Track upload start time\n const url = new URL(this.baseURL + path);\n const headers: Record<string, string> = {\n ...this.getAuthHeaders(path),\n // Don't set Content-Type - browser will set it with boundary\n };\n\n const controller = new AbortController();\n const requestTimeout = options?.timeout ?? this.timeout * 5; // 5x timeout for uploads\n const timeoutId = setTimeout(() => controller.abort(), requestTimeout);\n\n const fetchOptions: RequestInit = {\n method: \"POST\",\n headers,\n body: formData,\n signal: controller.signal,\n };\n\n try {\n const result = await this.requestWithRetry(\n url.toString(),\n fetchOptions,\n 0,\n startTime\n );\n const duration = performance.now() - startTime;\n if (typeof console !== \"undefined\") {\n console.log(\n `[HttpClient] POST ${path} (upload) completed in ${duration.toFixed(\n 2\n )}ms`\n );\n }\n return result;\n } catch (error) {\n const duration = performance.now() - startTime;\n if (typeof console !== \"undefined\") {\n console.error(\n `[HttpClient] POST ${path} (upload) failed after ${duration.toFixed(\n 2\n )}ms:`,\n error\n );\n }\n\n // Call the network error callback if configured\n if (this.onNetworkError) {\n const sdkError =\n error instanceof SDKError\n ? error\n : new SDKError(\n error instanceof Error ? error.message : String(error),\n 0,\n \"NETWORK_ERROR\"\n );\n this.onNetworkError(sdkError, {\n method: \"POST\",\n path,\n isRetry: false,\n attempt: this.maxRetries,\n });\n }\n\n throw error;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n /**\n * Get a binary response (returns Response object for streaming)\n */\n async getBinary(path: string): Promise<Response> {\n const url = new URL(this.baseURL + path);\n const headers: Record<string, string> = {\n ...this.getAuthHeaders(path),\n };\n\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout * 5); // 5x timeout for downloads\n\n const fetchOptions: RequestInit = {\n method: \"GET\",\n headers,\n signal: controller.signal,\n };\n\n try {\n const response = await this.fetch(url.toString(), fetchOptions);\n if (!response.ok) {\n clearTimeout(timeoutId);\n const errorBody = await response.json().catch(() => ({\n error: response.statusText,\n }));\n throw SDKError.fromResponse(response.status, errorBody);\n }\n return response;\n } catch (error) {\n clearTimeout(timeoutId);\n\n // Call the network error callback if configured\n if (this.onNetworkError) {\n const sdkError =\n error instanceof SDKError\n ? error\n : new SDKError(\n error instanceof Error ? error.message : String(error),\n 0,\n \"NETWORK_ERROR\"\n );\n this.onNetworkError(sdkError, {\n method: \"GET\",\n path,\n isRetry: false,\n attempt: 0,\n });\n }\n\n throw error;\n }\n }\n\n getToken(): string | undefined {\n return this.getAuthToken();\n }\n}\n","export interface AuthConfig {\n apiKey?: string;\n jwt?: string;\n}\n\nexport interface WhoAmI {\n address?: string;\n namespace?: string;\n authenticated: boolean;\n}\n\nexport interface StorageAdapter {\n get(key: string): Promise<string | null>;\n set(key: string, value: string): Promise<void>;\n clear(): Promise<void>;\n}\n\nexport class MemoryStorage implements StorageAdapter {\n private storage: Map<string, string> = new Map();\n\n async get(key: string): Promise<string | null> {\n return this.storage.get(key) ?? null;\n }\n\n async set(key: string, value: string): Promise<void> {\n this.storage.set(key, value);\n }\n\n async clear(): Promise<void> {\n this.storage.clear();\n }\n}\n\nexport class LocalStorageAdapter implements StorageAdapter {\n private prefix = \"@network/sdk:\";\n\n async get(key: string): Promise<string | null> {\n if (typeof globalThis !== \"undefined\" && globalThis.localStorage) {\n return globalThis.localStorage.getItem(this.prefix + key);\n }\n return null;\n }\n\n async set(key: string, value: string): Promise<void> {\n if (typeof globalThis !== \"undefined\" && globalThis.localStorage) {\n globalThis.localStorage.setItem(this.prefix + key, value);\n }\n }\n\n async clear(): Promise<void> {\n if (typeof globalThis !== \"undefined\" && globalThis.localStorage) {\n const keysToDelete: string[] = [];\n for (let i = 0; i < globalThis.localStorage.length; i++) {\n const key = globalThis.localStorage.key(i);\n if (key?.startsWith(this.prefix)) {\n keysToDelete.push(key);\n }\n }\n keysToDelete.forEach((key) => globalThis.localStorage.removeItem(key));\n }\n }\n}\n","import { HttpClient } from \"../core/http\";\nimport { AuthConfig, WhoAmI, StorageAdapter, MemoryStorage } from \"./types\";\n\nexport class AuthClient {\n private httpClient: HttpClient;\n private storage: StorageAdapter;\n private currentApiKey?: string;\n private currentJwt?: string;\n\n constructor(config: {\n httpClient: HttpClient;\n storage?: StorageAdapter;\n apiKey?: string;\n jwt?: string;\n }) {\n this.httpClient = config.httpClient;\n this.storage = config.storage ?? new MemoryStorage();\n this.currentApiKey = config.apiKey;\n this.currentJwt = config.jwt;\n\n if (this.currentApiKey) {\n this.httpClient.setApiKey(this.currentApiKey);\n }\n if (this.currentJwt) {\n this.httpClient.setJwt(this.currentJwt);\n }\n }\n\n setApiKey(apiKey: string) {\n this.currentApiKey = apiKey;\n // Don't clear JWT - it will be cleared explicitly on logout\n this.httpClient.setApiKey(apiKey);\n this.storage.set(\"apiKey\", apiKey);\n }\n\n setJwt(jwt: string) {\n this.currentJwt = jwt;\n // Don't clear API key - keep it as fallback for after logout\n this.httpClient.setJwt(jwt);\n this.storage.set(\"jwt\", jwt);\n }\n\n getToken(): string | undefined {\n return this.httpClient.getToken();\n }\n\n async whoami(): Promise<WhoAmI> {\n try {\n const response = await this.httpClient.get<WhoAmI>(\"/v1/auth/whoami\");\n return response;\n } catch {\n return { authenticated: false };\n }\n }\n\n async refresh(): Promise<string> {\n const response = await this.httpClient.post<{ token: string }>(\n \"/v1/auth/refresh\"\n );\n const token = response.token;\n this.setJwt(token);\n return token;\n }\n\n /**\n * Logout user and clear JWT, but preserve API key\n * Use this for user logout in apps where API key is app-level credential\n */\n async logoutUser(): Promise<void> {\n // Attempt server-side logout if using JWT\n if (this.currentJwt) {\n try {\n await this.httpClient.post(\"/v1/auth/logout\", { all: true });\n } catch (error) {\n // Log warning but don't fail - local cleanup is more important\n console.warn(\n \"Server-side logout failed, continuing with local cleanup:\",\n error\n );\n }\n }\n\n // Clear JWT only, preserve API key\n this.currentJwt = undefined;\n this.httpClient.setJwt(undefined);\n await this.storage.set(\"jwt\", \"\"); // Clear JWT from storage\n\n // Ensure API key is loaded and set as active auth method\n if (!this.currentApiKey) {\n // Try to load from storage\n const storedApiKey = await this.storage.get(\"apiKey\");\n if (storedApiKey) {\n this.currentApiKey = storedApiKey;\n }\n }\n\n // Restore API key as the active auth method\n if (this.currentApiKey) {\n this.httpClient.setApiKey(this.currentApiKey);\n console.log(\"[Auth] API key restored after user logout\");\n } else {\n console.warn(\"[Auth] No API key available after logout\");\n }\n }\n\n /**\n * Full logout - clears both JWT and API key\n * Use this to completely reset authentication state\n */\n async logout(): Promise<void> {\n // Only attempt server-side logout if using JWT\n // API keys don't support server-side logout with all=true\n if (this.currentJwt) {\n try {\n await this.httpClient.post(\"/v1/auth/logout\", { all: true });\n } catch (error) {\n // Log warning but don't fail - local cleanup is more important\n console.warn(\n \"Server-side logout failed, continuing with local cleanup:\",\n error\n );\n }\n }\n\n // Always clear local state\n this.currentApiKey = undefined;\n this.currentJwt = undefined;\n this.httpClient.setApiKey(undefined);\n this.httpClient.setJwt(undefined);\n await this.storage.clear();\n }\n\n async clear(): Promise<void> {\n this.currentApiKey = undefined;\n this.currentJwt = undefined;\n this.httpClient.setApiKey(undefined);\n this.httpClient.setJwt(undefined);\n await this.storage.clear();\n }\n\n /**\n * Request a challenge nonce for wallet authentication\n */\n async challenge(params: {\n wallet: string;\n purpose?: string;\n namespace?: string;\n }): Promise<{\n nonce: string;\n wallet: string;\n namespace: string;\n expires_at: string;\n }> {\n const response = await this.httpClient.post(\"/v1/auth/challenge\", {\n wallet: params.wallet,\n purpose: params.purpose || \"authentication\",\n namespace: params.namespace || \"default\",\n });\n return response;\n }\n\n /**\n * Verify wallet signature and get JWT token\n */\n async verify(params: {\n wallet: string;\n nonce: string;\n signature: string;\n namespace?: string;\n chain_type?: \"ETH\" | \"SOL\";\n }): Promise<{\n access_token: string;\n refresh_token?: string;\n subject: string;\n namespace: string;\n api_key?: string;\n expires_in?: number;\n token_type?: string;\n }> {\n const response = await this.httpClient.post(\"/v1/auth/verify\", {\n wallet: params.wallet,\n nonce: params.nonce,\n signature: params.signature,\n namespace: params.namespace || \"default\",\n chain_type: params.chain_type || \"ETH\",\n });\n\n // Persist JWT\n this.setJwt(response.access_token);\n\n // Persist API key if server provided it (created in verifyHandler)\n if ((response as any).api_key) {\n this.setApiKey((response as any).api_key);\n }\n\n // Persist refresh token if present (optional, for silent renewal)\n if ((response as any).refresh_token) {\n await this.storage.set(\"refreshToken\", (response as any).refresh_token);\n }\n\n return response as any;\n }\n\n /**\n * Get API key for wallet (creates namespace ownership)\n */\n async getApiKey(params: {\n wallet: string;\n nonce: string;\n signature: string;\n namespace?: string;\n chain_type?: \"ETH\" | \"SOL\";\n }): Promise<{\n api_key: string;\n namespace: string;\n wallet: string;\n }> {\n const response = await this.httpClient.post(\"/v1/auth/api-key\", {\n wallet: params.wallet,\n nonce: params.nonce,\n signature: params.signature,\n namespace: params.namespace || \"default\",\n chain_type: params.chain_type || \"ETH\",\n });\n\n // Automatically set the API key\n this.setApiKey(response.api_key);\n\n return response;\n }\n}\n","import { HttpClient } from \"../core/http\";\nimport { SelectOptions, QueryResponse } from \"./types\";\n\nexport class QueryBuilder {\n private httpClient: HttpClient;\n private table: string;\n private options: SelectOptions = {};\n\n constructor(httpClient: HttpClient, table: string) {\n this.httpClient = httpClient;\n this.table = table;\n }\n\n select(...columns: string[]): this {\n this.options.select = columns;\n return this;\n }\n\n innerJoin(table: string, on: string): this {\n if (!this.options.joins) this.options.joins = [];\n this.options.joins.push({ kind: \"INNER\", table, on });\n return this;\n }\n\n leftJoin(table: string, on: string): this {\n if (!this.options.joins) this.options.joins = [];\n this.options.joins.push({ kind: \"LEFT\", table, on });\n return this;\n }\n\n rightJoin(table: string, on: string): this {\n if (!this.options.joins) this.options.joins = [];\n this.options.joins.push({ kind: \"RIGHT\", table, on });\n return this;\n }\n\n where(expr: string, args?: any[]): this {\n if (!this.options.where) this.options.where = [];\n this.options.where.push({ conj: \"AND\", expr, args });\n return this;\n }\n\n andWhere(expr: string, args?: any[]): this {\n return this.where(expr, args);\n }\n\n orWhere(expr: string, args?: any[]): this {\n if (!this.options.where) this.options.where = [];\n this.options.where.push({ conj: \"OR\", expr, args });\n return this;\n }\n\n groupBy(...columns: string[]): this {\n this.options.group_by = columns;\n return this;\n }\n\n orderBy(...columns: string[]): this {\n this.options.order_by = columns;\n return this;\n }\n\n limit(n: number): this {\n this.options.limit = n;\n return this;\n }\n\n offset(n: number): this {\n this.options.offset = n;\n return this;\n }\n\n async getMany<T = any>(ctx?: any): Promise<T[]> {\n const response = await this.httpClient.post<QueryResponse>(\n \"/v1/rqlite/select\",\n {\n table: this.table,\n ...this.options,\n }\n );\n return response.items || [];\n }\n\n async getOne<T = any>(ctx?: any): Promise<T | null> {\n const response = await this.httpClient.post<QueryResponse>(\n \"/v1/rqlite/select\",\n {\n table: this.table,\n ...this.options,\n one: true,\n limit: 1,\n }\n );\n const items = response.items || [];\n return items.length > 0 ? items[0] : null;\n }\n\n async count(): Promise<number> {\n const response = await this.httpClient.post<QueryResponse>(\n \"/v1/rqlite/select\",\n {\n table: this.table,\n select: [\"COUNT(*) AS count\"],\n where: this.options.where,\n one: true,\n }\n );\n const items = response.items || [];\n return items.length > 0 ? items[0].count : 0;\n }\n}\n","import { HttpClient } from \"../core/http\";\nimport { QueryBuilder } from \"./qb\";\nimport { QueryResponse, FindOptions } from \"./types\";\nimport { SDKError } from \"../errors\";\n\nexport class Repository<T extends Record<string, any>> {\n private httpClient: HttpClient;\n private tableName: string;\n private primaryKey: string;\n\n constructor(httpClient: HttpClient, tableName: string, primaryKey = \"id\") {\n this.httpClient = httpClient;\n this.tableName = tableName;\n this.primaryKey = primaryKey;\n }\n\n createQueryBuilder(): QueryBuilder {\n return new QueryBuilder(this.httpClient, this.tableName);\n }\n\n async find(\n criteria: Record<string, any> = {},\n options: FindOptions = {}\n ): Promise<T[]> {\n const response = await this.httpClient.post<QueryResponse>(\n \"/v1/rqlite/find\",\n {\n table: this.tableName,\n criteria,\n options,\n }\n );\n return response.items || [];\n }\n\n async findOne(criteria: Record<string, any>): Promise<T | null> {\n try {\n const response = await this.httpClient.post<T | null>(\n \"/v1/rqlite/find-one\",\n {\n table: this.tableName,\n criteria,\n }\n );\n return response;\n } catch (error) {\n // Return null if not found instead of throwing\n if (error instanceof SDKError && error.httpStatus === 404) {\n return null;\n }\n throw error;\n }\n }\n\n async save(entity: T): Promise<T> {\n const pkValue = entity[this.primaryKey];\n\n if (!pkValue) {\n // INSERT\n const response = await this.httpClient.post<{\n rows_affected: number;\n last_insert_id: number;\n }>(\"/v1/rqlite/exec\", {\n sql: this.buildInsertSql(entity),\n args: this.buildInsertArgs(entity),\n });\n\n if (response.last_insert_id) {\n (entity as any)[this.primaryKey] = response.last_insert_id;\n }\n return entity;\n } else {\n // UPDATE\n await this.httpClient.post(\"/v1/rqlite/exec\", {\n sql: this.buildUpdateSql(entity),\n args: this.buildUpdateArgs(entity),\n });\n return entity;\n }\n }\n\n async remove(entity: T | Record<string, any>): Promise<void> {\n const pkValue = entity[this.primaryKey];\n if (!pkValue) {\n throw new SDKError(\n `Primary key \"${this.primaryKey}\" is required for remove`,\n 400,\n \"MISSING_PK\"\n );\n }\n\n await this.httpClient.post(\"/v1/rqlite/exec\", {\n sql: `DELETE FROM ${this.tableName} WHERE ${this.primaryKey} = ?`,\n args: [pkValue],\n });\n }\n\n private buildInsertSql(entity: T): string {\n const columns = Object.keys(entity).filter((k) => entity[k] !== undefined);\n const placeholders = columns.map(() => \"?\").join(\", \");\n return `INSERT INTO ${this.tableName} (${columns.join(\n \", \"\n )}) VALUES (${placeholders})`;\n }\n\n private buildInsertArgs(entity: T): any[] {\n return Object.entries(entity)\n .filter(([, v]) => v !== undefined)\n .map(([, v]) => v);\n }\n\n private buildUpdateSql(entity: T): string {\n const columns = Object.keys(entity)\n .filter((k) => entity[k] !== undefined && k !== this.primaryKey)\n .map((k) => `${k} = ?`);\n return `UPDATE ${this.tableName} SET ${columns.join(\", \")} WHERE ${\n this.primaryKey\n } = ?`;\n }\n\n private buildUpdateArgs(entity: T): any[] {\n const args = Object.entries(entity)\n .filter(([k, v]) => v !== undefined && k !== this.primaryKey)\n .map(([, v]) => v);\n args.push(entity[this.primaryKey]);\n return args;\n }\n}\n","import { HttpClient } from \"../core/http\";\nimport { QueryBuilder } from \"./qb\";\nimport { Repository } from \"./repository\";\nimport {\n QueryResponse,\n TransactionOp,\n TransactionRequest,\n Entity,\n FindOptions,\n} from \"./types\";\n\nexport class DBClient {\n private httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n /**\n * Execute a write/DDL SQL statement.\n */\n async exec(\n sql: string,\n args: any[] = []\n ): Promise<{ rows_affected: number; last_insert_id?: number }> {\n return this.httpClient.post(\"/v1/rqlite/exec\", { sql, args });\n }\n\n /**\n * Execute a SELECT query.\n */\n async query<T = any>(sql: string, args: any[] = []): Promise<T[]> {\n const response = await this.httpClient.post<QueryResponse>(\n \"/v1/rqlite/query\",\n { sql, args }\n );\n return response.items || [];\n }\n\n /**\n * Find rows with map-based criteria.\n */\n async find<T = any>(\n table: string,\n criteria: Record<string, any> = {},\n options: FindOptions = {}\n ): Promise<T[]> {\n const response = await this.httpClient.post<QueryResponse>(\n \"/v1/rqlite/find\",\n {\n table,\n criteria,\n options,\n }\n );\n return response.items || [];\n }\n\n /**\n * Find a single row with map-based criteria.\n */\n async findOne<T = any>(\n table: string,\n criteria: Record<string, any>\n ): Promise<T | null> {\n return this.httpClient.post<T | null>(\"/v1/rqlite/find-one\", {\n table,\n criteria,\n });\n }\n\n /**\n * Create a fluent QueryBuilder for complex SELECT queries.\n */\n createQueryBuilder(table: string): QueryBuilder {\n return new QueryBuilder(this.httpClient, table);\n }\n\n /**\n * Create a Repository for entity-based operations.\n */\n repository<T extends Record<string, any>>(\n tableName: string,\n primaryKey = \"id\"\n ): Repository<T> {\n return new Repository(this.httpClient, tableName, primaryKey);\n }\n\n /**\n * Execute multiple operations atomically.\n */\n async transaction(\n ops: TransactionOp[],\n returnResults = true\n ): Promise<any[]> {\n const response = await this.httpClient.post<{ results?: any[] }>(\n \"/v1/rqlite/transaction\",\n {\n ops,\n return_results: returnResults,\n }\n );\n return response.results || [];\n }\n\n /**\n * Create a table from DDL SQL.\n */\n async createTable(schema: string): Promise<void> {\n await this.httpClient.post(\"/v1/rqlite/create-table\", { schema });\n }\n\n /**\n * Drop a table.\n */\n async dropTable(table: string): Promise<void> {\n await this.httpClient.post(\"/v1/rqlite/drop-table\", { table });\n }\n\n /**\n * Get current database schema.\n */\n async getSchema(): Promise<any> {\n return this.httpClient.get(\"/v1/rqlite/schema\");\n }\n}\n","import WebSocket from \"isomorphic-ws\";\nimport { SDKError } from \"../errors\";\nimport { NetworkErrorCallback } from \"./http\";\n\nexport interface WSClientConfig {\n wsURL: string;\n timeout?: number;\n authToken?: string;\n WebSocket?: typeof WebSocket;\n /**\n * Callback invoked on WebSocket errors.\n * Use this to trigger gateway failover at the application layer.\n */\n onNetworkError?: NetworkErrorCallback;\n}\n\nexport type WSMessageHandler = (data: string) => void;\nexport type WSErrorHandler = (error: Error) => void;\nexport type WSCloseHandler = () => void;\nexport type WSOpenHandler = () => void;\n\n/**\n * Simple WebSocket client with minimal abstractions\n * No complex reconnection, no failover - keep it simple\n * Gateway failover is handled at the application layer\n */\nexport class WSClient {\n private wsURL: string;\n private timeout: number;\n private authToken?: string;\n private WebSocketClass: typeof WebSocket;\n private onNetworkError?: NetworkErrorCallback;\n\n private ws?: WebSocket;\n private messageHandlers: Set<WSMessageHandler> = new Set();\n private errorHandlers: Set<WSErrorHandler> = new Set();\n private closeHandlers: Set<WSCloseHandler> = new Set();\n private openHandlers: Set<WSOpenHandler> = new Set();\n private isClosed = false;\n\n constructor(config: WSClientConfig) {\n this.wsURL = config.wsURL;\n this.timeout = config.timeout ?? 30000;\n this.authToken = config.authToken;\n this.WebSocketClass = config.WebSocket ?? WebSocket;\n this.onNetworkError = config.onNetworkError;\n }\n\n /**\n * Set the network error callback\n */\n setOnNetworkError(callback: NetworkErrorCallback | undefined): void {\n this.onNetworkError = callback;\n }\n\n /**\n * Get the current WebSocket URL\n */\n get url(): string {\n return this.wsURL;\n }\n\n /**\n * Connect to WebSocket server\n */\n connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n try {\n const wsUrl = this.buildWSUrl();\n this.ws = new this.WebSocketClass(wsUrl);\n this.isClosed = false;\n\n const timeout = setTimeout(() => {\n this.ws?.close();\n const error = new SDKError(\"WebSocket connection timeout\", 408, \"WS_TIMEOUT\");\n\n // Call the network error callback if configured\n if (this.onNetworkError) {\n this.onNetworkError(error, {\n method: \"WS\",\n path: this.wsURL,\n isRetry: false,\n attempt: 0,\n });\n }\n\n reject(error);\n }, this.timeout);\n\n this.ws.addEventListener(\"open\", () => {\n clearTimeout(timeout);\n console.log(\"[WSClient] Connected to\", this.wsURL);\n this.openHandlers.forEach((handler) => handler());\n resolve();\n });\n\n this.ws.addEventListener(\"message\", (event: Event) => {\n const msgEvent = event as MessageEvent;\n this.messageHandlers.forEach((handler) => handler(msgEvent.data));\n });\n\n this.ws.addEventListener(\"error\", (event: Event) => {\n console.error(\"[WSClient] WebSocket error:\", event);\n clearTimeout(timeout);\n const error = new SDKError(\"WebSocket error\", 500, \"WS_ERROR\", event);\n\n // Call the network error callback if configured\n if (this.onNetworkError) {\n this.onNetworkError(error, {\n method: \"WS\",\n path: this.wsURL,\n isRetry: false,\n attempt: 0,\n });\n }\n\n this.errorHandlers.forEach((handler) => handler(error));\n reject(error);\n });\n\n this.ws.addEventListener(\"close\", () => {\n clearTimeout(timeout);\n console.log(\"[WSClient] Connection closed\");\n this.closeHandlers.forEach((handler) => handler());\n });\n } catch (error) {\n reject(error);\n }\n });\n }\n\n /**\n * Build WebSocket URL with auth token\n */\n private buildWSUrl(): string {\n let url = this.wsURL;\n\n if (this.authToken) {\n const separator = url.includes(\"?\") ? \"&\" : \"?\";\n const paramName = this.authToken.startsWith(\"ak_\") ? \"api_key\" : \"token\";\n url += `${separator}${paramName}=${encodeURIComponent(this.authToken)}`;\n }\n\n return url;\n }\n\n /**\n * Register message handler\n */\n onMessage(handler: WSMessageHandler): () => void {\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n /**\n * Unregister message handler\n */\n offMessage(handler: WSMessageHandler): void {\n this.messageHandlers.delete(handler);\n }\n\n /**\n * Register error handler\n */\n onError(handler: WSErrorHandler): () => void {\n this.errorHandlers.add(handler);\n return () => this.errorHandlers.delete(handler);\n }\n\n /**\n * Unregister error handler\n */\n offError(handler: WSErrorHandler): void {\n this.errorHandlers.delete(handler);\n }\n\n /**\n * Register close handler\n */\n onClose(handler: WSCloseHandler): () => void {\n this.closeHandlers.add(handler);\n return () => this.closeHandlers.delete(handler);\n }\n\n /**\n * Unregister close handler\n */\n offClose(handler: WSCloseHandler): void {\n this.closeHandlers.delete(handler);\n }\n\n /**\n * Register open handler\n */\n onOpen(handler: WSOpenHandler): () => void {\n this.openHandlers.add(handler);\n return () => this.openHandlers.delete(handler);\n }\n\n /**\n * Send data through WebSocket\n */\n send(data: string): void {\n if (this.ws?.readyState !== WebSocket.OPEN) {\n throw new SDKError(\"WebSocket is not connected\", 500, \"WS_NOT_CONNECTED\");\n }\n this.ws.send(data);\n }\n\n /**\n * Close WebSocket connection\n */\n close(): void {\n if (this.isClosed) {\n return;\n }\n this.isClosed = true;\n this.ws?.close();\n }\n\n /**\n * Check if WebSocket is connected\n */\n isConnected(): boolean {\n return !this.isClosed && this.ws?.readyState === WebSocket.OPEN;\n }\n\n /**\n * Update auth token\n */\n setAuthToken(token?: string): void {\n this.authToken = token;\n }\n}\n","import { HttpClient } from \"../core/http\";\nimport { WSClient, WSClientConfig } from \"../core/ws\";\nimport {\n PubSubMessage,\n RawEnvelope,\n MessageHandler,\n ErrorHandler,\n CloseHandler,\n SubscribeOptions,\n PresenceResponse,\n PresenceMember,\n PresenceOptions,\n} from \"./types\";\n\n// Cross-platform base64 encoding/decoding utilities\nfunction base64Encode(str: string): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(str).toString(\"base64\");\n } else if (typeof btoa !== \"undefined\") {\n return btoa(\n encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, (match, p1) =>\n String.fromCharCode(parseInt(p1, 16))\n )\n );\n }\n throw new Error(\"No base64 encoding method available\");\n}\n\nfunction base64EncodeBytes(bytes: Uint8Array): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(bytes).toString(\"base64\");\n } else if (typeof btoa !== \"undefined\") {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]);\n }\n return btoa(binary);\n }\n throw new Error(\"No base64 encoding method available\");\n}\n\nfunction base64Decode(b64: string): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(b64, \"base64\").toString(\"utf-8\");\n } else if (typeof atob !== \"undefined\") {\n const binary = atob(b64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return new TextDecoder().decode(bytes);\n }\n throw new Error(\"No base64 decoding method available\");\n}\n\n/**\n * Simple PubSub client - one WebSocket connection per topic\n * Gateway failover is handled at the application layer\n */\nexport class PubSubClient {\n private httpClient: HttpClient;\n private wsConfig: Partial<WSClientConfig>;\n\n constructor(httpClient: HttpClient, wsConfig: Partial<WSClientConfig> = {}) {\n this.httpClient = httpClient;\n this.wsConfig = wsConfig;\n }\n\n /**\n * Publish a message to a topic via HTTP\n */\n async publish(topic: string, data: string | Uint8Array): Promise<void> {\n let dataBase64: string;\n if (typeof data === \"string\") {\n dataBase64 = base64Encode(data);\n } else {\n dataBase64 = base64EncodeBytes(data);\n }\n\n await this.httpClient.post(\n \"/v1/pubsub/publish\",\n {\n topic,\n data_base64: dataBase64,\n },\n {\n timeout: 30000,\n }\n );\n }\n\n /**\n * List active topics in the current namespace\n */\n async topics(): Promise<string[]> {\n const response = await this.httpClient.get<{ topics: string[] }>(\n \"/v1/pubsub/topics\"\n );\n return response.topics || [];\n }\n\n /**\n * Get current presence for a topic without subscribing\n */\n async getPresence(topic: string): Promise<PresenceResponse> {\n const response = await this.httpClient.get<PresenceResponse>(\n `/v1/pubsub/presence?topic=${encodeURIComponent(topic)}`\n );\n return response;\n }\n\n /**\n * Subscribe to a topic via WebSocket\n * Creates one WebSocket connection per topic\n */\n async subscribe(\n topic: string,\n options: SubscribeOptions = {}\n ): Promise<Subscription> {\n // Build WebSocket URL for this topic\n const wsUrl = new URL(this.wsConfig.wsURL || \"ws://127.0.0.1:6001\");\n wsUrl.pathname = \"/v1/pubsub/ws\";\n wsUrl.searchParams.set(\"topic\", topic);\n\n // Handle presence options\n let presence: PresenceOptions | undefined;\n if (options.presence?.enabled) {\n presence = options.presence;\n wsUrl.searchParams.set(\"presence\", \"true\");\n wsUrl.searchParams.set(\"member_id\", presence.memberId);\n if (presence.meta) {\n wsUrl.searchParams.set(\"member_meta\", JSON.stringify(presence.meta));\n }\n }\n\n const authToken = this.httpClient.getApiKey() ?? this.httpClient.getToken();\n\n // Create WebSocket client\n const wsClient = new WSClient({\n ...this.wsConfig,\n wsURL: wsUrl.toString(),\n authToken,\n });\n\n await wsClient.connect();\n\n // Create subscription wrapper\n const subscription = new Subscription(wsClient, topic, presence, () =>\n this.getPresence(topic)\n );\n\n if (options.onMessage) {\n subscription.onMessage(options.onMessage);\n }\n if (options.onError) {\n subscription.onError(options.onError);\n }\n if (options.onClose) {\n subscription.onClose(options.onClose);\n }\n\n return subscription;\n }\n}\n\n/**\n * Subscription represents an active WebSocket subscription to a topic\n */\nexport class Subscription {\n private wsClient: WSClient;\n private topic: string;\n private presenceOptions?: PresenceOptions;\n private messageHandlers: Set<MessageHandler> = new Set();\n private errorHandlers: Set<ErrorHandler> = new Set();\n private closeHandlers: Set<CloseHandler> = new Set();\n private isClosed = false;\n private wsMessageHandler: ((data: string) => void) | null = null;\n private wsErrorHandler: ((error: Error) => void) | null = null;\n private wsCloseHandler: (() => void) | null = null;\n private getPresenceFn: () => Promise<PresenceResponse>;\n\n constructor(\n wsClient: WSClient,\n topic: string,\n presenceOptions: PresenceOptions | undefined,\n getPresenceFn: () => Promise<PresenceResponse>\n ) {\n this.wsClient = wsClient;\n this.topic = topic;\n this.presenceOptions = presenceOptions;\n this.getPresenceFn = getPresenceFn;\n\n // Register message handler\n this.wsMessageHandler = (data) => {\n try {\n // Parse gateway JSON envelope: {data: base64String, timestamp, topic}\n const envelope: RawEnvelope = JSON.parse(data);\n\n // Validate envelope structure\n if (!envelope || typeof envelope !== \"object\") {\n throw new Error(\"Invalid envelope: not an object\");\n }\n\n // Handle presence events\n if (\n envelope.type === \"presence.join\" ||\n envelope.type === \"presence.leave\"\n ) {\n if (!envelope.member_id) {\n console.warn(\"[Subscription] Presence event missing member_id\");\n return;\n }\n\n const presenceMember: PresenceMember = {\n memberId: envelope.member_id,\n joinedAt: envelope.timestamp,\n meta: envelope.meta,\n };\n\n if (\n envelope.type === \"presence.join\" &&\n this.presenceOptions?.onJoin\n ) {\n this.presenceOptions.onJoin(presenceMember);\n } else if (\n envelope.type === \"presence.leave\" &&\n this.presenceOptions?.onLeave\n ) {\n this.presenceOptions.onLeave(presenceMember);\n }\n return; // Don't call regular onMessage for presence events\n }\n\n if (!envelope.data || typeof envelope.data !== \"string\") {\n throw new Error(\"Invalid envelope: missing or invalid data field\");\n }\n if (!envelope.topic || typeof envelope.topic !== \"string\") {\n throw new Error(\"Invalid envelope: missing or invalid topic field\");\n }\n if (typeof envelope.timestamp !== \"number\") {\n throw new Error(\n \"Invalid envelope: missing or invalid timestamp field\"\n );\n }\n\n // Decode base64 data\n const messageData = base64Decode(envelope.data);\n\n const message: PubSubMessage = {\n topic: envelope.topic,\n data: messageData,\n timestamp: envelope.timestamp,\n };\n\n console.log(\"[Subscription] Received message on topic:\", this.topic);\n this.messageHandlers.forEach((handler) => handler(message));\n } catch (error) {\n console.error(\"[Subscription] Error processing message:\", error);\n this.errorHandlers.forEach((handler) =>\n handler(error instanceof Error ? error : new Error(String(error)))\n );\n }\n };\n\n this.wsClient.onMessage(this.wsMessageHandler);\n\n // Register error handler\n this.wsErrorHandler = (error) => {\n this.errorHandlers.forEach((handler) => handler(error));\n };\n this.wsClient.onError(this.wsErrorHandler);\n\n // Register close handler\n this.wsCloseHandler = () => {\n this.closeHandlers.forEach((handler) => handler());\n };\n this.wsClient.onClose(this.wsCloseHandler);\n }\n\n /**\n * Get current presence (requires presence.enabled on subscribe)\n */\n async getPresence(): Promise<PresenceMember[]> {\n if (!this.presenceOptions?.enabled) {\n throw new Error(\"Presence is not enabled for this subscription\");\n }\n\n const response = await this.getPresenceFn();\n return response.members;\n }\n\n /**\n * Check if presence is enabled for this subscription\n */\n hasPresence(): boolean {\n return !!this.presenceOptions?.enabled;\n }\n\n /**\n * Register message handler\n */\n onMessage(handler: MessageHandler): () => void {\n this.messageHandlers.add(handler);\n return () => this.messageHandlers.delete(handler);\n }\n\n /**\n * Register error handler\n */\n onError(handler: ErrorHandler): () => void {\n this.errorHandlers.add(handler);\n return () => this.errorHandlers.delete(handler);\n }\n\n /**\n * Register close handler\n */\n onClose(handler: CloseHandler): () => void {\n this.closeHandlers.add(handler);\n return () => this.closeHandlers.delete(handler);\n }\n\n /**\n * Close subscription and underlying WebSocket\n */\n close(): void {\n if (this.isClosed) {\n return;\n }\n this.isClosed = true;\n\n // Remove handlers from WSClient\n if (this.wsMessageHandler) {\n this.wsClient.offMessage(this.wsMessageHandler);\n this.wsMessageHandler = null;\n }\n if (this.wsErrorHandler) {\n this.wsClient.offError(this.wsErrorHandler);\n this.wsErrorHandler = null;\n }\n if (this.wsCloseHandler) {\n this.wsClient.offClose(this.wsCloseHandler);\n this.wsCloseHandler = null;\n }\n\n // Clear all local handlers\n this.messageHandlers.clear();\n this.errorHandlers.clear();\n this.closeHandlers.clear();\n\n // Close WebSocket connection\n this.wsClient.close();\n }\n\n /**\n * Check if subscription is active\n */\n isConnected(): boolean {\n return !this.isClosed && this.wsClient.isConnected();\n }\n}\n","import { HttpClient } from \"../core/http\";\n\nexport interface PeerInfo {\n id: string;\n addresses: string[];\n lastSeen?: string;\n}\n\nexport interface NetworkStatus {\n node_id: string;\n connected: boolean;\n peer_count: number;\n database_size: number;\n uptime: number;\n}\n\nexport interface ProxyRequest {\n url: string;\n method: string;\n headers?: Record<string, string>;\n body?: string;\n}\n\nexport interface ProxyResponse {\n status_code: number;\n headers: Record<string, string>;\n body: string;\n error?: string;\n}\n\nexport class NetworkClient {\n private httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n /**\n * Check gateway health.\n */\n async health(): Promise<boolean> {\n try {\n await this.httpClient.get(\"/v1/health\");\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Get network status.\n */\n async status(): Promise<NetworkStatus> {\n const response = await this.httpClient.get<NetworkStatus>(\n \"/v1/network/status\"\n );\n return response;\n }\n\n /**\n * Get connected peers.\n */\n async peers(): Promise<PeerInfo[]> {\n const response = await this.httpClient.get<{ peers: PeerInfo[] }>(\n \"/v1/network/peers\"\n );\n return response.peers || [];\n }\n\n /**\n * Connect to a peer.\n */\n async connect(peerAddr: string): Promise<void> {\n await this.httpClient.post(\"/v1/network/connect\", { peer_addr: peerAddr });\n }\n\n /**\n * Disconnect from a peer.\n */\n async disconnect(peerId: string): Promise<void> {\n await this.httpClient.post(\"/v1/network/disconnect\", { peer_id: peerId });\n }\n\n /**\n * Proxy an HTTP request through the Anyone network.\n * Requires authentication (API key or JWT).\n *\n * @param request - The proxy request configuration\n * @returns The proxied response\n * @throws {SDKError} If the Anyone proxy is not available or the request fails\n *\n * @example\n * ```ts\n * const response = await client.network.proxyAnon({\n * url: 'https://api.example.com/data',\n * method: 'GET',\n * headers: {\n * 'Accept': 'application/json'\n * }\n * });\n *\n * console.log(response.status_code); // 200\n * console.log(response.body); // Response data\n * ```\n */\n async proxyAnon(request: ProxyRequest): Promise<ProxyResponse> {\n const response = await this.httpClient.post<ProxyResponse>(\n \"/v1/proxy/anon\",\n request\n );\n\n // Check if the response contains an error\n if (response.error) {\n throw new Error(`Proxy request failed: ${response.error}`);\n }\n\n return response;\n }\n}\n","import { HttpClient } from \"../core/http\";\nimport { SDKError } from \"../errors\";\n\nexport interface CacheGetRequest {\n dmap: string;\n key: string;\n}\n\nexport interface CacheGetResponse {\n key: string;\n value: any;\n dmap: string;\n}\n\nexport interface CachePutRequest {\n dmap: string;\n key: string;\n value: any;\n ttl?: string; // Duration string like \"1h\", \"30m\"\n}\n\nexport interface CachePutResponse {\n status: string;\n key: string;\n dmap: string;\n}\n\nexport interface CacheDeleteRequest {\n dmap: string;\n key: string;\n}\n\nexport interface CacheDeleteResponse {\n status: string;\n key: string;\n dmap: string;\n}\n\nexport interface CacheMultiGetRequest {\n dmap: string;\n keys: string[];\n}\n\nexport interface CacheMultiGetResponse {\n results: Array<{\n key: string;\n value: any;\n }>;\n dmap: string;\n}\n\nexport interface CacheScanRequest {\n dmap: string;\n match?: string; // Optional regex pattern\n}\n\nexport interface CacheScanResponse {\n keys: string[];\n count: number;\n dmap: string;\n}\n\nexport interface CacheHealthResponse {\n status: string;\n service: string;\n}\n\nexport class CacheClient {\n private httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n /**\n * Check cache service health\n */\n async health(): Promise<CacheHealthResponse> {\n return this.httpClient.get(\"/v1/cache/health\");\n }\n\n /**\n * Get a value from cache\n * Returns null if the key is not found (cache miss/expired), which is normal behavior\n */\n async get(dmap: string, key: string): Promise<CacheGetResponse | null> {\n try {\n return await this.httpClient.post<CacheGetResponse>(\"/v1/cache/get\", {\n dmap,\n key,\n });\n } catch (error) {\n // Cache misses (404 or \"key not found\" messages) are normal behavior - return null instead of throwing\n if (\n error instanceof SDKError &&\n (error.httpStatus === 404 ||\n (error.httpStatus === 500 &&\n error.message?.toLowerCase().includes(\"key not found\")))\n ) {\n return null;\n }\n // Re-throw other errors (network issues, server errors, etc.)\n throw error;\n }\n }\n\n /**\n * Put a value into cache\n */\n async put(\n dmap: string,\n key: string,\n value: any,\n ttl?: string\n ): Promise<CachePutResponse> {\n return this.httpClient.post<CachePutResponse>(\"/v1/cache/put\", {\n dmap,\n key,\n value,\n ttl,\n });\n }\n\n /**\n * Delete a value from cache\n */\n async delete(dmap: string, key: string): Promise<CacheDeleteResponse> {\n return this.httpClient.post<CacheDeleteResponse>(\"/v1/cache/delete\", {\n dmap,\n key,\n });\n }\n\n /**\n * Get multiple values from cache in a single request\n * Returns a map of key -> value (or null if not found)\n * Gracefully handles 404 errors (endpoint not implemented) by returning empty results\n */\n async multiGet(\n dmap: string,\n keys: string[]\n ): Promise<Map<string, any | null>> {\n try {\n if (keys.length === 0) {\n return new Map();\n }\n\n const response = await this.httpClient.post<CacheMultiGetResponse>(\n \"/v1/cache/mget\",\n {\n dmap,\n keys,\n }\n );\n\n // Convert array to Map\n const resultMap = new Map<string, any | null>();\n\n // First, mark all keys as null (cache miss)\n keys.forEach((key) => {\n resultMap.set(key, null);\n });\n\n // Then, update with found values\n if (response.results) {\n response.results.forEach(({ key, value }) => {\n resultMap.set(key, value);\n });\n }\n\n return resultMap;\n } catch (error) {\n // Handle 404 errors silently (endpoint not implemented on backend)\n // This is expected behavior when the backend doesn't support multiGet yet\n if (error instanceof SDKError && error.httpStatus === 404) {\n // Return map with all nulls silently - caller can fall back to individual gets\n const resultMap = new Map<string, any | null>();\n keys.forEach((key) => {\n resultMap.set(key, null);\n });\n return resultMap;\n }\n\n // Log and return empty results for other errors\n const resultMap = new Map<string, any | null>();\n keys.forEach((key) => {\n resultMap.set(key, null);\n });\n console.error(`[CacheClient] Error in multiGet for ${dmap}:`, error);\n return resultMap;\n }\n }\n\n /**\n * Scan keys in a distributed map, optionally matching a regex pattern\n */\n async scan(dmap: string, match?: string): Promise<CacheScanResponse> {\n return this.httpClient.post<CacheScanResponse>(\"/v1/cache/scan\", {\n dmap,\n match,\n });\n }\n}\n","import { HttpClient } from \"../core/http\";\n\nexport interface StorageUploadResponse {\n cid: string;\n name: string;\n size: number;\n}\n\nexport interface StoragePinRequest {\n cid: string;\n name?: string;\n}\n\nexport interface StoragePinResponse {\n cid: string;\n name: string;\n}\n\nexport interface StorageStatus {\n cid: string;\n name: string;\n status: string; // \"pinned\", \"pinning\", \"queued\", \"unpinned\", \"error\"\n replication_min: number;\n replication_max: number;\n replication_factor: number;\n peers: string[];\n error?: string;\n}\n\nexport class StorageClient {\n private httpClient: HttpClient;\n\n constructor(httpClient: HttpClient) {\n this.httpClient = httpClient;\n }\n\n /**\n * Upload content to IPFS and optionally pin it.\n * Supports both File objects (browser) and Buffer/ReadableStream (Node.js).\n *\n * @param file - File to upload (File, Blob, or Buffer)\n * @param name - Optional filename\n * @param options - Optional upload options\n * @param options.pin - Whether to pin the content (default: true). Pinning happens asynchronously on the backend.\n * @returns Upload result with CID\n *\n * @example\n * ```ts\n * // Browser\n * const fileInput = document.querySelector('input[type=\"file\"]');\n * const file = fileInput.files[0];\n * const result = await client.storage.upload(file, file.name);\n * console.log(result.cid);\n *\n * // Node.js\n * const fs = require('fs');\n * const fileBuffer = fs.readFileSync('image.jpg');\n * const result = await client.storage.upload(fileBuffer, 'image.jpg', { pin: true });\n * ```\n */\n async upload(\n file: File | Blob | ArrayBuffer | Uint8Array | ReadableStream<Uint8Array>,\n name?: string,\n options?: {\n pin?: boolean;\n }\n ): Promise<StorageUploadResponse> {\n // Create FormData for multipart upload\n const formData = new FormData();\n\n // Handle different input types\n if (file instanceof File) {\n formData.append(\"file\", file);\n } else if (file instanceof Blob) {\n formData.append(\"file\", file, name);\n } else if (file instanceof ArrayBuffer) {\n const blob = new Blob([file]);\n formData.append(\"file\", blob, name);\n } else if (file instanceof Uint8Array) {\n // Convert Uint8Array to ArrayBuffer for Blob constructor\n const buffer = file.buffer.slice(\n file.byteOffset,\n file.byteOffset + file.byteLength\n ) as ArrayBuffer;\n const blob = new Blob([buffer], { type: \"application/octet-stream\" });\n formData.append(\"file\", blob, name);\n } else if (file instanceof ReadableStream) {\n // For ReadableStream, we need to read it into a blob first\n // This is a limitation - in practice, pass File/Blob/Buffer\n const chunks: ArrayBuffer[] = [];\n const reader = file.getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n const buffer = value.buffer.slice(\n value.byteOffset,\n value.byteOffset + value.byteLength\n ) as ArrayBuffer;\n chunks.push(buffer);\n }\n const blob = new Blob(chunks);\n formData.append(\"file\", blob, name);\n } else {\n throw new Error(\n \"Unsupported file type. Use File, Blob, ArrayBuffer, Uint8Array, or ReadableStream.\"\n );\n }\n\n // Add pin flag (default: true)\n const shouldPin = options?.pin !== false; // Default to true\n formData.append(\"pin\", shouldPin ? \"true\" : \"false\");\n\n return this.httpClient.uploadFile<StorageUploadResponse>(\n \"/v1/storage/upload\",\n formData,\n { timeout: 300000 } // 5 minute timeout for large files\n );\n }\n\n /**\n * Pin an existing CID\n *\n * @param cid - Content ID to pin\n * @param name - Optional name for the pin\n * @returns Pin result\n */\n async pin(cid: string, name?: string): Promise<StoragePinResponse> {\n return this.httpClient.post<StoragePinResponse>(\"/v1/storage/pin\", {\n cid,\n name,\n });\n }\n\n /**\n * Get the pin status for a CID\n *\n * @param cid - Content ID to check\n * @returns Pin status information\n */\n async status(cid: string): Promise<StorageStatus> {\n return this.httpClient.get<StorageStatus>(`/v1/storage/status/${cid}`);\n }\n\n /**\n * Retrieve content from IPFS by CID\n *\n * @param cid - Content ID to retrieve\n * @returns ReadableStream of the content\n *\n * @example\n * ```ts\n * const stream = await client.storage.get(cid);\n * const reader = stream.getReader();\n * while (true) {\n * const { done, value } = await reader.read();\n * if (done) break;\n * // Process chunk\n * }\n * ```\n */\n async get(cid: string): Promise<ReadableStream<Uint8Array>> {\n // Retry logic for content retrieval - content may not be immediately available\n // after upload due to eventual consistency in IPFS Cluster\n // IPFS Cluster pins can take 2-3+ seconds to complete across all nodes\n const maxAttempts = 8;\n let lastError: Error | null = null;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const response = await this.httpClient.getBinary(\n `/v1/storage/get/${cid}`\n );\n\n if (!response.body) {\n throw new Error(\"Response body is null\");\n }\n\n return response.body;\n } catch (error: any) {\n lastError = error;\n\n // Check if this is a 404 error (content not found)\n const isNotFound =\n error?.httpStatus === 404 ||\n error?.message?.includes(\"not found\") ||\n error?.message?.includes(\"404\");\n\n // If it's not a 404 error, or this is the last attempt, give up\n if (!isNotFound || attempt === maxAttempts) {\n throw error;\n }\n\n // Wait before retrying (exponential backoff: 400ms, 800ms, 1200ms, etc.)\n // This gives up to ~12 seconds total wait time, covering typical pin completion\n const backoffMs = attempt * 2500;\n await new Promise((resolve) => setTimeout(resolve, backoffMs));\n }\n }\n\n // This should never be reached, but TypeScript needs it\n throw lastError || new Error(\"Failed to retrieve content\");\n }\n\n /**\n * Retrieve content from IPFS by CID and return the full Response object\n * Useful when you need access to response headers (e.g., content-length)\n *\n * @param cid - Content ID to retrieve\n * @returns Response object with body stream and headers\n *\n * @example\n * ```ts\n * const response = await client.storage.getBinary(cid);\n * const contentLength = response.headers.get('content-length');\n * const reader = response.body.getReader();\n * // ... read stream\n * ```\n */\n async getBinary(cid: string): Promise<Response> {\n // Retry logic for content retrieval - content may not be immediately available\n // after upload due to eventual consistency in IPFS Cluster\n // IPFS Cluster pins can take 2-3+ seconds to complete across all nodes\n const maxAttempts = 8;\n let lastError: Error | null = null;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n const response = await this.httpClient.getBinary(\n `/v1/storage/get/${cid}`\n );\n\n if (!response) {\n throw new Error(\"Response is null\");\n }\n\n return response;\n } catch (error: any) {\n lastError = error;\n\n // Check if this is a 404 error (content not found)\n const isNotFound =\n error?.httpStatus === 404 ||\n error?.message?.includes(\"not found\") ||\n error?.message?.includes(\"404\");\n\n // If it's not a 404 error, or this is the last attempt, give up\n if (!isNotFound || attempt === maxAttempts) {\n throw error;\n }\n\n // Wait before retrying (exponential backoff: 400ms, 800ms, 1200ms, etc.)\n // This gives up to ~12 seconds total wait time, covering typical pin completion\n const backoffMs = attempt * 2500;\n await new Promise((resolve) => setTimeout(resolve, backoffMs));\n }\n }\n\n // This should never be reached, but TypeScript needs it\n throw lastError || new Error(\"Failed to retrieve content\");\n }\n\n /**\n * Unpin a CID\n *\n * @param cid - Content ID to unpin\n */\n async unpin(cid: string): Promise<void> {\n await this.httpClient.delete(`/v1/storage/unpin/${cid}`);\n }\n}\n","/**\n * Functions Client\n * Client for calling serverless functions on the Orama Network\n */\n\nimport { HttpClient } from \"../core/http\";\nimport { SDKError } from \"../errors\";\n\nexport interface FunctionsClientConfig {\n /**\n * Base URL for the functions gateway\n * Defaults to using the same baseURL as the HTTP client\n */\n gatewayURL?: string;\n \n /**\n * Namespace for the functions\n */\n namespace: string;\n}\n\nexport class FunctionsClient {\n private httpClient: HttpClient;\n private gatewayURL?: string;\n private namespace: string;\n\n constructor(httpClient: HttpClient, config?: FunctionsClientConfig) {\n this.httpClient = httpClient;\n this.gatewayURL = config?.gatewayURL;\n this.namespace = config?.namespace ?? \"default\";\n }\n\n /**\n * Invoke a serverless function by name\n * \n * @param functionName - Name of the function to invoke\n * @param input - Input payload for the function\n * @returns The function response\n */\n async invoke<TInput = any, TOutput = any>(\n functionName: string,\n input: TInput\n ): Promise<TOutput> {\n const url = this.gatewayURL\n ? `${this.gatewayURL}/v1/invoke/${this.namespace}/${functionName}`\n : `/v1/invoke/${this.namespace}/${functionName}`;\n\n try {\n const response = await this.httpClient.post<TOutput>(url, input);\n return response;\n } catch (error) {\n if (error instanceof SDKError) {\n throw error;\n }\n throw new SDKError(\n `Function ${functionName} failed`,\n 500,\n error instanceof Error ? error.message : String(error)\n );\n }\n }\n}\n","import { HttpClient, HttpClientConfig, NetworkErrorCallback } from \"./core/http\";\nimport { AuthClient } from \"./auth/client\";\nimport { DBClient } from \"./db/client\";\nimport { PubSubClient } from \"./pubsub/client\";\nimport { NetworkClient } from \"./network/client\";\nimport { CacheClient } from \"./cache/client\";\nimport { StorageClient } from \"./storage/client\";\nimport { FunctionsClient, FunctionsClientConfig } from \"./functions/client\";\nimport { WSClientConfig } from \"./core/ws\";\nimport {\n StorageAdapter,\n MemoryStorage,\n LocalStorageAdapter,\n} from \"./auth/types\";\n\nexport interface ClientConfig extends Omit<HttpClientConfig, \"fetch\"> {\n apiKey?: string;\n jwt?: string;\n storage?: StorageAdapter;\n wsConfig?: Partial<Omit<WSClientConfig, \"wsURL\">>;\n functionsConfig?: FunctionsClientConfig;\n fetch?: typeof fetch;\n /**\n * Callback invoked on network errors (HTTP and WebSocket).\n * Use this to trigger gateway failover at the application layer.\n */\n onNetworkError?: NetworkErrorCallback;\n}\n\nexport interface Client {\n auth: AuthClient;\n db: DBClient;\n pubsub: PubSubClient;\n network: NetworkClient;\n cache: CacheClient;\n storage: StorageClient;\n functions: FunctionsClient;\n}\n\nexport function createClient(config: ClientConfig): Client {\n const httpClient = new HttpClient({\n baseURL: config.baseURL,\n timeout: config.timeout,\n maxRetries: config.maxRetries,\n retryDelayMs: config.retryDelayMs,\n fetch: config.fetch,\n onNetworkError: config.onNetworkError,\n });\n\n const auth = new AuthClient({\n httpClient,\n storage: config.storage,\n apiKey: config.apiKey,\n jwt: config.jwt,\n });\n\n // Derive WebSocket URL from baseURL\n const wsURL = config.baseURL.replace(/^http/, \"ws\").replace(/\\/$/, \"\");\n\n const db = new DBClient(httpClient);\n const pubsub = new PubSubClient(httpClient, {\n ...config.wsConfig,\n wsURL,\n onNetworkError: config.onNetworkError,\n });\n const network = new NetworkClient(httpClient);\n const cache = new CacheClient(httpClient);\n const storage = new StorageClient(httpClient);\n const functions = new FunctionsClient(httpClient, config.functionsConfig);\n\n return {\n auth,\n db,\n pubsub,\n network,\n cache,\n storage,\n functions,\n };\n}\n\nexport { HttpClient } from \"./core/http\";\nexport type { NetworkErrorCallback, NetworkErrorContext } from \"./core/http\";\nexport { WSClient } from \"./core/ws\";\nexport { AuthClient } from \"./auth/client\";\nexport { DBClient } from \"./db/client\";\nexport { QueryBuilder } from \"./db/qb\";\nexport { Repository } from \"./db/repository\";\nexport { PubSubClient, Subscription } from \"./pubsub/client\";\nexport { NetworkClient } from \"./network/client\";\nexport { CacheClient } from \"./cache/client\";\nexport { StorageClient } from \"./storage/client\";\nexport { FunctionsClient } from \"./functions/client\";\nexport { SDKError } from \"./errors\";\nexport { MemoryStorage, LocalStorageAdapter } from \"./auth/types\";\nexport type { StorageAdapter, AuthConfig, WhoAmI } from \"./auth/types\";\nexport type * from \"./db/types\";\nexport type {\n MessageHandler,\n ErrorHandler,\n CloseHandler,\n PresenceMember,\n PresenceResponse,\n PresenceOptions,\n SubscribeOptions,\n} from \"./pubsub/types\";\nexport { type PubSubMessage } from \"./pubsub/types\";\nexport type {\n PeerInfo,\n NetworkStatus,\n ProxyRequest,\n ProxyResponse,\n} from \"./network/client\";\nexport type {\n CacheGetRequest,\n CacheGetResponse,\n CachePutRequest,\n CachePutResponse,\n CacheDeleteRequest,\n CacheDeleteResponse,\n CacheMultiGetRequest,\n CacheMultiGetResponse,\n CacheScanRequest,\n CacheScanResponse,\n CacheHealthResponse,\n} from \"./cache/client\";\nexport type {\n StorageUploadResponse,\n StoragePinRequest,\n StoragePinResponse,\n StorageStatus,\n} from \"./storage/client\";\nexport type { FunctionsClientConfig } from \"./functions/client\";\nexport type * from \"./functions/types\";\n"],"mappings":"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","names":["resultMap"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@debros/network-ts-sdk",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "TypeScript SDK for DeBros Network Gateway",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/src/core/http.ts CHANGED
@@ -1,11 +1,35 @@
1
1
  import { SDKError } from "../errors";
2
2
 
3
+ /**
4
+ * Context provided to the onNetworkError callback
5
+ */
6
+ export interface NetworkErrorContext {
7
+ method: "GET" | "POST" | "PUT" | "DELETE" | "WS";
8
+ path: string;
9
+ isRetry: boolean;
10
+ attempt: number;
11
+ }
12
+
13
+ /**
14
+ * Callback invoked when a network error occurs.
15
+ * Use this to trigger gateway failover or other error handling.
16
+ */
17
+ export type NetworkErrorCallback = (
18
+ error: SDKError,
19
+ context: NetworkErrorContext
20
+ ) => void;
21
+
3
22
  export interface HttpClientConfig {
4
23
  baseURL: string;
5
24
  timeout?: number;
6
25
  maxRetries?: number;
7
26
  retryDelayMs?: number;
8
27
  fetch?: typeof fetch;
28
+ /**
29
+ * Callback invoked on network errors (after all retries exhausted).
30
+ * Use this to trigger gateway failover at the application layer.
31
+ */
32
+ onNetworkError?: NetworkErrorCallback;
9
33
  }
10
34
 
11
35
  /**
@@ -39,6 +63,7 @@ export class HttpClient {
39
63
  private fetch: typeof fetch;
40
64
  private apiKey?: string;
41
65
  private jwt?: string;
66
+ private onNetworkError?: NetworkErrorCallback;
42
67
 
43
68
  constructor(config: HttpClientConfig) {
44
69
  this.baseURL = config.baseURL.replace(/\/$/, "");
@@ -47,6 +72,14 @@ export class HttpClient {
47
72
  this.retryDelayMs = config.retryDelayMs ?? 1000;
48
73
  // Use provided fetch or create one with proper TLS configuration for staging certificates
49
74
  this.fetch = config.fetch ?? createFetchWithTLSConfig();
75
+ this.onNetworkError = config.onNetworkError;
76
+ }
77
+
78
+ /**
79
+ * Set the network error callback
80
+ */
81
+ setOnNetworkError(callback: NetworkErrorCallback | undefined): void {
82
+ this.onNetworkError = callback;
50
83
  }
51
84
 
52
85
  setApiKey(apiKey?: string) {
@@ -258,6 +291,27 @@ export class HttpClient {
258
291
  }
259
292
  }
260
293
  }
294
+
295
+ // Call the network error callback if configured
296
+ // This allows the app to trigger gateway failover
297
+ if (this.onNetworkError) {
298
+ // Convert native errors (TypeError, AbortError) to SDKError for the callback
299
+ const sdkError =
300
+ error instanceof SDKError
301
+ ? error
302
+ : new SDKError(
303
+ error instanceof Error ? error.message : String(error),
304
+ 0, // httpStatus 0 indicates network-level failure
305
+ "NETWORK_ERROR"
306
+ );
307
+ this.onNetworkError(sdkError, {
308
+ method,
309
+ path,
310
+ isRetry: false,
311
+ attempt: this.maxRetries, // All retries exhausted
312
+ });
313
+ }
314
+
261
315
  throw error;
262
316
  } finally {
263
317
  clearTimeout(timeoutId);
@@ -397,6 +451,25 @@ export class HttpClient {
397
451
  error
398
452
  );
399
453
  }
454
+
455
+ // Call the network error callback if configured
456
+ if (this.onNetworkError) {
457
+ const sdkError =
458
+ error instanceof SDKError
459
+ ? error
460
+ : new SDKError(
461
+ error instanceof Error ? error.message : String(error),
462
+ 0,
463
+ "NETWORK_ERROR"
464
+ );
465
+ this.onNetworkError(sdkError, {
466
+ method: "POST",
467
+ path,
468
+ isRetry: false,
469
+ attempt: this.maxRetries,
470
+ });
471
+ }
472
+
400
473
  throw error;
401
474
  } finally {
402
475
  clearTimeout(timeoutId);
@@ -425,17 +498,33 @@ export class HttpClient {
425
498
  const response = await this.fetch(url.toString(), fetchOptions);
426
499
  if (!response.ok) {
427
500
  clearTimeout(timeoutId);
428
- const error = await response.json().catch(() => ({
501
+ const errorBody = await response.json().catch(() => ({
429
502
  error: response.statusText,
430
503
  }));
431
- throw SDKError.fromResponse(response.status, error);
504
+ throw SDKError.fromResponse(response.status, errorBody);
432
505
  }
433
506
  return response;
434
507
  } catch (error) {
435
508
  clearTimeout(timeoutId);
436
- if (error instanceof SDKError) {
437
- throw error;
509
+
510
+ // Call the network error callback if configured
511
+ if (this.onNetworkError) {
512
+ const sdkError =
513
+ error instanceof SDKError
514
+ ? error
515
+ : new SDKError(
516
+ error instanceof Error ? error.message : String(error),
517
+ 0,
518
+ "NETWORK_ERROR"
519
+ );
520
+ this.onNetworkError(sdkError, {
521
+ method: "GET",
522
+ path,
523
+ isRetry: false,
524
+ attempt: 0,
525
+ });
438
526
  }
527
+
439
528
  throw error;
440
529
  }
441
530
  }
package/src/core/ws.ts CHANGED
@@ -1,11 +1,17 @@
1
1
  import WebSocket from "isomorphic-ws";
2
2
  import { SDKError } from "../errors";
3
+ import { NetworkErrorCallback } from "./http";
3
4
 
4
5
  export interface WSClientConfig {
5
6
  wsURL: string;
6
7
  timeout?: number;
7
8
  authToken?: string;
8
9
  WebSocket?: typeof WebSocket;
10
+ /**
11
+ * Callback invoked on WebSocket errors.
12
+ * Use this to trigger gateway failover at the application layer.
13
+ */
14
+ onNetworkError?: NetworkErrorCallback;
9
15
  }
10
16
 
11
17
  export type WSMessageHandler = (data: string) => void;
@@ -23,6 +29,7 @@ export class WSClient {
23
29
  private timeout: number;
24
30
  private authToken?: string;
25
31
  private WebSocketClass: typeof WebSocket;
32
+ private onNetworkError?: NetworkErrorCallback;
26
33
 
27
34
  private ws?: WebSocket;
28
35
  private messageHandlers: Set<WSMessageHandler> = new Set();
@@ -36,6 +43,14 @@ export class WSClient {
36
43
  this.timeout = config.timeout ?? 30000;
37
44
  this.authToken = config.authToken;
38
45
  this.WebSocketClass = config.WebSocket ?? WebSocket;
46
+ this.onNetworkError = config.onNetworkError;
47
+ }
48
+
49
+ /**
50
+ * Set the network error callback
51
+ */
52
+ setOnNetworkError(callback: NetworkErrorCallback | undefined): void {
53
+ this.onNetworkError = callback;
39
54
  }
40
55
 
41
56
  /**
@@ -57,9 +72,19 @@ export class WSClient {
57
72
 
58
73
  const timeout = setTimeout(() => {
59
74
  this.ws?.close();
60
- reject(
61
- new SDKError("WebSocket connection timeout", 408, "WS_TIMEOUT")
62
- );
75
+ const error = new SDKError("WebSocket connection timeout", 408, "WS_TIMEOUT");
76
+
77
+ // Call the network error callback if configured
78
+ if (this.onNetworkError) {
79
+ this.onNetworkError(error, {
80
+ method: "WS",
81
+ path: this.wsURL,
82
+ isRetry: false,
83
+ attempt: 0,
84
+ });
85
+ }
86
+
87
+ reject(error);
63
88
  }, this.timeout);
64
89
 
65
90
  this.ws.addEventListener("open", () => {
@@ -78,6 +103,17 @@ export class WSClient {
78
103
  console.error("[WSClient] WebSocket error:", event);
79
104
  clearTimeout(timeout);
80
105
  const error = new SDKError("WebSocket error", 500, "WS_ERROR", event);
106
+
107
+ // Call the network error callback if configured
108
+ if (this.onNetworkError) {
109
+ this.onNetworkError(error, {
110
+ method: "WS",
111
+ path: this.wsURL,
112
+ isRetry: false,
113
+ attempt: 0,
114
+ });
115
+ }
116
+
81
117
  this.errorHandlers.forEach((handler) => handler(error));
82
118
  reject(error);
83
119
  });
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { HttpClient, HttpClientConfig } from "./core/http";
1
+ import { HttpClient, HttpClientConfig, NetworkErrorCallback } from "./core/http";
2
2
  import { AuthClient } from "./auth/client";
3
3
  import { DBClient } from "./db/client";
4
4
  import { PubSubClient } from "./pubsub/client";
@@ -20,6 +20,11 @@ export interface ClientConfig extends Omit<HttpClientConfig, "fetch"> {
20
20
  wsConfig?: Partial<Omit<WSClientConfig, "wsURL">>;
21
21
  functionsConfig?: FunctionsClientConfig;
22
22
  fetch?: typeof fetch;
23
+ /**
24
+ * Callback invoked on network errors (HTTP and WebSocket).
25
+ * Use this to trigger gateway failover at the application layer.
26
+ */
27
+ onNetworkError?: NetworkErrorCallback;
23
28
  }
24
29
 
25
30
  export interface Client {
@@ -39,6 +44,7 @@ export function createClient(config: ClientConfig): Client {
39
44
  maxRetries: config.maxRetries,
40
45
  retryDelayMs: config.retryDelayMs,
41
46
  fetch: config.fetch,
47
+ onNetworkError: config.onNetworkError,
42
48
  });
43
49
 
44
50
  const auth = new AuthClient({
@@ -55,6 +61,7 @@ export function createClient(config: ClientConfig): Client {
55
61
  const pubsub = new PubSubClient(httpClient, {
56
62
  ...config.wsConfig,
57
63
  wsURL,
64
+ onNetworkError: config.onNetworkError,
58
65
  });
59
66
  const network = new NetworkClient(httpClient);
60
67
  const cache = new CacheClient(httpClient);
@@ -73,6 +80,7 @@ export function createClient(config: ClientConfig): Client {
73
80
  }
74
81
 
75
82
  export { HttpClient } from "./core/http";
83
+ export type { NetworkErrorCallback, NetworkErrorContext } from "./core/http";
76
84
  export { WSClient } from "./core/ws";
77
85
  export { AuthClient } from "./auth/client";
78
86
  export { DBClient } from "./db/client";