@parcae/sdk 0.2.8 → 0.3.1

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.
@@ -100,7 +100,13 @@ var SocketTransport = class extends EventEmitter {
100
100
  this.isConnected = true;
101
101
  this.isConnecting = false;
102
102
  hasConnected = true;
103
- this.emit(wasDisconnected ? "reconnected" : "connected");
103
+ if (wasDisconnected && this.key) {
104
+ this.socket.emit("authenticate", this.key, () => {
105
+ this.emit("reconnected");
106
+ });
107
+ } else {
108
+ this.emit(wasDisconnected ? "reconnected" : "connected");
109
+ }
104
110
  });
105
111
  this.socket.on("disconnect", () => {
106
112
  this.isConnected = false;
@@ -422,5 +428,5 @@ function createClient(config) {
422
428
  }
423
429
 
424
430
  export { SSETransport, SocketTransport, createClient };
425
- //# sourceMappingURL=chunk-XAFYMW5P.js.map
426
- //# sourceMappingURL=chunk-XAFYMW5P.js.map
431
+ //# sourceMappingURL=chunk-IETH2XOR.js.map
432
+ //# sourceMappingURL=chunk-IETH2XOR.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/transports/socket.ts","../src/transports/sse.ts","../src/client.ts"],"names":["EventEmitter","body"],"mappings":"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","file":"chunk-IETH2XOR.js","sourcesContent":["/**\n * SocketTransport — Socket.IO implementation of the Transport interface.\n *\n * Bidirectional, full-duplex. Best for apps that need realtime subscriptions\n * (live query updates, collaborative editing, chat, etc.).\n *\n * Extracted from Dollhouse Studio's Dollhouse.ts (667 lines).\n */\n\nimport SocketIO from \"socket.io-client\";\nimport pako from \"pako\";\nimport { decompress } from \"compress-json\";\nimport { EventEmitter } from \"eventemitter3\";\nimport ShortId from \"short-unique-id\";\nimport type { Transport } from \"@parcae/model\";\n\nconst uid = new ShortId({ length: 10 });\nconst SOCKET_CONNECTIONS = new Map<string, any>();\n\nexport interface SocketTransportConfig {\n url: string;\n key?: string | null | (() => Promise<string | null>);\n version?: string;\n /** Socket.IO path. Default: \"/ws\" */\n path?: string;\n}\n\nexport class SocketTransport extends EventEmitter implements Transport {\n private socket: any = null;\n private pendingHandlers: Array<{\n event: string;\n handler: (...args: any[]) => void;\n }> = [];\n private apiKey: string | null | (() => Promise<string | null>);\n private key: string | null = null;\n private url: string;\n private version: string;\n private socketPath: string;\n private waitForAuth: Promise<void> | null = null;\n private resolveAuth: (() => void) | null = null;\n private inflight = new Map<string, Promise<any>>();\n\n public loading: Promise<void>;\n public isLoading = true;\n public isConnected = false;\n public isConnecting = false;\n public authVersion = 0;\n\n constructor(config: SocketTransportConfig) {\n super();\n this.url = config.url;\n this.apiKey = config.key ?? null;\n this.version = config.version ?? \"v1\";\n this.socketPath = config.path ?? \"/ws\";\n this.loading = this.init(this.apiKey);\n }\n\n // ── Auth ──────────────────────────────────────────────────────────────\n\n async setKey(\n key: string | null | (() => Promise<string | null>),\n ): Promise<void> {\n this.apiKey = key;\n this.isLoading = true;\n this.loading = this.init(key);\n await this.loading;\n }\n\n // ── Init ──────────────────────────────────────────────────────────────\n\n private async init(\n key: string | null | (() => Promise<string | null>),\n ): Promise<void> {\n this.isLoading = true;\n this.isConnecting = true;\n\n try {\n this.key = typeof key === \"function\" ? await key() : key;\n const socketKey = `${this.url}:${this.version}`;\n\n if (!SOCKET_CONNECTIONS.has(socketKey)) {\n SOCKET_CONNECTIONS.set(\n socketKey,\n SocketIO(this.url, {\n path: this.socketPath,\n agent: true,\n transports: [\"websocket\"],\n withCredentials: true,\n query: { key: this.key ?? undefined, compression: true },\n }),\n );\n }\n\n this.socket = SOCKET_CONNECTIONS.get(socketKey);\n\n if (this.key) {\n const prevResolve = this.resolveAuth;\n this.waitForAuth = new Promise<void>((resolve) => {\n this.resolveAuth = resolve;\n this.socket.emit(\"authenticate\", this.key, () => {\n this.waitForAuth = null;\n this.resolveAuth = null;\n this.authVersion++;\n this.emit(\"authenticated\");\n if (prevResolve) prevResolve();\n resolve();\n });\n });\n } else {\n this.waitForAuth = null;\n this.resolveAuth = null;\n }\n\n this.isLoading = false;\n } catch (error) {\n this.isLoading = false;\n this.isConnecting = false;\n this.emit(\"error\", error);\n throw error;\n }\n\n this.setupEvents();\n }\n\n private setupEvents(): void {\n if (!this.socket) return;\n\n for (const { event, handler } of this.pendingHandlers) {\n this.socket.on(event, handler);\n }\n this.pendingHandlers = [];\n\n let hasConnected = this.isConnected;\n this.socket.off(\"connect\");\n this.socket.off(\"disconnect\");\n this.socket.off(\"error\");\n\n this.socket.on(\"connect\", () => {\n const wasDisconnected = !this.isConnected && hasConnected;\n this.isConnected = true;\n this.isConnecting = false;\n hasConnected = true;\n\n // Re-authenticate on reconnect\n if (wasDisconnected && this.key) {\n this.socket.emit(\"authenticate\", this.key, () => {\n this.emit(\"reconnected\");\n });\n } else {\n this.emit(wasDisconnected ? \"reconnected\" : \"connected\");\n }\n });\n\n this.socket.on(\"disconnect\", () => {\n this.isConnected = false;\n this.emit(\"disconnected\");\n });\n\n this.socket.on(\"error\", (error: Error) => {\n this.emit(\"error\", error);\n });\n }\n\n // ── Request/Response ──────────────────────────────────────────────────\n\n private async fetch(\n method: string,\n path: string,\n data: any = {},\n ): Promise<any> {\n await this.loading;\n if (this.waitForAuth) await this.waitForAuth;\n if (!this.socket) throw new Error(\"Socket not initialized\");\n\n const upper = method.toUpperCase();\n if (upper === \"GET\") {\n const dedupeKey = `GET:${path}:${this.authVersion}:${JSON.stringify(data)}`;\n const existing = this.inflight.get(dedupeKey);\n if (existing) return existing;\n const req = this._doFetch(method, path, data);\n this.inflight.set(dedupeKey, req);\n req.finally(() => this.inflight.delete(dedupeKey));\n return req;\n }\n\n return this._doFetch(method, path, data);\n }\n\n private async _doFetch(\n method: string,\n path: string,\n data: any = {},\n ): Promise<any> {\n if (!this.isConnected) {\n await new Promise<void>((resolve, reject) => {\n if (this.socket.connected) return resolve();\n const timeout = setTimeout(() => {\n cleanup();\n reject(new Error(\"Connection timeout\"));\n }, 30000);\n const onConnect = () => {\n cleanup();\n resolve();\n };\n const onError = (err: Error) => {\n cleanup();\n reject(new Error(`Connection failed: ${err.message}`));\n };\n const cleanup = () => {\n clearTimeout(timeout);\n this.socket.off(\"connect\", onConnect);\n this.socket.off(\"connect_error\", onError);\n };\n this.socket.once(\"connect\", onConnect);\n this.socket.once(\"connect_error\", onError);\n });\n }\n\n const id = uid.rnd();\n\n return new Promise((resolve, reject) => {\n this.socket.once(id, (msg: any) => {\n try {\n const uncompressed = pako.ungzip(msg, { to: \"string\" });\n const { success, result, message, error } = decompress(\n JSON.parse(uncompressed),\n );\n if (success) resolve(result);\n else\n reject(\n new Error(\n message || error || `Request failed: ${method}:${path}`,\n ),\n );\n } catch (err) {\n reject(err);\n }\n });\n this.socket.emit(\n \"call\",\n id,\n method.toUpperCase(),\n `/${this.version}${path}`,\n data,\n );\n });\n }\n\n async get(path: string, data?: any): Promise<any> {\n return this.fetch(\"get\", path, data);\n }\n async post(path: string, data?: any): Promise<any> {\n return this.fetch(\"post\", path, data);\n }\n async put(path: string, data?: any): Promise<any> {\n return this.fetch(\"put\", path, data);\n }\n async patch(path: string, data?: any): Promise<any> {\n return this.fetch(\"patch\", path, data);\n }\n async delete(path: string, data?: any): Promise<any> {\n return this.fetch(\"delete\", path, data);\n }\n\n // ── Subscriptions ─────────────────────────────────────────────────────\n\n subscribe(event: string, handler: (...args: any[]) => void): () => void {\n if (this.socket) {\n this.socket.on(event, handler);\n } else {\n this.pendingHandlers.push({ event, handler });\n }\n return () => this.unsubscribe(event, handler);\n }\n\n unsubscribe(event: string, handler?: (...args: any[]) => void): void {\n if (this.socket) this.socket.off(event, handler);\n this.pendingHandlers = this.pendingHandlers.filter(\n (h) => !(h.event === event && (!handler || h.handler === handler)),\n );\n }\n\n // ── Control messages ──────────────────────────────────────────────────\n\n async send(event: string, ...args: any[]): Promise<void> {\n if (!this.isConnected && this.socket) {\n await new Promise<void>((resolve) => {\n if (this.socket.connected) return resolve();\n this.socket.once(\"connect\", () => resolve());\n });\n }\n if (this.waitForAuth) await this.waitForAuth;\n if (this.socket) this.socket.emit(event, ...args);\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────\n\n disconnect(): void {\n if (this.socket) {\n this.socket.disconnect();\n SOCKET_CONNECTIONS.delete(`${this.url}:${this.version}`);\n this.socket = null;\n this.isConnected = false;\n }\n }\n\n async reconnect(): Promise<void> {\n this.loading = this.init(this.apiKey);\n await this.loading;\n }\n}\n\nexport default SocketTransport;\n","/**\n * SSETransport — HTTP + Server-Sent Events implementation of the Transport interface.\n *\n * Request/response via standard fetch(). Subscriptions via EventSource.\n * Simpler than Socket.IO — no websocket infra needed. Good for read-heavy\n * apps, serverless backends, or environments where WebSocket isn't available.\n *\n * Trade-offs vs SocketTransport:\n * - Simpler infra (no sticky sessions, works behind any CDN/proxy)\n * - Server → client streaming only (no client → server streaming)\n * - Request/response is standard HTTP (cacheable, observable, debuggable)\n * - No compression (relies on HTTP gzip)\n * - No request deduplication (relies on HTTP/2 multiplexing)\n */\n\nimport { EventEmitter } from \"eventemitter3\";\nimport type { Transport } from \"@parcae/model\";\n\nexport interface SSETransportConfig {\n /** Base URL of the Parcae backend. */\n url: string;\n /** API key or async function returning a key. */\n key?: string | null | (() => Promise<string | null>);\n /** API version prefix. Default: \"v1\" */\n version?: string;\n}\n\nexport class SSETransport extends EventEmitter implements Transport {\n private url: string;\n private version: string;\n private apiKey: string | null | (() => Promise<string | null>);\n private key: string | null = null;\n private eventSources = new Map<string, EventSource>();\n\n public isConnected = true; // HTTP is \"always connected\"\n public isLoading = true;\n public loading: Promise<void>;\n\n constructor(config: SSETransportConfig) {\n super();\n this.url = config.url.replace(/\\/$/, \"\");\n this.version = config.version ?? \"v1\";\n this.apiKey = config.key ?? null;\n this.loading = this.resolveKey();\n }\n\n private async resolveKey(): Promise<void> {\n try {\n this.key =\n typeof this.apiKey === \"function\" ? await this.apiKey() : this.apiKey;\n this.isLoading = false;\n this.emit(\"connected\");\n } catch (err) {\n this.isLoading = false;\n this.emit(\"error\", err);\n }\n }\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this.key) h[\"Authorization\"] = `Bearer ${this.key}`;\n return h;\n }\n\n private fullUrl(path: string): string {\n return `${this.url}/${this.version}${path}`;\n }\n\n // ── Request/Response ──────────────────────────────────────────────────\n\n private async request(\n method: string,\n path: string,\n data?: any,\n ): Promise<any> {\n await this.loading;\n\n const isGet = method.toUpperCase() === \"GET\";\n let url = this.fullUrl(path);\n\n if (isGet && data) {\n const params = new URLSearchParams();\n for (const [k, v] of Object.entries(data)) {\n params.set(k, typeof v === \"object\" ? JSON.stringify(v) : String(v));\n }\n url += `?${params.toString()}`;\n }\n\n const res = await fetch(url, {\n method: method.toUpperCase(),\n headers: this.headers(),\n body: isGet ? undefined : JSON.stringify(data),\n });\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({ error: res.statusText }));\n throw new Error(body.error || body.message || `HTTP ${res.status}`);\n }\n\n const body = await res.json();\n if (body.success === false) throw new Error(body.error || \"Request failed\");\n return body.result ?? body;\n }\n\n async get(path: string, data?: any): Promise<any> {\n return this.request(\"GET\", path, data);\n }\n async post(path: string, data?: any): Promise<any> {\n return this.request(\"POST\", path, data);\n }\n async put(path: string, data?: any): Promise<any> {\n return this.request(\"PUT\", path, data);\n }\n async patch(path: string, data?: any): Promise<any> {\n return this.request(\"PATCH\", path, data);\n }\n async delete(path: string, data?: any): Promise<any> {\n return this.request(\"DELETE\", path, data);\n }\n\n // ── Subscriptions (via Server-Sent Events) ────────────────────────────\n\n subscribe(event: string, handler: (...args: any[]) => void): () => void {\n const url = `${this.url}/${this.version}/__events/${encodeURIComponent(event)}`;\n const source = new EventSource(url, { withCredentials: true });\n\n source.onmessage = (e) => {\n try {\n const data = JSON.parse(e.data);\n handler(data);\n } catch {\n handler(e.data);\n }\n };\n\n source.onerror = () => {\n // EventSource auto-reconnects\n };\n\n this.eventSources.set(event, source);\n\n return () => {\n source.close();\n this.eventSources.delete(event);\n };\n }\n\n unsubscribe(event: string): void {\n const source = this.eventSources.get(event);\n if (source) {\n source.close();\n this.eventSources.delete(event);\n }\n }\n\n // ── Control messages ──────────────────────────────────────────────────\n\n async send(event: string, ...args: any[]): Promise<void> {\n await this.request(\"POST\", \"/__control\", { event, args });\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────\n\n disconnect(): void {\n for (const [, source] of this.eventSources) source.close();\n this.eventSources.clear();\n this.isConnected = false;\n this.emit(\"disconnected\");\n }\n\n async reconnect(): Promise<void> {\n this.loading = this.resolveKey();\n await this.loading;\n }\n}\n\nexport default SSETransport;\n","/**\n * @parcae/sdk — createClient()\n *\n * Creates a Parcae client with a pluggable transport layer.\n * Default: Socket.IO (bidirectional, realtime).\n * Alternative: SSE (HTTP + Server-Sent Events, simpler).\n *\n * The transport is abstracted — the client exposes the same API\n * regardless of which transport is used underneath.\n */\n\nimport { Model, FrontendAdapter } from \"@parcae/model\";\nimport type { Transport } from \"@parcae/model\";\nimport { SocketTransport } from \"./transports/socket\";\nimport type { SocketTransportConfig } from \"./transports/socket\";\nimport { SSETransport } from \"./transports/sse\";\nimport type { SSETransportConfig } from \"./transports/sse\";\n\n// ─── Configuration ───────────────────────────────────────────────────────────\n\nexport interface ClientConfig {\n /** URL of the Parcae backend. */\n url: string;\n /** API key — string or async function that returns a key. */\n key?: string | null | (() => Promise<string | null>);\n /** API version prefix. Default: \"v1\" */\n version?: string;\n /**\n * Transport type. Default: \"socket\"\n * - \"socket\": Socket.IO (bidirectional, realtime subscriptions)\n * - \"sse\": HTTP + Server-Sent Events (read-heavy, simpler infra)\n * - Transport instance: provide your own Transport implementation\n */\n transport?: \"socket\" | \"sse\" | Transport;\n}\n\nexport interface ParcaeClient {\n /** The underlying transport instance. */\n transport: Transport;\n /** Shorthand for transport methods. */\n get(path: string, data?: any): Promise<any>;\n post(path: string, data?: any): Promise<any>;\n put(path: string, data?: any): Promise<any>;\n patch(path: string, data?: any): Promise<any>;\n delete(path: string, data?: any): Promise<any>;\n /** Subscribe to a named event. Returns dispose function. */\n subscribe(event: string, handler: (...args: any[]) => void): () => void;\n /** Unsubscribe from a named event. */\n unsubscribe(event: string, handler?: (...args: any[]) => void): void;\n /** Send a control message. */\n send(event: string, ...args: any[]): void;\n /** Connection state. */\n readonly isConnected: boolean;\n readonly isLoading: boolean;\n /** Promise that resolves when the client is ready. */\n loading: Promise<void>;\n /** Update the auth key. */\n setKey(key: string | null | (() => Promise<string | null>)): Promise<void>;\n /** Listen for transport events. */\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler?: (...args: any[]) => void): void;\n /** Disconnect from the server. */\n disconnect(): void;\n /** Reconnect. */\n reconnect(): Promise<void>;\n /** Auth version — incremented on auth changes. Useful for cache invalidation. */\n readonly authVersion: number;\n}\n\n// ─── createClient ────────────────────────────────────────────────────────────\n\nexport function createClient(config: ClientConfig): ParcaeClient {\n const version = config.version ?? \"v1\";\n\n // Create the transport\n let transport: Transport & {\n loading?: Promise<void>;\n isLoading?: boolean;\n isConnected?: boolean;\n authVersion?: number;\n setKey?: (key: any) => Promise<void>;\n on?: (event: string, handler: (...args: any[]) => void) => void;\n off?: (event: string, handler?: (...args: any[]) => void) => void;\n disconnect?: () => void;\n reconnect?: () => Promise<void>;\n };\n\n if (config.transport && typeof config.transport === \"object\") {\n // Custom transport instance\n transport = config.transport as any;\n } else if (config.transport === \"sse\") {\n transport = new SSETransport({\n url: config.url,\n key: config.key,\n version,\n });\n } else {\n // Default: Socket.IO\n transport = new SocketTransport({\n url: config.url,\n key: config.key,\n version,\n });\n }\n\n // Wire up FrontendAdapter so Model.where(), .findById() etc work\n Model.use(new FrontendAdapter(transport));\n\n const client: ParcaeClient = {\n transport,\n\n get: (path, data) => transport.get(path, data),\n post: (path, data) => transport.post(path, data),\n put: (path, data) => transport.put(path, data),\n patch: (path, data) => transport.patch(path, data),\n delete: (path, data) => transport.delete(path, data),\n\n subscribe(event, handler) {\n if (transport.subscribe) return transport.subscribe(event, handler);\n return () => {}; // no-op if transport doesn't support subscriptions\n },\n\n unsubscribe(event, handler) {\n transport.unsubscribe?.(event, handler);\n },\n\n send(event, ...args) {\n (transport as any).send?.(event, ...args);\n },\n\n get isConnected() {\n return transport.isConnected ?? false;\n },\n get isLoading() {\n return transport.isLoading ?? false;\n },\n get loading() {\n return (transport as any).loading ?? Promise.resolve();\n },\n get authVersion() {\n return (transport as any).authVersion ?? 0;\n },\n\n async setKey(key) {\n if ((transport as any).setKey) await (transport as any).setKey(key);\n },\n\n on(event, handler) {\n transport.on?.(event, handler);\n },\n off(event, handler) {\n transport.off?.(event, handler);\n },\n\n disconnect() {\n transport.disconnect?.();\n },\n async reconnect() {\n await transport.reconnect?.();\n },\n };\n\n return client;\n}\n"]}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { SSETransport, SocketTransport, createClient } from './chunk-XAFYMW5P.js';
1
+ export { SSETransport, SocketTransport, createClient } from './chunk-IETH2XOR.js';
2
2
  export { FrontendAdapter, Model } from '@parcae/model';
3
3
  //# sourceMappingURL=index.js.map
4
4
  //# sourceMappingURL=index.js.map
@@ -8,8 +8,8 @@ interface ParcaeProviderProps {
8
8
  client?: ParcaeClient;
9
9
  /** API base URL (required if no client provided). */
10
10
  url?: string;
11
- /** Bearer token or null (pre-auth). */
12
- apiKey?: string | null;
11
+ /** Bearer token, null (no session), or undefined (still loading). */
12
+ apiKey?: string | null | undefined;
13
13
  /** Stable user ID — triggers re-auth when it changes. */
14
14
  userId?: string | null;
15
15
  /** API version. Default: "v1" */
@@ -20,26 +20,16 @@ interface ParcaeProviderProps {
20
20
  onReady?: (client: ParcaeClient) => void;
21
21
  onError?: (error: Error) => void;
22
22
  }
23
- /**
24
- * ParcaeProvider — creates the SDK client once and re-authenticates on userId change.
25
- *
26
- * Usage with pre-created client:
27
- * ```tsx
28
- * const client = createClient({ url: "...", transport: "socket" });
29
- * <ParcaeProvider client={client}><App /></ParcaeProvider>
30
- * ```
31
- *
32
- * Usage with inline config:
33
- * ```tsx
34
- * <ParcaeProvider url="http://localhost:3000" apiKey={token} userId={user.id}>
35
- * <App />
36
- * </ParcaeProvider>
37
- * ```
38
- */
39
23
  declare const ParcaeProvider: React__default.FC<ParcaeProviderProps>;
40
24
 
41
- declare const ParcaeContext: React.Context<ParcaeClient | null>;
42
- declare function useParcae(): ParcaeClient;
25
+ type AuthState = "loading" | "authenticated" | "unauthenticated";
26
+ interface ParcaeContextValue {
27
+ client: ParcaeClient;
28
+ authState: AuthState;
29
+ authVersion: number;
30
+ }
31
+ declare const ParcaeContext: React.Context<ParcaeContextValue | null>;
32
+ declare function useParcae(): ParcaeContextValue;
43
33
 
44
34
  interface QueryChain<T> {
45
35
  find(): Promise<T[]>;
@@ -47,7 +37,10 @@ interface QueryChain<T> {
47
37
  __modelType?: string;
48
38
  __modelClass?: any;
49
39
  __adapter?: any;
50
- __debounceMs?: number;
40
+ }
41
+ interface UseQueryOptions {
42
+ /** Wait for auth before firing. Default: true. */
43
+ waitForAuth?: boolean;
51
44
  }
52
45
  interface UseQueryResult<T> {
53
46
  items: T[];
@@ -55,7 +48,7 @@ interface UseQueryResult<T> {
55
48
  error: Error | null;
56
49
  refetch: () => void;
57
50
  }
58
- declare function useQuery<T>(chain: QueryChain<T> | null | undefined): UseQueryResult<T>;
51
+ declare function useQuery<T>(chain: QueryChain<T> | null | undefined, options?: UseQueryOptions): UseQueryResult<T>;
59
52
 
60
53
  declare function useApi(): {
61
54
  get: (path: string, data?: any) => Promise<any>;
@@ -69,15 +62,20 @@ declare function useApi(): {
69
62
  */
70
63
  declare function useSDK(): ParcaeClient;
71
64
  /**
72
- * useConnectionStatus — reactive connection state.
65
+ * useConnectionStatus — connection + auth state.
73
66
  */
74
67
  declare function useConnectionStatus(): {
75
68
  isConnected: boolean;
76
69
  isLoading: boolean;
70
+ authState: AuthState;
77
71
  };
72
+ /**
73
+ * useAuthState — just the auth state.
74
+ */
75
+ declare function useAuthState(): AuthState;
78
76
 
79
77
  declare function useSetting<T = string>(key: string, defaultValue: T): [T, (value: T) => Promise<void>, {
80
78
  isLoading: boolean;
81
79
  }];
82
80
 
83
- export { ParcaeContext, ParcaeProvider, type ParcaeProviderProps, useApi, useConnectionStatus, useParcae, useQuery, useSDK, useSetting };
81
+ export { type AuthState, ParcaeContext, type ParcaeContextValue, ParcaeProvider, type ParcaeProviderProps, useApi, useAuthState, useConnectionStatus, useParcae, useQuery, useSDK, useSetting };
@@ -1,14 +1,14 @@
1
- import { createClient } from '../chunk-XAFYMW5P.js';
2
- import { createContext, useContext, useMemo, useRef, useEffect, useCallback, useSyncExternalStore, useState } from 'react';
1
+ import { createClient } from '../chunk-IETH2XOR.js';
2
+ import { createContext, useContext, useState, useMemo, useRef, useEffect, useSyncExternalStore, useCallback } from 'react';
3
3
  import { jsx } from 'react/jsx-runtime';
4
4
 
5
5
  var ParcaeContext = createContext(null);
6
6
  function useParcae() {
7
- const client = useContext(ParcaeContext);
8
- if (!client) {
7
+ const ctx = useContext(ParcaeContext);
8
+ if (!ctx) {
9
9
  throw new Error("useParcae must be used within a <ParcaeProvider>");
10
10
  }
11
- return client;
11
+ return ctx;
12
12
  }
13
13
  var ParcaeProvider = ({
14
14
  client: externalClient,
@@ -21,6 +21,13 @@ var ParcaeProvider = ({
21
21
  onReady,
22
22
  onError
23
23
  }) => {
24
+ const [authState, setAuthState] = useState(
25
+ // If apiKey is undefined, the frontend auth provider is still loading.
26
+ // If apiKey is null, the user is not logged in.
27
+ // If apiKey is a string, we have a token but haven't verified it yet.
28
+ apiKey === void 0 ? "loading" : apiKey === null ? "unauthenticated" : "loading"
29
+ );
30
+ const [authVersion, setAuthVersion] = useState(0);
24
31
  const client = useMemo(() => {
25
32
  if (externalClient) return externalClient;
26
33
  if (!url)
@@ -29,15 +36,31 @@ var ParcaeProvider = ({
29
36
  );
30
37
  return createClient({ url, version, transport, key: null });
31
38
  }, [externalClient, url, version, transport]);
32
- const apiKeyRef = useRef(apiKey);
33
- apiKeyRef.current = apiKey;
34
39
  const onReadyRef = useRef(onReady);
35
40
  onReadyRef.current = onReady;
36
41
  const onErrorRef = useRef(onError);
37
42
  onErrorRef.current = onError;
38
43
  useEffect(() => {
39
- client.setKey(apiKeyRef.current ?? null).then(() => onReadyRef.current?.(client)).catch((err) => onErrorRef.current?.(err));
40
- }, [userId, client]);
44
+ if (apiKey === void 0) {
45
+ setAuthState("loading");
46
+ return;
47
+ }
48
+ if (apiKey === null) {
49
+ setAuthState("unauthenticated");
50
+ setAuthVersion((v) => v + 1);
51
+ return;
52
+ }
53
+ setAuthState("loading");
54
+ client.setKey(apiKey).then(() => {
55
+ setAuthState("authenticated");
56
+ setAuthVersion((v) => v + 1);
57
+ onReadyRef.current?.(client);
58
+ }).catch((err) => {
59
+ setAuthState("unauthenticated");
60
+ setAuthVersion((v) => v + 1);
61
+ onErrorRef.current?.(err);
62
+ });
63
+ }, [apiKey, userId, client]);
41
64
  useEffect(() => {
42
65
  const onErr = (err) => onErrorRef.current?.(err);
43
66
  client.on("error", onErr);
@@ -45,165 +68,165 @@ var ParcaeProvider = ({
45
68
  client.off("error", onErr);
46
69
  };
47
70
  }, [client]);
48
- return /* @__PURE__ */ jsx(ParcaeContext.Provider, { value: client, children });
71
+ const contextValue = useMemo(
72
+ () => ({ client, authState, authVersion }),
73
+ [client, authState, authVersion]
74
+ );
75
+ return /* @__PURE__ */ jsx(ParcaeContext.Provider, { value: contextValue, children });
49
76
  };
50
- var CACHE_TIMEOUT_MS = 6e4;
51
- var DEFAULT_DEBOUNCE_MS = 100;
52
- var queryCache = /* @__PURE__ */ new Map();
53
- function buildCacheKey(chain, authVersion) {
54
- const type = chain.__modelType ?? "unknown";
55
- const steps = JSON.stringify(chain.__steps ?? []);
56
- return `${type}:${authVersion}:${steps}`;
57
- }
58
- function useQuery(chain) {
59
- const client = useParcae();
60
- const authVersion = client.authVersion;
61
- const cacheKey = chain ? buildCacheKey(chain, authVersion) : "__null__";
62
- if (!queryCache.has(cacheKey) && chain) {
63
- queryCache.set(cacheKey, {
64
- items: [],
65
- itemMap: /* @__PURE__ */ new Map(),
77
+ var cache = /* @__PURE__ */ new Map();
78
+ var GC_DELAY = 6e4;
79
+ var EMPTY = [];
80
+ var EMPTY_RESULT = {
81
+ items: EMPTY,
82
+ loading: true,
83
+ error: null,
84
+ refetch: () => {
85
+ }
86
+ };
87
+ function getOrCreate(key) {
88
+ let entry = cache.get(key);
89
+ if (!entry) {
90
+ entry = {
91
+ items: EMPTY,
66
92
  loading: true,
67
93
  error: null,
68
- refCount: 0,
69
- timeoutHandle: null,
70
- version: 0,
71
- stateVersion: 0,
94
+ refs: 0,
72
95
  listeners: /* @__PURE__ */ new Set(),
73
- subscriptionHash: null,
74
- pendingOps: [],
75
- debounceTimer: null,
76
- debounceMs: chain.__debounceMs ?? DEFAULT_DEBOUNCE_MS,
77
- disposeSubscription: null
78
- });
79
- }
80
- const entry = queryCache.get(cacheKey);
81
- const subscribe = useCallback(
82
- (listener) => {
83
- if (!entry) return () => {
84
- };
85
- entry.listeners.add(listener);
86
- entry.refCount++;
87
- if (entry.timeoutHandle) {
88
- clearTimeout(entry.timeoutHandle);
89
- entry.timeoutHandle = null;
90
- }
91
- return () => {
92
- entry.listeners.delete(listener);
93
- entry.refCount--;
94
- if (entry.refCount <= 0) {
95
- entry.timeoutHandle = setTimeout(() => {
96
- entry.disposeSubscription?.();
97
- queryCache.delete(cacheKey);
98
- }, CACHE_TIMEOUT_MS);
99
- }
100
- };
101
- },
102
- [entry, cacheKey]
103
- );
104
- const getSnapshot = useCallback(() => entry?.stateVersion ?? 0, [entry]);
105
- useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
106
- const refetch = useCallback(() => {
107
- if (!chain || !entry) return;
108
- entry.loading = true;
109
- notifyListeners(entry);
110
- chain.find().then((items) => {
111
- entry.items = items;
112
- entry.itemMap = new Map(items.map((item) => [item.id, item]));
113
- entry.loading = false;
114
- entry.error = null;
115
- entry.version++;
116
- notifyListeners(entry);
117
- }).catch((err) => {
118
- entry.error = err;
119
- entry.loading = false;
120
- notifyListeners(entry);
121
- });
122
- if (!entry.disposeSubscription && chain.__modelType) {
123
- const subEvent = `query:${cacheKey}`;
124
- client.send("subscribe:query", {
125
- hash: cacheKey,
126
- modelType: chain.__modelType,
127
- steps: chain.__steps ?? []
128
- });
129
- const dispose = client.subscribe(subEvent, (ops) => {
130
- if (!entry) return;
131
- entry.pendingOps.push(...ops);
132
- if (entry.debounceTimer) clearTimeout(entry.debounceTimer);
133
- entry.debounceTimer = setTimeout(() => {
134
- applyDiffOps(entry, chain);
135
- entry.debounceTimer = null;
136
- }, entry.debounceMs);
137
- });
138
- entry.subscriptionHash = cacheKey;
139
- entry.disposeSubscription = () => {
140
- dispose();
141
- client.send("unsubscribe:query", { hash: cacheKey });
142
- };
143
- }
144
- }, [chain, entry, cacheKey, client]);
145
- useEffect(() => {
146
- if (chain) refetch();
147
- }, [cacheKey]);
148
- if (!entry) {
149
- return { items: [], loading: false, error: null, refetch: () => {
150
- } };
96
+ dispose: null,
97
+ gcTimer: null
98
+ };
99
+ cache.set(key, entry);
151
100
  }
152
- return {
153
- items: entry.items,
154
- loading: entry.loading,
155
- error: entry.error,
156
- refetch
157
- };
101
+ return entry;
158
102
  }
159
- function notifyListeners(entry) {
160
- entry.stateVersion++;
161
- for (const listener of entry.listeners) listener();
103
+ function notify(entry) {
104
+ for (const fn of entry.listeners) fn();
162
105
  }
163
- function applyDiffOps(entry, chain) {
164
- const ops = entry.pendingOps.splice(0);
165
- if (!ops.length) return;
166
- const ModelClass = chain.__modelClass;
167
- const adapter = chain.__adapter;
168
- let changed = false;
169
- for (const op of ops) {
170
- switch (op.op) {
171
- case "add": {
172
- if (!entry.itemMap.has(op.id) && op.data && ModelClass && adapter) {
173
- const instance = new ModelClass(adapter, op.data);
174
- entry.items.push(instance);
175
- entry.itemMap.set(op.id, instance);
176
- changed = true;
106
+ function fetchAndSubscribe(key, entry, chain, client) {
107
+ entry.loading = true;
108
+ entry.error = null;
109
+ notify(entry);
110
+ chain.find().then((result) => {
111
+ entry.items = result;
112
+ entry.loading = false;
113
+ notify(entry);
114
+ }).catch((err) => {
115
+ entry.error = err;
116
+ entry.loading = false;
117
+ notify(entry);
118
+ });
119
+ if (!entry.dispose && chain.__modelType) {
120
+ const event = `query:${key}`;
121
+ client.send("subscribe:query", {
122
+ hash: key,
123
+ modelType: chain.__modelType,
124
+ steps: chain.__steps ?? []
125
+ });
126
+ const unsub = client.subscribe(event, (ops) => {
127
+ if (!ops?.length) return;
128
+ const map = new Map(entry.items.map((item) => [item.id, item]));
129
+ let changed = false;
130
+ for (const op of ops) {
131
+ switch (op.op) {
132
+ case "add":
133
+ if (!map.has(op.id) && op.data && chain.__modelClass) {
134
+ map.set(op.id, new chain.__modelClass(chain.__adapter, op.data));
135
+ changed = true;
136
+ }
137
+ break;
138
+ case "remove":
139
+ if (map.has(op.id)) {
140
+ map.delete(op.id);
141
+ changed = true;
142
+ }
143
+ break;
144
+ case "update": {
145
+ const existing = map.get(op.id);
146
+ if (existing && op.data) {
147
+ for (const [k, v] of Object.entries(op.data)) {
148
+ existing[k] = v;
149
+ }
150
+ changed = true;
151
+ }
152
+ break;
153
+ }
177
154
  }
178
- break;
179
155
  }
180
- case "remove": {
181
- if (entry.itemMap.has(op.id)) {
182
- entry.items = entry.items.filter((item) => item.id !== op.id);
183
- entry.itemMap.delete(op.id);
184
- changed = true;
185
- }
186
- break;
156
+ if (changed) {
157
+ entry.items = [...map.values()];
158
+ notify(entry);
187
159
  }
188
- case "update": {
189
- const existing = entry.itemMap.get(op.id);
190
- if (existing && op.data) {
191
- for (const [key, value] of Object.entries(op.data)) {
192
- existing.__data[key] = value;
193
- }
194
- changed = true;
195
- }
196
- break;
160
+ });
161
+ entry.dispose = () => {
162
+ unsub();
163
+ client.send("unsubscribe:query", { hash: key });
164
+ entry.dispose = null;
165
+ };
166
+ }
167
+ }
168
+ function useQuery(chain, options = {}) {
169
+ const { client, authState, authVersion } = useParcae();
170
+ const waitForAuth = options.waitForAuth ?? true;
171
+ const authReady = !waitForAuth || authState !== "loading";
172
+ const key = chain && authReady ? `${chain.__modelType}:${authVersion}:${JSON.stringify(chain.__steps ?? [])}` : null;
173
+ const keyRef = useRef(key);
174
+ keyRef.current = key;
175
+ const subscribe = (onStoreChange) => {
176
+ const k = keyRef.current;
177
+ if (!k) return () => {
178
+ };
179
+ const entry2 = getOrCreate(k);
180
+ entry2.refs++;
181
+ entry2.listeners.add(onStoreChange);
182
+ if (entry2.gcTimer) {
183
+ clearTimeout(entry2.gcTimer);
184
+ entry2.gcTimer = null;
185
+ }
186
+ return () => {
187
+ entry2.listeners.delete(onStoreChange);
188
+ entry2.refs--;
189
+ if (entry2.refs <= 0) {
190
+ entry2.gcTimer = setTimeout(() => {
191
+ entry2.dispose?.();
192
+ cache.delete(k);
193
+ }, GC_DELAY);
197
194
  }
195
+ };
196
+ };
197
+ const getSnapshot = () => {
198
+ const k = keyRef.current;
199
+ if (!k) return EMPTY;
200
+ return cache.get(k)?.items ?? EMPTY;
201
+ };
202
+ const items = useSyncExternalStore(
203
+ subscribe,
204
+ getSnapshot,
205
+ getSnapshot
206
+ );
207
+ useEffect(() => {
208
+ if (!key || !chain) return;
209
+ const entry2 = getOrCreate(key);
210
+ if (entry2.items === EMPTY || entry2.items.length === 0) {
211
+ fetchAndSubscribe(key, entry2, chain, client);
198
212
  }
199
- }
200
- if (changed) {
201
- entry.version++;
202
- notifyListeners(entry);
203
- }
213
+ }, [key]);
214
+ const refetch = () => {
215
+ if (!key || !chain) return;
216
+ const entry2 = getOrCreate(key);
217
+ fetchAndSubscribe(key, entry2, chain, client);
218
+ };
219
+ if (!key) return EMPTY_RESULT;
220
+ const entry = cache.get(key);
221
+ return {
222
+ items,
223
+ loading: entry?.loading ?? true,
224
+ error: entry?.error ?? null,
225
+ refetch
226
+ };
204
227
  }
205
228
  function useApi() {
206
- const client = useParcae();
229
+ const { client } = useParcae();
207
230
  return useMemo(
208
231
  () => ({
209
232
  get: client.get.bind(client),
@@ -216,20 +239,29 @@ function useApi() {
216
239
  );
217
240
  }
218
241
  function useSDK() {
219
- return useParcae();
242
+ return useParcae().client;
220
243
  }
221
244
  function useConnectionStatus() {
222
- const client = useParcae();
245
+ const { client, authState } = useParcae();
223
246
  return {
224
247
  isConnected: client.isConnected,
225
- isLoading: client.isLoading
248
+ isLoading: client.isLoading,
249
+ authState
226
250
  };
227
251
  }
252
+ function useAuthState() {
253
+ return useParcae().authState;
254
+ }
228
255
  function useSetting(key, defaultValue) {
229
- const client = useParcae();
256
+ const { client, authState } = useParcae();
230
257
  const [value, setValue] = useState(defaultValue);
231
258
  const [isLoading, setIsLoading] = useState(true);
232
259
  useEffect(() => {
260
+ if (authState === "loading") return;
261
+ if (authState === "unauthenticated") {
262
+ setIsLoading(false);
263
+ return;
264
+ }
233
265
  let cancelled = false;
234
266
  client.get(`/settings/${encodeURIComponent(key)}`).then((result) => {
235
267
  if (!cancelled && result?.value !== void 0) {
@@ -242,7 +274,7 @@ function useSetting(key, defaultValue) {
242
274
  return () => {
243
275
  cancelled = true;
244
276
  };
245
- }, [key, client]);
277
+ }, [key, client, authState]);
246
278
  const update = useCallback(
247
279
  async (newValue) => {
248
280
  setValue(newValue);
@@ -255,6 +287,6 @@ function useSetting(key, defaultValue) {
255
287
  return [value, update, { isLoading }];
256
288
  }
257
289
 
258
- export { ParcaeContext, ParcaeProvider, useApi, useConnectionStatus, useParcae, useQuery, useSDK, useSetting };
290
+ export { ParcaeContext, ParcaeProvider, useApi, useAuthState, useConnectionStatus, useParcae, useQuery, useSDK, useSetting };
259
291
  //# sourceMappingURL=index.js.map
260
292
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/context.ts","../../src/react/Provider.tsx","../../src/react/useQuery.ts","../../src/react/useApi.ts","../../src/react/useSetting.ts"],"names":["useEffect","useMemo","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { ParcaeClient } from \"../client\";\n\nexport const ParcaeContext = createContext<ParcaeClient | null>(null);\n\nexport function useParcae(): ParcaeClient {\n const client = useContext(ParcaeContext);\n if (!client) {\n throw new Error(\"useParcae must be used within a <ParcaeProvider>\");\n }\n return client;\n}\n","\"use client\";\n\nimport React, { useEffect, useMemo, useRef } from \"react\";\nimport { createClient } from \"../client\";\nimport type { ParcaeClient, ClientConfig } from \"../client\";\nimport { ParcaeContext } from \"./context\";\n\nexport interface ParcaeProviderProps {\n /** Pre-created client instance. If provided, url/key/transport are ignored. */\n client?: ParcaeClient;\n /** API base URL (required if no client provided). */\n url?: string;\n /** Bearer token or null (pre-auth). */\n apiKey?: string | null;\n /** Stable user ID — triggers re-auth when it changes. */\n userId?: string | null;\n /** API version. Default: \"v1\" */\n version?: string;\n /** Transport type. Default: \"socket\" */\n transport?: ClientConfig[\"transport\"];\n children: React.ReactNode;\n onReady?: (client: ParcaeClient) => void;\n onError?: (error: Error) => void;\n}\n\n/**\n * ParcaeProvider — creates the SDK client once and re-authenticates on userId change.\n *\n * Usage with pre-created client:\n * ```tsx\n * const client = createClient({ url: \"...\", transport: \"socket\" });\n * <ParcaeProvider client={client}><App /></ParcaeProvider>\n * ```\n *\n * Usage with inline config:\n * ```tsx\n * <ParcaeProvider url=\"http://localhost:3000\" apiKey={token} userId={user.id}>\n * <App />\n * </ParcaeProvider>\n * ```\n */\nexport const ParcaeProvider: React.FC<ParcaeProviderProps> = ({\n client: externalClient,\n url,\n apiKey,\n userId,\n version = \"v1\",\n transport = \"socket\",\n children,\n onReady,\n onError,\n}) => {\n // Create client once per url+version+transport (or use external)\n const client = useMemo(() => {\n if (externalClient) return externalClient;\n if (!url)\n throw new Error(\n \"ParcaeProvider requires either a `client` prop or a `url` prop\",\n );\n return createClient({ url, version, transport, key: null });\n }, [externalClient, url, version, transport]);\n\n // Refs for callbacks to avoid re-running effects on unstable inline functions\n const apiKeyRef = useRef(apiKey);\n apiKeyRef.current = apiKey;\n const onReadyRef = useRef(onReady);\n onReadyRef.current = onReady;\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n\n // Re-authenticate when userId changes\n useEffect(() => {\n client\n .setKey(apiKeyRef.current ?? null)\n .then(() => onReadyRef.current?.(client))\n .catch((err) => onErrorRef.current?.(err));\n }, [userId, client]);\n\n // Forward transport errors\n useEffect(() => {\n const onErr = (err: Error) => onErrorRef.current?.(err);\n client.on(\"error\", onErr);\n return () => {\n client.off(\"error\", onErr);\n };\n }, [client]);\n\n return (\n <ParcaeContext.Provider value={client}>{children}</ParcaeContext.Provider>\n );\n};\n\nexport default ParcaeProvider;\n","\"use client\";\n\n/**\n * useQuery — reactive data fetching with realtime subscriptions.\n *\n * Takes a query chain, returns an array of typed model instances.\n * Subscribes to realtime updates — the server diffs queries on model changes\n * and pushes surgical add/remove/update ops.\n *\n * @example\n * ```tsx\n * const { items, loading } = useQuery(Post.where({ published: true }));\n * ```\n */\n\nimport { useCallback, useEffect, useSyncExternalStore } from \"react\";\nimport { useParcae } from \"./context\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\ninterface QueryChain<T> {\n find(): Promise<T[]>;\n __steps?: any[];\n __modelType?: string;\n __modelClass?: any;\n __adapter?: any;\n __debounceMs?: number;\n}\n\ninterface UseQueryResult<T> {\n items: T[];\n loading: boolean;\n error: Error | null;\n refetch: () => void;\n}\n\ninterface DiffOp {\n op: \"add\" | \"remove\" | \"update\";\n id: string;\n data?: Record<string, any>;\n}\n\n// ─── Query Cache ─────────────────────────────────────────────────────────────\n\nconst CACHE_TIMEOUT_MS = 60_000;\nconst DEFAULT_DEBOUNCE_MS = 100;\n\ninterface CacheEntry<T = any> {\n items: T[];\n itemMap: Map<string, T>;\n loading: boolean;\n error: Error | null;\n refCount: number;\n timeoutHandle: ReturnType<typeof setTimeout> | null;\n version: number;\n stateVersion: number;\n listeners: Set<() => void>;\n subscriptionHash: string | null;\n pendingOps: DiffOp[];\n debounceTimer: ReturnType<typeof setTimeout> | null;\n debounceMs: number;\n disposeSubscription: (() => void) | null;\n}\n\nconst queryCache = new Map<string, CacheEntry>();\n\nfunction buildCacheKey(chain: QueryChain<any>, authVersion: number): string {\n const type = chain.__modelType ?? \"unknown\";\n const steps = JSON.stringify(chain.__steps ?? []);\n return `${type}:${authVersion}:${steps}`;\n}\n\n// ─── useQuery ────────────────────────────────────────────────────────────────\n\nexport function useQuery<T>(\n chain: QueryChain<T> | null | undefined,\n): UseQueryResult<T> {\n const client = useParcae();\n const authVersion = client.authVersion;\n\n const cacheKey = chain ? buildCacheKey(chain, authVersion) : \"__null__\";\n\n // ── Get or create cache entry ──────────────────────────────────────\n\n if (!queryCache.has(cacheKey) && chain) {\n queryCache.set(cacheKey, {\n items: [],\n itemMap: new Map(),\n loading: true,\n error: null,\n refCount: 0,\n timeoutHandle: null,\n version: 0,\n stateVersion: 0,\n listeners: new Set(),\n subscriptionHash: null,\n pendingOps: [],\n debounceTimer: null,\n debounceMs: chain.__debounceMs ?? DEFAULT_DEBOUNCE_MS,\n disposeSubscription: null,\n });\n }\n\n const entry = queryCache.get(cacheKey);\n\n // ── useSyncExternalStore for tear-safe rendering ───────────────────\n\n const subscribe = useCallback(\n (listener: () => void) => {\n if (!entry) return () => {};\n entry.listeners.add(listener);\n entry.refCount++;\n\n // Cancel pending GC\n if (entry.timeoutHandle) {\n clearTimeout(entry.timeoutHandle);\n entry.timeoutHandle = null;\n }\n\n return () => {\n entry.listeners.delete(listener);\n entry.refCount--;\n\n // GC: if no subscribers left, schedule cleanup\n if (entry.refCount <= 0) {\n entry.timeoutHandle = setTimeout(() => {\n entry.disposeSubscription?.();\n queryCache.delete(cacheKey);\n }, CACHE_TIMEOUT_MS);\n }\n };\n },\n [entry, cacheKey],\n );\n\n const getSnapshot = useCallback(() => entry?.stateVersion ?? 0, [entry]);\n\n useSyncExternalStore(subscribe, getSnapshot, getSnapshot);\n\n // ── Fetch + subscribe ──────────────────────────────────────────────\n\n const refetch = useCallback(() => {\n if (!chain || !entry) return;\n\n entry.loading = true;\n notifyListeners(entry);\n\n chain\n .find()\n .then((items) => {\n entry.items = items;\n entry.itemMap = new Map(items.map((item: any) => [item.id, item]));\n entry.loading = false;\n entry.error = null;\n entry.version++;\n notifyListeners(entry);\n })\n .catch((err) => {\n entry.error = err;\n entry.loading = false;\n notifyListeners(entry);\n });\n\n // Set up realtime subscription if transport supports it\n if (!entry.disposeSubscription && chain.__modelType) {\n const subEvent = `query:${cacheKey}`;\n\n // Ask server to subscribe to this query\n client.send(\"subscribe:query\", {\n hash: cacheKey,\n modelType: chain.__modelType,\n steps: chain.__steps ?? [],\n });\n\n // Listen for diff ops from the server\n const dispose = client.subscribe(subEvent, (ops: DiffOp[]) => {\n if (!entry) return;\n entry.pendingOps.push(...ops);\n\n // Debounce application of ops\n if (entry.debounceTimer) clearTimeout(entry.debounceTimer);\n entry.debounceTimer = setTimeout(() => {\n applyDiffOps(entry, chain);\n entry.debounceTimer = null;\n }, entry.debounceMs);\n });\n\n entry.subscriptionHash = cacheKey;\n entry.disposeSubscription = () => {\n dispose();\n client.send(\"unsubscribe:query\", { hash: cacheKey });\n };\n }\n }, [chain, entry, cacheKey, client]);\n\n // Initial fetch on mount / chain change\n useEffect(() => {\n if (chain) refetch();\n }, [cacheKey]); // eslint-disable-line react-hooks/exhaustive-deps\n\n if (!entry) {\n return { items: [], loading: false, error: null, refetch: () => {} };\n }\n\n return {\n items: entry.items,\n loading: entry.loading,\n error: entry.error,\n refetch,\n };\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction notifyListeners(entry: CacheEntry): void {\n entry.stateVersion++;\n for (const listener of entry.listeners) listener();\n}\n\nfunction applyDiffOps<T>(entry: CacheEntry<T>, chain: QueryChain<T>): void {\n const ops = entry.pendingOps.splice(0);\n if (!ops.length) return;\n\n const ModelClass = chain.__modelClass;\n const adapter = chain.__adapter;\n let changed = false;\n\n for (const op of ops) {\n switch (op.op) {\n case \"add\": {\n if (!entry.itemMap.has(op.id) && op.data && ModelClass && adapter) {\n const instance = new ModelClass(adapter, op.data);\n entry.items.push(instance);\n entry.itemMap.set(op.id, instance);\n changed = true;\n }\n break;\n }\n case \"remove\": {\n if (entry.itemMap.has(op.id)) {\n entry.items = entry.items.filter((item: any) => item.id !== op.id);\n entry.itemMap.delete(op.id);\n changed = true;\n }\n break;\n }\n case \"update\": {\n const existing = entry.itemMap.get(op.id) as any;\n if (existing && op.data) {\n for (const [key, value] of Object.entries(op.data)) {\n existing.__data[key] = value;\n }\n changed = true;\n }\n break;\n }\n }\n }\n\n if (changed) {\n entry.version++;\n notifyListeners(entry);\n }\n}\n","\"use client\";\n\n/**\n * useApi — pre-bound HTTP methods from the Parcae client.\n *\n * @example\n * ```tsx\n * const { get, post } = useApi();\n * const data = await get(\"/custom-endpoint\");\n * ```\n */\n\nimport { useMemo } from \"react\";\nimport { useParcae } from \"./context\";\n\nexport function useApi() {\n const client = useParcae();\n\n return useMemo(\n () => ({\n get: client.get.bind(client),\n post: client.post.bind(client),\n put: client.put.bind(client),\n patch: client.patch.bind(client),\n delete: client.delete.bind(client),\n }),\n [client],\n );\n}\n\n/**\n * useSDK — raw client instance.\n */\nexport function useSDK() {\n return useParcae();\n}\n\n/**\n * useConnectionStatus — reactive connection state.\n */\nexport function useConnectionStatus() {\n const client = useParcae();\n // This is a snapshot — for true reactivity, components should\n // listen to client.on(\"connected\"/\"disconnected\") events.\n return {\n isConnected: client.isConnected,\n isLoading: client.isLoading,\n };\n}\n","\"use client\";\n\n/**\n * useSetting — key-value user settings stored as a Setting model.\n *\n * @example\n * ```tsx\n * const [theme, setTheme, { isLoading }] = useSetting(\"theme\", \"light\");\n * ```\n */\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport { useParcae } from \"./context\";\n\nexport function useSetting<T = string>(\n key: string,\n defaultValue: T,\n): [T, (value: T) => Promise<void>, { isLoading: boolean }] {\n const client = useParcae();\n const [value, setValue] = useState<T>(defaultValue);\n const [isLoading, setIsLoading] = useState(true);\n\n useEffect(() => {\n let cancelled = false;\n\n client\n .get(`/settings/${encodeURIComponent(key)}`)\n .then((result) => {\n if (!cancelled && result?.value !== undefined) {\n setValue(result.value);\n }\n })\n .catch(() => {\n // Setting doesn't exist yet — use default\n })\n .finally(() => {\n if (!cancelled) setIsLoading(false);\n });\n\n return () => {\n cancelled = true;\n };\n }, [key, client]);\n\n const update = useCallback(\n async (newValue: T) => {\n setValue(newValue);\n await client.put(`/settings/${encodeURIComponent(key)}`, {\n value: newValue,\n });\n },\n [key, client],\n );\n\n return [value, update, { isLoading }];\n}\n"]}
1
+ {"version":3,"sources":["../../src/react/context.ts","../../src/react/Provider.tsx","../../src/react/useQuery.ts","../../src/react/useApi.ts","../../src/react/useSetting.ts"],"names":["useRef","entry","useEffect","useMemo","useState","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["import { createContext, useContext } from \"react\";\nimport type { ParcaeClient } from \"../client\";\n\nexport type AuthState = \"loading\" | \"authenticated\" | \"unauthenticated\";\n\nexport interface ParcaeContextValue {\n client: ParcaeClient;\n authState: AuthState;\n authVersion: number;\n}\n\nexport const ParcaeContext = createContext<ParcaeContextValue | null>(null);\n\nexport function useParcae(): ParcaeContextValue {\n const ctx = useContext(ParcaeContext);\n if (!ctx) {\n throw new Error(\"useParcae must be used within a <ParcaeProvider>\");\n }\n return ctx;\n}\n","\"use client\";\n\nimport React, {\n useEffect,\n useMemo,\n useRef,\n useState,\n useCallback,\n} from \"react\";\nimport { createClient } from \"../client\";\nimport type { ParcaeClient, ClientConfig } from \"../client\";\nimport { ParcaeContext } from \"./context\";\nimport type { ParcaeContextValue, AuthState } from \"./context\";\n\nexport interface ParcaeProviderProps {\n /** Pre-created client instance. If provided, url/key/transport are ignored. */\n client?: ParcaeClient;\n /** API base URL (required if no client provided). */\n url?: string;\n /** Bearer token, null (no session), or undefined (still loading). */\n apiKey?: string | null | undefined;\n /** Stable user ID — triggers re-auth when it changes. */\n userId?: string | null;\n /** API version. Default: \"v1\" */\n version?: string;\n /** Transport type. Default: \"socket\" */\n transport?: ClientConfig[\"transport\"];\n children: React.ReactNode;\n onReady?: (client: ParcaeClient) => void;\n onError?: (error: Error) => void;\n}\n\nexport const ParcaeProvider: React.FC<ParcaeProviderProps> = ({\n client: externalClient,\n url,\n apiKey,\n userId,\n version = \"v1\",\n transport = \"socket\",\n children,\n onReady,\n onError,\n}) => {\n const [authState, setAuthState] = useState<AuthState>(\n // If apiKey is undefined, the frontend auth provider is still loading.\n // If apiKey is null, the user is not logged in.\n // If apiKey is a string, we have a token but haven't verified it yet.\n apiKey === undefined\n ? \"loading\"\n : apiKey === null\n ? \"unauthenticated\"\n : \"loading\",\n );\n const [authVersion, setAuthVersion] = useState(0);\n\n const client = useMemo(() => {\n if (externalClient) return externalClient;\n if (!url)\n throw new Error(\n \"ParcaeProvider requires either a `client` prop or a `url` prop\",\n );\n return createClient({ url, version, transport, key: null });\n }, [externalClient, url, version, transport]);\n\n const onReadyRef = useRef(onReady);\n onReadyRef.current = onReady;\n const onErrorRef = useRef(onError);\n onErrorRef.current = onError;\n\n // Authenticate when apiKey changes\n useEffect(() => {\n // apiKey is undefined → frontend auth still loading, do nothing\n if (apiKey === undefined) {\n setAuthState(\"loading\");\n return;\n }\n\n // apiKey is null → user is not logged in\n if (apiKey === null) {\n setAuthState(\"unauthenticated\");\n setAuthVersion((v) => v + 1);\n return;\n }\n\n // apiKey is a string → send to backend for verification\n setAuthState(\"loading\");\n client\n .setKey(apiKey)\n .then(() => {\n setAuthState(\"authenticated\");\n setAuthVersion((v) => v + 1);\n onReadyRef.current?.(client);\n })\n .catch((err) => {\n setAuthState(\"unauthenticated\");\n setAuthVersion((v) => v + 1);\n onErrorRef.current?.(err);\n });\n }, [apiKey, userId, client]);\n\n useEffect(() => {\n const onErr = (err: Error) => onErrorRef.current?.(err);\n client.on(\"error\", onErr);\n return () => {\n client.off(\"error\", onErr);\n };\n }, [client]);\n\n const contextValue = useMemo<ParcaeContextValue>(\n () => ({ client, authState, authVersion }),\n [client, authState, authVersion],\n );\n\n return (\n <ParcaeContext.Provider value={contextValue}>\n {children}\n </ParcaeContext.Provider>\n );\n};\n\nexport default ParcaeProvider;\n","\"use client\";\n\n/**\n * useQuery — efficient reactive data fetching.\n *\n * - Deduplicates: same query from multiple components = one fetch\n * - Caches: unmount/remount doesn't re-fetch if data is fresh\n * - Realtime: subscribes to server-pushed diffs (add/remove/update)\n * - Auth-aware: waits for auth before firing scoped queries\n * - Efficient: React only re-renders when the items array reference changes\n */\n\nimport { useEffect, useRef, useSyncExternalStore } from \"react\";\nimport { useParcae } from \"./context\";\nimport type { ParcaeClient } from \"../client\";\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\ninterface QueryChain<T> {\n find(): Promise<T[]>;\n __steps?: any[];\n __modelType?: string;\n __modelClass?: any;\n __adapter?: any;\n}\n\ninterface UseQueryOptions {\n /** Wait for auth before firing. Default: true. */\n waitForAuth?: boolean;\n}\n\ninterface UseQueryResult<T> {\n items: T[];\n loading: boolean;\n error: Error | null;\n refetch: () => void;\n}\n\n// ─── External Cache ──────────────────────────────────────────────────────────\n\ninterface CacheEntry {\n items: any[];\n loading: boolean;\n error: Error | null;\n refs: number;\n listeners: Set<() => void>;\n dispose: (() => void) | null;\n gcTimer: ReturnType<typeof setTimeout> | null;\n}\n\nconst cache = new Map<string, CacheEntry>();\nconst GC_DELAY = 60_000;\n\nconst EMPTY: any[] = [];\nconst EMPTY_RESULT: UseQueryResult<any> = {\n items: EMPTY,\n loading: true,\n error: null,\n refetch: () => {},\n};\n\nfunction getOrCreate(key: string): CacheEntry {\n let entry = cache.get(key);\n if (!entry) {\n entry = {\n items: EMPTY,\n loading: true,\n error: null,\n refs: 0,\n listeners: new Set(),\n dispose: null,\n gcTimer: null,\n };\n cache.set(key, entry);\n }\n return entry;\n}\n\nfunction notify(entry: CacheEntry): void {\n for (const fn of entry.listeners) fn();\n}\n\n// ─── Fetch + Subscribe ───────────────────────────────────────────────────────\n\nfunction fetchAndSubscribe(\n key: string,\n entry: CacheEntry,\n chain: QueryChain<any>,\n client: ParcaeClient,\n): void {\n // Fetch\n entry.loading = true;\n entry.error = null;\n notify(entry);\n\n chain\n .find()\n .then((result: any[]) => {\n entry.items = result;\n entry.loading = false;\n notify(entry);\n })\n .catch((err: Error) => {\n entry.error = err;\n entry.loading = false;\n notify(entry);\n });\n\n // Subscribe to realtime diffs\n if (!entry.dispose && chain.__modelType) {\n const event = `query:${key}`;\n\n client.send(\"subscribe:query\", {\n hash: key,\n modelType: chain.__modelType,\n steps: chain.__steps ?? [],\n });\n\n const unsub = client.subscribe(event, (ops: any[]) => {\n if (!ops?.length) return;\n\n const map = new Map(entry.items.map((item: any) => [item.id, item]));\n let changed = false;\n\n for (const op of ops) {\n switch (op.op) {\n case \"add\":\n if (!map.has(op.id) && op.data && chain.__modelClass) {\n map.set(op.id, new chain.__modelClass(chain.__adapter, op.data));\n changed = true;\n }\n break;\n case \"remove\":\n if (map.has(op.id)) {\n map.delete(op.id);\n changed = true;\n }\n break;\n case \"update\": {\n const existing = map.get(op.id);\n if (existing && op.data) {\n for (const [k, v] of Object.entries(op.data)) {\n (existing as any)[k] = v;\n }\n changed = true;\n }\n break;\n }\n }\n }\n\n if (changed) {\n entry.items = [...map.values()];\n notify(entry);\n }\n });\n\n entry.dispose = () => {\n unsub();\n client.send(\"unsubscribe:query\", { hash: key });\n entry.dispose = null;\n };\n }\n}\n\n// ─── useQuery ────────────────────────────────────────────────────────────────\n\nexport function useQuery<T>(\n chain: QueryChain<T> | null | undefined,\n options: UseQueryOptions = {},\n): UseQueryResult<T> {\n const { client, authState, authVersion } = useParcae();\n const waitForAuth = options.waitForAuth ?? true;\n const authReady = !waitForAuth || authState !== \"loading\";\n\n const key =\n chain && authReady\n ? `${chain.__modelType}:${authVersion}:${JSON.stringify(chain.__steps ?? [])}`\n : null;\n\n // Ref to track the current key (for cleanup)\n const keyRef = useRef(key);\n keyRef.current = key;\n\n // ── useSyncExternalStore ──────────────────────────────────────────\n\n const subscribe = (onStoreChange: () => void) => {\n const k = keyRef.current;\n if (!k) return () => {};\n\n const entry = getOrCreate(k);\n entry.refs++;\n entry.listeners.add(onStoreChange);\n\n // Cancel GC\n if (entry.gcTimer) {\n clearTimeout(entry.gcTimer);\n entry.gcTimer = null;\n }\n\n return () => {\n entry.listeners.delete(onStoreChange);\n entry.refs--;\n\n if (entry.refs <= 0) {\n entry.gcTimer = setTimeout(() => {\n entry.dispose?.();\n cache.delete(k);\n }, GC_DELAY);\n }\n };\n };\n\n const getSnapshot = (): any[] => {\n const k = keyRef.current;\n if (!k) return EMPTY;\n return cache.get(k)?.items ?? EMPTY;\n };\n\n const items = useSyncExternalStore(\n subscribe,\n getSnapshot,\n getSnapshot,\n ) as T[];\n\n // ── Trigger fetch when key changes ────────────────────────────────\n\n useEffect(() => {\n if (!key || !chain) return;\n\n const entry = getOrCreate(key);\n\n // Only fetch if this is the first subscriber or items are empty\n if (entry.items === EMPTY || entry.items.length === 0) {\n fetchAndSubscribe(key, entry, chain, client);\n }\n }, [key]); // eslint-disable-line react-hooks/exhaustive-deps\n\n // ── Refetch ───────────────────────────────────────────────────────\n\n const refetch = () => {\n if (!key || !chain) return;\n const entry = getOrCreate(key);\n fetchAndSubscribe(key, entry, chain, client);\n };\n\n // ── Return ────────────────────────────────────────────────────────\n\n if (!key) return EMPTY_RESULT;\n\n const entry = cache.get(key);\n return {\n items,\n loading: entry?.loading ?? true,\n error: entry?.error ?? null,\n refetch,\n };\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport { useParcae } from \"./context\";\n\nexport function useApi() {\n const { client } = useParcae();\n\n return useMemo(\n () => ({\n get: client.get.bind(client),\n post: client.post.bind(client),\n put: client.put.bind(client),\n patch: client.patch.bind(client),\n delete: client.delete.bind(client),\n }),\n [client],\n );\n}\n\n/**\n * useSDK — raw client instance.\n */\nexport function useSDK() {\n return useParcae().client;\n}\n\n/**\n * useConnectionStatus — connection + auth state.\n */\nexport function useConnectionStatus() {\n const { client, authState } = useParcae();\n return {\n isConnected: client.isConnected,\n isLoading: client.isLoading,\n authState,\n };\n}\n\n/**\n * useAuthState — just the auth state.\n */\nexport function useAuthState() {\n return useParcae().authState;\n}\n","\"use client\";\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport { useParcae } from \"./context\";\n\nexport function useSetting<T = string>(\n key: string,\n defaultValue: T,\n): [T, (value: T) => Promise<void>, { isLoading: boolean }] {\n const { client, authState } = useParcae();\n const [value, setValue] = useState<T>(defaultValue);\n const [isLoading, setIsLoading] = useState(true);\n\n // Wait for auth before fetching settings (they're user-scoped)\n useEffect(() => {\n if (authState === \"loading\") return;\n if (authState === \"unauthenticated\") {\n setIsLoading(false);\n return;\n }\n\n let cancelled = false;\n\n client\n .get(`/settings/${encodeURIComponent(key)}`)\n .then((result) => {\n if (!cancelled && result?.value !== undefined) {\n setValue(result.value);\n }\n })\n .catch(() => {})\n .finally(() => {\n if (!cancelled) setIsLoading(false);\n });\n\n return () => {\n cancelled = true;\n };\n }, [key, client, authState]);\n\n const update = useCallback(\n async (newValue: T) => {\n setValue(newValue);\n await client.put(`/settings/${encodeURIComponent(key)}`, {\n value: newValue,\n });\n },\n [key, client],\n );\n\n return [value, update, { isLoading }];\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@parcae/sdk",
3
- "version": "0.2.8",
3
+ "version": "0.3.1",
4
4
  "description": "Parcae SDK — client transport and React hooks for Parcae backends",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/transports/socket.ts","../src/transports/sse.ts","../src/client.ts"],"names":["EventEmitter","body"],"mappings":"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","file":"chunk-XAFYMW5P.js","sourcesContent":["/**\n * SocketTransport — Socket.IO implementation of the Transport interface.\n *\n * Bidirectional, full-duplex. Best for apps that need realtime subscriptions\n * (live query updates, collaborative editing, chat, etc.).\n *\n * Extracted from Dollhouse Studio's Dollhouse.ts (667 lines).\n */\n\nimport SocketIO from \"socket.io-client\";\nimport pako from \"pako\";\nimport { decompress } from \"compress-json\";\nimport { EventEmitter } from \"eventemitter3\";\nimport ShortId from \"short-unique-id\";\nimport type { Transport } from \"@parcae/model\";\n\nconst uid = new ShortId({ length: 10 });\nconst SOCKET_CONNECTIONS = new Map<string, any>();\n\nexport interface SocketTransportConfig {\n url: string;\n key?: string | null | (() => Promise<string | null>);\n version?: string;\n /** Socket.IO path. Default: \"/ws\" */\n path?: string;\n}\n\nexport class SocketTransport extends EventEmitter implements Transport {\n private socket: any = null;\n private pendingHandlers: Array<{\n event: string;\n handler: (...args: any[]) => void;\n }> = [];\n private apiKey: string | null | (() => Promise<string | null>);\n private key: string | null = null;\n private url: string;\n private version: string;\n private socketPath: string;\n private waitForAuth: Promise<void> | null = null;\n private resolveAuth: (() => void) | null = null;\n private inflight = new Map<string, Promise<any>>();\n\n public loading: Promise<void>;\n public isLoading = true;\n public isConnected = false;\n public isConnecting = false;\n public authVersion = 0;\n\n constructor(config: SocketTransportConfig) {\n super();\n this.url = config.url;\n this.apiKey = config.key ?? null;\n this.version = config.version ?? \"v1\";\n this.socketPath = config.path ?? \"/ws\";\n this.loading = this.init(this.apiKey);\n }\n\n // ── Auth ──────────────────────────────────────────────────────────────\n\n async setKey(\n key: string | null | (() => Promise<string | null>),\n ): Promise<void> {\n this.apiKey = key;\n this.isLoading = true;\n this.loading = this.init(key);\n await this.loading;\n }\n\n // ── Init ──────────────────────────────────────────────────────────────\n\n private async init(\n key: string | null | (() => Promise<string | null>),\n ): Promise<void> {\n this.isLoading = true;\n this.isConnecting = true;\n\n try {\n this.key = typeof key === \"function\" ? await key() : key;\n const socketKey = `${this.url}:${this.version}`;\n\n if (!SOCKET_CONNECTIONS.has(socketKey)) {\n SOCKET_CONNECTIONS.set(\n socketKey,\n SocketIO(this.url, {\n path: this.socketPath,\n agent: true,\n transports: [\"websocket\"],\n withCredentials: true,\n query: { key: this.key ?? undefined, compression: true },\n }),\n );\n }\n\n this.socket = SOCKET_CONNECTIONS.get(socketKey);\n\n if (this.key) {\n const prevResolve = this.resolveAuth;\n this.waitForAuth = new Promise<void>((resolve) => {\n this.resolveAuth = resolve;\n this.socket.emit(\"authenticate\", this.key, () => {\n this.waitForAuth = null;\n this.resolveAuth = null;\n this.authVersion++;\n this.emit(\"authenticated\");\n if (prevResolve) prevResolve();\n resolve();\n });\n });\n } else {\n this.waitForAuth = null;\n this.resolveAuth = null;\n }\n\n this.isLoading = false;\n } catch (error) {\n this.isLoading = false;\n this.isConnecting = false;\n this.emit(\"error\", error);\n throw error;\n }\n\n this.setupEvents();\n }\n\n private setupEvents(): void {\n if (!this.socket) return;\n\n for (const { event, handler } of this.pendingHandlers) {\n this.socket.on(event, handler);\n }\n this.pendingHandlers = [];\n\n let hasConnected = this.isConnected;\n this.socket.off(\"connect\");\n this.socket.off(\"disconnect\");\n this.socket.off(\"error\");\n\n this.socket.on(\"connect\", () => {\n const wasDisconnected = !this.isConnected && hasConnected;\n this.isConnected = true;\n this.isConnecting = false;\n hasConnected = true;\n this.emit(wasDisconnected ? \"reconnected\" : \"connected\");\n });\n\n this.socket.on(\"disconnect\", () => {\n this.isConnected = false;\n this.emit(\"disconnected\");\n });\n\n this.socket.on(\"error\", (error: Error) => {\n this.emit(\"error\", error);\n });\n }\n\n // ── Request/Response ──────────────────────────────────────────────────\n\n private async fetch(\n method: string,\n path: string,\n data: any = {},\n ): Promise<any> {\n await this.loading;\n if (this.waitForAuth) await this.waitForAuth;\n if (!this.socket) throw new Error(\"Socket not initialized\");\n\n const upper = method.toUpperCase();\n if (upper === \"GET\") {\n const dedupeKey = `GET:${path}:${this.authVersion}:${JSON.stringify(data)}`;\n const existing = this.inflight.get(dedupeKey);\n if (existing) return existing;\n const req = this._doFetch(method, path, data);\n this.inflight.set(dedupeKey, req);\n req.finally(() => this.inflight.delete(dedupeKey));\n return req;\n }\n\n return this._doFetch(method, path, data);\n }\n\n private async _doFetch(\n method: string,\n path: string,\n data: any = {},\n ): Promise<any> {\n if (!this.isConnected) {\n await new Promise<void>((resolve, reject) => {\n if (this.socket.connected) return resolve();\n const timeout = setTimeout(() => {\n cleanup();\n reject(new Error(\"Connection timeout\"));\n }, 30000);\n const onConnect = () => {\n cleanup();\n resolve();\n };\n const onError = (err: Error) => {\n cleanup();\n reject(new Error(`Connection failed: ${err.message}`));\n };\n const cleanup = () => {\n clearTimeout(timeout);\n this.socket.off(\"connect\", onConnect);\n this.socket.off(\"connect_error\", onError);\n };\n this.socket.once(\"connect\", onConnect);\n this.socket.once(\"connect_error\", onError);\n });\n }\n\n const id = uid.rnd();\n\n return new Promise((resolve, reject) => {\n this.socket.once(id, (msg: any) => {\n try {\n const uncompressed = pako.ungzip(msg, { to: \"string\" });\n const { success, result, message, error } = decompress(\n JSON.parse(uncompressed),\n );\n if (success) resolve(result);\n else\n reject(\n new Error(\n message || error || `Request failed: ${method}:${path}`,\n ),\n );\n } catch (err) {\n reject(err);\n }\n });\n this.socket.emit(\n \"call\",\n id,\n method.toUpperCase(),\n `/${this.version}${path}`,\n data,\n );\n });\n }\n\n async get(path: string, data?: any): Promise<any> {\n return this.fetch(\"get\", path, data);\n }\n async post(path: string, data?: any): Promise<any> {\n return this.fetch(\"post\", path, data);\n }\n async put(path: string, data?: any): Promise<any> {\n return this.fetch(\"put\", path, data);\n }\n async patch(path: string, data?: any): Promise<any> {\n return this.fetch(\"patch\", path, data);\n }\n async delete(path: string, data?: any): Promise<any> {\n return this.fetch(\"delete\", path, data);\n }\n\n // ── Subscriptions ─────────────────────────────────────────────────────\n\n subscribe(event: string, handler: (...args: any[]) => void): () => void {\n if (this.socket) {\n this.socket.on(event, handler);\n } else {\n this.pendingHandlers.push({ event, handler });\n }\n return () => this.unsubscribe(event, handler);\n }\n\n unsubscribe(event: string, handler?: (...args: any[]) => void): void {\n if (this.socket) this.socket.off(event, handler);\n this.pendingHandlers = this.pendingHandlers.filter(\n (h) => !(h.event === event && (!handler || h.handler === handler)),\n );\n }\n\n // ── Control messages ──────────────────────────────────────────────────\n\n async send(event: string, ...args: any[]): Promise<void> {\n if (!this.isConnected && this.socket) {\n await new Promise<void>((resolve) => {\n if (this.socket.connected) return resolve();\n this.socket.once(\"connect\", () => resolve());\n });\n }\n if (this.waitForAuth) await this.waitForAuth;\n if (this.socket) this.socket.emit(event, ...args);\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────\n\n disconnect(): void {\n if (this.socket) {\n this.socket.disconnect();\n SOCKET_CONNECTIONS.delete(`${this.url}:${this.version}`);\n this.socket = null;\n this.isConnected = false;\n }\n }\n\n async reconnect(): Promise<void> {\n this.loading = this.init(this.apiKey);\n await this.loading;\n }\n}\n\nexport default SocketTransport;\n","/**\n * SSETransport — HTTP + Server-Sent Events implementation of the Transport interface.\n *\n * Request/response via standard fetch(). Subscriptions via EventSource.\n * Simpler than Socket.IO — no websocket infra needed. Good for read-heavy\n * apps, serverless backends, or environments where WebSocket isn't available.\n *\n * Trade-offs vs SocketTransport:\n * - Simpler infra (no sticky sessions, works behind any CDN/proxy)\n * - Server → client streaming only (no client → server streaming)\n * - Request/response is standard HTTP (cacheable, observable, debuggable)\n * - No compression (relies on HTTP gzip)\n * - No request deduplication (relies on HTTP/2 multiplexing)\n */\n\nimport { EventEmitter } from \"eventemitter3\";\nimport type { Transport } from \"@parcae/model\";\n\nexport interface SSETransportConfig {\n /** Base URL of the Parcae backend. */\n url: string;\n /** API key or async function returning a key. */\n key?: string | null | (() => Promise<string | null>);\n /** API version prefix. Default: \"v1\" */\n version?: string;\n}\n\nexport class SSETransport extends EventEmitter implements Transport {\n private url: string;\n private version: string;\n private apiKey: string | null | (() => Promise<string | null>);\n private key: string | null = null;\n private eventSources = new Map<string, EventSource>();\n\n public isConnected = true; // HTTP is \"always connected\"\n public isLoading = true;\n public loading: Promise<void>;\n\n constructor(config: SSETransportConfig) {\n super();\n this.url = config.url.replace(/\\/$/, \"\");\n this.version = config.version ?? \"v1\";\n this.apiKey = config.key ?? null;\n this.loading = this.resolveKey();\n }\n\n private async resolveKey(): Promise<void> {\n try {\n this.key =\n typeof this.apiKey === \"function\" ? await this.apiKey() : this.apiKey;\n this.isLoading = false;\n this.emit(\"connected\");\n } catch (err) {\n this.isLoading = false;\n this.emit(\"error\", err);\n }\n }\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = { \"Content-Type\": \"application/json\" };\n if (this.key) h[\"Authorization\"] = `Bearer ${this.key}`;\n return h;\n }\n\n private fullUrl(path: string): string {\n return `${this.url}/${this.version}${path}`;\n }\n\n // ── Request/Response ──────────────────────────────────────────────────\n\n private async request(\n method: string,\n path: string,\n data?: any,\n ): Promise<any> {\n await this.loading;\n\n const isGet = method.toUpperCase() === \"GET\";\n let url = this.fullUrl(path);\n\n if (isGet && data) {\n const params = new URLSearchParams();\n for (const [k, v] of Object.entries(data)) {\n params.set(k, typeof v === \"object\" ? JSON.stringify(v) : String(v));\n }\n url += `?${params.toString()}`;\n }\n\n const res = await fetch(url, {\n method: method.toUpperCase(),\n headers: this.headers(),\n body: isGet ? undefined : JSON.stringify(data),\n });\n\n if (!res.ok) {\n const body = await res.json().catch(() => ({ error: res.statusText }));\n throw new Error(body.error || body.message || `HTTP ${res.status}`);\n }\n\n const body = await res.json();\n if (body.success === false) throw new Error(body.error || \"Request failed\");\n return body.result ?? body;\n }\n\n async get(path: string, data?: any): Promise<any> {\n return this.request(\"GET\", path, data);\n }\n async post(path: string, data?: any): Promise<any> {\n return this.request(\"POST\", path, data);\n }\n async put(path: string, data?: any): Promise<any> {\n return this.request(\"PUT\", path, data);\n }\n async patch(path: string, data?: any): Promise<any> {\n return this.request(\"PATCH\", path, data);\n }\n async delete(path: string, data?: any): Promise<any> {\n return this.request(\"DELETE\", path, data);\n }\n\n // ── Subscriptions (via Server-Sent Events) ────────────────────────────\n\n subscribe(event: string, handler: (...args: any[]) => void): () => void {\n const url = `${this.url}/${this.version}/__events/${encodeURIComponent(event)}`;\n const source = new EventSource(url, { withCredentials: true });\n\n source.onmessage = (e) => {\n try {\n const data = JSON.parse(e.data);\n handler(data);\n } catch {\n handler(e.data);\n }\n };\n\n source.onerror = () => {\n // EventSource auto-reconnects\n };\n\n this.eventSources.set(event, source);\n\n return () => {\n source.close();\n this.eventSources.delete(event);\n };\n }\n\n unsubscribe(event: string): void {\n const source = this.eventSources.get(event);\n if (source) {\n source.close();\n this.eventSources.delete(event);\n }\n }\n\n // ── Control messages ──────────────────────────────────────────────────\n\n async send(event: string, ...args: any[]): Promise<void> {\n await this.request(\"POST\", \"/__control\", { event, args });\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────\n\n disconnect(): void {\n for (const [, source] of this.eventSources) source.close();\n this.eventSources.clear();\n this.isConnected = false;\n this.emit(\"disconnected\");\n }\n\n async reconnect(): Promise<void> {\n this.loading = this.resolveKey();\n await this.loading;\n }\n}\n\nexport default SSETransport;\n","/**\n * @parcae/sdk — createClient()\n *\n * Creates a Parcae client with a pluggable transport layer.\n * Default: Socket.IO (bidirectional, realtime).\n * Alternative: SSE (HTTP + Server-Sent Events, simpler).\n *\n * The transport is abstracted — the client exposes the same API\n * regardless of which transport is used underneath.\n */\n\nimport { Model, FrontendAdapter } from \"@parcae/model\";\nimport type { Transport } from \"@parcae/model\";\nimport { SocketTransport } from \"./transports/socket\";\nimport type { SocketTransportConfig } from \"./transports/socket\";\nimport { SSETransport } from \"./transports/sse\";\nimport type { SSETransportConfig } from \"./transports/sse\";\n\n// ─── Configuration ───────────────────────────────────────────────────────────\n\nexport interface ClientConfig {\n /** URL of the Parcae backend. */\n url: string;\n /** API key — string or async function that returns a key. */\n key?: string | null | (() => Promise<string | null>);\n /** API version prefix. Default: \"v1\" */\n version?: string;\n /**\n * Transport type. Default: \"socket\"\n * - \"socket\": Socket.IO (bidirectional, realtime subscriptions)\n * - \"sse\": HTTP + Server-Sent Events (read-heavy, simpler infra)\n * - Transport instance: provide your own Transport implementation\n */\n transport?: \"socket\" | \"sse\" | Transport;\n}\n\nexport interface ParcaeClient {\n /** The underlying transport instance. */\n transport: Transport;\n /** Shorthand for transport methods. */\n get(path: string, data?: any): Promise<any>;\n post(path: string, data?: any): Promise<any>;\n put(path: string, data?: any): Promise<any>;\n patch(path: string, data?: any): Promise<any>;\n delete(path: string, data?: any): Promise<any>;\n /** Subscribe to a named event. Returns dispose function. */\n subscribe(event: string, handler: (...args: any[]) => void): () => void;\n /** Unsubscribe from a named event. */\n unsubscribe(event: string, handler?: (...args: any[]) => void): void;\n /** Send a control message. */\n send(event: string, ...args: any[]): void;\n /** Connection state. */\n readonly isConnected: boolean;\n readonly isLoading: boolean;\n /** Promise that resolves when the client is ready. */\n loading: Promise<void>;\n /** Update the auth key. */\n setKey(key: string | null | (() => Promise<string | null>)): Promise<void>;\n /** Listen for transport events. */\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler?: (...args: any[]) => void): void;\n /** Disconnect from the server. */\n disconnect(): void;\n /** Reconnect. */\n reconnect(): Promise<void>;\n /** Auth version — incremented on auth changes. Useful for cache invalidation. */\n readonly authVersion: number;\n}\n\n// ─── createClient ────────────────────────────────────────────────────────────\n\nexport function createClient(config: ClientConfig): ParcaeClient {\n const version = config.version ?? \"v1\";\n\n // Create the transport\n let transport: Transport & {\n loading?: Promise<void>;\n isLoading?: boolean;\n isConnected?: boolean;\n authVersion?: number;\n setKey?: (key: any) => Promise<void>;\n on?: (event: string, handler: (...args: any[]) => void) => void;\n off?: (event: string, handler?: (...args: any[]) => void) => void;\n disconnect?: () => void;\n reconnect?: () => Promise<void>;\n };\n\n if (config.transport && typeof config.transport === \"object\") {\n // Custom transport instance\n transport = config.transport as any;\n } else if (config.transport === \"sse\") {\n transport = new SSETransport({\n url: config.url,\n key: config.key,\n version,\n });\n } else {\n // Default: Socket.IO\n transport = new SocketTransport({\n url: config.url,\n key: config.key,\n version,\n });\n }\n\n // Wire up FrontendAdapter so Model.where(), .findById() etc work\n Model.use(new FrontendAdapter(transport));\n\n const client: ParcaeClient = {\n transport,\n\n get: (path, data) => transport.get(path, data),\n post: (path, data) => transport.post(path, data),\n put: (path, data) => transport.put(path, data),\n patch: (path, data) => transport.patch(path, data),\n delete: (path, data) => transport.delete(path, data),\n\n subscribe(event, handler) {\n if (transport.subscribe) return transport.subscribe(event, handler);\n return () => {}; // no-op if transport doesn't support subscriptions\n },\n\n unsubscribe(event, handler) {\n transport.unsubscribe?.(event, handler);\n },\n\n send(event, ...args) {\n (transport as any).send?.(event, ...args);\n },\n\n get isConnected() {\n return transport.isConnected ?? false;\n },\n get isLoading() {\n return transport.isLoading ?? false;\n },\n get loading() {\n return (transport as any).loading ?? Promise.resolve();\n },\n get authVersion() {\n return (transport as any).authVersion ?? 0;\n },\n\n async setKey(key) {\n if ((transport as any).setKey) await (transport as any).setKey(key);\n },\n\n on(event, handler) {\n transport.on?.(event, handler);\n },\n off(event, handler) {\n transport.off?.(event, handler);\n },\n\n disconnect() {\n transport.disconnect?.();\n },\n async reconnect() {\n await transport.reconnect?.();\n },\n };\n\n return client;\n}\n"]}