@sylphx/lens-react 2.3.4 → 2.4.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.
package/dist/index.d.ts CHANGED
@@ -1,13 +1,35 @@
1
1
  import { LensClientConfig, QueryResult, SelectionObject, TypedClientConfig } from "@sylphx/lens-client";
2
2
  import { MutationDef, QueryDef, RouterDef, RouterRoutes } from "@sylphx/lens-core";
3
+ /**
4
+ * Debug callbacks for query hooks.
5
+ * @internal For debugging purposes only - not recommended for production use.
6
+ */
7
+ interface QueryDebugOptions<T> {
8
+ /** Called when data is received */
9
+ onData?: (data: T) => void;
10
+ /** Called when an error occurs */
11
+ onError?: (error: Error) => void;
12
+ /** Called when subscription starts */
13
+ onSubscribe?: () => void;
14
+ /** Called when subscription ends */
15
+ onUnsubscribe?: () => void;
16
+ }
3
17
  /** Query hook options */
4
- interface QueryHookOptions<TInput> {
18
+ interface QueryHookOptions<
19
+ TInput,
20
+ TOutput = unknown
21
+ > {
5
22
  /** Query input parameters */
6
23
  input?: TInput;
7
24
  /** Field selection */
8
25
  select?: SelectionObject;
9
26
  /** Skip query execution */
10
27
  skip?: boolean;
28
+ /**
29
+ * Debug callbacks for development.
30
+ * @internal For debugging purposes only - not recommended for production use.
31
+ */
32
+ debug?: QueryDebugOptions<TOutput>;
11
33
  }
12
34
  /** Query hook result */
13
35
  interface QueryHookResult<T> {
@@ -59,7 +81,7 @@ interface QueryEndpoint<
59
81
  select?: SelectionObject;
60
82
  }): QueryResult<TOutput>;
61
83
  /** React hook for reactive queries */
62
- useQuery: (options?: TInput extends void ? QueryHookOptions<void> | void : QueryHookOptions<TInput>) => QueryHookResult<TOutput>;
84
+ useQuery: (options?: TInput extends void ? QueryHookOptions<void, TOutput> | void : QueryHookOptions<TInput, TOutput>) => QueryHookResult<TOutput>;
63
85
  }
64
86
  /** Mutation endpoint with React hooks */
65
87
  interface MutationEndpoint<
