@lunora/react 1.0.0-alpha.22 → 1.0.0-alpha.23

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 CHANGED
@@ -6,15 +6,15 @@ export { CheckoutButton, CustomerPortalButton, useCheckout } from './packem_shar
6
6
  export { lunoraQueryOptions } from './packem_shared/lunoraQueryOptions-C3uwOTMW.mjs';
7
7
  export { default as useAuth } from './packem_shared/useAuth-BSutjJaa.mjs';
8
8
  export { default as useConnectionStatus } from './packem_shared/useConnectionStatus-PJ7vyCHy.mjs';
9
- export { useFlag, useFlags } from './packem_shared/useFlag-hhoN_xYA.mjs';
10
- export { default as useInfiniteQuery } from './packem_shared/useInfiniteQuery-Dy42_srs.mjs';
9
+ export { useFlag, useFlags } from './packem_shared/useFlag-C2Pkghli.mjs';
10
+ export { default as useInfiniteQuery } from './packem_shared/useInfiniteQuery-BeaehE9f.mjs';
11
11
  export { useMutation } from './packem_shared/useMutation-BeqeIjTr.mjs';
12
12
  export { useMutator } from './packem_shared/useMutator-IIrLtDiM.mjs';
13
- export { usePaginatedQuery } from './packem_shared/usePaginatedQuery-Tx-B3mAP.mjs';
14
- export { hydratePreloaded, default as usePreloadedQuery } from './packem_shared/hydratePreloaded-Dsf9YuII.mjs';
15
- export { usePresence } from './packem_shared/usePresence-DC8VIyLB.mjs';
16
- export { default as useQuery } from './packem_shared/useQuery-_fTR6DCQ.mjs';
13
+ export { usePaginatedQuery } from './packem_shared/usePaginatedQuery-_6ETVUmf.mjs';
14
+ export { hydratePreloaded, default as usePreloadedQuery } from './packem_shared/hydratePreloaded-uMDH_xA9.mjs';
15
+ export { usePresence } from './packem_shared/usePresence-Rnx1Fznc.mjs';
16
+ export { default as useQuery } from './packem_shared/useQuery-D3_ZxMYs.mjs';
17
17
  export { useRateLimit } from './packem_shared/useRateLimit-DTEffQEi.mjs';
18
- export { useStream } from './packem_shared/useStream-DFuryaIC.mjs';
18
+ export { useStream } from './packem_shared/useStream-CGC26afa.mjs';
19
19
  export { default as useSubscription } from './packem_shared/useSubscription-D38Jdyr8.mjs';
20
20
  export { getErrorCode, getRetryAfterMs, isConflictError, isForbiddenError, isRateLimitedError, isUnauthorizedError } from '@lunora/client';
@@ -46,7 +46,12 @@ class LunoraSubscriptionRegistry {
46
46
  }
47
47
  }
48
48
  entry.refCount += 1;
49
+ let detached = false;
49
50
  return () => {
51
+ if (detached) {
52
+ return;
53
+ }
54
+ detached = true;
50
55
  const current = this.entries.get(key);
51
56
  if (!current) {
52
57
  return;
@@ -2,7 +2,7 @@
2
2
  import { c } from 'react/compiler-runtime';
3
3
  import { useQueryClient, useQuery } from '@tanstack/react-query';
4
4
  import { useEffect } from 'react';
5
- import { g as getSubscriptionRegistry } from './cache-BFlsXmup.mjs';
5
+ import { g as getSubscriptionRegistry } from './cache-D1O_xfAe.mjs';
6
6
  import { useLunora } from './LunoraProvider-BsuiW4Lk.mjs';
7
7
  import { s as serializeQueryKey, l as lunoraQueryKey } from './query-key-BmCbgidV.mjs';
8
8
 
@@ -45,7 +45,7 @@ const usePreloadedQuery = function(preloaded) {
45
45
  const registry = getSubscriptionRegistry(client);
46
46
  return registry.attach(queryClient, queryKey, functionRef, args, shardKey);
47
47
  }, t1);
48
- return data ?? value;
48
+ return data === void 0 ? value : data;
49
49
  };
