better-near-auth 1.4.0 → 1.4.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "better-near-auth",
3
- "version": "1.4.0",
3
+ "version": "1.4.2",
4
4
  "description": "Sign in with NEAR (SIWN) plugin for Better Auth",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",
@@ -8,7 +8,7 @@ description: >
8
8
  using authClient.near.* methods, or building delegate actions for gasless relay.
9
9
  type: core
10
10
  library: better-near-auth
11
- library_version: "1.2.1"
11
+ library_version: "1.4.1"
12
12
  sources:
13
13
  - "elliotBraem/better-near-auth:src/client.ts"
14
14
  - "elliotBraem/better-near-auth:src/types.ts"
@@ -8,7 +8,7 @@ description: >
8
8
  configuring RotatingKeyStore for high-throughput relay.
9
9
  type: core
10
10
  library: better-near-auth
11
- library_version: "1.2.1"
11
+ library_version: "1.4.1"
12
12
  sources:
13
13
  - "elliotBraem/better-near-auth:src/index.ts"
14
14
  - "elliotBraem/better-near-auth:src/utils.ts"
@@ -8,7 +8,7 @@ description: >
8
8
  or debugging NEP-413 verify or nonce issues.
9
9
  type: core
10
10
  library: better-near-auth
11
- library_version: "1.2.1"
11
+ library_version: "1.4.1"
12
12
  sources:
13
13
  - "elliotBraem/better-near-auth:src/index.ts"
14
14
  - "elliotBraem/better-near-auth:src/profile.ts"
@@ -8,8 +8,11 @@ description: >
8
8
  wiring auth into router context, or debugging wallet state loss after
9
9
  sign-in in SSR/CSR TanStack apps.
10
10
  type: framework
11
+ requires:
12
+ - client
13
+ - siwn
11
14
  library: better-near-auth
12
- library_version: "1.2.1"
15
+ library_version: "1.4.1"
13
16
  sources:
14
17
  - "elliotBraem/better-near-auth:src/client.ts"
15
18
  - "elliotBraem/better-near-auth:examples/auth.everything.dev/ui/src/auth.ts"
@@ -57,13 +60,19 @@ import { useRouter } from "@tanstack/react-router";
57
60
  import { useQuery } from "@tanstack/react-query";
58
61
  import type { Auth } from "./auth-types.gen";
59
62
  import { getAccount, getHostUrl, getNetworkId } from "@/app";
63
+ import type { ClientRuntimeConfig } from "./app";
60
64
 
