elm-ssr 1.0.3 → 1.0.4
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/lib/scaffold.mjs +55 -50
- package/package.json +1 -1
package/lib/scaffold.mjs
CHANGED
|
@@ -495,23 +495,17 @@ view user =
|
|
|
495
495
|
`;
|
|
496
496
|
|
|
497
497
|
const betterAuthEndpointTemplate = () => `import { betterAuth } from "better-auth";
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
//
|
|
502
|
-
//
|
|
503
|
-
//
|
|
504
|
-
const createAuth = (env: any) =>
|
|
505
|
-
|
|
506
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
507
|
-
const { Database } = require("bun:sqlite");
|
|
508
|
-
return new Database("app.db");
|
|
509
|
-
})();
|
|
510
|
-
|
|
511
|
-
return betterAuth({
|
|
498
|
+
|
|
499
|
+
// BetterAuth is initialised per-request to pick up the right database binding.
|
|
500
|
+
// On Cloudflare Workers env.DB is the D1 binding; on Bun (local dev) the
|
|
501
|
+
// runtime injects a bun:sqlite Database as env.DB — see runtime.ts.
|
|
502
|
+
// Pass env.DB directly so BetterAuth's adapter auto-detects the dialect
|
|
503
|
+
// (D1 via "batch"/"exec"/"prepare", bun:sqlite via "fileControl").
|
|
504
|
+
export const createAuth = (env: any) =>
|
|
505
|
+
betterAuth({
|
|
512
506
|
baseURL: (env?.BETTER_AUTH_URL as string) ?? "http://localhost:8787",
|
|
513
507
|
secret: (env?.BETTER_AUTH_SECRET as string) ?? "change-me-in-production",
|
|
514
|
-
database:
|
|
508
|
+
database: env?.DB,
|
|
515
509
|
emailAndPassword: { enabled: true },
|
|
516
510
|
// Uncomment to add social providers (add matching env vars in .dev.vars):
|
|
517
511
|
// socialProviders: {
|
|
@@ -521,39 +515,9 @@ const createAuth = (env: any) => {
|
|
|
521
515
|
// },
|
|
522
516
|
// },
|
|
523
517
|
});
|
|
524
|
-
};
|
|
525
518
|
|
|
526
519
|
export const handleAuth = (request: Request, env: any): Promise<Response> =>
|
|
527
520
|
createAuth(env).handler(request);
|
|
528
|
-
|
|
529
|
-
// Reads the BetterAuth session from the request and returns the user.
|
|
530
|
-
const getSessionUser = async (
|
|
531
|
-
request: Request,
|
|
532
|
-
env: any
|
|
533
|
-
): Promise<{ email: string; name: string } | null> => {
|
|
534
|
-
try {
|
|
535
|
-
const session = await createAuth(env).api.getSession({ headers: request.headers });
|
|
536
|
-
if (!session?.user) return null;
|
|
537
|
-
return { email: session.user.email, name: session.user.name ?? session.user.email };
|
|
538
|
-
} catch {
|
|
539
|
-
return null;
|
|
540
|
-
}
|
|
541
|
-
};
|
|
542
|
-
|
|
543
|
-
// elm-ssr middleware: reads BetterAuth's session and injects the user into
|
|
544
|
-
// context.session so Loader.session / Loader.requireUser work on every request.
|
|
545
|
-
export const betterAuthMiddleware: Middleware = async (context, next) => {
|
|
546
|
-
const user = await getSessionUser(context.request, context.env);
|
|
547
|
-
context.session = {
|
|
548
|
-
id: user ? \`ba:\${user.email}\` : "",
|
|
549
|
-
data: user,
|
|
550
|
-
csrf: "",
|
|
551
|
-
dirty: false,
|
|
552
|
-
destroyed: false,
|
|
553
|
-
isNew: false,
|
|
554
|
-
} as RequestSession;
|
|
555
|
-
return next(context);
|
|
556
|
-
};
|
|
557
521
|
`;
|
|
558
522
|
|
|
559
523
|
const auth0EndpointTemplate = () => `import { generateSessionId, signValue, generateCsrfToken, readSignedCookie } from "elm-ssr/sessions";
|
|
@@ -686,7 +650,9 @@ const runtimeTemplate = (appRoot, db = false, auth = undefined) => {
|
|
|
686
650
|
|
|
687
651
|
if (isBetterAuth) {
|
|
688
652
|
imports.push(`import { sessionEffects } from "elm-ssr/sessions";`);
|
|
689
|
-
imports.push(`import {
|
|
653
|
+
imports.push(`import type { Middleware } from "elm-ssr/http";`);
|
|
654
|
+
imports.push(`import type { RequestSession } from "elm-ssr/sessions";`);
|
|
655
|
+
imports.push(`import { createAuth, handleAuth } from "./src/Endpoints/Auth";`);
|
|
690
656
|
} else if (isAuth0) {
|
|
691
657
|
imports.push(`import { memorySessionStore } from "elm-ssr/sessions";`);
|
|
692
658
|
imports.push(`import { handleAuth } from "./src/Endpoints/Auth";`);
|
|
@@ -746,13 +712,52 @@ if (typeof Bun !== "undefined") {
|
|
|
746
712
|
}`;
|
|
747
713
|
|
|
748
714
|
const effectsConfig = isBetterAuth
|
|
749
|
-
? `,\n effects: sessionEffects(${baseEffectsBody}),\n middlewares: [
|
|
715
|
+
? `,\n effects: sessionEffects(${baseEffectsBody}),\n middlewares: [betterAuthBridge]`
|
|
750
716
|
: `,\n effects: ${baseEffectsBody}`;
|
|
751
717
|
|
|
752
718
|
// Auth0 keeps elm-ssr session middleware; BetterAuth manages sessions itself.
|
|
753
719
|
let sessionsConfig = '';
|
|
754
720
|
let authInit = '';
|
|
755
|
-
if (
|
|
721
|
+
if (isBetterAuth) {
|
|
722
|
+
authInit = `
|
|
723
|
+
// Local dev: open a SQLite database so BetterAuth works without a Cloudflare D1 binding.
|
|
724
|
+
// On Cloudflare Workers this block is eliminated by esbuild (typeof Bun is statically "undefined").
|
|
725
|
+
let bunAuthDb: any = undefined;
|
|
726
|
+
if (typeof (globalThis as any).Bun !== "undefined") {
|
|
727
|
+
const sqliteModule = "bun" + ":sqlite";
|
|
728
|
+
const { Database } = require(sqliteModule);
|
|
729
|
+
bunAuthDb = new Database(import.meta.dir + "/app.db");
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
const getAuthEnv = (env: any): any =>
|
|
733
|
+
bunAuthDb && !env?.DB ? { ...(env ?? {}), DB: bunAuthDb } : env;
|
|
734
|
+
|
|
735
|
+
// Bridge: reads BetterAuth session on every request so Loader.requireUser works.
|
|
736
|
+
const betterAuthBridge: Middleware = async (context, next) => {
|
|
737
|
+
try {
|
|
738
|
+
const session = await createAuth(getAuthEnv(context.env)).api.getSession({
|
|
739
|
+
headers: context.request.headers,
|
|
740
|
+
});
|
|
741
|
+
const user = session?.user
|
|
742
|
+
? { email: session.user.email, name: session.user.name ?? session.user.email }
|
|
743
|
+
: null;
|
|
744
|
+
context.session = {
|
|
745
|
+
id: user ? \`ba:\${user.email}\` : "",
|
|
746
|
+
data: user,
|
|
747
|
+
csrf: "",
|
|
748
|
+
dirty: false,
|
|
749
|
+
destroyed: false,
|
|
750
|
+
isNew: false,
|
|
751
|
+
} as RequestSession;
|
|
752
|
+
} catch {
|
|
753
|
+
context.session = {
|
|
754
|
+
id: "", data: null, csrf: "", dirty: false, destroyed: false, isNew: false,
|
|
755
|
+
} as RequestSession;
|
|
756
|
+
}
|
|
757
|
+
return next(context);
|
|
758
|
+
};
|
|
759
|
+
`;
|
|
760
|
+
} else if (isAuth0) {
|
|
756
761
|
authInit = `\nexport const sessionStore = memorySessionStore();\n`;
|
|
757
762
|
sessionsConfig = `,
|
|
758
763
|
sessions: {
|
|
@@ -766,12 +771,12 @@ if (typeof Bun !== "undefined") {
|
|
|
766
771
|
let authIntercept = '';
|
|
767
772
|
if (isBetterAuth) {
|
|
768
773
|
authIntercept = `
|
|
769
|
-
// Delegate all /api/auth/* requests to BetterAuth.
|
|
774
|
+
// Delegate all /api/auth/* requests to BetterAuth, injecting the local db when needed.
|
|
770
775
|
const baseWorkerFetch = worker.fetch;
|
|
771
776
|
worker.fetch = async (request, env, ctx) => {
|
|
772
777
|
const url = new URL(request.url);
|
|
773
778
|
if (url.pathname.startsWith("/api/auth/")) {
|
|
774
|
-
return handleAuth(request, env);
|
|
779
|
+
return handleAuth(request, getAuthEnv(env));
|
|
775
780
|
}
|
|
776
781
|
return baseWorkerFetch(request, env, ctx);
|
|
777
782
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "elm-ssr",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.4",
|
|
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>",
|