50
50
  const hydratePreloaded = function(preloaded) {
51
51
  return usePreloadedQuery(preloaded);
@@ -2,7 +2,7 @@
2
2
  import { initialPages, rebalance, derivePaginationStatus, applyLoadMore } from '@lunora/client/pagination';
3
3
  import { useQueryClient } from '@tanstack/react-query';
4
4
  import { useRef, useReducer, useState, useEffect, useCallback } from 'react';
5
- import { g as getSubscriptionRegistry } from './cache-BFlsXmup.mjs';
5
+ import { g as getSubscriptionRegistry } from './cache-D1O_xfAe.mjs';
6
6
  import { useLunora } from './LunoraProvider-BsuiW4Lk.mjs';
7
7
  import { s as serializeQueryKey, l as lunoraQueryKey } from './query-key-BmCbgidV.mjs';
8
8
 
@@ -21,10 +21,9 @@ const usePaginatedCore = function(function_, args, options) {
21
21
  } = options;
22
22
  const skipped = args === "skip";
23
23
  const baseArgs = skipped ? {} : args;
24
- const baseArgsKey = JSON.stringify(baseArgs);
25
24
  const [, forceRender] = useReducer((tick) => tick + 1, 0);
26
25
  const [pages, setPages] = useState(() => initialPages(initialNumItems));
27
- const resetKey = `${function_.__lunoraRef}::${baseArgsKey}::${String(initialNumItems)}::${shardKey ?? ""}`;
26
+ const resetKey = `${serializeQueryKey(lunoraQueryKey(function_, baseArgs, shardKey))}::${String(initialNumItems)}`;
28
27
  const resetKeyRef = useRef(resetKey);
29
28
  if (resetKeyRef.current !== resetKey) {
30
29
  resetKeyRef.current = resetKey;
@@ -0,0 +1,128 @@
1
+ 'use client';
2
+ import { useState, useRef, useEffect } from 'react';
3
+ import { useLunora } from './LunoraProvider-BsuiW4Lk.mjs';
4
+ import { s as stableStringify } from './stable-key-CGp4e2Ux.mjs';
5
+
6
+ const FLAGS_EVAL_PATH = "__lunora_flags__:eval";
7
+ const flagKind = (value) => {
8
+ const kind = typeof value;
9
+ if (kind === "boolean" || kind === "number" || kind === "string") {
10
+ return kind;
11
+ }
12
+ return "object";
13
+ };
14
+ const flagsReference = {
15
+ __lunoraRef: FLAGS_EVAL_PATH
16
+ };
17
+ const useFlag = (key, defaultValue, context) => {
18
+ const client = useLunora();
19
+ const [value, setValue] = useState(defaultValue);
20
+ const type = flagKind(defaultValue);
21
+ const serializedContext = context === void 0 ? "" : stableStringify(context);
22
+ const resetKey = `${key}::${type}::${serializedContext}`;
23
+ const resetKeyRef = useRef(resetKey);
24
+ if (resetKeyRef.current !== resetKey) {
25
+ resetKeyRef.current = resetKey;
26
+ setValue(defaultValue);
27
+ }
28
+ const latest = useRef({
29
+ context,
30
+ defaultValue
31
+ });
32
+ useEffect(() => {
33
+ latest.current = {
34
+ context,
35
+ defaultValue
36
+ };
37
+ });
38
+ useEffect(() => {
39
+ let cancelled = false;
40
+ const {
41
+ context: currentContext,
42
+ defaultValue: currentDefault
43
+ } = latest.current;
44
+ setValue(currentDefault);
45
+ let unsubscribe;
46
+ try {
47
+ unsubscribe = client.subscribe(flagsReference, {
48
+ context: currentContext,
49
+ default: currentDefault,
50
+ key,
51
+ type
52
+ }, (next) => {
53
+ if (!cancelled) {
54
+ setValue(next);
55
+ }
56
+ });
57
+ } catch {
58
+ return () => {
59
+ cancelled = true;
60
+ };
61
+ }
62
+ return () => {
63
+ cancelled = true;
64
+ unsubscribe();
65
+ };
66
+ }, [client, key, type, serializedContext]);
67
+ return value;
68
+ };
69
+ const useFlags = (flags, context) => {
70
+ const client = useLunora();
71
+ const [values, setValues] = useState(flags);
72
+ const spec = stableStringify(flags);
73
+ const serializedContext = context === void 0 ? "" : stableStringify(context);
74
+ const resetKey = `${spec}::${serializedContext}`;
75
+ const resetKeyRef = useRef(resetKey);
76
+ if (resetKeyRef.current !== resetKey) {
77
+ resetKeyRef.current = resetKey;
78
+ setValues(flags);
79
+ }
80
+ const latest = useRef({
81
+ context,
82
+ flags
83
+ });
84
+ useEffect(() => {
85
+ latest.current = {
86
+ context,
87
+ flags
88
+ };
89
+ });
90
+ useEffect(() => {
91
+ let cancelled = false;
92
+ const {
93
+ context: currentContext,
94
+ flags: currentFlags
95
+ } = latest.current;
96
+ setValues(currentFlags);
97
+ const unsubscribes = [];
98
+ for (const [key, defaultValue] of Object.entries(currentFlags)) {
99
+ try {
100
+ unsubscribes.push(client.subscribe(flagsReference, {
101
+ context: currentContext,
102
+ default: defaultValue,
103
+ key,
104
+ type: flagKind(defaultValue)
105
+ }, (next) => {
106
+ if (!cancelled) {
107
+ setValues((previous) => {
108
+ return {
109
+ ...previous,
110
+ [key]: next
111
+ };
112
+ });
113
+ }
114
+ }));
115
+ } catch {
116
+ }
117
+ }
118
+ return () => {
119
+ cancelled = true;
120
+ for (const unsubscribe of unsubscribes) {
121
+ unsubscribe();
122
+ }
123
+ };
124
+ }, [client, spec, serializedContext]);
125
+ return values;
126
+ };
127
+
128
+ export { useFlag, useFlags };
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
  import { c } from 'react/compiler-runtime';
3
3
  import { useRef, useEffect } from 'react';
4
- import { u as usePaginatedCore } from './use-paginated-core-CWSzk1J1.mjs';
4
+ import { u as usePaginatedCore } from './use-paginated-core-DafedU4l.mjs';
5
5
 
6
6
  const useInfiniteQuery = (function_, args, options) => {
7
7
  const $ = c(15);
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
  import { c } from 'react/compiler-runtime';
3
- import { u as usePaginatedCore } from './use-paginated-core-CWSzk1J1.mjs';
3
+ import { u as usePaginatedCore } from './use-paginated-core-DafedU4l.mjs';
4
4
 
5
5
  const usePaginatedQuery = (function_, args, options) => {
6
6
  const $ = c(7);
@@ -2,12 +2,19 @@
2
2
  import { useMemo, useState, useRef, useEffect, useCallback } from 'react';
3
3
  import { useLunora } from './LunoraProvider-BsuiW4Lk.mjs';
4
4
 
5
- const makeSessionId = () => {
6
- if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
7
- return crypto.randomUUID();
5
+ const randomSessionId = (prefix = "sess") => {
6
+ if (typeof crypto !== "undefined") {
7
+ if (typeof crypto.randomUUID === "function") {
8
+ return crypto.randomUUID();
9
+ }
10
+ if (typeof crypto.getRandomValues === "function") {
11
+ const bytes = crypto.getRandomValues(new Uint8Array(16));
12
+ return `${prefix}-${Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("")}`;
13
+ }
8
14
  }
9
- return `sess-${Math.random().toString(36).slice(2)}-${String(Date.now())}`;
15
+ return `${prefix}-${Date.now().toString(36)}`;
10
16
  };
17
+
11
18
  const DEFAULT_INTERVAL_MS = 1e4;
12
19
  const usePresence = (roomId, options) => {
13
20
  const client = useLunora();
@@ -17,7 +24,7 @@ const usePresence = (roomId, options) => {
17
24
  listPresent,
18
25
  shardKey
19
26
  } = options;
20
- const generatedSessionId = useMemo(() => options.sessionId ?? makeSessionId(), [options.sessionId]);
27
+ const generatedSessionId = useMemo(() => options.sessionId ?? randomSessionId(), [options.sessionId]);
21
28
  const [present, setPresent] = useState(void 0);
22
29
  const dataRef = useRef(options.data);
23
30
  const inputsRef = useRef({
@@ -2,7 +2,7 @@
2
2
  import { c } from 'react/compiler-runtime';
3
3
  import { useQueryClient, useQuery as useQuery$1 } from '@tanstack/react-query';
4
4
  import { useEffect } from 'react';
5
- import { g as getSubscriptionRegistry } from './cache-BFlsXmup.mjs';
5
+ import { g as getSubscriptionRegistry } from './cache-D1O_xfAe.mjs';
6
6
  import { useLunora } from './LunoraProvider-BsuiW4Lk.mjs';
7
7
  import { s as serializeQueryKey, l as lunoraQueryKey } from './query-key-BmCbgidV.mjs';
8
8
 
@@ -46,7 +46,7 @@ const useQuery = (function_, args, t0) => {
46
46
  const registry = getSubscriptionRegistry(client);
47
47
  return registry.attach(queryClient, queryKey, function_, argsRecord, shardKey);
48
48
  }, t2);
49
- return data;
49
+ return skipped ? void 0 : data;
50
50
  };
51
51
  function _temp() {
52
52
  }
@@ -55,6 +55,9 @@ const useStream = (function_, args, options = {}) => {
55
55
  const cancelRef = useRef(void 0);
56
56
  useEffect(() => {
57
57
  if (skipped) {
58
+ dispatch({
59
+ type: "reset"
60
+ });
58
61
  return () => {
59
62
  };
60
63
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/react",
3
- "version": "1.0.0-alpha.22",
3
+ "version": "1.0.0-alpha.23",
4
4
  "description": "React hooks for Lunora: useQuery, useMutation, useSubscription, and useAuth",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -49,9 +49,9 @@
49
49
  "access": "public"
50
50
  },
51
51
  "dependencies": {
52
- "@lunora/client": "1.0.0-alpha.20",
53
- "@lunora/errors": "1.0.0-alpha.3",
54
- "@lunora/ratelimit": "1.0.0-alpha.6"
52
+ "@lunora/client": "1.0.0-alpha.21",
53
+ "@lunora/errors": "1.0.0-alpha.4",
54
+ "@lunora/ratelimit": "1.0.0-alpha.7"
55
55
  },
56
56
  "peerDependencies": {
57
57
  "@tanstack/react-query": "^5.101.0",
@@ -1,224 +0,0 @@
1
- 'use client';
2
- import { c } from 'react/compiler-runtime';
3
- import { useState, useRef, useEffect } from 'react';
4
- import { useLunora } from './LunoraProvider-BsuiW4Lk.mjs';
5
- import { s as stableStringify } from './stable-key-CGp4e2Ux.mjs';
6
-
7
- const FLAGS_EVAL_PATH = "__lunora_flags__:eval";
8
- const flagKind = (value) => {
9
- const kind = typeof value;
10
- if (kind === "boolean" || kind === "number" || kind === "string") {
11
- return kind;
12
- }
13
- return "object";
14
- };
15
- const flagsReference = {
16
- __lunoraRef: FLAGS_EVAL_PATH
17
- };
18
- const useFlag = (key, defaultValue, context) => {
19
- const $ = c(19);
20
- const client = useLunora();
21
- const [value, setValue] = useState(defaultValue);
22
- let t0;
23
- if ($[0] !== defaultValue) {
24
- t0 = flagKind(defaultValue);
25
- $[0] = defaultValue;
26
- $[1] = t0;
27
- } else {
28
- t0 = $[1];
29
- }
30
- const type = t0;
31
- let t1;
32
- if ($[2] !== context) {
33
- t1 = context === void 0 ? "" : stableStringify(context);
34
- $[2] = context;
35
- $[3] = t1;
36
- } else {
37
- t1 = $[3];
38
- }
39
- const serializedContext = t1;
40
- let t2;
41
- if ($[4] !== context || $[5] !== defaultValue) {
42
- t2 = {
43
- context,
44
- defaultValue
45
- };
46
- $[4] = context;
47
- $[5] = defaultValue;
48
- $[6] = t2;
49
- } else {
50
- t2 = $[6];
51
- }
52
- const latest = useRef(t2);
53
- let t3;
54
- if ($[7] !== context || $[8] !== defaultValue) {
55
- t3 = () => {
56
- latest.current = {
57
- context,
58
- defaultValue
59
- };
60
- };
61
- $[7] = context;
62
- $[8] = defaultValue;
63
- $[9] = t3;
64
- } else {
65
- t3 = $[9];
66
- }
67
- useEffect(t3);
68
- let t4;
69
- if ($[10] !== client || $[11] !== key || $[12] !== type) {
70
- t4 = () => {
71
- let cancelled = false;
72
- const {
73
- context: currentContext,
74
- defaultValue: currentDefault
75
- } = latest.current;
76
- setValue(currentDefault);
77
- let unsubscribe;
78
- try {
79
- unsubscribe = client.subscribe(flagsReference, {
80
- context: currentContext,
81
- default: currentDefault,
82
- key,
83
- type
84
- }, (next) => {
85
- if (!cancelled) {
86
- setValue(next);
87
- }
88
- });
89
- } catch {
90
- return () => {
91
- cancelled = true;
92
- };
93
- }
94
- return () => {
95
- cancelled = true;
96
- unsubscribe();
97
- };
98
- };
99
- $[10] = client;
100
- $[11] = key;
101
- $[12] = type;
102
- $[13] = t4;
103
- } else {
104
- t4 = $[13];
105
- }
106
- let t5;
107
- if ($[14] !== client || $[15] !== key || $[16] !== serializedContext || $[17] !== type) {
108
- t5 = [client, key, type, serializedContext];
109
- $[14] = client;
110
- $[15] = key;
111
- $[16] = serializedContext;
112
- $[17] = type;
113
- $[18] = t5;
114
- } else {
115
- t5 = $[18];
116
- }
117
- useEffect(t4, t5);
118
- return value;
119
- };
120
- const useFlags = (flags, context) => {
121
- const $ = c(16);
122
- const client = useLunora();
123
- const [values, setValues] = useState(flags);
124
- let t0;
125
- if ($[0] !== flags) {
126
- t0 = stableStringify(flags);
127
- $[0] = flags;
128
- $[1] = t0;
129
- } else {
130
- t0 = $[1];
131
- }
132
- const spec = t0;
133
- let t1;
134
- if ($[2] !== context) {
135
- t1 = context === void 0 ? "" : stableStringify(context);
136
- $[2] = context;
137
- $[3] = t1;
138
- } else {
139
- t1 = $[3];
140
- }
141
- const serializedContext = t1;
142
- let t2;
143
- if ($[4] !== context || $[5] !== flags) {
144
- t2 = {
145
- context,
146
- flags
147
- };
148
- $[4] = context;
149
- $[5] = flags;
150
- $[6] = t2;
151
- } else {
152
- t2 = $[6];
153
- }
154
- const latest = useRef(t2);
155
- let t3;
156
- if ($[7] !== context || $[8] !== flags) {
157
- t3 = () => {
158
- latest.current = {
159
- context,
160
- flags
161
- };
162
- };
163
- $[7] = context;
164
- $[8] = flags;
165
- $[9] = t3;
166
- } else {
167
- t3 = $[9];
168
- }
169
- useEffect(t3);
170
- let t4;
171
- if ($[10] !== client) {
172
- t4 = () => {
173
- let cancelled = false;
174
- const {
175
- context: currentContext,
176
- flags: currentFlags
177
- } = latest.current;
178
- setValues(currentFlags);
179
- const unsubscribes = [];
180
- for (const [key, defaultValue] of Object.entries(currentFlags)) {
181
- try {
182
- unsubscribes.push(client.subscribe(flagsReference, {
183
- context: currentContext,
184
- default: defaultValue,
185
- key,
186
- type: flagKind(defaultValue)
187
- }, (next) => {
188
- if (!cancelled) {
189
- setValues((previous) => ({
190
- ...previous,
191
- [key]: next
192
- }));
193
- }
194
- }));
195
- } catch {
196
- }
197
- }
198
- return () => {
199
- cancelled = true;
200
- for (const unsubscribe of unsubscribes) {
201
- unsubscribe();
202
- }
203
- };
204
- };
205
- $[10] = client;
206
- $[11] = t4;
207
- } else {
208
- t4 = $[11];
209
- }
210
- let t5;
211
- if ($[12] !== client || $[13] !== serializedContext || $[14] !== spec) {
212
- t5 = [client, spec, serializedContext];
213
- $[12] = client;
214
- $[13] = serializedContext;
215
- $[14] = spec;
216
- $[15] = t5;
217
- } else {
218
- t5 = $[15];
219
- }
220
- useEffect(t4, t5);
221
- return values;
222
- };
223
-
224
- export { useFlag, useFlags };