@usels/integrations 0.0.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.mjs ADDED
@@ -0,0 +1,397 @@
1
+ // src/tanstack-query/QueryClientProvider.tsx
2
+ import { createContext } from "react";
3
+ import { QueryClient } from "@tanstack/query-core";
4
+ import { jsx } from "react/jsx-runtime";
5
+ var QueryClientContext = createContext(
6
+ void 0
7
+ );
8
+ function QueryClientProvider({
9
+ client,
10
+ children
11
+ }) {
12
+ return /* @__PURE__ */ jsx(QueryClientContext.Provider, { value: client, children });
13
+ }
14
+
15
+ // src/tanstack-query/useQueryClient.ts
16
+ import { useContext } from "react";
17
+ function useQueryClient() {
18
+ const client = useContext(QueryClientContext);
19
+ if (!client) {
20
+ throw new Error(
21
+ "useQueryClient must be used within a QueryClientProvider. Make sure your component tree is wrapped with <QueryClientProvider client={queryClient}>."
22
+ );
23
+ }
24
+ return client;
25
+ }
26
+
27
+ // src/tanstack-query/useQuery.ts
28
+ import { useMount, useObservable, useObserve } from "@legendapp/state/react";
29
+ import { isObservable } from "@legendapp/state";
30
+ import { QueryObserver } from "@tanstack/query-core";
31
+ import { useRef } from "react";
32
+ import { get } from "@usels/core";
33
+ function serializeQueryKey(queryKey) {
34
+ return JSON.stringify(queryKey, (_key, value) => {
35
+ if (isObservable(value)) {
36
+ return value.get();
37
+ }
38
+ return value;
39
+ });
40
+ }
41
+ function useQuery(options) {
42
+ const queryClient = useQueryClient();
43
+ const observerRef = useRef(null);
44
+ const previousQueryKeyRef = useRef(null);
45
+ const initialOptions = get(options);
46
+ const state$ = useObservable({
47
+ data: void 0,
48
+ error: null,
49
+ status: "pending",
50
+ fetchStatus: "idle",
51
+ isPending: true,
52
+ isSuccess: false,
53
+ isError: false,
54
+ isLoadingError: false,
55
+ isRefetchError: false,
56
+ isFetching: false,
57
+ isPaused: false,
58
+ isRefetching: false,
59
+ isLoading: true,
60
+ isInitialLoading: true,
61
+ isStale: true,
62
+ isPlaceholderData: false,
63
+ isFetched: false,
64
+ isFetchedAfterMount: false,
65
+ isEnabled: get(initialOptions.enabled) ?? true,
66
+ dataUpdatedAt: 0,
67
+ errorUpdatedAt: 0,
68
+ failureCount: 0,
69
+ failureReason: null,
70
+ errorUpdateCount: 0,
71
+ refetch() {
72
+ observerRef.current?.refetch();
73
+ }
74
+ });
75
+ if (!observerRef.current) {
76
+ const initialQueryKeyString = serializeQueryKey(initialOptions.queryKey);
77
+ previousQueryKeyRef.current = initialQueryKeyString;
78
+ observerRef.current = new QueryObserver(queryClient, {
79
+ queryKey: [initialQueryKeyString],
80
+ queryFn: initialOptions.queryFn,
81
+ enabled: get(initialOptions.enabled) ?? true,
82
+ staleTime: get(initialOptions.staleTime),
83
+ gcTime: get(initialOptions.gcTime),
84
+ retry: get(initialOptions.retry),
85
+ refetchOnWindowFocus: get(initialOptions.refetchOnWindowFocus),
86
+ refetchOnMount: get(initialOptions.refetchOnMount),
87
+ refetchOnReconnect: get(initialOptions.refetchOnReconnect),
88
+ throwOnError: initialOptions.throwOnError
89
+ });
90
+ }
91
+ useObserve(() => {
92
+ const resolved = get(options);
93
+ const queryKeyString = serializeQueryKey(resolved.queryKey);
94
+ const hasQueryKeyChanged = previousQueryKeyRef.current !== queryKeyString;
95
+ observerRef.current?.setOptions({
96
+ queryKey: [queryKeyString],
97
+ queryFn: resolved.queryFn,
98
+ enabled: get(resolved.enabled) ?? true,
99
+ staleTime: get(resolved.staleTime),
100
+ gcTime: get(resolved.gcTime),
101
+ retry: get(resolved.retry),
102
+ refetchOnWindowFocus: get(resolved.refetchOnWindowFocus),
103
+ refetchOnMount: get(resolved.refetchOnMount),
104
+ refetchOnReconnect: get(resolved.refetchOnReconnect),
105
+ throwOnError: resolved.throwOnError
106
+ });
107
+ if (hasQueryKeyChanged && previousQueryKeyRef.current !== null) {
108
+ observerRef.current?.refetch();
109
+ }
110
+ previousQueryKeyRef.current = queryKeyString;
111
+ });
112
+ useMount(() => {
113
+ const observer = observerRef.current;
114
+ if (!observer) return;
115
+ const unsubscribe = observer.subscribe((result) => {
116
+ state$.assign({
117
+ data: result.data,
118
+ error: result.error ?? null,
119
+ status: result.status,
120
+ fetchStatus: result.fetchStatus,
121
+ isPending: result.isPending,
122
+ isSuccess: result.isSuccess,
123
+ isError: result.isError,
124
+ isLoadingError: result.isLoadingError,
125
+ isRefetchError: result.isRefetchError,
126
+ isFetching: result.isFetching,
127
+ isPaused: result.isPaused,
128
+ isRefetching: result.isRefetching,
129
+ isLoading: result.isLoading,
130
+ isInitialLoading: result.isLoading,
131
+ isStale: result.isStale,
132
+ isPlaceholderData: result.isPlaceholderData,
133
+ isFetched: result.isFetched,
134
+ isFetchedAfterMount: result.isFetchedAfterMount,
135
+ isEnabled: result.isEnabled ?? true,
136
+ dataUpdatedAt: result.dataUpdatedAt,
137
+ errorUpdatedAt: result.errorUpdatedAt,
138
+ failureCount: result.failureCount,
139
+ failureReason: result.failureReason ?? null,
140
+ errorUpdateCount: result.errorUpdateCount
141
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
142
+ });
143
+ });
144
+ return () => {
145
+ unsubscribe();
146
+ };
147
+ });
148
+ return state$;
149
+ }
150
+
151
+ // src/tanstack-query/useMutation.ts
152
+ import { useMount as useMount2, useObservable as useObservable2, useObserve as useObserve2 } from "@legendapp/state/react";
153
+ import { MutationObserver } from "@tanstack/query-core";
154
+ import { useRef as useRef2 } from "react";
155
+ function useMutation(options) {
156
+ const queryClient = useQueryClient();
157
+ const observerRef = useRef2(null);
158
+ const state$ = useObservable2({
159
+ data: void 0,
160
+ error: null,
161
+ status: "idle",
162
+ isIdle: true,
163
+ isPending: false,
164
+ isPaused: false,
165
+ isSuccess: false,
166
+ isError: false,
167
+ failureCount: 0,
168
+ failureReason: null,
169
+ submittedAt: 0,
170
+ variables: void 0,
171
+ context: void 0,
172
+ mutate(variables) {
173
+ observerRef.current?.mutate(variables)?.catch?.(() => {
174
+ });
175
+ },
176
+ mutateAsync(variables) {
177
+ if (observerRef.current) {
178
+ return new Promise((resolve, reject) => {
179
+ observerRef.current.mutate(variables, {
180
+ onSuccess: (data) => resolve(data),
181
+ onError: (error) => reject(error)
182
+ })?.catch?.(() => {
183
+ });
184
+ });
185
+ }
186
+ throw new Error("Mutation not initialized");
187
+ },
188
+ reset() {
189
+ observerRef.current?.reset();
190
+ }
191
+ });
192
+ if (!observerRef.current) {
193
+ observerRef.current = new MutationObserver(queryClient, {
194
+ mutationKey: options.mutationKey,
195
+ mutationFn: options.mutationFn,
196
+ onMutate: options.onMutate,
197
+ onSuccess: options.onSuccess,
198
+ onError: options.onError,
199
+ onSettled: options.onSettled
200
+ });
201
+ }
202
+ useObserve2(() => {
203
+ observerRef.current?.setOptions({
204
+ mutationKey: options.mutationKey,
205
+ mutationFn: options.mutationFn,
206
+ onMutate: options.onMutate,
207
+ onSuccess: options.onSuccess,
208
+ onError: options.onError,
209
+ onSettled: options.onSettled
210
+ });
211
+ });
212
+ useMount2(() => {
213
+ const observer = observerRef.current;
214
+ if (!observer) return;
215
+ const unsubscribe = observer.subscribe((result) => {
216
+ state$.assign({
217
+ data: result.data,
218
+ error: result.error ?? null,
219
+ status: result.status,
220
+ isIdle: result.isIdle,
221
+ isPending: result.isPending,
222
+ isPaused: result.isPaused,
223
+ isSuccess: result.isSuccess,
224
+ isError: result.isError,
225
+ failureCount: result.failureCount,
226
+ failureReason: result.failureReason ?? null,
227
+ submittedAt: result.submittedAt,
228
+ variables: result.variables,
229
+ context: result.context
230
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
231
+ });
232
+ });
233
+ return () => {
234
+ unsubscribe();
235
+ };
236
+ });
237
+ return state$;
238
+ }
239
+
240
+ // src/tanstack-query/useInfiniteQuery.ts
241
+ import { useMount as useMount3, useObservable as useObservable3, useObserve as useObserve3 } from "@legendapp/state/react";
242
+ import { isObservable as isObservable2 } from "@legendapp/state";
243
+ import {
244
+ InfiniteQueryObserver
245
+ } from "@tanstack/query-core";
246
+ import { useRef as useRef3 } from "react";
247
+ import { get as get2 } from "@usels/core";
248
+ function serializeQueryKey2(queryKey) {
249
+ return JSON.stringify(queryKey, (_key, value) => {
250
+ if (isObservable2(value)) {
251
+ return value.get();
252
+ }
253
+ return value;
254
+ });
255
+ }
256
+ function useInfiniteQuery(options) {
257
+ const queryClient = useQueryClient();
258
+ const observerRef = useRef3(null);
259
+ const previousQueryKeyRef = useRef3(null);
260
+ const initialOptions = get2(options);
261
+ const state$ = useObservable3({
262
+ data: void 0,
263
+ error: null,
264
+ status: "pending",
265
+ fetchStatus: "idle",
266
+ isPending: true,
267
+ isSuccess: false,
268
+ isError: false,
269
+ isLoadingError: false,
270
+ isRefetchError: false,
271
+ isFetching: false,
272
+ isPaused: false,
273
+ isRefetching: false,
274
+ isLoading: true,
275
+ isStale: true,
276
+ isPlaceholderData: false,
277
+ isFetched: false,
278
+ isFetchedAfterMount: false,
279
+ dataUpdatedAt: 0,
280
+ errorUpdatedAt: 0,
281
+ failureCount: 0,
282
+ failureReason: null,
283
+ errorUpdateCount: 0,
284
+ isEnabled: get2(initialOptions.enabled) ?? true,
285
+ isInitialLoading: true,
286
+ hasNextPage: false,
287
+ hasPreviousPage: false,
288
+ isFetchingNextPage: false,
289
+ isFetchingPreviousPage: false,
290
+ isFetchNextPageError: false,
291
+ isFetchPreviousPageError: false,
292
+ refetch() {
293
+ observerRef.current?.refetch();
294
+ },
295
+ fetchNextPage() {
296
+ observerRef.current?.fetchNextPage();
297
+ },
298
+ fetchPreviousPage() {
299
+ observerRef.current?.fetchPreviousPage();
300
+ }
301
+ });
302
+ if (!observerRef.current) {
303
+ const initialQueryKeyString = serializeQueryKey2(initialOptions.queryKey);
304
+ previousQueryKeyRef.current = initialQueryKeyString;
305
+ observerRef.current = new InfiniteQueryObserver(queryClient, {
306
+ queryKey: [initialQueryKeyString],
307
+ queryFn: initialOptions.queryFn,
308
+ enabled: get2(initialOptions.enabled) ?? true,
309
+ staleTime: get2(initialOptions.staleTime),
310
+ gcTime: get2(initialOptions.gcTime),
311
+ retry: get2(initialOptions.retry),
312
+ refetchOnWindowFocus: get2(initialOptions.refetchOnWindowFocus),
313
+ refetchOnMount: get2(initialOptions.refetchOnMount),
314
+ refetchOnReconnect: get2(initialOptions.refetchOnReconnect),
315
+ initialPageParam: initialOptions.initialPageParam,
316
+ getNextPageParam: initialOptions.getNextPageParam,
317
+ getPreviousPageParam: initialOptions.getPreviousPageParam,
318
+ maxPages: initialOptions.maxPages
319
+ });
320
+ }
321
+ useObserve3(() => {
322
+ const resolved = get2(options);
323
+ const queryKeyString = serializeQueryKey2(resolved.queryKey);
324
+ const hasQueryKeyChanged = previousQueryKeyRef.current !== queryKeyString;
325
+ observerRef.current?.setOptions({
326
+ queryKey: [queryKeyString],
327
+ queryFn: resolved.queryFn,
328
+ enabled: get2(resolved.enabled) ?? true,
329
+ staleTime: get2(resolved.staleTime),
330
+ gcTime: get2(resolved.gcTime),
331
+ retry: get2(resolved.retry),
332
+ refetchOnWindowFocus: get2(resolved.refetchOnWindowFocus),
333
+ refetchOnMount: get2(resolved.refetchOnMount),
334
+ refetchOnReconnect: get2(resolved.refetchOnReconnect),
335
+ initialPageParam: resolved.initialPageParam,
336
+ getNextPageParam: resolved.getNextPageParam,
337
+ getPreviousPageParam: resolved.getPreviousPageParam,
338
+ maxPages: resolved.maxPages
339
+ });
340
+ if (hasQueryKeyChanged && previousQueryKeyRef.current !== null) {
341
+ observerRef.current?.refetch();
342
+ }
343
+ previousQueryKeyRef.current = queryKeyString;
344
+ });
345
+ useMount3(() => {
346
+ const observer = observerRef.current;
347
+ if (!observer) return;
348
+ const unsubscribe = observer.subscribe((result) => {
349
+ state$.assign({
350
+ data: result.data,
351
+ error: result.error ?? null,
352
+ status: result.status,
353
+ fetchStatus: result.fetchStatus,
354
+ isPending: result.isPending,
355
+ isSuccess: result.isSuccess,
356
+ isError: result.isError,
357
+ isLoadingError: result.isLoadingError,
358
+ isRefetchError: result.isRefetchError,
359
+ isFetching: result.isFetching,
360
+ isPaused: result.isPaused,
361
+ isRefetching: result.isRefetching,
362
+ isLoading: result.isLoading,
363
+ isInitialLoading: result.isLoading,
364
+ isStale: result.isStale,
365
+ isPlaceholderData: result.isPlaceholderData,
366
+ isFetched: result.isFetched,
367
+ isFetchedAfterMount: result.isFetchedAfterMount,
368
+ isEnabled: result.isEnabled ?? true,
369
+ dataUpdatedAt: result.dataUpdatedAt,
370
+ errorUpdatedAt: result.errorUpdatedAt,
371
+ failureCount: result.failureCount,
372
+ failureReason: result.failureReason ?? null,
373
+ errorUpdateCount: result.errorUpdateCount,
374
+ hasNextPage: result.hasNextPage ?? false,
375
+ hasPreviousPage: result.hasPreviousPage ?? false,
376
+ isFetchingNextPage: result.isFetchingNextPage ?? false,
377
+ isFetchingPreviousPage: result.isFetchingPreviousPage ?? false,
378
+ isFetchNextPageError: result.isFetchNextPageError ?? false,
379
+ isFetchPreviousPageError: result.isFetchPreviousPageError ?? false
380
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
381
+ });
382
+ });
383
+ return () => {
384
+ unsubscribe();
385
+ };
386
+ });
387
+ return state$;
388
+ }
389
+ export {
390
+ QueryClient,
391
+ QueryClientProvider,
392
+ useInfiniteQuery,
393
+ useMutation,
394
+ useQuery,
395
+ useQueryClient
396
+ };
397
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/tanstack-query/QueryClientProvider.tsx","../src/tanstack-query/useQueryClient.ts","../src/tanstack-query/useQuery.ts","../src/tanstack-query/useMutation.ts","../src/tanstack-query/useInfiniteQuery.ts"],"sourcesContent":["\"use client\";\nimport { createContext, ReactNode } from \"react\";\nimport { QueryClient } from \"@tanstack/query-core\";\n\n/**\n * React Context for QueryClient\n */\nexport const QueryClientContext = createContext<QueryClient | undefined>(\n undefined,\n);\n\nexport interface QueryClientProviderProps {\n client: QueryClient;\n children: ReactNode;\n}\n\n/**\n * Provider component that makes QueryClient available to hooks\n *\n * @example\n * ```tsx\n * import { QueryClient } from '@tanstack/react-query'\n * import { QueryClientProvider } from '@usels/integrations'\n *\n * const queryClient = new QueryClient()\n *\n * function App() {\n * return (\n * <QueryClientProvider client={queryClient}>\n * <YourApp />\n * </QueryClientProvider>\n * )\n * }\n * ```\n */\nexport function QueryClientProvider({\n client,\n children,\n}: QueryClientProviderProps) {\n return (\n <QueryClientContext.Provider value={client}>\n {children}\n </QueryClientContext.Provider>\n );\n}\n\nexport { QueryClient };\n","\"use client\"\nimport { useContext } from 'react'\nimport { QueryClient } from '@tanstack/react-query'\nimport { QueryClientContext } from './QueryClientProvider'\n\n/**\n * Hook to retrieve the QueryClient from context\n *\n * @throws Error if used outside of QueryClientProvider\n *\n * @example\n * ```tsx\n * import { useQueryClient } from '@usels/integrations'\n *\n * function MyComponent() {\n * const queryClient = useQueryClient()\n * // Use queryClient...\n * }\n * ```\n */\nexport function useQueryClient(): QueryClient {\n const client = useContext(QueryClientContext)\n\n if (!client) {\n throw new Error(\n 'useQueryClient must be used within a QueryClientProvider. ' +\n 'Make sure your component tree is wrapped with <QueryClientProvider client={queryClient}>.'\n )\n }\n\n return client\n}\n","\"use client\";\nimport { useMount, useObservable, useObserve } from \"@legendapp/state/react\";\nimport { isObservable } from \"@legendapp/state\";\n// import { QueryKey, QueryObserver } from \"@tanstack/react-query\";\nimport { QueryKey, QueryObserver } from \"@tanstack/query-core\";\nimport { useRef } from \"react\";\nimport type { Observable } from \"@legendapp/state\";\nimport { get, type MaybeObservable } from \"@usels/core\";\nimport { useQueryClient } from \"./useQueryClient\";\n\n/**\n * QueryKey를 직렬화하면서 Observable 값을 추출합니다.\n * JSON.stringify는 Observable을 자동으로 .get()하지 않으므로\n * 커스텀 replacer를 사용하여 Observable 값을 추출합니다.\n */\nfunction serializeQueryKey(queryKey: QueryKey): string {\n return JSON.stringify(queryKey, (_key, value) => {\n // isObservable을 사용하여 안전하게 Observable을 감지하고 값을 추출\n if (isObservable(value)) {\n return value.get();\n }\n return value;\n });\n}\n\nexport interface UseQueryOptions<TData = unknown> {\n queryKey: QueryKey;\n queryFn: () => Promise<TData>;\n enabled?: MaybeObservable<boolean>;\n staleTime?: MaybeObservable<number>;\n gcTime?: MaybeObservable<number>;\n retry?: MaybeObservable<number | boolean>;\n refetchOnWindowFocus?: MaybeObservable<boolean>;\n refetchOnMount?: MaybeObservable<boolean>;\n refetchOnReconnect?: MaybeObservable<boolean>;\n /**\n * Set this to `true` to throw errors to the nearest error boundary.\n * Set to a function to control which errors should be thrown.\n */\n throwOnError?: boolean | ((error: Error) => boolean);\n /**\n * Set this to `true` to enable React Suspense mode.\n * The hook will throw a promise while fetching, suspending the component.\n *\n * Note: Requires a React Suspense boundary in the component tree.\n * The query state is still available as an observable when not suspended.\n */\n suspense?: boolean;\n}\n\nexport interface QueryState<TData = unknown> {\n data: TData | undefined;\n error: Error | null;\n status: \"pending\" | \"error\" | \"success\";\n fetchStatus: \"fetching\" | \"paused\" | \"idle\";\n isPending: boolean;\n isSuccess: boolean;\n isError: boolean;\n isLoadingError: boolean;\n isRefetchError: boolean;\n isFetching: boolean;\n isPaused: boolean;\n isRefetching: boolean;\n isLoading: boolean;\n /**\n * @deprecated Use `isLoading` instead. Will be removed in TanStack Query v6.\n */\n isInitialLoading: boolean;\n isStale: boolean;\n isPlaceholderData: boolean;\n isFetched: boolean;\n isFetchedAfterMount: boolean;\n isEnabled: boolean;\n dataUpdatedAt: number;\n errorUpdatedAt: number;\n failureCount: number;\n failureReason: Error | null;\n errorUpdateCount: number;\n\n refetch: () => void;\n}\n\n/**\n * TanStack Query와 Legend-App-State를 연결하는 커스텀 훅\n * QueryObserver를 사용하여 쿼리 상태를 observable로 관리합니다.\n *\n * Observable 값을 파라미터로 받을 수 있으며, 변경 시 자동으로 refetch됩니다.\n *\n * @example\n * ```tsx\n * import { QueryClient } from '@tanstack/react-query'\n * import { QueryClientProvider, useQuery } from '@usels/integrations'\n *\n * // QueryClient를 생성하고 Provider로 제공\n * const queryClient = new QueryClient()\n *\n * function App() {\n * return (\n * <QueryClientProvider client={queryClient}>\n * <YourApp />\n * </QueryClientProvider>\n * )\n * }\n *\n * // 컴포넌트에서 사용\n * function YourComponent() {\n * // 일반 값\n * const products$ = useQuery({\n * queryKey: ['products'],\n * queryFn: () => fetch('/api/products').then(r => r.json())\n * })\n *\n * // Observable 값 (자동 반응)\n * const filter$ = useObservable({ category: 'electronics' })\n * const filteredProducts$ = useQuery({\n * queryKey: ['products', filter$],\n * queryFn: () => fetch(`/api/products?category=${filter$.category.get()}`).then(r => r.json())\n * })\n * // filter$가 변경되면 자동으로 refetch!\n *\n *\n * // 렌더링\n * return (\n * <Show if={() => products$.isSuccess.get()}>\n * {() => (\n * <For each={() => products$.data.get()}>\n * {(product$) => <ProductCard $product={product$} />}\n * </For>\n * )}\n * </Show>\n * )\n * }\n * ```\n */\nexport function useQuery<TData = unknown>(\n options: MaybeObservable<UseQueryOptions<TData>>,\n): Observable<QueryState<TData>> {\n const queryClient = useQueryClient();\n // Observer는 한 번만 생성\n const observerRef = useRef<QueryObserver<TData, Error> | null>(null);\n const previousQueryKeyRef = useRef<string | null>(null);\n\n // options 자체가 Observable인 경우 초기 스냅샷 추출 (최초 1회용)\n const initialOptions = get(options);\n\n // Observable 상태 초기화 (refetch는 별도 함수로 분리 - observable 안에 넣으면 Observable<Function>이 됨)\n const state$ = useObservable({\n data: undefined as TData | undefined,\n error: null as Error | null,\n status: \"pending\" as \"pending\" | \"error\" | \"success\",\n fetchStatus: \"idle\" as \"fetching\" | \"paused\" | \"idle\",\n isPending: true,\n isSuccess: false,\n isError: false,\n isLoadingError: false,\n isRefetchError: false,\n isFetching: false,\n isPaused: false,\n isRefetching: false,\n isLoading: true,\n isInitialLoading: true,\n isStale: true,\n isPlaceholderData: false,\n isFetched: false,\n isFetchedAfterMount: false,\n isEnabled: get(initialOptions.enabled) ?? true,\n dataUpdatedAt: 0,\n errorUpdatedAt: 0,\n failureCount: 0,\n failureReason: null as Error | null,\n errorUpdateCount: 0,\n refetch() {\n observerRef.current?.refetch();\n },\n });\n\n if (!observerRef.current) {\n const initialQueryKeyString = serializeQueryKey(initialOptions.queryKey);\n previousQueryKeyRef.current = initialQueryKeyString;\n observerRef.current = new QueryObserver<TData, Error>(queryClient, {\n queryKey: [initialQueryKeyString],\n queryFn: initialOptions.queryFn,\n enabled: get(initialOptions.enabled) ?? true,\n staleTime: get(initialOptions.staleTime),\n gcTime: get(initialOptions.gcTime),\n retry: get(initialOptions.retry),\n refetchOnWindowFocus: get(initialOptions.refetchOnWindowFocus),\n refetchOnMount: get(initialOptions.refetchOnMount),\n refetchOnReconnect: get(initialOptions.refetchOnReconnect),\n throwOnError: initialOptions.throwOnError as never,\n });\n }\n\n // useObserve로 options 변화 추적 (렌더링 중 동기 실행)\n // options 자체가 Observable이면 get(options)로 추적,\n // 각 필드가 Observable이면 get(field)로 추적\n useObserve(() => {\n const resolved = get(options);\n\n // options 객체를 직렬화하면서 Observable 값을 추출\n // serializeQueryKey의 replacer에서 .get()을 호출하므로 useObserve가 추적\n const queryKeyString = serializeQueryKey(resolved.queryKey);\n\n // queryKey가 변경되었는지 확인\n const hasQueryKeyChanged = previousQueryKeyRef.current !== queryKeyString;\n\n observerRef.current?.setOptions({\n queryKey: [queryKeyString] as QueryKey,\n queryFn: resolved.queryFn,\n enabled: get(resolved.enabled) ?? true,\n staleTime: get(resolved.staleTime),\n gcTime: get(resolved.gcTime),\n retry: get(resolved.retry),\n refetchOnWindowFocus: get(resolved.refetchOnWindowFocus),\n refetchOnMount: get(resolved.refetchOnMount),\n refetchOnReconnect: get(resolved.refetchOnReconnect),\n throwOnError: resolved.throwOnError as never,\n });\n\n // queryKey가 변경되면 refetch 트리거\n if (hasQueryKeyChanged && previousQueryKeyRef.current !== null) {\n observerRef.current?.refetch();\n }\n\n previousQueryKeyRef.current = queryKeyString;\n });\n\n // 구독은 한 번만 설정 (React lifecycle)\n useMount(() => {\n const observer = observerRef.current;\n if (!observer) return;\n\n const unsubscribe = observer.subscribe((result) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n state$.assign({\n data: result.data,\n error: result.error ?? null,\n status: result.status,\n fetchStatus: result.fetchStatus as \"fetching\" | \"paused\" | \"idle\",\n isPending: result.isPending,\n isSuccess: result.isSuccess,\n isError: result.isError,\n isLoadingError: result.isLoadingError,\n isRefetchError: result.isRefetchError,\n isFetching: result.isFetching,\n isPaused: result.isPaused,\n isRefetching: result.isRefetching,\n isLoading: result.isLoading,\n isInitialLoading: result.isLoading,\n isStale: result.isStale,\n isPlaceholderData: result.isPlaceholderData,\n isFetched: result.isFetched,\n isFetchedAfterMount: result.isFetchedAfterMount,\n isEnabled: result.isEnabled ?? true,\n dataUpdatedAt: result.dataUpdatedAt,\n errorUpdatedAt: result.errorUpdatedAt,\n failureCount: result.failureCount,\n failureReason: result.failureReason ?? null,\n errorUpdateCount: result.errorUpdateCount,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n });\n\n return () => {\n unsubscribe();\n };\n // state$는 stable하므로 의존성에 불필요\n // eslint-disable-next-line react-hooks/exhaustive-deps\n });\n\n return state$;\n}\n","\"use client\";\nimport { useMount, useObservable, useObserve } from \"@legendapp/state/react\";\nimport { MutationKey, MutationObserver } from \"@tanstack/query-core\";\nimport { useRef } from \"react\";\nimport type { Observable } from \"@legendapp/state\";\nimport { useQueryClient } from \"./useQueryClient\";\n\nexport interface UseMutationOptions<\n TData = unknown,\n TVariables = void,\n TContext = unknown,\n> {\n mutationKey?: MutationKey;\n mutationFn: (variables: TVariables) => Promise<TData>;\n onMutate?: (variables: TVariables) => TContext | Promise<TContext>;\n onSuccess?: (\n data: TData,\n variables: TVariables,\n context: TContext | undefined,\n ) => void | Promise<void>;\n onError?: (\n error: Error,\n variables: TVariables,\n context: TContext | undefined,\n ) => void | Promise<void>;\n onSettled?: (\n data: TData | undefined,\n error: Error | null,\n variables: TVariables,\n context: TContext | undefined,\n ) => void | Promise<void>;\n}\n\nexport interface MutationState<\n TData = unknown,\n TVariables = void,\n TContext = unknown,\n> {\n data: TData | undefined;\n error: Error | null;\n status: \"idle\" | \"pending\" | \"error\" | \"success\";\n isIdle: boolean;\n isPending: boolean;\n isPaused: boolean;\n isSuccess: boolean;\n isError: boolean;\n failureCount: number;\n failureReason: Error | null;\n submittedAt: number;\n variables: TVariables | undefined;\n context: TContext | undefined;\n\n mutate: (variables: TVariables) => void;\n mutateAsync: (variables: TVariables) => Promise<TData>;\n reset: () => void;\n}\n\n/**\n * TanStack Query Mutation과 Legend-App-State를 연결하는 커스텀 훅\n * MutationObserver를 사용하여 뮤테이션 상태를 observable로 관리합니다.\n *\n * @example\n * ```tsx\n * import { QueryClient } from '@tanstack/react-query'\n * import { QueryClientProvider, useMutation } from '@usels/integrations'\n *\n * // QueryClient를 생성하고 Provider로 제공\n * const queryClient = new QueryClient()\n *\n * function App() {\n * return (\n * <QueryClientProvider client={queryClient}>\n * <YourApp />\n * </QueryClientProvider>\n * )\n * }\n *\n * // 컴포넌트에서 사용\n * function YourComponent() {\n * const createProduct$ = useMutation({\n * mutationFn: (product: NewProduct) =>\n * fetch('/api/products', {\n * method: 'POST',\n * body: JSON.stringify(product)\n * }).then(r => r.json()),\n * onSuccess: () => {\n * alert('Product created!')\n * }\n * })\n *\n * const handleSubmit = (product: NewProduct) => {\n * createProduct$.mutate(product)\n * }\n * }\n * ```\n */\nexport function useMutation<\n TData = unknown,\n TVariables = void,\n TContext = unknown,\n>(\n options: UseMutationOptions<TData, TVariables, TContext>,\n): Observable<MutationState<TData, TVariables, TContext>> {\n const queryClient = useQueryClient();\n\n // Observer는 한 번만 생성\n const observerRef = useRef<MutationObserver<\n TData,\n Error,\n TVariables,\n TContext\n > | null>(null);\n\n // Observable 상태 초기화 (mutate/mutateAsync/reset는 별도 함수로 분리 - observable 안에 넣으면 Observable<Function>이 됨)\n const state$ = useObservable({\n data: undefined as TData | undefined,\n error: null as Error | null,\n status: \"idle\" as \"idle\" | \"pending\" | \"error\" | \"success\",\n isIdle: true,\n isPending: false,\n isPaused: false,\n isSuccess: false,\n isError: false,\n failureCount: 0,\n failureReason: null as Error | null,\n submittedAt: 0,\n variables: undefined as TVariables | undefined,\n context: undefined as TContext | undefined,\n mutate(variables: TVariables) {\n // Cast to any: TanStack Query mutate() returns void in types but may return\n // a Promise at runtime. Swallow it to prevent unhandled rejection warnings.\n (observerRef.current?.mutate(variables) as any)?.catch?.(() => {});\n },\n mutateAsync(variables: TVariables): Promise<TData> {\n if (observerRef.current) {\n return new Promise((resolve, reject) => {\n // Suppress TanStack Query's internal execute() Promise rejection.\n (\n observerRef.current!.mutate(variables, {\n onSuccess: (data) => resolve(data),\n onError: (error) => reject(error),\n }) as any\n )?.catch?.(() => {});\n });\n }\n throw new Error(\"Mutation not initialized\");\n },\n reset() {\n observerRef.current?.reset();\n },\n });\n\n if (!observerRef.current) {\n observerRef.current = new MutationObserver<\n TData,\n Error,\n TVariables,\n TContext\n >(queryClient, {\n mutationKey: options.mutationKey,\n mutationFn: options.mutationFn,\n onMutate: options.onMutate,\n onSuccess: options.onSuccess,\n onError: options.onError,\n onSettled: options.onSettled,\n });\n }\n\n // useObserve로 options 변화 추적\n useObserve(() => {\n observerRef.current?.setOptions({\n mutationKey: options.mutationKey,\n mutationFn: options.mutationFn,\n onMutate: options.onMutate,\n onSuccess: options.onSuccess,\n onError: options.onError,\n onSettled: options.onSettled,\n });\n });\n\n // 구독은 한 번만 설정 (React lifecycle)\n useMount(() => {\n const observer = observerRef.current;\n if (!observer) return;\n\n const unsubscribe = observer.subscribe((result) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n state$.assign({\n data: result.data,\n error: result.error ?? null,\n status: result.status,\n isIdle: result.isIdle,\n isPending: result.isPending,\n isPaused: result.isPaused,\n isSuccess: result.isSuccess,\n isError: result.isError,\n failureCount: result.failureCount,\n failureReason: result.failureReason ?? null,\n submittedAt: result.submittedAt,\n variables: result.variables,\n context: result.context,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n });\n\n return () => {\n unsubscribe();\n };\n // state$는 stable하므로 의존성에 불필요\n // eslint-disable-next-line react-hooks/exhaustive-deps\n });\n\n return state$;\n}\n","\"use client\";\nimport { useMount, useObservable, useObserve } from \"@legendapp/state/react\";\nimport { isObservable } from \"@legendapp/state\";\nimport {\n QueryKey,\n InfiniteQueryObserver,\n InfiniteData,\n QueryFunctionContext,\n} from \"@tanstack/query-core\";\nimport { useRef } from \"react\";\nimport type { Observable } from \"@legendapp/state\";\nimport { get, type MaybeObservable } from \"@usels/core\";\nimport { useQueryClient } from \"./useQueryClient\";\n\n/**\n * QueryKey를 직렬화하면서 Observable 값을 추출합니다.\n * JSON.stringify는 Observable을 자동으로 .get()하지 않으므로\n * 커스텀 replacer를 사용하여 Observable 값을 추출합니다.\n */\nfunction serializeQueryKey(queryKey: QueryKey): string {\n return JSON.stringify(queryKey, (_key, value) => {\n if (isObservable(value)) {\n return value.get();\n }\n return value;\n });\n}\n\nexport interface UseInfiniteQueryOptions<\n TQueryFnData = unknown,\n TQueryKey extends QueryKey = QueryKey,\n TPageParam = unknown,\n> {\n queryKey: TQueryKey;\n queryFn: (\n context: QueryFunctionContext<TQueryKey, TPageParam>,\n ) => Promise<TQueryFnData>;\n\n // REQUIRED in v5\n initialPageParam: TPageParam;\n getNextPageParam: (\n lastPage: TQueryFnData,\n allPages: Array<TQueryFnData>,\n lastPageParam: TPageParam,\n allPageParams: Array<TPageParam>,\n ) => TPageParam | undefined | null;\n\n // Optional\n getPreviousPageParam?: (\n firstPage: TQueryFnData,\n allPages: Array<TQueryFnData>,\n firstPageParam: TPageParam,\n allPageParams: Array<TPageParam>,\n ) => TPageParam | undefined | null;\n\n enabled?: MaybeObservable<boolean>;\n staleTime?: MaybeObservable<number>;\n gcTime?: MaybeObservable<number>;\n retry?: MaybeObservable<number | boolean>;\n refetchOnWindowFocus?: MaybeObservable<boolean>;\n refetchOnMount?: MaybeObservable<boolean>;\n refetchOnReconnect?: MaybeObservable<boolean>;\n maxPages?: number;\n}\n\nexport interface InfiniteQueryState<TData = unknown> {\n data: TData | undefined;\n error: Error | null;\n status: \"pending\" | \"error\" | \"success\";\n fetchStatus: \"fetching\" | \"paused\" | \"idle\";\n isPending: boolean;\n isSuccess: boolean;\n isError: boolean;\n isLoadingError: boolean;\n isRefetchError: boolean;\n isFetching: boolean;\n isPaused: boolean;\n isRefetching: boolean;\n isLoading: boolean;\n isStale: boolean;\n isPlaceholderData: boolean;\n isFetched: boolean;\n isFetchedAfterMount: boolean;\n dataUpdatedAt: number;\n errorUpdatedAt: number;\n failureCount: number;\n failureReason: Error | null;\n errorUpdateCount: number;\n isEnabled: boolean;\n /**\n * @deprecated Use isLoading instead. Will be removed in TanStack Query v6.\n */\n isInitialLoading: boolean;\n hasNextPage: boolean;\n hasPreviousPage: boolean;\n isFetchingNextPage: boolean;\n isFetchingPreviousPage: boolean;\n isFetchNextPageError: boolean;\n isFetchPreviousPageError: boolean;\n\n refetch: () => void;\n fetchNextPage: () => void;\n fetchPreviousPage: () => void;\n}\n\n/**\n * TanStack Query Infinite Query와 Legend-App-State를 연결하는 커스텀 훅\n * InfiniteQueryObserver를 사용하여 쿼리 상태를 observable로 관리합니다.\n *\n * Observable 값을 파라미터로 받을 수 있으며, 변경 시 자동으로 refetch됩니다.\n *\n * @example\n * ```tsx\n * // Cursor-based pagination\n * const items$ = useInfiniteQuery({\n * queryKey: ['items'],\n * queryFn: ({ pageParam }) =>\n * fetch(`/api/items?cursor=${pageParam}`).then(r => r.json()),\n * initialPageParam: undefined,\n * getNextPageParam: (lastPage) => lastPage.nextCursor,\n * })\n *\n * // Observable reactivity\n * const filter$ = useObservable({ category: 'electronics' })\n * const items$ = useInfiniteQuery({\n * queryKey: ['items', filter$],\n * queryFn: ({ pageParam }) =>\n * fetch(`/api/items?category=${filter$.category.get()}&cursor=${pageParam}`)\n * .then(r => r.json()),\n * initialPageParam: undefined,\n * getNextPageParam: (lastPage) => lastPage.nextCursor,\n * })\n * ```\n */\nexport function useInfiniteQuery<\n TQueryFnData = unknown,\n TQueryKey extends QueryKey = QueryKey,\n TPageParam = unknown,\n>(\n options: MaybeObservable<UseInfiniteQueryOptions<TQueryFnData, TQueryKey, TPageParam>>,\n): Observable<InfiniteQueryState<InfiniteData<TQueryFnData>>> {\n const queryClient = useQueryClient();\n\n // Observer는 한 번만 생성\n const observerRef = useRef<InfiniteQueryObserver<\n TQueryFnData,\n Error,\n InfiniteData<TQueryFnData>,\n TQueryKey,\n TPageParam\n > | null>(null);\n const previousQueryKeyRef = useRef<string | null>(null);\n\n // options 자체가 Observable인 경우 초기 스냅샷 추출 (최초 1회용)\n const initialOptions = get(options);\n\n // Observable 상태 초기화 (refetch/fetchNextPage/fetchPreviousPage는 별도 함수로 분리 - observable 안에 넣으면 Observable<Function>이 됨)\n const state$ = useObservable({\n data: undefined as InfiniteData<TQueryFnData> | undefined,\n error: null as Error | null,\n status: \"pending\" as \"pending\" | \"error\" | \"success\",\n fetchStatus: \"idle\" as \"fetching\" | \"paused\" | \"idle\",\n isPending: true,\n isSuccess: false,\n isError: false,\n isLoadingError: false,\n isRefetchError: false,\n isFetching: false,\n isPaused: false,\n isRefetching: false,\n isLoading: true,\n isStale: true,\n isPlaceholderData: false,\n isFetched: false,\n isFetchedAfterMount: false,\n dataUpdatedAt: 0,\n errorUpdatedAt: 0,\n failureCount: 0,\n failureReason: null as Error | null,\n errorUpdateCount: 0,\n isEnabled: get(initialOptions.enabled) ?? true,\n isInitialLoading: true,\n hasNextPage: false,\n hasPreviousPage: false,\n isFetchingNextPage: false,\n isFetchingPreviousPage: false,\n isFetchNextPageError: false,\n isFetchPreviousPageError: false,\n refetch() {\n observerRef.current?.refetch();\n },\n fetchNextPage() {\n observerRef.current?.fetchNextPage();\n },\n fetchPreviousPage() {\n observerRef.current?.fetchPreviousPage();\n },\n });\n\n if (!observerRef.current) {\n const initialQueryKeyString = serializeQueryKey(initialOptions.queryKey);\n previousQueryKeyRef.current = initialQueryKeyString;\n\n observerRef.current = new InfiniteQueryObserver<\n TQueryFnData,\n Error,\n InfiniteData<TQueryFnData>,\n TQueryKey,\n TPageParam\n >(queryClient, {\n queryKey: [initialQueryKeyString] as unknown as TQueryKey,\n queryFn: initialOptions.queryFn,\n enabled: get(initialOptions.enabled) ?? true,\n staleTime: get(initialOptions.staleTime),\n gcTime: get(initialOptions.gcTime),\n retry: get(initialOptions.retry),\n refetchOnWindowFocus: get(initialOptions.refetchOnWindowFocus),\n refetchOnMount: get(initialOptions.refetchOnMount),\n refetchOnReconnect: get(initialOptions.refetchOnReconnect),\n initialPageParam: initialOptions.initialPageParam,\n getNextPageParam: initialOptions.getNextPageParam,\n getPreviousPageParam: initialOptions.getPreviousPageParam,\n maxPages: initialOptions.maxPages,\n });\n }\n\n // useObserve로 options 변화 추적 (렌더링 중 동기 실행)\n // options 자체가 Observable이면 get(options)로 추적,\n // 각 필드가 Observable이면 get(field)로 추적\n useObserve(() => {\n const resolved = get(options);\n\n // options 객체를 직렬화하면서 Observable 값을 추출\n // serializeQueryKey의 replacer에서 .get()을 호출하므로 useObserve가 추적\n const queryKeyString = serializeQueryKey(resolved.queryKey);\n\n // queryKey가 변경되었는지 확인\n const hasQueryKeyChanged = previousQueryKeyRef.current !== queryKeyString;\n\n observerRef.current?.setOptions({\n queryKey: [queryKeyString] as unknown as TQueryKey,\n queryFn: resolved.queryFn,\n enabled: get(resolved.enabled) ?? true,\n staleTime: get(resolved.staleTime),\n gcTime: get(resolved.gcTime),\n retry: get(resolved.retry),\n refetchOnWindowFocus: get(resolved.refetchOnWindowFocus),\n refetchOnMount: get(resolved.refetchOnMount),\n refetchOnReconnect: get(resolved.refetchOnReconnect),\n initialPageParam: resolved.initialPageParam,\n getNextPageParam: resolved.getNextPageParam,\n getPreviousPageParam: resolved.getPreviousPageParam,\n maxPages: resolved.maxPages,\n });\n\n // queryKey가 변경되면 refetch 트리거\n if (hasQueryKeyChanged && previousQueryKeyRef.current !== null) {\n observerRef.current?.refetch();\n }\n\n previousQueryKeyRef.current = queryKeyString;\n });\n\n // 구독은 한 번만 설정 (React lifecycle)\n useMount(() => {\n const observer = observerRef.current;\n if (!observer) return;\n\n const unsubscribe = observer.subscribe((result: any) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n state$.assign({\n data: result.data,\n error: result.error ?? null,\n status: result.status,\n fetchStatus: result.fetchStatus as \"fetching\" | \"paused\" | \"idle\",\n isPending: result.isPending,\n isSuccess: result.isSuccess,\n isError: result.isError,\n isLoadingError: result.isLoadingError,\n isRefetchError: result.isRefetchError,\n isFetching: result.isFetching,\n isPaused: result.isPaused,\n isRefetching: result.isRefetching,\n isLoading: result.isLoading,\n isInitialLoading: result.isLoading,\n isStale: result.isStale,\n isPlaceholderData: result.isPlaceholderData,\n isFetched: result.isFetched,\n isFetchedAfterMount: result.isFetchedAfterMount,\n isEnabled: result.isEnabled ?? true,\n dataUpdatedAt: result.dataUpdatedAt,\n errorUpdatedAt: result.errorUpdatedAt,\n failureCount: result.failureCount,\n failureReason: result.failureReason ?? null,\n errorUpdateCount: result.errorUpdateCount,\n hasNextPage: result.hasNextPage ?? false,\n hasPreviousPage: result.hasPreviousPage ?? false,\n isFetchingNextPage: result.isFetchingNextPage ?? false,\n isFetchingPreviousPage: result.isFetchingPreviousPage ?? false,\n isFetchNextPageError: result.isFetchNextPageError ?? false,\n isFetchPreviousPageError: result.isFetchPreviousPageError ?? false,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } as any);\n });\n\n return () => {\n unsubscribe();\n };\n // state$는 stable하므로 의존성에 불필요\n // eslint-disable-next-line react-hooks/exhaustive-deps\n });\n\n return state$;\n}\n"],"mappings":"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","names":["useMount","useObservable","useObserve","useRef","useRef","useObservable","useObserve","useMount","useMount","useObservable","useObserve","isObservable","useRef","get","serializeQueryKey","isObservable","useRef","get","useObservable","useObserve","useMount"]}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@usels/integrations",
3
+ "version": "0.0.1",
4
+ "description": "Third-party integrations for Legend-App State utilities",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.mjs",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "keywords": [
16
+ "legendapp",
17
+ "state",
18
+ "integrations",
19
+ "react-query",
20
+ "zustand"
21
+ ],
22
+ "dependencies": {
23
+ "@tanstack/query-core": "^5.90.20",
24
+ "@usels/core": "0.0.1"
25
+ },
26
+ "peerDependencies": {
27
+ "@legendapp/state": "^2.0.0 || ^3.0.0-beta.0",
28
+ "react": "^18.0.0 || ^19.0.0",
29
+ "react-dom": "^18.0.0 || ^19.0.0"
30
+ },
31
+ "peerDependenciesMeta": {
32
+ "@legendapp/state": {
33
+ "optional": true
34
+ },
35
+ "react": {
36
+ "optional": true
37
+ },
38
+ "react-dom": {
39
+ "optional": true
40
+ }
41
+ },
42
+ "devDependencies": {
43
+ "typescript": "^5.3.3",
44
+ "tsup": "^8.0.1",
45
+ "@legendapp/state": "3.0.0-beta.44",
46
+ "react": "^19.0.0",
47
+ "react-dom": "^19.0.0",
48
+ "@types/react": "^19.0.0",
49
+ "@types/react-dom": "^19.0.0",
50
+ "@tanstack/query-core": "^5.90.20",
51
+ "@tanstack/react-query": "^5.60.0",
52
+ "@testing-library/react": "^16.1.0",
53
+ "@testing-library/jest-dom": "^6.6.0",
54
+ "jsdom": "^25.0.0"
55
+ },
56
+ "files": [
57
+ "dist"
58
+ ],
59
+ "publishConfig": {
60
+ "access": "public"
61
+ },
62
+ "scripts": {
63
+ "build": "tsup",
64
+ "dev": "tsup --watch",
65
+ "test": "vitest",
66
+ "test:watch": "vitest --watch"
67
+ }
68
+ }