added nextjs detection and added exception for auth redirection to also work inside stackblitz

This commit is contained in:
dswbx
2025-01-11 16:23:20 +01:00
parent d8671355a6
commit b1a32f3705
6 changed files with 65 additions and 18 deletions

View File

@@ -3,7 +3,7 @@
"type": "module",
"sideEffects": false,
"bin": "./dist/cli/index.js",
"version": "0.5.0-rc14",
"version": "0.5.0-rc15",
"scripts": {
"build:all": "NODE_ENV=production bun run build.ts --minify --types --clean && bun run build:cli",
"dev": "vite",

View File

@@ -1,14 +1,6 @@
import { Exception } from "core";
import { addFlashMessage } from "core/server/flash";
import {
type Static,
StringEnum,
type TSchema,
Type,
parse,
randomString,
transformObject
} from "core/utils";
import { type Static, StringEnum, Type, parse, runtimeSupports, transformObject } from "core/utils";
import type { Context, Hono } from "hono";
import { deleteCookie, getSignedCookie, setSignedCookie } from "hono/cookie";
import { sign, verify } from "hono/jwt";
@@ -282,20 +274,31 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
return c.req.header("Content-Type") === "application/json";
}
private getSuccessPath(c: Context) {
const p = (this.config.cookie.pathSuccess ?? "/").replace(/\/+$/, "/");
// nextjs doesn't support non-fq urls
// but env could be proxied (stackblitz), so we shouldn't fq every url
if (!runtimeSupports("redirects_non_fq")) {
return new URL(c.req.url).origin + p;
}
return p;
}
async respond(c: Context, data: AuthResponse | Error | any, redirect?: string) {
if (this.isJsonRequest(c)) {
return c.json(data);
}
const successPath = this.config.cookie.pathSuccess ?? "/";
const successUrl = new URL(c.req.url).origin + successPath.replace(/\/+$/, "/");
const referer = new URL(redirect ?? c.req.header("Referer") ?? successUrl);
console.log("auth respond", { redirect, successUrl, successPath });
const successUrl = this.getSuccessPath(c);
const referer = redirect ?? c.req.header("Referer") ?? successUrl;
//console.log("auth respond", { redirect, successUrl, successPath });
if ("token" in data) {
await this.setAuthCookie(c, data.token);
// can't navigate to "/" doesn't work on nextjs
console.log("auth success, redirecting to", successUrl);
//console.log("auth success, redirecting to", successUrl);
return c.redirect(successUrl);
}
@@ -305,7 +308,7 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
}
await addFlashMessage(c, message, "error");
console.log("auth failed, redirecting to", referer);
//console.log("auth failed, redirecting to", referer);
return c.redirect(referer);
}

View File

@@ -11,3 +11,4 @@ export * from "./crypto";
export * from "./uuid";
export { FromSchema } from "./typebox/from-schema";
export * from "./test";
export * from "./runtime";

View File

@@ -0,0 +1,41 @@
import { getRuntimeKey as honoGetRuntimeKey } from "hono/adapter";
/**
* Adds additional checks for nextjs
*/
export function getRuntimeKey(): string {
const global = globalThis as any;
// Detect Next.js server-side runtime
if (global?.process?.env?.NEXT_RUNTIME === "nodejs") {
return "nextjs";
}
// Detect Next.js edge runtime
if (global?.process?.env?.NEXT_RUNTIME === "edge") {
return "nextjs-edge";
}
// Detect Next.js client-side runtime
// @ts-ignore
if (typeof window !== "undefined" && window.__NEXT_DATA__) {
return "nextjs-client";
}
return honoGetRuntimeKey();
}
const features = {
// supports the redirect of not full qualified addresses
// not supported in nextjs
redirects_non_fq: true
};
export function runtimeSupports(feature: keyof typeof features) {
const runtime = getRuntimeKey();
if (runtime.startsWith("nextjs")) {
features.redirects_non_fq = false;
}
return features[feature];
}

View File

@@ -3,6 +3,7 @@
import type { App } from "App";
import { tbValidator as tb } from "core";
import { StringEnum, Type, TypeInvalidError } from "core/utils";
import { getRuntimeKey } from "core/utils";
import type { Context, Hono } from "hono";
import { Controller } from "modules/Controller";
@@ -292,7 +293,8 @@ export class SystemController extends Controller {
return c.json({
version: this.app.version(),
test: 2,
app: c.get("app")?.version()
app: c.get("app")?.version(),
runtime: getRuntimeKey()
});
});