@lunora/react-native 1.0.0-alpha.36 → 1.0.0-alpha.37

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/README.md CHANGED
@@ -131,10 +131,24 @@ import { client } from "./lunora";
131
131
  function Root() {
132
132
  const { data: session } = authClient.useSession();
133
133
 
134
+ // `expoBearerToken` is async since better-auth 1.7.1, and an async function
135
+ // is not a valid effect cleanup return — so kick off a promise instead.
136
+ // `cancelled` is load-bearing: two session changes in quick succession leave
137
+ // two reads in flight, and without it the slower one reinstates the previous
138
+ // session's token.
134
139
  useEffect(() => {
135
- const token = expoBearerToken(authClient);
136
- client.setAuthToken(token); // HTTP `Authorization: Bearer …`
137
- client.setWsToken(token ?? undefined); // WS `?token=…`
140
+ let cancelled = false;
141
+
142
+ void (async () => {
143
+ const token = await expoBearerToken(authClient);
144
+ if (cancelled) return;
145
+ client.setAuthToken(token); // HTTP `Authorization: Bearer …`
146
+ client.setWsToken(token ?? undefined); // WS `?token=…`
147
+ })();
148
+
149
+ return () => {
150
+ cancelled = true;
151
+ };
138
152
  }, [session]);
139
153
 
140
154
  // …render the app
package/dist/auth.d.mts CHANGED
@@ -1,6 +1,20 @@
1
- import { expoClient as expoClient$1 } from '@better-auth/expo/client';
2
- export { setupExpoFocusManager, setupExpoOnlineManager } from '@better-auth/expo/client';
3
- import { BetterAuthClientPlugin } from 'better-auth/client';
1
+ export {
2
+ /**
3
+ * The slice of a key/value store the better-auth Expo plugin needs. Pass Expo
4
+ * `SecureStore` straight in.
5
+ *
6
+ * Re-exported from `@better-auth/expo/client` rather than restated here. This
7
+ * used to be a hand-written `SecureStorageLike` mirroring what upstream needed
8
+ * — two synchronous methods — and better-auth 1.7 moved the Expo storage
9
+ * integration to asynchronous `SecureStore` methods, so the real shape is now
10
+ * `getItem` + `getItemAsync` + `setItem` + `setItemAsync`. A hand-written
11
+ * mirror does not fail when upstream widens like that; it just silently
12
+ * describes a store the plugin will not accept. Re-exporting makes the
13
+ * compiler track it, which is the same lesson the `getCookie` shim taught in
14
+ * this file's history.
15
+ * @experimental
16
+ */
17
+ type ExpoClientStorage, expoClient, setupExpoFocusManager, setupExpoOnlineManager } from '@better-auth/expo/client';
4
18
  /**
5
19
  * Read the current better-auth session token from an Expo auth client, for use
6
20
  * as a **bearer** credential on the Lunora client — `client.setAuthToken(token)`
@@ -11,68 +25,27 @@ import { BetterAuthClientPlugin } from 'better-auth/client';
11
25
  * better-auth's `bearer` plugin accepts that value verbatim in the
12
26
  * `Authorization` header — so the native client authenticates WITHOUT sending a
13
27
  * `Cookie`, which the runtime's CSRF guard rejects on an `Origin`-less native
14
- * request (React Native sends no `Origin`). Returns `null` when signed out.
28
+ * request (React Native sends no `Origin`). Resolves `null` when signed out.
29
+ *
30
+ * **Async since better-auth 1.7.1**, which changed `@better-auth/expo`'s
31
+ * `getCookie` from `() => string` to `() => Promise<string>` (it reads
32
+ * `SecureStore` asynchronously now). The awaited value is what gets matched:
33
+ * regexing the Promise itself would test `"[object Promise]"`, find no
34
+ * `session_token`, and return `null` on every call — a signed-in native app
35
+ * that silently behaves as anonymous, which is exactly the failure this
36
+ * signature change prevents by making callers await.
15
37
  *
16
38
  * Re-run it whenever the session changes and feed the result to the client (see
17
39
  * the package README):
18
40
  *
19
41
  * ```ts
20
- * const token = expoBearerToken(authClient);
42
+ * const token = await expoBearerToken(authClient);
21
43
  * client.setAuthToken(token);
22
44
  * client.setWsToken(token ?? undefined);
23
45
  * ```
24
46
  * @experimental
25
47
  */
26
48
  declare const expoBearerToken: (authClient: {
27
- getCookie: () => string;
28
- }) => null | string;
29
- /**
30
- * The slice of a key/value store the better-auth Expo plugin needs — the shape
31
- * of `expo-secure-store` (a synchronous `getItem`, plus `setItem`). Pass Expo
32
- * `SecureStore` straight in.
33
- * @experimental
34
- */
35
- interface SecureStorageLike {
36
- getItem: (key: string) => null | string;
37
- setItem: (key: string, value: string) => unknown;
38
- }
39
- /** The actions `expoClient` contributes to the auth client. */
40
- interface ExpoClientActions {
41
- /** The session cookie persisted in `SecureStore`, as a `name=value; …` string. */
42
- getCookie: () => string;
43
- }
44
- /**
45
- * `expoClient`'s plugin type, restated so it satisfies `BetterAuthClientPlugin`.
46
- *
47
- * From better-auth 1.6.24 through 1.7.0-rc.2, `@better-auth/expo`'s own declaration
48
- * does not: its `getActions` types the `$fetch` parameter as a *different*
49
- * `BetterFetch` instantiation than the interface requires, and under
50
- * `strictFunctionTypes` parameter contravariance rejects the assignment — so
51
- * `createAuthClient({ plugins: [expoClient(…)] })` fails to typecheck with a TS2322
52
- * whose error text is several hundred characters of generic-inference expansion.
53
- * The knock-on is a TS2345 wherever the inferred `getCookie` action is then read.
54
- *
55
- * The base has to stay upstream's own return type, with only `getActions` replaced:
56
- * better-auth infers the whole client API (`signIn`, `signUp`, the session shape)
57
- * from the literal plugin members, so rebuilding the type on top of
58
- * `BetterAuthClientPlugin` instead — or merely intersecting with it — collapses that
59
- * inference to `never` and the errors reappear as "Property 'signIn' does not exist".
60
- * The replacement takes its parameters from better-auth's interface (making the
61
- * assignment trivially valid) and returns {@link ExpoClientActions}, which is what
62
- * keeps `authClient.getCookie()` typed for `expoBearerToken`. Runtime behaviour
63
- * is untouched — this is a declaration-level correction of an upstream bug.
64
- *
65
- * Delete this shim (and re-export `expoClient` directly) once upstream's
66
- * `getActions` signature matches the interface again.
67
- * @experimental
68
- */
69
- type ExpoClientPlugin = Omit<ReturnType<typeof expoClient$1>, "getActions"> & {
70
- getActions: (...arguments_: Parameters<NonNullable<BetterAuthClientPlugin["getActions"]>>) => ExpoClientActions;
71
- };
72
- /**
73
- * The better-auth Expo client plugin — session persisted in `SecureStore`, OAuth via
74
- * the app scheme. Pass it to `createAuthClient({ plugins: [expoClient({ scheme, storage })] })`.
75
- * @experimental
76
- */
77
- declare const expoClient: (options: Parameters<typeof expoClient$1>[0]) => ExpoClientPlugin;
78
- export { ExpoClientActions, ExpoClientPlugin, SecureStorageLike, expoBearerToken, expoClient };
49
+ getCookie: () => Promise<string> | string;
50
+ }) => Promise<null | string>;
51
+ export { expoBearerToken };
package/dist/auth.d.ts CHANGED
@@ -1,6 +1,20 @@
1
- import { expoClient as expoClient$1 } from '@better-auth/expo/client';
2
- export { setupExpoFocusManager, setupExpoOnlineManager } from '@better-auth/expo/client';
3
- import { BetterAuthClientPlugin } from 'better-auth/client';
1
+ export {
2
+ /**
3
+ * The slice of a key/value store the better-auth Expo plugin needs. Pass Expo
4
+ * `SecureStore` straight in.
5
+ *
6
+ * Re-exported from `@better-auth/expo/client` rather than restated here. This
7
+ * used to be a hand-written `SecureStorageLike` mirroring what upstream needed
8
+ * — two synchronous methods — and better-auth 1.7 moved the Expo storage
9
+ * integration to asynchronous `SecureStore` methods, so the real shape is now
10
+ * `getItem` + `getItemAsync` + `setItem` + `setItemAsync`. A hand-written
11
+ * mirror does not fail when upstream widens like that; it just silently
12
+ * describes a store the plugin will not accept. Re-exporting makes the
13
+ * compiler track it, which is the same lesson the `getCookie` shim taught in
14
+ * this file's history.
15
+ * @experimental
16
+ */
17
+ type ExpoClientStorage, expoClient, setupExpoFocusManager, setupExpoOnlineManager } from '@better-auth/expo/client';
4
18
  /**
5
19
  * Read the current better-auth session token from an Expo auth client, for use
6
20
  * as a **bearer** credential on the Lunora client — `client.setAuthToken(token)`
@@ -11,68 +25,27 @@ import { BetterAuthClientPlugin } from 'better-auth/client';
11
25
  * better-auth's `bearer` plugin accepts that value verbatim in the
12
26
  * `Authorization` header — so the native client authenticates WITHOUT sending a
13
27
  * `Cookie`, which the runtime's CSRF guard rejects on an `Origin`-less native
14
- * request (React Native sends no `Origin`). Returns `null` when signed out.
28
+ * request (React Native sends no `Origin`). Resolves `null` when signed out.
29
+ *
30
+ * **Async since better-auth 1.7.1**, which changed `@better-auth/expo`'s
31
+ * `getCookie` from `() => string` to `() => Promise<string>` (it reads
32
+ * `SecureStore` asynchronously now). The awaited value is what gets matched:
33
+ * regexing the Promise itself would test `"[object Promise]"`, find no
34
+ * `session_token`, and return `null` on every call — a signed-in native app
35
+ * that silently behaves as anonymous, which is exactly the failure this
36
+ * signature change prevents by making callers await.
15
37
  *
16
38
  * Re-run it whenever the session changes and feed the result to the client (see
17
39
  * the package README):
18
40
  *
19
41
  * ```ts
20
- * const token = expoBearerToken(authClient);
42
+ * const token = await expoBearerToken(authClient);
21
43
  * client.setAuthToken(token);
22
44
  * client.setWsToken(token ?? undefined);
23
45
  * ```
24
46
  * @experimental
25
47
  */
