@parcae/sdk 0.4.0 → 0.4.2

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.
@@ -1,14 +1,66 @@
1
- import { createClient } from '../chunk-KFISHMU4.js';
2
- import { createContext, useContext, useState, useMemo, useRef, useEffect, useSyncExternalStore, useCallback } from 'react';
1
+ import { createClient, log, subscribe, snapshot, isChanged, createProxy, affectedToPathList } from '../chunk-LGUSPLZM.js';
2
+ import { createContext, useContext, useMemo, useRef, useEffect, useSyncExternalStore, useState, useCallback, useLayoutEffect, useDebugValue } from 'react';
3
3
  import { jsx } from 'react/jsx-runtime';
4
4
 
5
+ var useAffectedDebugValue = (state, affected) => {
6
+ const pathList = useRef(void 0);
7
+ useEffect(() => {
8
+ pathList.current = affectedToPathList(state, affected, true);
9
+ });
10
+ useDebugValue(pathList.current);
11
+ };
12
+ var condUseAffectedDebugValue = useAffectedDebugValue;
13
+ var targetCache = /* @__PURE__ */ new WeakMap();
14
+ function useSnapshot(proxyObject, options) {
15
+ const notifyInSync = void 0 ;
16
+ const affected = useMemo(
17
+ () => proxyObject && /* @__PURE__ */ new WeakMap(),
18
+ [proxyObject]
19
+ );
20
+ const lastSnapshot = useRef(void 0);
21
+ let inRender = true;
22
+ const currSnapshot = useSyncExternalStore(
23
+ useCallback(
24
+ (callback) => {
25
+ const unsub = subscribe(proxyObject, callback, notifyInSync);
26
+ callback();
27
+ return unsub;
28
+ },
29
+ [proxyObject, notifyInSync]
30
+ ),
31
+ () => {
32
+ const nextSnapshot = snapshot(proxyObject);
33
+ try {
34
+ if (!inRender && lastSnapshot.current && !isChanged(
35
+ lastSnapshot.current,
36
+ nextSnapshot,
37
+ affected,
38
+ /* @__PURE__ */ new WeakMap()
39
+ )) {
40
+ return lastSnapshot.current;
41
+ }
42
+ } catch (e) {
43
+ }
44
+ return nextSnapshot;
45
+ },
46
+ () => snapshot(proxyObject)
47
+ );
48
+ inRender = false;
49
+ useLayoutEffect(() => {
50
+ lastSnapshot.current = currSnapshot;
51
+ });
52
+ if ((import.meta.env ? import.meta.env.MODE : void 0) !== "production") {
53
+ condUseAffectedDebugValue(currSnapshot, affected);
54
+ }
55
+ const proxyCache = useMemo(() => /* @__PURE__ */ new WeakMap(), []);
56
+ return createProxy(currSnapshot, affected, proxyCache, targetCache);
57
+ }
5
58
  var ParcaeContext = createContext(null);
6
59
  function useParcae() {
7
- const ctx = useContext(ParcaeContext);
8
- if (!ctx) {
60
+ const client = useContext(ParcaeContext);
61
+ if (!client)
9
62
  throw new Error("useParcae must be used within a <ParcaeProvider>");
10
- }
11
- return ctx;
63
+ return client;
12
64
  }
