@lunora/react 1.0.0-alpha.6 → 1.0.0-alpha.61
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/LICENSE.md +6 -0
- package/dist/index.d.mts +1091 -285
- package/dist/index.d.ts +1091 -285
- package/dist/index.mjs +1 -17
- package/dist/packem_shared/AuthLoading-dC08yqew.mjs +2 -0
- package/dist/packem_shared/CheckoutButton-D8MutXhg.mjs +2 -0
- package/dist/packem_shared/LunoraProvider-DC06S-p1.mjs +2 -0
- package/dist/packem_shared/cache-CTiPqpnJ.mjs +1 -0
- package/dist/packem_shared/hydratePreloaded-BPpDZCHN.mjs +2 -0
- package/dist/packem_shared/lunoraQueryOptions-DD7WJ_yD.mjs +1 -0
- package/dist/packem_shared/query-key-ClQy24bz.mjs +1 -0
- package/dist/packem_shared/query-options.d-CdgGQ9s4.d.mts +38 -0
- package/dist/packem_shared/query-options.d-CdgGQ9s4.d.ts +38 -0
- package/dist/packem_shared/stable-key-ITGZkfuz.mjs +1 -0
- package/dist/packem_shared/stream-state-abygFxmy.mjs +1 -0
- package/dist/packem_shared/use-paginated-core-h9Wli0Mz.mjs +2 -0
- package/dist/packem_shared/useAction-CUSJu4yq.mjs +2 -0
- package/dist/packem_shared/useAgent-CS_LwSOE.mjs +2 -0
- package/dist/packem_shared/useAgentChat-DkJWSaoP.mjs +2 -0
- package/dist/packem_shared/useAgentState-IDjPrM2M.mjs +2 -0
- package/dist/packem_shared/useAgentToolEvents-BkmO_ier.mjs +2 -0
- package/dist/packem_shared/useAuth-x4boOoAR.mjs +2 -0
- package/dist/packem_shared/useAuthSessions-Bq4-f3g-.mjs +2 -0
- package/dist/packem_shared/useAuthState-CoOG9XdT.mjs +2 -0
- package/dist/packem_shared/useClientQuery-DFs7trEf.mjs +2 -0
- package/dist/packem_shared/useConnectionStatus-XYsYGiT6.mjs +2 -0
- package/dist/packem_shared/useFlag-D1_5nm0u.mjs +2 -0
- package/dist/packem_shared/useHttpStream-G6MZua0D.mjs +2 -0
- package/dist/packem_shared/useInfiniteQuery-vjMIP0oP.mjs +2 -0
- package/dist/packem_shared/useMutation-BnKec7bE.mjs +2 -0
- package/dist/packem_shared/useMutator-BtUd-xEA.mjs +2 -0
- package/dist/packem_shared/usePaginatedQuery-CmjjsHpF.mjs +2 -0
- package/dist/packem_shared/usePresence-DsYEO_XX.mjs +2 -0
- package/dist/packem_shared/useQuery-DF5z4yjg.mjs +2 -0
- package/dist/packem_shared/useRateLimit-Cckxi8m9.mjs +2 -0
- package/dist/packem_shared/useStream-CHFc-JdW.mjs +2 -0
- package/dist/packem_shared/useSubscription-CgncCiE2.mjs +2 -0
- package/dist/packem_shared/useVoiceAgent-BziH3D-1.mjs +2 -0
- package/dist/packem_shared/wire-key-D-_PTDGR.mjs +1 -0
- package/dist/server.d.mts +47 -29
- package/dist/server.d.ts +47 -29
- package/dist/server.mjs +1 -31
- package/dist/upload.d.mts +23 -0
- package/dist/upload.d.ts +23 -0
- package/dist/upload.mjs +2 -0
- package/package.json +10 -4
- package/dist/packem_shared/AuthLoading-DtKgZT2Z.mjs +0 -33
- package/dist/packem_shared/CheckoutButton-CVSry8U1.mjs +0 -185
- package/dist/packem_shared/LunoraProvider-D38Xp16l.mjs +0 -80
- package/dist/packem_shared/cache-CAp1fVNL.mjs +0 -75
- package/dist/packem_shared/hydratePreloaded-B6OHn0eL.mjs +0 -46
- package/dist/packem_shared/lunoraQueryOptions-Cij4KWBK.mjs +0 -16
- package/dist/packem_shared/query-key-B5eRQCbR.mjs +0 -13
- package/dist/packem_shared/query-options.d-D4okOpO8.d.mts +0 -38
- package/dist/packem_shared/query-options.d-D4okOpO8.d.ts +0 -38
- package/dist/packem_shared/stable-key-CaKZv9lp.mjs +0 -30
- package/dist/packem_shared/use-paginated-core-DxGvzQVR.mjs +0 -161
- package/dist/packem_shared/useAuth-CNUKtOOp.mjs +0 -129
- package/dist/packem_shared/useAuthState-BiGhtSCs.mjs +0 -36
- package/dist/packem_shared/useConnectionStatus-DRSY9ldm.mjs +0 -30
- package/dist/packem_shared/useFlag-Bg5DpkGv.mjs +0 -224
- package/dist/packem_shared/useInfiniteQuery-HjOCDd3R.mjs +0 -97
- package/dist/packem_shared/useMutation-CrvMXRsk.mjs +0 -67
- package/dist/packem_shared/usePaginatedQuery-BGYvICZU.mjs +0 -46
- package/dist/packem_shared/usePresence-D7jLuxj0.mjs +0 -108
- package/dist/packem_shared/useQuery-EB74gtBJ.mjs +0 -42
- package/dist/packem_shared/useRateLimit-DTEffQEi.mjs +0 -64
- package/dist/packem_shared/useStream-MdYnWDL_.mjs +0 -125
- package/dist/packem_shared/useSubscription-DSJuryrU.mjs +0 -139
package/dist/upload.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export { RestrictionError, UploadControl, UploadError,
|
|
2
|
+
/**
|
|
3
|
+
* `@lunora/react/upload` — end-user file-upload hooks.
|
|
4
|
+
*
|
|
5
|
+
* A thin re-export of `@visulima/storage-client`'s React upload hooks (Lunora
|
|
6
|
+
* does not hand-roll the uploader). `useUpload` auto-selects TUS / chunked-REST /
|
|
7
|
+
* multipart by file size; the TUS path gives live progress, pause/resume and
|
|
8
|
+
* resume-after-a-dropped-connection. Point the hook's endpoint at a route backed
|
|
9
|
+
* by `@lunora/storage/upload`'s RLS-gated handler — end-user uploads gated by
|
|
10
|
+
* _your_ per-user policy, not an `adminToken`.
|
|
11
|
+
*
|
|
12
|
+
* ### TanStack Query
|
|
13
|
+
*
|
|
14
|
+
* The upload hooks re-exported here (`useUpload`, `useMultipartUpload`,
|
|
15
|
+
* `useTusUpload`, `useChunkedRestUpload`, `useFileInput`, `usePasteUpload`) hold
|
|
16
|
+
* their own state and need no `QueryClientProvider`. `@visulima/storage-client`'s
|
|
17
|
+
* _data_ hooks (`useGetFileList` etc.) do use TanStack Query — and `LunoraProvider`
|
|
18
|
+
* already mounts a `QueryClient`, so they work inside a Lunora app without extra
|
|
19
|
+
* wiring. That is the reconciliation: Lunora's own `useQuery` and the visulima
|
|
20
|
+
* upload hooks coexist because the upload hooks never touch the query cache.
|
|
21
|
+
*/
|
|
22
|
+
type UploadRestrictions } from '@visulima/storage-client';
|
|
23
|
+
export { type UploadMethod, type UploadResult, type UseChunkedRestUploadOptions, type UseChunkedRestUploadReturn, type UseFileInputOptions, type UseFileInputReturn, type UseMultipartUploadOptions, type UseMultipartUploadReturn, type UsePasteUploadOptions, type UsePasteUploadReturn, type UseTusUploadOptions, type UseTusUploadReturn, type UseUploadOptions, type UseUploadReturn, useChunkedRestUpload, useFileInput, useMultipartUpload, usePasteUpload, useTusUpload, useUpload } from '@visulima/storage-client/react';
|
package/dist/upload.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import{RestrictionError as r,UploadControl as p,UploadError as l}from"@visulima/storage-client";import{useChunkedRestUpload as t,useFileInput as u,useMultipartUpload as a,usePasteUpload as d,useTusUpload as U,useUpload as i}from"@visulima/storage-client/react";export{r as RestrictionError,p as UploadControl,l as UploadError,t as useChunkedRestUpload,u as useFileInput,a as useMultipartUpload,d as usePasteUpload,U as useTusUpload,i as useUpload};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/react",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.61",
|
|
4
4
|
"description": "React hooks for Lunora: useQuery, useMutation, useSubscription, and useAuth",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -43,14 +43,20 @@
|
|
|
43
43
|
"types": "./dist/server.d.ts",
|
|
44
44
|
"import": "./dist/server.mjs"
|
|
45
45
|
},
|
|
46
|
+
"./upload": {
|
|
47
|
+
"types": "./dist/upload.d.ts",
|
|
48
|
+
"import": "./dist/upload.mjs"
|
|
49
|
+
},
|
|
46
50
|
"./package.json": "./package.json"
|
|
47
51
|
},
|
|
48
52
|
"publishConfig": {
|
|
49
53
|
"access": "public"
|
|
50
54
|
},
|
|
51
55
|
"dependencies": {
|
|
52
|
-
"@lunora/client": "1.0.0-alpha.
|
|
53
|
-
"@lunora/
|
|
56
|
+
"@lunora/client": "1.0.0-alpha.56",
|
|
57
|
+
"@lunora/errors": "1.0.0-alpha.22",
|
|
58
|
+
"@lunora/ratelimit": "1.0.0-alpha.25",
|
|
59
|
+
"@visulima/storage-client": "1.0.2"
|
|
54
60
|
},
|
|
55
61
|
"peerDependencies": {
|
|
56
62
|
"@tanstack/react-query": "^5.101.0",
|
|
@@ -65,7 +71,7 @@
|
|
|
65
71
|
"optional": false
|
|
66
72
|
},
|
|
67
73
|
"react-dom": {
|
|
68
|
-
"optional":
|
|
74
|
+
"optional": true
|
|
69
75
|
}
|
|
70
76
|
},
|
|
71
77
|
"engines": {
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { useAuthState } from './useAuthState-BiGhtSCs.mjs';
|
|
3
|
-
|
|
4
|
-
const Authenticated = (t0) => {
|
|
5
|
-
const {
|
|
6
|
-
children
|
|
7
|
-
} = t0;
|
|
8
|
-
const {
|
|
9
|
-
isAuthenticated
|
|
10
|
-
} = useAuthState();
|
|
11
|
-
return isAuthenticated ? children : void 0;
|
|
12
|
-
};
|
|
13
|
-
const Unauthenticated = (t0) => {
|
|
14
|
-
const {
|
|
15
|
-
children
|
|
16
|
-
} = t0;
|
|
17
|
-
const {
|
|
18
|
-
isAuthenticated,
|
|
19
|
-
isLoading
|
|
20
|
-
} = useAuthState();
|
|
21
|
-
return !isLoading && !isAuthenticated ? children : void 0;
|
|
22
|
-
};
|
|
23
|
-
const AuthLoading = (t0) => {
|
|
24
|
-
const {
|
|
25
|
-
children
|
|
26
|
-
} = t0;
|
|
27
|
-
const {
|
|
28
|
-
isLoading
|
|
29
|
-
} = useAuthState();
|
|
30
|
-
return isLoading ? children : void 0;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
export { AuthLoading, Authenticated, Unauthenticated };
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { c } from 'react/compiler-runtime';
|
|
3
|
-
import { useState, useCallback } from 'react';
|
|
4
|
-
import { jsxDEV } from 'react/jsx-dev-runtime';
|
|
5
|
-
|
|
6
|
-
const useCheckout = (trigger) => {
|
|
7
|
-
const [pending, setPending] = useState(false);
|
|
8
|
-
const [error, setError] = useState(void 0);
|
|
9
|
-
const checkout = useCallback(async () => {
|
|
10
|
-
setPending(true);
|
|
11
|
-
setError(void 0);
|
|
12
|
-
try {
|
|
13
|
-
const target = await trigger();
|
|
14
|
-
const {
|
|
15
|
-
url
|
|
16
|
-
} = target;
|
|
17
|
-
globalThis.location.assign(url);
|
|
18
|
-
} catch (error_) {
|
|
19
|
-
const normalized = error_ instanceof Error ? error_ : new Error(String(error_));
|
|
20
|
-
setError(normalized);
|
|
21
|
-
throw normalized;
|
|
22
|
-
} finally {
|
|
23
|
-
setPending(false);
|
|
24
|
-
}
|
|
25
|
-
}, [trigger]);
|
|
26
|
-
return {
|
|
27
|
-
checkout,
|
|
28
|
-
error,
|
|
29
|
-
pending
|
|
30
|
-
};
|
|
31
|
-
};
|
|
32
|
-
const RedirectButton = (t0) => {
|
|
33
|
-
const $ = c(11);
|
|
34
|
-
const {
|
|
35
|
-
"aria-label": ariaLabel,
|
|
36
|
-
children,
|
|
37
|
-
className,
|
|
38
|
-
disabled,
|
|
39
|
-
onError,
|
|
40
|
-
title,
|
|
41
|
-
trigger
|
|
42
|
-
} = t0;
|
|
43
|
-
const {
|
|
44
|
-
checkout,
|
|
45
|
-
pending
|
|
46
|
-
} = useCheckout(trigger);
|
|
47
|
-
let t1;
|
|
48
|
-
if ($[0] !== checkout || $[1] !== onError) {
|
|
49
|
-
t1 = () => {
|
|
50
|
-
checkout().catch((error) => {
|
|
51
|
-
const normalized = error instanceof Error ? error : new Error(String(error));
|
|
52
|
-
onError?.(normalized);
|
|
53
|
-
});
|
|
54
|
-
};
|
|
55
|
-
$[0] = checkout;
|
|
56
|
-
$[1] = onError;
|
|
57
|
-
$[2] = t1;
|
|
58
|
-
} else {
|
|
59
|
-
t1 = $[2];
|
|
60
|
-
}
|
|
61
|
-
const handleClick = t1;
|
|
62
|
-
const t2 = disabled === true || pending;
|
|
63
|
-
let t3;
|
|
64
|
-
if ($[3] !== ariaLabel || $[4] !== children || $[5] !== className || $[6] !== handleClick || $[7] !== pending || $[8] !== t2 || $[9] !== title) {
|
|
65
|
-
t3 = /* @__PURE__ */ jsxDEV("button", {
|
|
66
|
-
"aria-busy": pending,
|
|
67
|
-
"aria-label": ariaLabel,
|
|
68
|
-
className,
|
|
69
|
-
disabled: t2,
|
|
70
|
-
onClick: handleClick,
|
|
71
|
-
title,
|
|
72
|
-
type: "button",
|
|
73
|
-
children
|
|
74
|
-
}, void 0, false);
|
|
75
|
-
$[3] = ariaLabel;
|
|
76
|
-
$[4] = children;
|
|
77
|
-
$[5] = className;
|
|
78
|
-
$[6] = handleClick;
|
|
79
|
-
$[7] = pending;
|
|
80
|
-
$[8] = t2;
|
|
81
|
-
$[9] = title;
|
|
82
|
-
$[10] = t3;
|
|
83
|
-
} else {
|
|
84
|
-
t3 = $[10];
|
|
85
|
-
}
|
|
86
|
-
return t3;
|
|
87
|
-
};
|
|
88
|
-
const CheckoutButton = (t0) => {
|
|
89
|
-
const $ = c(11);
|
|
90
|
-
let onCheckout;
|
|
91
|
-
let rest;
|
|
92
|
-
if ($[0] !== t0) {
|
|
93
|
-
({
|
|
94
|
-
onCheckout,
|
|
95
|
-
...rest
|
|
96
|
-
} = t0);
|
|
97
|
-
$[0] = t0;
|
|
98
|
-
$[1] = onCheckout;
|
|
99
|
-
$[2] = rest;
|
|
100
|
-
} else {
|
|
101
|
-
onCheckout = $[1];
|
|
102
|
-
rest = $[2];
|
|
103
|
-
}
|
|
104
|
-
const {
|
|
105
|
-
"aria-label": ariaLabel,
|
|
106
|
-
children,
|
|
107
|
-
className,
|
|
108
|
-
disabled,
|
|
109
|
-
onError,
|
|
110
|
-
title
|
|
111
|
-
} = rest;
|
|
112
|
-
let t1;
|
|
113
|
-
if ($[3] !== ariaLabel || $[4] !== children || $[5] !== className || $[6] !== disabled || $[7] !== onCheckout || $[8] !== onError || $[9] !== title) {
|
|
114
|
-
t1 = /* @__PURE__ */ jsxDEV(RedirectButton, {
|
|
115
|
-
"aria-label": ariaLabel,
|
|
116
|
-
className,
|
|
117
|
-
disabled,
|
|
118
|
-
onError,
|
|
119
|
-
title,
|
|
120
|
-
trigger: onCheckout,
|
|
121
|
-
children
|
|
122
|
-
}, void 0, false);
|
|
123
|
-
$[3] = ariaLabel;
|
|
124
|
-
$[4] = children;
|
|
125
|
-
$[5] = className;
|
|
126
|
-
$[6] = disabled;
|
|
127
|
-
$[7] = onCheckout;
|
|
128
|
-
$[8] = onError;
|
|
129
|
-
$[9] = title;
|
|
130
|
-
$[10] = t1;
|
|
131
|
-
} else {
|
|
132
|
-
t1 = $[10];
|
|
133
|
-
}
|
|
134
|
-
return t1;
|
|
135
|
-
};
|
|
136
|
-
const CustomerPortalButton = (t0) => {
|
|
137
|
-
const $ = c(11);
|
|
138
|
-
let onPortal;
|
|
139
|
-
let rest;
|
|
140
|
-
if ($[0] !== t0) {
|
|
141
|
-
({
|
|
142
|
-
onPortal,
|
|
143
|
-
...rest
|
|
144
|
-
} = t0);
|
|
145
|
-
$[0] = t0;
|
|
146
|
-
$[1] = onPortal;
|
|
147
|
-
$[2] = rest;
|
|
148
|
-
} else {
|
|
149
|
-
onPortal = $[1];
|
|
150
|
-
rest = $[2];
|
|
151
|
-
}
|
|
152
|
-
const {
|
|
153
|
-
"aria-label": ariaLabel,
|
|
154
|
-
children,
|
|
155
|
-
className,
|
|
156
|
-
disabled,
|
|
157
|
-
onError,
|
|
158
|
-
title
|
|
159
|
-
} = rest;
|
|
160
|
-
let t1;
|
|
161
|
-
if ($[3] !== ariaLabel || $[4] !== children || $[5] !== className || $[6] !== disabled || $[7] !== onError || $[8] !== onPortal || $[9] !== title) {
|
|
162
|
-
t1 = /* @__PURE__ */ jsxDEV(RedirectButton, {
|
|
163
|
-
"aria-label": ariaLabel,
|
|
164
|
-
className,
|
|
165
|
-
disabled,
|
|
166
|
-
onError,
|
|
167
|
-
title,
|
|
168
|
-
trigger: onPortal,
|
|
169
|
-
children
|
|
170
|
-
}, void 0, false);
|
|
171
|
-
$[3] = ariaLabel;
|
|
172
|
-
$[4] = children;
|
|
173
|
-
$[5] = className;
|
|
174
|
-
$[6] = disabled;
|
|
175
|
-
$[7] = onError;
|
|
176
|
-
$[8] = onPortal;
|
|
177
|
-
$[9] = title;
|
|
178
|
-
$[10] = t1;
|
|
179
|
-
} else {
|
|
180
|
-
t1 = $[10];
|
|
181
|
-
}
|
|
182
|
-
return t1;
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
export { CheckoutButton, CustomerPortalButton, useCheckout };
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { c } from 'react/compiler-runtime';
|
|
3
|
-
import { QueryClientContext, QueryClientProvider, QueryClient } from '@tanstack/react-query';
|
|
4
|
-
import { use, useState, createContext } from 'react';
|
|
5
|
-
import { jsxDEV } from 'react/jsx-dev-runtime';
|
|
6
|
-
|
|
7
|
-
const LunoraContext = /* @__PURE__ */ createContext(null);
|
|
8
|
-
const createDefaultQueryClient = () => new QueryClient({
|
|
9
|
-
defaultOptions: {
|
|
10
|
-
mutations: {
|
|
11
|
-
retry: 0
|
|
12
|
-
},
|
|
13
|
-
queries: {
|
|
14
|
-
gcTime: 5 * 6e4,
|
|
15
|
-
retry: 0,
|
|
16
|
-
staleTime: Number.POSITIVE_INFINITY
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
});
|
|
20
|
-
const LunoraProvider = (t0) => {
|
|
21
|
-
const $ = c(9);
|
|
22
|
-
const {
|
|
23
|
-
children,
|
|
24
|
-
client,
|
|
25
|
-
queryClient
|
|
26
|
-
} = t0;
|
|
27
|
-
const parentQueryClient = use(QueryClientContext);
|
|
28
|
-
let t1;
|
|
29
|
-
if ($[0] !== parentQueryClient || $[1] !== queryClient) {
|
|
30
|
-
t1 = () => queryClient ?? parentQueryClient ?? createDefaultQueryClient();
|
|
31
|
-
$[0] = parentQueryClient;
|
|
32
|
-
$[1] = queryClient;
|
|
33
|
-
$[2] = t1;
|
|
34
|
-
} else {
|
|
35
|
-
t1 = $[2];
|
|
36
|
-
}
|
|
37
|
-
const [internalClient] = useState(t1);
|
|
38
|
-
const effectiveClient = queryClient ?? parentQueryClient ?? internalClient;
|
|
39
|
-
if (!effectiveClient) {
|
|
40
|
-
throw new Error("LunoraProvider: failed to resolve a QueryClient");
|
|
41
|
-
}
|
|
42
|
-
let t2;
|
|
43
|
-
if ($[3] !== children || $[4] !== client) {
|
|
44
|
-
t2 = /* @__PURE__ */ jsxDEV(LunoraContext, {
|
|
45
|
-
value: client,
|
|
46
|
-
children
|
|
47
|
-
}, void 0, false);
|
|
48
|
-
$[3] = children;
|
|
49
|
-
$[4] = client;
|
|
50
|
-
$[5] = t2;
|
|
51
|
-
} else {
|
|
52
|
-
t2 = $[5];
|
|
53
|
-
}
|
|
54
|
-
const content = t2;
|
|
55
|
-
if (parentQueryClient === effectiveClient) {
|
|
56
|
-
return content;
|
|
57
|
-
}
|
|
58
|
-
let t3;
|
|
59
|
-
if ($[6] !== content || $[7] !== effectiveClient) {
|
|
60
|
-
t3 = /* @__PURE__ */ jsxDEV(QueryClientProvider, {
|
|
61
|
-
client: effectiveClient,
|
|
62
|
-
children: content
|
|
63
|
-
}, void 0, false);
|
|
64
|
-
$[6] = content;
|
|
65
|
-
$[7] = effectiveClient;
|
|
66
|
-
$[8] = t3;
|
|
67
|
-
} else {
|
|
68
|
-
t3 = $[8];
|
|
69
|
-
}
|
|
70
|
-
return t3;
|
|
71
|
-
};
|
|
72
|
-
const useLunora = () => {
|
|
73
|
-
const client = use(LunoraContext);
|
|
74
|
-
if (!client) {
|
|
75
|
-
throw new Error("useLunora must be used inside <LunoraProvider />");
|
|
76
|
-
}
|
|
77
|
-
return client;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export { LunoraProvider, useLunora };
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { k as keyHash } from './query-key-B5eRQCbR.mjs';
|
|
2
|
-
|
|
3
|
-
class LunoraSubscriptionRegistry {
|
|
4
|
-
constructor(client) {
|
|
5
|
-
this.client = client;
|
|
6
|
-
}
|
|
7
|
-
client;
|
|
8
|
-
entries = /* @__PURE__ */ new Map();
|
|
9
|
-
/**
|
|
10
|
-
* Hash a TanStack `queryKey` to the internal registry index. Exposed so a
|
|
11
|
-
* hook can look up the registry without re-implementing the hash.
|
|
12
|
-
*/
|
|
13
|
-
// eslint-disable-next-line class-methods-use-this -- instance method by design: callers reach the hash through a registry handle rather than importing the module-level helper.
|
|
14
|
-
keyOf(queryKey) {
|
|
15
|
-
return keyHash(queryKey);
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Attach a consumer to the live subscription for `queryKey`. The first
|
|
19
|
-
* attach opens the underlying WS subscription; subsequent attaches reuse
|
|
20
|
-
* it (refcount-bumped). Returns the detach function — call it exactly once
|
|
21
|
-
* per attach.
|
|
22
|
-
*/
|
|
23
|
-
attach(queryClient, queryKey, function_, args, shardKey, options = {}) {
|
|
24
|
-
const key = keyHash(queryKey);
|
|
25
|
-
let entry = this.entries.get(key);
|
|
26
|
-
if (!entry) {
|
|
27
|
-
entry = {
|
|
28
|
-
pollTimer: void 0,
|
|
29
|
-
refCount: 0,
|
|
30
|
-
unsubscribe: void 0
|
|
31
|
-
};
|
|
32
|
-
this.entries.set(key, entry);
|
|
33
|
-
try {
|
|
34
|
-
entry.unsubscribe = this.client.subscribe(function_, args, (value) => {
|
|
35
|
-
queryClient.setQueryData(queryKey, value);
|
|
36
|
-
}, {
|
|
37
|
-
shardKey
|
|
38
|
-
});
|
|
39
|
-
} catch {
|
|
40
|
-
entry.pollTimer = setInterval(() => {
|
|
41
|
-
queryClient.invalidateQueries({
|
|
42
|
-
queryKey
|
|
43
|
-
}).catch(() => {
|
|
44
|
-
});
|
|
45
|
-
}, options.pollIntervalMs ?? 5e3);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
entry.refCount += 1;
|
|
49
|
-
return () => {
|
|
50
|
-
const current = this.entries.get(key);
|
|
51
|
-
if (!current) {
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
current.refCount -= 1;
|
|
55
|
-
if (current.refCount <= 0) {
|
|
56
|
-
current.unsubscribe?.();
|
|
57
|
-
if (current.pollTimer) {
|
|
58
|
-
clearInterval(current.pollTimer);
|
|
59
|
-
}
|
|
60
|
-
this.entries.delete(key);
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
const registryByClient = /* @__PURE__ */ new WeakMap();
|
|
66
|
-
const getSubscriptionRegistry = (client) => {
|
|
67
|
-
let registry = registryByClient.get(client);
|
|
68
|
-
if (!registry) {
|
|
69
|
-
registry = new LunoraSubscriptionRegistry(client);
|
|
70
|
-
registryByClient.set(client, registry);
|
|
71
|
-
}
|
|
72
|
-
return registry;
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
export { getSubscriptionRegistry as g };
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { useQueryClient, useQuery } from '@tanstack/react-query';
|
|
3
|
-
import { useMemo, useEffect } from 'react';
|
|
4
|
-
import { g as getSubscriptionRegistry } from './cache-CAp1fVNL.mjs';
|
|
5
|
-
import { useLunora } from './LunoraProvider-D38Xp16l.mjs';
|
|
6
|
-
import { l as lunoraQueryKey, s as serializeQueryKey } from './query-key-B5eRQCbR.mjs';
|
|
7
|
-
|
|
8
|
-
const usePreloadedQuery = function(preloaded) {
|
|
9
|
-
const client = useLunora();
|
|
10
|
-
const queryClient = useQueryClient();
|
|
11
|
-
const {
|
|
12
|
-
args,
|
|
13
|
-
functionPath,
|
|
14
|
-
shardKey,
|
|
15
|
-
value
|
|
16
|
-
} = preloaded;
|
|
17
|
-
const functionRef = useMemo(() => {
|
|
18
|
-
return {
|
|
19
|
-
__lunoraRef: functionPath
|
|
20
|
-
};
|
|
21
|
-
}, [functionPath]);
|
|
22
|
-
const queryKey = useMemo(() => lunoraQueryKey(functionRef, args, shardKey), [functionRef.__lunoraRef, JSON.stringify(args), shardKey]);
|
|
23
|
-
const {
|
|
24
|
-
data
|
|
25
|
-
} = useQuery({
|
|
26
|
-
// Seed the cache with the server value so the first paint doesn't
|
|
27
|
-
// re-fetch. TanStack treats `initialData` as fresh — the WS push from
|
|
28
|
-
// the registry is what supplies subsequent updates.
|
|
29
|
-
initialData: value,
|
|
30
|
-
queryFn: () => client.query(functionRef, args, {
|
|
31
|
-
shardKey
|
|
32
|
-
}),
|
|
33
|
-
queryKey,
|
|
34
|
-
staleTime: Number.POSITIVE_INFINITY
|
|
35
|
-
});
|
|
36
|
-
useEffect(() => {
|
|
37
|
-
const registry = getSubscriptionRegistry(client);
|
|
38
|
-
return registry.attach(queryClient, queryKey, functionRef, args, shardKey);
|
|
39
|
-
}, [client, queryClient, serializeQueryKey(queryKey)]);
|
|
40
|
-
return data ?? value;
|
|
41
|
-
};
|
|
42
|
-
const hydratePreloaded = function(preloaded) {
|
|
43
|
-
return usePreloadedQuery(preloaded);
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
export { usePreloadedQuery as default, hydratePreloaded };
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { l as lunoraQueryKey } from './query-key-B5eRQCbR.mjs';
|
|
2
|
-
|
|
3
|
-
const lunoraQueryOptions = (client, function_, args, options = {}) => {
|
|
4
|
-
const argsRecord = args ?? {};
|
|
5
|
-
return {
|
|
6
|
-
queryFn: () => client.query(function_, argsRecord, {
|
|
7
|
-
shardKey: options.shardKey
|
|
8
|
-
}),
|
|
9
|
-
queryKey: lunoraQueryKey(function_, argsRecord, options.shardKey),
|
|
10
|
-
// Lunora is push-driven: the value never goes stale on a timer. For
|
|
11
|
-
// reactivity use `useQuery`; this adapter is a one-shot/suspense read.
|
|
12
|
-
staleTime: Number.POSITIVE_INFINITY
|
|
13
|
-
};
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
export { lunoraQueryOptions };
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { s as stableStringify } from './stable-key-CaKZv9lp.mjs';
|
|
2
|
-
|
|
3
|
-
const keyHash = (queryKey) => stableStringify(queryKey);
|
|
4
|
-
const lunoraQueryKey = (function_, args, shardKey) => [
|
|
5
|
-
"lunora",
|
|
6
|
-
function_.__lunoraRef,
|
|
7
|
-
args,
|
|
8
|
-
// eslint-disable-next-line unicorn/no-null -- this literal is part of the JSON-serialized query key TanStack hashes for dedup; `null` keeps a stable, distinct slot from an absent shardKey across renders.
|
|
9
|
-
shardKey ?? null
|
|
10
|
-
];
|
|
11
|
-
const serializeQueryKey = (queryKey) => keyHash(queryKey);
|
|
12
|
-
|
|
13
|
-
export { keyHash as k, lunoraQueryKey as l, serializeQueryKey as s };
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { FunctionReference, ReturnOf, LunoraClient, ArgsOf } from '@lunora/client';
|
|
2
|
-
import { QueryKey } from '@tanstack/react-query';
|
|
3
|
-
/**
|
|
4
|
-
* Pure, transport-free adapter between a Lunora function reference and a
|
|
5
|
-
* TanStack Query options object. No `"use client"` directive and only a
|
|
6
|
-
* type-level `@lunora/client` import, so it is safe to use on either side of an
|
|
7
|
-
* RSC boundary (the runtime transport is the `LunoraClient` you pass in).
|
|
8
|
-
*
|
|
9
|
-
* Use it when you want to drive a Lunora query through TanStack's own hooks —
|
|
10
|
-
* `useSuspenseQuery`, `useQueries`, or the server-side
|
|
11
|
-
* `queryClient.ensureQueryData` / `prefetchQuery` — rather than the first-class
|
|
12
|
-
* `useQuery` from `@lunora/react`.
|
|
13
|
-
*/
|
|
14
|
-
/** Shape returned by `lunoraQueryOptions`, spread into a TanStack hook. */
|
|
15
|
-
interface LunoraQueryOptions<F extends FunctionReference> {
|
|
16
|
-
queryFn: () => Promise<ReturnOf<F>>;
|
|
17
|
-
queryKey: QueryKey;
|
|
18
|
-
staleTime: number;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Build a TanStack Query options object for a Lunora query, keyed identically
|
|
22
|
-
* to the first-class hooks (see `lunoraQueryKey`) so a value fetched through
|
|
23
|
-
* this adapter shares cache identity with anything `useQuery` /
|
|
24
|
-
* `prefetchQuery` reads or writes for the same `(fn, args, shardKey)` triple.
|
|
25
|
-
*
|
|
26
|
-
* ```ts
|
|
27
|
-
* const { data } = useSuspenseQuery(lunoraQueryOptions(client, api.posts.list, {}));
|
|
28
|
-
* ```
|
|
29
|
-
*
|
|
30
|
-
* This is a one-shot fetch: it resolves once and `staleTime` is infinite, so
|
|
31
|
-
* TanStack never refetches on its own. It does not open a WebSocket — for live
|
|
32
|
-
* updates that re-render on every server push, use `useQuery` from
|
|
33
|
-
* `@lunora/react`, which attaches a shared subscription to the same cache key.
|
|
34
|
-
*/
|
|
35
|
-
declare const lunoraQueryOptions: <F extends FunctionReference>(client: LunoraClient, function_: F, args: ArgsOf<F>, options?: {
|
|
36
|
-
shardKey?: string;
|
|
37
|
-
}) => LunoraQueryOptions<F>;
|
|
38
|
-
export { LunoraQueryOptions as L, lunoraQueryOptions as l };
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { FunctionReference, ReturnOf, LunoraClient, ArgsOf } from '@lunora/client';
|
|
2
|
-
import { QueryKey } from '@tanstack/react-query';
|
|
3
|
-
/**
|
|
4
|
-
* Pure, transport-free adapter between a Lunora function reference and a
|
|
5
|
-
* TanStack Query options object. No `"use client"` directive and only a
|
|
6
|
-
* type-level `@lunora/client` import, so it is safe to use on either side of an
|
|
7
|
-
* RSC boundary (the runtime transport is the `LunoraClient` you pass in).
|
|
8
|
-
*
|
|
9
|
-
* Use it when you want to drive a Lunora query through TanStack's own hooks —
|
|
10
|
-
* `useSuspenseQuery`, `useQueries`, or the server-side
|
|
11
|
-
* `queryClient.ensureQueryData` / `prefetchQuery` — rather than the first-class
|
|
12
|
-
* `useQuery` from `@lunora/react`.
|
|
13
|
-
*/
|
|
14
|
-
/** Shape returned by `lunoraQueryOptions`, spread into a TanStack hook. */
|
|
15
|
-
interface LunoraQueryOptions<F extends FunctionReference> {
|
|
16
|
-
queryFn: () => Promise<ReturnOf<F>>;
|
|
17
|
-
queryKey: QueryKey;
|
|
18
|
-
staleTime: number;
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Build a TanStack Query options object for a Lunora query, keyed identically
|
|
22
|
-
* to the first-class hooks (see `lunoraQueryKey`) so a value fetched through
|
|
23
|
-
* this adapter shares cache identity with anything `useQuery` /
|
|
24
|
-
* `prefetchQuery` reads or writes for the same `(fn, args, shardKey)` triple.
|
|
25
|
-
*
|
|
26
|
-
* ```ts
|
|
27
|
-
* const { data } = useSuspenseQuery(lunoraQueryOptions(client, api.posts.list, {}));
|
|
28
|
-
* ```
|
|
29
|
-
*
|
|
30
|
-
* This is a one-shot fetch: it resolves once and `staleTime` is infinite, so
|
|
31
|
-
* TanStack never refetches on its own. It does not open a WebSocket — for live
|
|
32
|
-
* updates that re-render on every server push, use `useQuery` from
|
|
33
|
-
* `@lunora/react`, which attaches a shared subscription to the same cache key.
|
|
34
|
-
*/
|
|
35
|
-
declare const lunoraQueryOptions: <F extends FunctionReference>(client: LunoraClient, function_: F, args: ArgsOf<F>, options?: {
|
|
36
|
-
shardKey?: string;
|
|
37
|
-
}) => LunoraQueryOptions<F>;
|
|
38
|
-
export { LunoraQueryOptions as L, lunoraQueryOptions as l };
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
const compareKeys = (a, b) => {
|
|
2
|
-
if (a < b) {
|
|
3
|
-
return -1;
|
|
4
|
-
}
|
|
5
|
-
return a > b ? 1 : 0;
|
|
6
|
-
};
|
|
7
|
-
const stableStringify = (value) => {
|
|
8
|
-
if (value === void 0) {
|
|
9
|
-
return "null";
|
|
10
|
-
}
|
|
11
|
-
if (value === null || typeof value !== "object") {
|
|
12
|
-
return JSON.stringify(value);
|
|
13
|
-
}
|
|
14
|
-
if (Array.isArray(value)) {
|
|
15
|
-
return `[${value.map((item) => stableStringify(item)).join(",")}]`;
|
|
16
|
-
}
|
|
17
|
-
const record = value;
|
|
18
|
-
const keys = Object.keys(record).toSorted(compareKeys);
|
|
19
|
-
const parts = [];
|
|
20
|
-
for (const key of keys) {
|
|
21
|
-
const raw = record[key];
|
|
22
|
-
if (raw === void 0) {
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
parts.push(`${JSON.stringify(key)}:${stableStringify(raw)}`);
|
|
26
|
-
}
|
|
27
|
-
return `{${parts.join(",")}}`;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export { stableStringify as s };
|