26
48
  declare const expoBearerToken: (authClient: {
27
- getCookie: () => string;
28
- }) => null | string;
29
- /**
30
- * The slice of a key/value store the better-auth Expo plugin needs — the shape
31
- * of `expo-secure-store` (a synchronous `getItem`, plus `setItem`). Pass Expo
32
- * `SecureStore` straight in.
33
- * @experimental
34
- */
35
- interface SecureStorageLike {
36
- getItem: (key: string) => null | string;
37
- setItem: (key: string, value: string) => unknown;
38
- }
39
- /** The actions `expoClient` contributes to the auth client. */
40
- interface ExpoClientActions {
41
- /** The session cookie persisted in `SecureStore`, as a `name=value; …` string. */
42
- getCookie: () => string;
43
- }
44
- /**
45
- * `expoClient`'s plugin type, restated so it satisfies `BetterAuthClientPlugin`.
46
- *
47
- * From better-auth 1.6.24 through 1.7.0-rc.2, `@better-auth/expo`'s own declaration
48
- * does not: its `getActions` types the `$fetch` parameter as a *different*
49
- * `BetterFetch` instantiation than the interface requires, and under
50
- * `strictFunctionTypes` parameter contravariance rejects the assignment — so
51
- * `createAuthClient({ plugins: [expoClient(…)] })` fails to typecheck with a TS2322
52
- * whose error text is several hundred characters of generic-inference expansion.
53
- * The knock-on is a TS2345 wherever the inferred `getCookie` action is then read.
54
- *
55
- * The base has to stay upstream's own return type, with only `getActions` replaced:
56
- * better-auth infers the whole client API (`signIn`, `signUp`, the session shape)
57
- * from the literal plugin members, so rebuilding the type on top of
58
- * `BetterAuthClientPlugin` instead — or merely intersecting with it — collapses that
59
- * inference to `never` and the errors reappear as "Property 'signIn' does not exist".
60
- * The replacement takes its parameters from better-auth's interface (making the
61
- * assignment trivially valid) and returns {@link ExpoClientActions}, which is what
62
- * keeps `authClient.getCookie()` typed for `expoBearerToken`. Runtime behaviour
63
- * is untouched — this is a declaration-level correction of an upstream bug.
64
- *
65
- * Delete this shim (and re-export `expoClient` directly) once upstream's
66
- * `getActions` signature matches the interface again.
67
- * @experimental
68
- */
69
- type ExpoClientPlugin = Omit<ReturnType<typeof expoClient$1>, "getActions"> & {
70
- getActions: (...arguments_: Parameters<NonNullable<BetterAuthClientPlugin["getActions"]>>) => ExpoClientActions;
71
- };
72
- /**
73
- * The better-auth Expo client plugin — session persisted in `SecureStore`, OAuth via
74
- * the app scheme. Pass it to `createAuthClient({ plugins: [expoClient({ scheme, storage })] })`.
75
- * @experimental
76
- */
77
- declare const expoClient: (options: Parameters<typeof expoClient$1>[0]) => ExpoClientPlugin;
78
- export { ExpoClientActions, ExpoClientPlugin, SecureStorageLike, expoBearerToken, expoClient };
49
+ getCookie: () => Promise<string> | string;
50
+ }) => Promise<null | string>;
51
+ export { expoBearerToken };
package/dist/auth.mjs CHANGED
@@ -1 +1 @@
1
- import{expoClient as e}from"@better-auth/expo/client";import{setupExpoFocusManager as n,setupExpoOnlineManager as x}from"@better-auth/expo/client";import{default as s}from"./packem_shared/expoBearerToken-D4y9YP0s.mjs";const p=e;export{s as expoBearerToken,p as expoClient,n as setupExpoFocusManager,x as setupExpoOnlineManager};
1
+ import{default as p}from"./packem_shared/expoBearerToken-CA88JtQp.mjs";import{expoClient as a,setupExpoFocusManager as n,setupExpoOnlineManager as t}from"@better-auth/expo/client";export{p as expoBearerToken,a as expoClient,n as setupExpoFocusManager,t as setupExpoOnlineManager};
@@ -0,0 +1 @@
1
+ const t=/(?:^|;)[^;=]*session_token=([^;]+)/,n=async e=>t.exec(await e.getCookie())?.[1]??null;export{n as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/react-native",
3
- "version": "1.0.0-alpha.36",
3
+ "version": "1.0.0-alpha.37",
4
4
  "description": "React Native / Expo integration for Lunora: an AsyncStorage-backed client factory, the useQuery/useMutation/useSubscription hooks, and a one-call better-auth Expo client",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -54,9 +54,9 @@
54
54
  "@lunora/react": "1.0.0-alpha.61"
55
55
  },
56
56
  "peerDependencies": {
57
- "@better-auth/expo": "^1.6.23",
57
+ "@better-auth/expo": "^1.7.1",
58
58
  "@tanstack/react-query": "^5.101.0",
59
- "better-auth": "^1.6.23",
59
+ "better-auth": "^1.7.1",
60
60
  "react": "^19.2.7"
61
61
  },
62
62
  "peerDependenciesMeta": {
@@ -1 +0,0 @@
1
- const o=/(?:^|;)[^;=]*session_token=([^;]+)/,n=e=>o.exec(e.getCookie())?.[1]??null;export{n as default};