elm-ssr 1.0.7 → 1.0.9

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": "elm-ssr",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Elm-first SSR library and framework for Cloudflare Workers (and Bun): file-based routes/islands, backend-neutral effect adapters (KV/D1/Redis/Postgres), background tasks (waitUntil/Queues), SQL-file migrations, CLI scaffold + build.",
5
5
  "license": "MIT",
6
6
  "author": "Michał Majchrzak <michmajchrzak@gmail.com>",
@@ -69,7 +69,11 @@
69
69
  "@better-auth/infra": "0.3.4"
70
70
  },
71
71
  "peerDependenciesMeta": {
72
- "better-auth": { "optional": true },
73
- "@better-auth/infra": { "optional": true }
74
- }
72
+ "better-auth": {
73
+ "optional": true
74
+ },
75
+ "@better-auth/infra": {
76
+ "optional": true
77
+ }
78
+ }
75
79
  }
@@ -27,7 +27,14 @@ const cookiePairsFromSetCookie = (setCookie: string | null): string[] => {
27
27
  /** Creates a BetterAuth-backed AuthProvider. Sign-in/sign-up call BetterAuth for
28
28
  * credential validation only — elm-ssr sessions remain the system of record. */
29
29
  export const createBetterAuthProvider = (options: BetterAuthProviderOptions): AuthProvider => {
30
- // Singleton per isolate — recreated only when the resolved DB binding changes.
30
+ // Singleton per isolate — recreated whenever ANY resolved config value
31
+ // changes, not just the DB binding. The DB binding alone is not a safe
32
+ // cache key on Cloudflare Workers: env.DB is the same object reference on
33
+ // every request to a warm isolate, so caching by DB alone would freeze
34
+ // whatever baseURL/secret/apiKey happened to resolve on the very first
35
+ // request (e.g. apiKey undefined before a dashboard key was configured)
36
+ // for the isolate's entire lifetime — every later request, even with a
37
+ // correct env, would silently keep using the stale first-resolved config.
31
38
  // Typed `any`: betterAuth()'s return type is parameterised by the exact
32
39
  // plugins/config literal passed in, which doesn't collapse to a stable
33
40
  // reusable type across the two call sites below (TS infers a fresh
@@ -35,18 +42,26 @@ export const createBetterAuthProvider = (options: BetterAuthProviderOptions): Au
35
42
  // exports is still fully typed — this is an internal cache detail.
36
43
  let _auth: any = null;
37
44
  let _authDb: any = undefined;
45
+ let _authKey: string | null = null;
38
46
 
39
47
  const getAuth = (env: any): any => {
40
48
  const db = options.database(env);
41
- if (_auth !== null && _authDb === db) return _auth;
49
+ const baseURL = options.baseURL(env);
50
+ const secret = options.secret(env);
51
+ const apiKey = options.apiKey?.(env);
52
+ // db is an object (D1 binding / bun:sqlite handle) — keyed by reference
53
+ // identity alongside the primitive config values.
54
+ const key = JSON.stringify([baseURL, secret, apiKey]);
55
+ if (_auth !== null && _authDb === db && _authKey === key) return _auth;
42
56
  _auth = betterAuth({
43
- baseURL: options.baseURL(env),
44
- secret: options.secret(env),
57
+ baseURL,
58
+ secret,
45
59
  database: db,
46
60
  emailAndPassword: { enabled: true },
47
- plugins: [dash({ apiKey: options.apiKey?.(env) })],
61
+ plugins: [dash({ apiKey })],
48
62
  });
49
63
  _authDb = db;
64
+ _authKey = key;
50
65
  return _auth;
51
66
  };
52
67