61
- export function createAuthClient() {
65
+ interface AuthClientOpts {
66
+ runtimeConfig?: Partial<ClientRuntimeConfig>;
67
+ }
68
+
69
+ export function createAuthClient(opts?: AuthClientOpts) {
70
+ const config = opts?.runtimeConfig;
62
71
  return createBetterAuthClient({
63
- baseURL: getHostUrl(),
72
+ baseURL: getHostUrl(config),
64
73
  fetchOptions: { credentials: "include" },
65
74
  plugins: [
66
- siwnClient({ recipient: getAccount(), networkId: getNetworkId() }),
75
+ siwnClient({ recipient: getAccount(config), networkId: getNetworkId(config) }),
67
76
  ],
68
77
  });
69
78
  }
@@ -79,7 +88,7 @@ export function useAuthClient(): AuthClient {
79
88
  The auth client is created once in the router setup (not per component call) and accessed via context:
80
89
 
81
90
  ```typescript
82
- // hydrate.tsx
91
+ // hydrate.tsx — browser, no runtimeConfig needed (reads window.__RUNTIME_CONFIG__)
83
92
  import { createAuthClient } from "./auth";
84
93
 
85
94
  const { router } = createRouter({
@@ -88,23 +97,19 @@ const { router } = createRouter({
88
97
  },
89
98
  });
90
99
 
91
- // router.server.tsx — same pattern
100
+ // router.server.tsx — server, MUST pass runtimeConfig
92
101
  context: {
93
- authClient: createAuthClient(),
102
+ authClient: createAuthClient({ runtimeConfig: renderOptions.runtimeConfig }),
94
103
  }
95
104
  ```
96
105
 
97
106
  ## Type Inference from AuthClient
98
107
 
99
- Don't manually define `Organization`, `Passkey`, or other entity types. Infer them from the client's API responses:
108
+ Don't manually define `Organization`, `Passkey`, or other entity types. Use `$Infer` to get them directly from the auth client's type system:
100
109
 
101
110
  ```typescript
102
- type UnwrapListResponse<T> = T extends (...args: any[]) => Promise<{
103
- data: (infer U)[] | null; error: any
104
- }> ? U : never;
105
-
106
- export type Organization = UnwrapListResponse<AuthClient["organization"]["list"]>;
107
- export type Passkey = UnwrapListResponse<AuthClient["passkey"]["listUserPasskeys"]>;
111
+ export type Organization = AuthClient["$Infer"]["Organization"];
112
+ export type Passkey = AuthClient["$Infer"]["Passkey"];
108
113
  ```
109
114
 
110
115
  This automatically includes any additional fields the server configured. Single source of truth: the `AuthClient` type, which is itself derived from the plugin list.
@@ -214,7 +219,15 @@ This means UI can display the user's NEAR account even when the wallet is discon
214
219
 
215
220
  ## SSR Safety
216
221
 
217
- `siwnClient()` is SSR-safe — wallet resources are lazily initialized on first client-side access. On the server they sit dormant. This means `createAuthClient()` can safely run in `router.server.tsx` without accessing browser APIs.
222
+ `siwnClient()` is SSR-safe — wallet resources are lazily initialized on first client-side access. On the server they sit dormant. However, `createAuthClient()` calls `getHostUrl()`, `getAccount()`, and `getNetworkId()`, which read `window.__RUNTIME_CONFIG__` by default. On the server, you **must** pass `{ runtimeConfig }` so these helpers read from the provided config instead of the browser-only `window` object:
223
+
224
+ ```typescript
225
+ // Server (router.server.tsx) — MUST pass runtimeConfig
226
+ createAuthClient({ runtimeConfig: renderOptions.runtimeConfig })
227
+
228
+ // Client (hydrate.tsx) — no config needed, reads window.__RUNTIME_CONFIG__
229
+ createAuthClient()
230
+ ```
218
231
 
219
232
  Methods that work on server (via `$fetch` only): `nonce`, `verify`, `view`, `relayTransaction`, `getRelayStatus`, `getRelayerInfo`, `relayHistory`, `getProfile`, `listAccounts`.
220
233
 
@@ -258,9 +271,10 @@ export const authClient = createAuthClient({
258
271
  });
259
272
 
260
273
  // OR: Router context singleton (SSR)
261
- export function createAuthClient() {
274
+ export function createAuthClient(opts?: AuthClientOpts) {
275
+ const config = opts?.runtimeConfig;
262
276
  return createBetterAuthClient({
263
- plugins: [siwnClient({ recipient: getAccount() })],
277
+ plugins: [siwnClient({ recipient: getAccount(config) })],
264
278
  });
265
279
  }
266
280
  // Create once in router setup, access via useAuthClient()
@@ -343,14 +357,35 @@ Correct (SSR):
343
357
 
344
358
  ```typescript
345
359
  // Factory — one instance per router/request
346
- export function createAuthClient() {
360
+ export function createAuthClient(opts?: AuthClientOpts) {
361
+ const config = opts?.runtimeConfig;
347
362
  return createBetterAuthClient({
348
- plugins: [siwnClient({ recipient: getAccount() })],
363
+ plugins: [siwnClient({ recipient: getAccount(config) })],
349
364
  });
350
365
  }
351
- // Created in createRouter() context
366
+ // Created in createRouter() context with runtimeConfig
352
367
  ```
353
368
 
354
369
  On the server, a module-level singleton's `$fetch` and session state would be shared across concurrent requests. Router context isolates one client per request on server, one per app on client.
355
370
 
356
371
  Source: router.server.tsx:60-71
372
+
373
+ ### MEDIUM Calling createAuthClient() without runtimeConfig on the server
374
+
375
+ Wrong:
376
+
377
+ ```typescript
378
+ // router.server.tsx — throws "Runtime config is only available in the browser"
379
+ authClient: createAuthClient(),
380
+ ```
381
+
382
+ Correct:
383
+
384
+ ```typescript
385
+ // router.server.tsx — pass runtimeConfig from renderOptions
386
+ authClient: createAuthClient({ runtimeConfig: renderOptions.runtimeConfig }),
387
+ ```
388
+
389
+ `getHostUrl()`, `getAccount()`, and `getNetworkId()` read `window.__RUNTIME_CONFIG__` by default. On the server, `window` is undefined, so they throw. Always pass `{ runtimeConfig }` when calling `createAuthClient()` in `router.server.tsx` or `getRouteHead()`.
390
+
391
+ Source: auth.ts:18-27