13
65
  var ParcaeProvider = ({
14
66
  client: externalClient,
@@ -21,58 +73,26 @@ var ParcaeProvider = ({
21
73
  onReady,
22
74
  onError
23
75
  }) => {
24
- const [authState, setAuthState] = useState(
25
- apiKey === void 0 ? "loading" : apiKey === null ? "unauthenticated" : "loading"
26
- );
27
- const [authVersion, setAuthVersion] = useState(0);
28
76
  const client = useMemo(() => {
29
77
  if (externalClient) return externalClient;
30
78
  if (!url)
31
79
  throw new Error(
32
- "ParcaeProvider requires either a `client` prop or a `url` prop"
80
+ "ParcaeProvider requires either a `client` or `url` prop"
33
81
  );
34
- return createClient({ url, version, transport });
82
+ return createClient({ url, version, transport, token: apiKey });
35
83
  }, [externalClient, url, version, transport]);
36
- const apiKeyRef = useRef(apiKey);
37
- apiKeyRef.current = apiKey;
38
84
  const onReadyRef = useRef(onReady);
39
85
  onReadyRef.current = onReady;
40
86
  const onErrorRef = useRef(onError);
41
87
  onErrorRef.current = onError;
42
88
  useEffect(() => {
43
- if (apiKey === void 0) {
44
- setAuthState("loading");
45
- return;
46
- }
47
- setAuthState("loading");
48
- client.authenticate(apiKey).then(({ userId: uid }) => {
49
- setAuthState(uid ? "authenticated" : "unauthenticated");
50
- setAuthVersion((v) => v + 1);
89
+ if (apiKey === void 0) return;
90
+ client.authenticate(apiKey).then(() => {
51
91
  onReadyRef.current?.(client);
52
92
  }).catch((err) => {
53
- setAuthState("unauthenticated");
54
- setAuthVersion((v) => v + 1);
55
93
  onErrorRef.current?.(err);
56
94
  });
57
95
  }, [apiKey, userId, client]);
58
- useEffect(() => {
59
- const onReconnect = () => {
60
- const key = apiKeyRef.current;
61
- if (key === void 0) return;
62
- setAuthState("loading");
63
- client.authenticate(key).then(({ userId: uid }) => {
64
- setAuthState(uid ? "authenticated" : "unauthenticated");
65
- setAuthVersion((v) => v + 1);
66
- }).catch(() => {
67
- setAuthState("unauthenticated");
68
- setAuthVersion((v) => v + 1);
69
- });
70
- };
71
- client.on("reconnected", onReconnect);
72
- return () => {
73
- client.off("reconnected", onReconnect);
74
- };
75
- }, [client]);
76
96
  useEffect(() => {
77
97
  const onErr = (err) => onErrorRef.current?.(err);
78
98
  client.on("error", onErr);
@@ -80,11 +100,7 @@ var ParcaeProvider = ({
80
100
  client.off("error", onErr);
81
101
  };
82
102
  }, [client]);
83
- const contextValue = useMemo(
84
- () => ({ client, authState, authVersion }),
85
- [client, authState, authVersion]
86
- );
87
- return /* @__PURE__ */ jsx(ParcaeContext.Provider, { value: contextValue, children });
103
+ return /* @__PURE__ */ jsx(ParcaeContext.Provider, { value: client, children });
88
104
  };
89
105
  var cache = /* @__PURE__ */ new Map();
90
106
  var GC_DELAY = 6e4;
@@ -108,58 +124,40 @@ function getOrCreate(key) {
108
124
  function notify(e) {
109
125
  for (const fn of e.listeners) fn();
110
126
  }
111
- function doFetch(key, entry, chain, client) {
127
+ function doFetch(key, entry, chain) {
128
+ log.info("useQuery: fetching", chain.__modelType, "key:", key.slice(0, 40));
112
129
  entry.loading = true;
113
130
  entry.error = null;
114
131
  notify(entry);
115
132
  chain.find().then((result) => {
133
+ log.info("useQuery: got", result.length, "items for", chain.__modelType);
116
134
  entry.items = result;
117
135
  entry.loading = false;
118
136
  notify(entry);
119
137
  }).catch((err) => {
138
+ log.error("useQuery: error", err.message);
120
139
  entry.error = err;
121
140
  entry.loading = false;
122
141
  notify(entry);
123
142
  });
124
- if (!entry.dispose && chain.__modelType) {
125
- const diffEvent = `query:diff:${key}`;
126
- const unsub = client.subscribe(diffEvent, (ops) => {
127
- if (!ops?.length) return;
128
- const map = new Map(entry.items.map((i) => [i.id, i]));
129
- let changed = false;
130
- for (const op of ops) {
131
- if (op.op === "add" && !map.has(op.id) && op.data && chain.__modelClass) {
132
- map.set(op.id, new chain.__modelClass(chain.__adapter, op.data));
133
- changed = true;
134
- } else if (op.op === "remove" && map.has(op.id)) {
135
- map.delete(op.id);
136
- changed = true;
137
- } else if (op.op === "update" && map.has(op.id) && op.data) {
138
- const existing = map.get(op.id);
139
- for (const [k, v] of Object.entries(op.data))
140
- existing[k] = v;
141
- changed = true;
142
- }
143
- }
144
- if (changed) {
145
- entry.items = [...map.values()];
146
- notify(entry);
147
- }
148
- });
149
- entry.dispose = () => {
150
- unsub();
151
- entry.dispose = null;
152
- };
153
- }
143
+ }
144
+ function getAuthGate(client) {
145
+ const transport = client.transport;
146
+ return transport?.auth?.state ?? null;
154
147
  }
155
148
  function useQuery(chain, options = {}) {
156
- const { client, authState, authVersion } = useParcae();
149
+ const client = useParcae();
157
150
  const waitForAuth = options.waitForAuth ?? true;
158
- const authReady = !waitForAuth || authState !== "loading";
151
+ const authGate = getAuthGate(client);
152
+ const authSnap = authGate ? useSnapshot(authGate) : null;
153
+ const authStatus = authSnap?.status ?? "pending";
154
+ const authVersion = authSnap?.version ?? 0;
155
+ const authReady = !waitForAuth || authStatus !== "pending";
159
156
  const key = chain && authReady ? `${chain.__modelType}:${authVersion}:${JSON.stringify(chain.__steps ?? [])}` : null;
157
+ log.debug("useQuery:", chain?.__modelType, "auth=" + authStatus, "ready=" + authReady, "key=" + (key ? "yes" : "null"));
160
158
  const keyRef = useRef(key);
161
159
  keyRef.current = key;
162
- const subscribe = (onChange) => {
160
+ const subscribe2 = (onChange) => {
163
161
  const k = keyRef.current;
164
162
  if (!k) return () => {
165
163
  };
@@ -187,7 +185,7 @@ function useQuery(chain, options = {}) {
187
185
  return cache.get(k)?.items ?? EMPTY;
188
186
  };
189
187
  const items = useSyncExternalStore(
190
- subscribe,
188
+ subscribe2,
191
189
  getSnapshot,
192
190
  getSnapshot
193
191
  );
@@ -195,12 +193,12 @@ function useQuery(chain, options = {}) {
195
193
  if (!key || !chain) return;
196
194
  const entry2 = getOrCreate(key);
197
195
  if (entry2.items === EMPTY) {
198
- doFetch(key, entry2, chain, client);
196
+ doFetch(key, entry2, chain);
199
197
  }
200
198
  }, [key]);
201
199
  const refetch = () => {
202
200
  if (!key || !chain) return;
203
- doFetch(key, getOrCreate(key), chain, client);
201
+ doFetch(key, getOrCreate(key), chain);
204
202
  };
205
203
  if (!key)
206
204
  return {
@@ -219,7 +217,7 @@ function useQuery(chain, options = {}) {
219
217
  };
220
218
  }
221
219
  function useApi() {
222
- const { client } = useParcae();
220
+ const client = useParcae();
223
221
  return useMemo(
224
222
  () => ({
225
223
  get: client.get.bind(client),
@@ -232,30 +230,46 @@ function useApi() {
232
230
  );
233
231
  }
234
232
  function useSDK() {
235
- return useParcae().client;
233
+ return useParcae();
236
234
  }
237
235
  function useConnectionStatus() {
238
- const { client, authState } = useParcae();
239
- return { isConnected: client.isConnected, authState };
236
+ const client = useParcae();
237
+ const transport = client.transport;
238
+ const authState = transport?.auth?.state;
239
+ const snap = authState ? useSnapshot(authState) : null;
240
+ return {
241
+ isConnected: client.isConnected,
242
+ authStatus: snap?.status ?? "pending"
243
+ };
240
244
  }
241
245
  function useAuthState() {
242
- return useParcae().authState;
246
+ const client = useParcae();
247
+ const transport = client.transport;
248
+ const authState = transport?.auth?.state;
249
+ const snap = authState ? useSnapshot(authState) : null;
250
+ return {
251
+ status: snap?.status ?? "pending",
252
+ userId: snap?.userId ?? null,
253
+ version: snap?.version ?? 0
254
+ };
243
255
  }
244
256
  function useSetting(key, defaultValue) {
245
- const { client, authState } = useParcae();
257
+ const client = useParcae();
258
+ const transport = client.transport;
259
+ const authState = transport?.auth?.state;
260
+ const snap = authState ? useSnapshot(authState) : null;
261
+ const authStatus = snap?.status ?? "pending";
246
262
  const [value, setValue] = useState(defaultValue);
247
263
  const [isLoading, setIsLoading] = useState(true);
248
264
  useEffect(() => {
249
- if (authState === "loading") return;
250
- if (authState === "unauthenticated") {
265
+ if (authStatus === "pending") return;
266
+ if (authStatus === "unauthenticated") {
251
267
  setIsLoading(false);
252
268
  return;
253
269
  }
254
270
  let cancelled = false;
255
271
  client.get(`/settings/${encodeURIComponent(key)}`).then((result) => {
256
- if (!cancelled && result?.value !== void 0) {
257
- setValue(result.value);
258
- }
272
+ if (!cancelled && result?.value !== void 0) setValue(result.value);
259
273
  }).catch(() => {
260
274
  }).finally(() => {
261
275
  if (!cancelled) setIsLoading(false);
@@ -263,7 +277,7 @@ function useSetting(key, defaultValue) {
263
277
  return () => {
264
278
  cancelled = true;
265
279
  };
266
- }, [key, client, authState]);
280
+ }, [key, client, authStatus]);
267
281
  const update = useCallback(
268
282
  async (newValue) => {
269
283
  setValue(newValue);
@@ -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","useEffect","entry","useMemo","useState"],"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, { useEffect, useMemo, useRef, useState } from \"react\";\nimport { createClient } from \"../client\";\nimport type { ParcaeClient, ClientConfig } from \"../client\";\nimport { ParcaeContext } from \"./context\";\nimport type { AuthState } from \"./context\";\n\nexport interface ParcaeProviderProps {\n client?: ParcaeClient;\n url?: string;\n /** undefined = auth loading, null = no session, string = token */\n apiKey?: string | null | undefined;\n userId?: string | null;\n version?: string;\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 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 });\n }, [externalClient, url, version, transport]);\n\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 // Authenticate when apiKey changes\n useEffect(() => {\n if (apiKey === undefined) {\n setAuthState(\"loading\");\n return;\n }\n\n setAuthState(\"loading\");\n client\n .authenticate(apiKey)\n .then(({ userId: uid }) => {\n setAuthState(uid ? \"authenticated\" : \"unauthenticated\");\n setAuthVersion((v) => v + 1);\n onReadyRef.current?.(client);\n })\n .catch((err: Error) => {\n setAuthState(\"unauthenticated\");\n setAuthVersion((v) => v + 1);\n onErrorRef.current?.(err);\n });\n }, [apiKey, userId, client]);\n\n // Re-authenticate on reconnect\n useEffect(() => {\n const onReconnect = () => {\n const key = apiKeyRef.current;\n if (key === undefined) return;\n\n setAuthState(\"loading\");\n client\n .authenticate(key)\n .then(({ userId: uid }) => {\n setAuthState(uid ? \"authenticated\" : \"unauthenticated\");\n setAuthVersion((v) => v + 1);\n })\n .catch(() => {\n setAuthState(\"unauthenticated\");\n setAuthVersion((v) => v + 1);\n });\n };\n\n client.on(\"reconnected\", onReconnect);\n return () => {\n client.off(\"reconnected\", onReconnect);\n };\n }, [client]);\n\n // Forward 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 const contextValue = useMemo(\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 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\nexport function useSDK() {\n return useParcae().client;\n}\n\nexport function useConnectionStatus() {\n const { client, authState } = useParcae();\n return { isConnected: client.isConnected, authState };\n}\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":["../../../../node_modules/.pnpm/valtio@2.3.1_@types+react@19.2.14_react@19.2.4/node_modules/valtio/esm/react.mjs","../../src/react/context.ts","../../src/react/Provider.tsx","../../src/react/useQuery.ts","../../src/react/useApi.ts","../../src/react/useSetting.ts"],"names":["useMemo","useRef","useEffect","subscribe","useSyncExternalStore","entry","useCallback"],"mappings":"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","file":"index.js","sourcesContent":["import { useMemo, useRef, useSyncExternalStore, useCallback, useLayoutEffect, useEffect, useDebugValue } from 'react';\nimport { isChanged, createProxy, affectedToPathList } from 'proxy-compare';\nimport { subscribe, snapshot } from 'valtio/vanilla';\n\nconst useAffectedDebugValue = (state, affected) => {\n const pathList = useRef(void 0);\n useEffect(() => {\n pathList.current = affectedToPathList(state, affected, true);\n });\n useDebugValue(pathList.current);\n};\nconst condUseAffectedDebugValue = useAffectedDebugValue;\nconst targetCache = /* @__PURE__ */ new WeakMap();\nfunction useSnapshot(proxyObject, options) {\n const notifyInSync = options == null ? void 0 : options.sync;\n const affected = useMemo(\n () => proxyObject && /* @__PURE__ */ new WeakMap(),\n [proxyObject]\n );\n const lastSnapshot = useRef(void 0);\n let inRender = true;\n const currSnapshot = useSyncExternalStore(\n useCallback(\n (callback) => {\n const unsub = subscribe(proxyObject, callback, notifyInSync);\n callback();\n return unsub;\n },\n [proxyObject, notifyInSync]\n ),\n () => {\n const nextSnapshot = snapshot(proxyObject);\n try {\n if (!inRender && lastSnapshot.current && !isChanged(\n lastSnapshot.current,\n nextSnapshot,\n affected,\n /* @__PURE__ */ new WeakMap()\n )) {\n return lastSnapshot.current;\n }\n } catch (e) {\n }\n return nextSnapshot;\n },\n () => snapshot(proxyObject)\n );\n inRender = false;\n useLayoutEffect(() => {\n lastSnapshot.current = currSnapshot;\n });\n if ((import.meta.env ? import.meta.env.MODE : void 0) !== \"production\") {\n condUseAffectedDebugValue(currSnapshot, affected);\n }\n const proxyCache = useMemo(() => /* @__PURE__ */ new WeakMap(), []);\n return createProxy(currSnapshot, affected, proxyCache, targetCache);\n}\n\nexport { useSnapshot };\n","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 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 client?: ParcaeClient;\n url?: string;\n /** undefined = auth loading, null = no session, string = token */\n apiKey?: string | null | undefined;\n userId?: string | null;\n version?: string;\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 client = useMemo(() => {\n if (externalClient) return externalClient;\n if (!url)\n throw new Error(\n \"ParcaeProvider requires either a `client` or `url` prop\",\n );\n return createClient({ url, version, transport, token: apiKey });\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 // When apiKey changes, re-authenticate\n useEffect(() => {\n if (apiKey === undefined) return;\n client\n .authenticate(apiKey)\n .then(() => {\n onReadyRef.current?.(client);\n })\n .catch((err: Error) => {\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 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. Auth state from Valtio snapshot.\n */\n\nimport { useEffect, useRef, useSyncExternalStore } from \"react\";\nimport { useSnapshot } from \"valtio\";\nimport { log } from \"../log\";\nimport { useParcae } from \"./context\";\nimport type { ParcaeClient } from \"../client\";\nimport type { AuthState } from \"../auth-gate\";\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\nfunction doFetch(key: string, entry: CacheEntry, chain: QueryChain<any>): void {\n log.info(\"useQuery: fetching\", chain.__modelType, \"key:\", key.slice(0, 40));\n entry.loading = true;\n entry.error = null;\n notify(entry);\n\n chain\n .find()\n .then((result: any[]) => {\n log.info(\"useQuery: got\", result.length, \"items for\", chain.__modelType);\n entry.items = result;\n entry.loading = false;\n notify(entry);\n })\n .catch((err: Error) => {\n log.error(\"useQuery: error\", err.message);\n entry.error = err;\n entry.loading = false;\n notify(entry);\n });\n}\n\n// ── useQuery ─────────────────────────────────────────────────────────────────\n\nfunction getAuthGate(client: ParcaeClient): AuthState | null {\n const transport = client.transport as any;\n return transport?.auth?.state ?? null;\n}\n\nexport function useQuery<T>(\n chain: QueryChain<T> | null | undefined,\n options: UseQueryOptions = {},\n): UseQueryResult<T> {\n const client = useParcae();\n const waitForAuth = options.waitForAuth ?? true;\n\n // Read auth state reactively via Valtio snapshot\n const authGate = getAuthGate(client);\n const authSnap = authGate ? useSnapshot(authGate as any) : null;\n const authStatus = (authSnap as any)?.status ?? \"pending\";\n const authVersion = (authSnap as any)?.version ?? 0;\n const authReady = !waitForAuth || authStatus !== \"pending\";\n\n const key =\n chain && authReady\n ? `${chain.__modelType}:${authVersion}:${JSON.stringify(chain.__steps ?? [])}`\n : null;\n\n log.debug(\"useQuery:\", chain?.__modelType, \"auth=\" + authStatus, \"ready=\" + authReady, \"key=\" + (key ? \"yes\" : \"null\"));\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);\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);\n };\n\n if (!key)\n return {\n items: EMPTY as T[],\n loading: !authReady,\n error: null,\n refetch: () => {},\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 { useSnapshot } from \"valtio\";\nimport { useParcae } from \"./context\";\n\nexport function useApi() {\n const client = useParcae();\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\nexport function useSDK() {\n return useParcae();\n}\n\nexport function useConnectionStatus() {\n const client = useParcae();\n const transport = client.transport as any;\n const authState = transport?.auth?.state;\n const snap = authState ? useSnapshot(authState) : null;\n return {\n isConnected: client.isConnected,\n authStatus: (snap as any)?.status ?? \"pending\",\n };\n}\n\nexport function useAuthState() {\n const client = useParcae();\n const transport = client.transport as any;\n const authState = transport?.auth?.state;\n const snap = authState ? useSnapshot(authState) : null;\n return {\n status: (snap as any)?.status ?? \"pending\",\n userId: (snap as any)?.userId ?? null,\n version: (snap as any)?.version ?? 0,\n };\n}\n","\"use client\";\n\nimport { useState, useEffect, useCallback } from \"react\";\nimport { useSnapshot } from \"valtio\";\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 transport = client.transport as any;\n const authState = transport?.auth?.state;\n const snap = authState ? useSnapshot(authState) : null;\n const authStatus = (snap as any)?.status ?? \"pending\";\n\n const [value, setValue] = useState<T>(defaultValue);\n const [isLoading, setIsLoading] = useState(true);\n\n useEffect(() => {\n if (authStatus === \"pending\") return;\n if (authStatus === \"unauthenticated\") {\n setIsLoading(false);\n return;\n }\n\n let cancelled = false;\n client\n .get(`/settings/${encodeURIComponent(key)}`)\n .then((result: any) => {\n if (!cancelled && result?.value !== undefined) setValue(result.value);\n })\n .catch(() => {})\n .finally(() => {\n if (!cancelled) setIsLoading(false);\n });\n\n return () => {\n cancelled = true;\n };\n }, [key, client, authStatus]);\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.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Parcae SDK — client transport and React hooks for Parcae backends",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",