@parcae/sdk 0.3.2 → 0.3.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/react/index.d.ts +0 -1
- package/dist/react/index.js +45 -64
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
package/dist/react/index.d.ts
CHANGED
package/dist/react/index.js
CHANGED
|
@@ -77,17 +77,10 @@ var ParcaeProvider = ({
|
|
|
77
77
|
var cache = /* @__PURE__ */ new Map();
|
|
78
78
|
var GC_DELAY = 6e4;
|
|
79
79
|
var EMPTY = [];
|
|
80
|
-
var EMPTY_RESULT = {
|
|
81
|
-
items: EMPTY,
|
|
82
|
-
loading: true,
|
|
83
|
-
error: null,
|
|
84
|
-
refetch: () => {
|
|
85
|
-
}
|
|
86
|
-
};
|
|
87
80
|
function getOrCreate(key) {
|
|
88
|
-
let
|
|
89
|
-
if (!
|
|
90
|
-
|
|
81
|
+
let e = cache.get(key);
|
|
82
|
+
if (!e) {
|
|
83
|
+
e = {
|
|
91
84
|
items: EMPTY,
|
|
92
85
|
loading: true,
|
|
93
86
|
error: null,
|
|
@@ -96,14 +89,14 @@ function getOrCreate(key) {
|
|
|
96
89
|
dispose: null,
|
|
97
90
|
gcTimer: null
|
|
98
91
|
};
|
|
99
|
-
cache.set(key,
|
|
92
|
+
cache.set(key, e);
|
|
100
93
|
}
|
|
101
|
-
return
|
|
94
|
+
return e;
|
|
102
95
|
}
|
|
103
|
-
function notify(
|
|
104
|
-
for (const fn of
|
|
96
|
+
function notify(e) {
|
|
97
|
+
for (const fn of e.listeners) fn();
|
|
105
98
|
}
|
|
106
|
-
function
|
|
99
|
+
function doFetch(key, entry, chain, client) {
|
|
107
100
|
entry.loading = true;
|
|
108
101
|
entry.error = null;
|
|
109
102
|
notify(entry);
|
|
@@ -117,40 +110,23 @@ function fetchAndSubscribe(key, entry, chain, client) {
|
|
|
117
110
|
notify(entry);
|
|
118
111
|
});
|
|
119
112
|
if (!entry.dispose && chain.__modelType) {
|
|
120
|
-
const
|
|
121
|
-
client.
|
|
122
|
-
hash: key,
|
|
123
|
-
modelType: chain.__modelType,
|
|
124
|
-
steps: chain.__steps ?? []
|
|
125
|
-
});
|
|
126
|
-
const unsub = client.subscribe(event, (ops) => {
|
|
113
|
+
const diffEvent = `query:diff:${key}`;
|
|
114
|
+
const unsub = client.subscribe(diffEvent, (ops) => {
|
|
127
115
|
if (!ops?.length) return;
|
|
128
|
-
const map = new Map(entry.items.map((
|
|
116
|
+
const map = new Map(entry.items.map((i) => [i.id, i]));
|
|
129
117
|
let changed = false;
|
|
130
118
|
for (const op of ops) {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
}
|
|
119
|
+
if (op.op === "add" && !map.has(op.id) && op.data && chain.__modelClass) {
|
|
120
|
+
map.set(op.id, new chain.__modelClass(chain.__adapter, op.data));
|
|
121
|
+
changed = true;
|
|
122
|
+
} else if (op.op === "remove" && map.has(op.id)) {
|
|
123
|
+
map.delete(op.id);
|
|
124
|
+
changed = true;
|
|
125
|
+
} else if (op.op === "update" && map.has(op.id) && op.data) {
|
|
126
|
+
const existing = map.get(op.id);
|
|
127
|
+
for (const [k, v] of Object.entries(op.data))
|
|
128
|
+
existing[k] = v;
|
|
129
|
+
changed = true;
|
|
154
130
|
}
|
|
155
131
|
}
|
|
156
132
|
if (changed) {
|
|
@@ -160,7 +136,6 @@ function fetchAndSubscribe(key, entry, chain, client) {
|
|
|
160
136
|
});
|
|
161
137
|
entry.dispose = () => {
|
|
162
138
|
unsub();
|
|
163
|
-
client.send("unsubscribe:query", { hash: key });
|
|
164
139
|
entry.dispose = null;
|
|
165
140
|
};
|
|
166
141
|
}
|
|
@@ -172,23 +147,23 @@ function useQuery(chain, options = {}) {
|
|
|
172
147
|
const key = chain && authReady ? `${chain.__modelType}:${authVersion}:${JSON.stringify(chain.__steps ?? [])}` : null;
|
|
173
148
|
const keyRef = useRef(key);
|
|
174
149
|
keyRef.current = key;
|
|
175
|
-
const subscribe = (
|
|
150
|
+
const subscribe = (onChange) => {
|
|
176
151
|
const k = keyRef.current;
|
|
177
152
|
if (!k) return () => {
|
|
178
153
|
};
|
|
179
|
-
const
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (
|
|
183
|
-
clearTimeout(
|
|
184
|
-
|
|
154
|
+
const e = getOrCreate(k);
|
|
155
|
+
e.refs++;
|
|
156
|
+
e.listeners.add(onChange);
|
|
157
|
+
if (e.gcTimer) {
|
|
158
|
+
clearTimeout(e.gcTimer);
|
|
159
|
+
e.gcTimer = null;
|
|
185
160
|
}
|
|
186
161
|
return () => {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (
|
|
190
|
-
|
|
191
|
-
|
|
162
|
+
e.listeners.delete(onChange);
|
|
163
|
+
e.refs--;
|
|
164
|
+
if (e.refs <= 0) {
|
|
165
|
+
e.gcTimer = setTimeout(() => {
|
|
166
|
+
e.dispose?.();
|
|
192
167
|
cache.delete(k);
|
|
193
168
|
}, GC_DELAY);
|
|
194
169
|
}
|
|
@@ -207,16 +182,22 @@ function useQuery(chain, options = {}) {
|
|
|
207
182
|
useEffect(() => {
|
|
208
183
|
if (!key || !chain) return;
|
|
209
184
|
const entry2 = getOrCreate(key);
|
|
210
|
-
if (entry2.items === EMPTY
|
|
211
|
-
|
|
185
|
+
if (entry2.items === EMPTY) {
|
|
186
|
+
doFetch(key, entry2, chain, client);
|
|
212
187
|
}
|
|
213
188
|
}, [key]);
|
|
214
189
|
const refetch = () => {
|
|
215
190
|
if (!key || !chain) return;
|
|
216
|
-
|
|
217
|
-
fetchAndSubscribe(key, entry2, chain, client);
|
|
191
|
+
doFetch(key, getOrCreate(key), chain, client);
|
|
218
192
|
};
|
|
219
|
-
if (!key)
|
|
193
|
+
if (!key)
|
|
194
|
+
return {
|
|
195
|
+
items: EMPTY,
|
|
196
|
+
loading: !authReady,
|
|
197
|
+
error: null,
|
|
198
|
+
refetch: () => {
|
|
199
|
+
}
|
|
200
|
+
};
|
|
220
201
|
const entry = cache.get(key);
|
|
221
202
|
return {
|
|
222
203
|
items,
|
package/dist/react/index.js.map
CHANGED
|
@@ -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":["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"]}
|
|
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","useEffect","entry","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 — calls chain.find() via socket RPC, subscribes to diffs automatically.\n *\n * No separate subscribe:query event. The server auto-subscribes when you\n * query a list endpoint. Diffs arrive on the same query key.\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 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;\nconst EMPTY: any[] = [];\n\nfunction getOrCreate(key: string): CacheEntry {\n let e = cache.get(key);\n if (!e) {\n e = {\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, e);\n }\n return e;\n}\n\nfunction notify(e: CacheEntry): void {\n for (const fn of e.listeners) fn();\n}\n\n// ─── Fetch via chain.find() ──────────────────────────────────────────────────\n\nfunction doFetch(\n key: string,\n entry: CacheEntry,\n chain: QueryChain<any>,\n client: ParcaeClient,\n): void {\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 // Listen for realtime diffs (server auto-subscribes on the call)\n if (!entry.dispose && chain.__modelType) {\n const diffEvent = `query:diff:${key}`;\n\n const unsub = client.subscribe(diffEvent, (ops: any[]) => {\n if (!ops?.length) return;\n\n const map = new Map(entry.items.map((i: any) => [i.id, i]));\n let changed = false;\n\n for (const op of ops) {\n if (\n op.op === \"add\" &&\n !map.has(op.id) &&\n op.data &&\n chain.__modelClass\n ) {\n map.set(op.id, new chain.__modelClass(chain.__adapter, op.data));\n changed = true;\n } else if (op.op === \"remove\" && map.has(op.id)) {\n map.delete(op.id);\n changed = true;\n } else if (op.op === \"update\" && map.has(op.id) && op.data) {\n const existing = map.get(op.id);\n for (const [k, v] of Object.entries(op.data))\n (existing as any)[k] = v;\n changed = true;\n }\n }\n\n if (changed) {\n entry.items = [...map.values()];\n notify(entry);\n }\n });\n\n entry.dispose = () => {\n unsub();\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 const keyRef = useRef(key);\n keyRef.current = key;\n\n const subscribe = (onChange: () => void) => {\n const k = keyRef.current;\n if (!k) return () => {};\n const e = getOrCreate(k);\n e.refs++;\n e.listeners.add(onChange);\n if (e.gcTimer) {\n clearTimeout(e.gcTimer);\n e.gcTimer = null;\n }\n return () => {\n e.listeners.delete(onChange);\n e.refs--;\n if (e.refs <= 0) {\n e.gcTimer = setTimeout(() => {\n e.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 useEffect(() => {\n if (!key || !chain) return;\n const entry = getOrCreate(key);\n if (entry.items === EMPTY) {\n doFetch(key, entry, chain, client);\n }\n }, [key]); // eslint-disable-line react-hooks/exhaustive-deps\n\n const refetch = () => {\n if (!key || !chain) return;\n doFetch(key, getOrCreate(key), chain, client);\n };\n\n if (!key)\n return {\n items: EMPTY as T[],\n loading: !authReady,\n error: null,\n refetch: () => {},\n };\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"]}
|