package/dist/index.js CHANGED
@@ -23,6 +23,8 @@ function createUseQueryHook(getEndpoint) {
23
23
  return function useQuery(options) {
24
24
  const inputKey = JSON.stringify(options?.input);
25
25
  const selectKey = JSON.stringify(options?.select);
26
+ const debugRef = useRef(options?.debug);
27
+ debugRef.current = options?.debug;
26
28
  const query = useMemo(() => {
27
29
  if (options?.skip)
28
30
  return null;
@@ -45,32 +47,35 @@ function createUseQueryHook(getEndpoint) {
45
47
  return;
46
48
  }
47
49
  dispatch({ type: "START" });
50
+ debugRef.current?.onSubscribe?.();
48
51
  let hasReceivedData = false;
49
52
  const unsubscribe = query.subscribe((value) => {
50
53
  if (mountedRef.current) {
51
54
  hasReceivedData = true;
52
55
  dispatch({ type: "SUCCESS", data: value });
56
+ debugRef.current?.onData?.(value);
53
57
  }
54
58
  });
55
59
  query.then((value) => {
56
60
  if (mountedRef.current) {
57
61
  if (!hasReceivedData) {
58
62
  dispatch({ type: "SUCCESS", data: value });
63
+ debugRef.current?.onData?.(value);
59
64
  } else {
60
65
  dispatch({ type: "LOADING_DONE" });
61
66
  }
62
67
  }
63
68
  }, (err) => {
64
69
  if (mountedRef.current) {
65
- dispatch({
66
- type: "ERROR",
67
- error: err instanceof Error ? err : new Error(String(err))
68
- });
70
+ const error = err instanceof Error ? err : new Error(String(err));
71
+ dispatch({ type: "ERROR", error });
72
+ debugRef.current?.onError?.(error);
69
73
  }
70
74
  });
71
75
  return () => {
72
76
  mountedRef.current = false;
73
77
  unsubscribe();
78
+ debugRef.current?.onUnsubscribe?.();
74
79
  };
75
80
  }, [query]);
76
81
  const refetch = useCallback(() => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sylphx/lens-react",
3
- "version": "2.3.4",
3
+ "version": "2.4.1",
4
4
  "description": "React bindings for Lens API framework",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -30,8 +30,8 @@
30
30
  "author": "SylphxAI",
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
- "@sylphx/lens-client": "^2.3.1",
34
- "@sylphx/lens-core": "^2.2.0"
33
+ "@sylphx/lens-client": "^2.3.2",
34
+ "@sylphx/lens-core": "^2.3.0"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "react": ">=18.0.0"
package/src/create.tsx CHANGED
@@ -39,14 +39,34 @@ import { useCallback, useEffect, useMemo, useReducer, useRef, useState } from "r
39
39
  // Types
40
40
  // =============================================================================
41
41
 
42
+ /**
43
+ * Debug callbacks for query hooks.
44
+ * @internal For debugging purposes only - not recommended for production use.
45
+ */
46
+ export interface QueryDebugOptions<T> {
47
+ /** Called when data is received */
48
+ onData?: (data: T) => void;
49
+ /** Called when an error occurs */
50
+ onError?: (error: Error) => void;
51
+ /** Called when subscription starts */
52
+ onSubscribe?: () => void;
53
+ /** Called when subscription ends */
54
+ onUnsubscribe?: () => void;
55
+ }
56
+
42
57
  /** Query hook options */
43
- export interface QueryHookOptions<TInput> {
58
+ export interface QueryHookOptions<TInput, TOutput = unknown> {
44
59
  /** Query input parameters */
45
60
  input?: TInput;
46
61
  /** Field selection */
47
62
  select?: SelectionObject;
48
63
  /** Skip query execution */
49
64
  skip?: boolean;
65
+ /**
66
+ * Debug callbacks for development.
67
+ * @internal For debugging purposes only - not recommended for production use.
68
+ */
69
+ debug?: QueryDebugOptions<TOutput>;
50
70
  }
51
71
 
52
72
  /** Query hook result */
@@ -92,7 +112,9 @@ export interface QueryEndpoint<TInput, TOutput> {
92
112
 
93
113
  /** React hook for reactive queries */
94
114
  useQuery: (
95
- options?: TInput extends void ? QueryHookOptions<void> | void : QueryHookOptions<TInput>,
115
+ options?: TInput extends void
116
+ ? QueryHookOptions<void, TOutput> | void
117
+ : QueryHookOptions<TInput, TOutput>,
96
118
  ) => QueryHookResult<TOutput>;
97
119
  }
98
120
 
@@ -164,12 +186,16 @@ function queryReducer<T>(state: QueryState<T>, action: QueryAction<T>): QuerySta
164
186
  function createUseQueryHook<TInput, TOutput>(
165
187
  getEndpoint: () => (options: unknown) => QueryResult<TOutput>,
166
188
  ) {
167
- return function useQuery(options?: QueryHookOptions<TInput>): QueryHookResult<TOutput> {
189
+ return function useQuery(options?: QueryHookOptions<TInput, TOutput>): QueryHookResult<TOutput> {
168
190
  // Use JSON.stringify for stable dependency comparison
169
191
  // This prevents re-fetching when input object reference changes but content is the same
170
192
  const inputKey = JSON.stringify(options?.input);
171
193
  const selectKey = JSON.stringify(options?.select);
172
194
 
195
+ // Store debug callbacks in ref to avoid dependency issues
196
+ const debugRef = useRef(options?.debug);
197
+ debugRef.current = options?.debug;
198
+
173
199
  // Get query result from base client
174
200
  // biome-ignore lint/correctness/useExhaustiveDependencies: Using JSON.stringify keys (inputKey, selectKey) for stable comparison instead of object references
175
201
  const query = useMemo(() => {
@@ -201,6 +227,7 @@ function createUseQueryHook<TInput, TOutput>(
201
227
  }
202
228
 
203
229
  dispatch({ type: "START" });
230
+ debugRef.current?.onSubscribe?.();
204
231
 
205
232
  let hasReceivedData = false;
206
233
 
@@ -208,6 +235,7 @@ function createUseQueryHook<TInput, TOutput>(
208
235
  if (mountedRef.current) {
209
236
  hasReceivedData = true;
210
237
  dispatch({ type: "SUCCESS", data: value });
238
+ debugRef.current?.onData?.(value);
211
239
  }
212
240
  });
213
241
 
@@ -216,6 +244,7 @@ function createUseQueryHook<TInput, TOutput>(
216
244
  if (mountedRef.current) {
217
245
  if (!hasReceivedData) {
218
246
  dispatch({ type: "SUCCESS", data: value });
247
+ debugRef.current?.onData?.(value);
219
248
  } else {
220
249
  dispatch({ type: "LOADING_DONE" });
221
250
  }
@@ -223,10 +252,9 @@ function createUseQueryHook<TInput, TOutput>(
223
252
  },
224
253
  (err) => {
225
254
  if (mountedRef.current) {
226
- dispatch({
227
- type: "ERROR",
228
- error: err instanceof Error ? err : new Error(String(err)),
229
- });
255
+ const error = err instanceof Error ? err : new Error(String(err));
256
+ dispatch({ type: "ERROR", error });
257
+ debugRef.current?.onError?.(error);
230
258
  }
231
259
  },
232
260
  );
@@ -234,6 +262,7 @@ function createUseQueryHook<TInput, TOutput>(
234
262
  return () => {
235
263
  mountedRef.current = false;
236
264
  unsubscribe();
265
+ debugRef.current?.onUnsubscribe?.();
237
266
  };
238
267
  }, [query]);
239
268