mirror of
https://github.com/better-auth/better-auth.git
synced 2026-06-04 13:26:23 -05:00
chore: move env to core
This commit is contained in:
@@ -29,11 +29,11 @@ export default function Dashboard() {
|
||||
</View>
|
||||
</View>
|
||||
</CardHeader>
|
||||
<View className="my-2">
|
||||
<View className="my-2 flex-row items-center justify-between px-6">
|
||||
<Button
|
||||
variant="default"
|
||||
size="sm"
|
||||
className="mx-6 flex-row items-center gap-2 "
|
||||
className="flex-row items-center gap-2 "
|
||||
>
|
||||
<Ionicons name="edit" size={16} color="white" />
|
||||
<Text>Edit User</Text>
|
||||
|
||||
147
examples/expo-example/src/components/ui/dialog.tsx
Normal file
147
examples/expo-example/src/components/ui/dialog.tsx
Normal file
@@ -0,0 +1,147 @@
|
||||
import * as DialogPrimitive from '@rn-primitives/dialog';
|
||||
import * as React from 'react';
|
||||
import { Platform, StyleSheet, View, type ViewProps } from 'react-native';
|
||||
import Animated, { FadeIn, FadeOut } from 'react-native-reanimated';
|
||||
import { X } from '@/lib/icons/X';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const Dialog = DialogPrimitive.Root;
|
||||
|
||||
const DialogTrigger = DialogPrimitive.Trigger;
|
||||
|
||||
const DialogPortal = DialogPrimitive.Portal;
|
||||
|
||||
const DialogClose = DialogPrimitive.Close;
|
||||
|
||||
const DialogOverlayWeb = React.forwardRef<DialogPrimitive.OverlayRef, DialogPrimitive.OverlayProps>(
|
||||
({ className, ...props }, ref) => {
|
||||
const { open } = DialogPrimitive.useRootContext();
|
||||
return (
|
||||
<DialogPrimitive.Overlay
|
||||
className={cn(
|
||||
'bg-black/80 flex justify-center items-center p-2 absolute top-0 right-0 bottom-0 left-0',
|
||||
open ? 'web:animate-in web:fade-in-0' : 'web:animate-out web:fade-out-0',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
DialogOverlayWeb.displayName = 'DialogOverlayWeb';
|
||||
|
||||
const DialogOverlayNative = React.forwardRef<
|
||||
DialogPrimitive.OverlayRef,
|
||||
DialogPrimitive.OverlayProps
|
||||
>(({ className, children, ...props }, ref) => {
|
||||
return (
|
||||
<DialogPrimitive.Overlay
|
||||
style={StyleSheet.absoluteFill}
|
||||
className={cn('flex bg-black/80 justify-center items-center p-2', className)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
>
|
||||
<Animated.View entering={FadeIn.duration(150)} exiting={FadeOut.duration(150)}>
|
||||
<>{children}</>
|
||||
</Animated.View>
|
||||
</DialogPrimitive.Overlay>
|
||||
);
|
||||
});
|
||||
|
||||
DialogOverlayNative.displayName = 'DialogOverlayNative';
|
||||
|
||||
const DialogOverlay = Platform.select({
|
||||
web: DialogOverlayWeb,
|
||||
default: DialogOverlayNative,
|
||||
});
|
||||
|
||||
const DialogContent = React.forwardRef<
|
||||
DialogPrimitive.ContentRef,
|
||||
DialogPrimitive.ContentProps & { portalHost?: string }
|
||||
>(({ className, children, portalHost, ...props }, ref) => {
|
||||
const { open } = DialogPrimitive.useRootContext();
|
||||
return (
|
||||
<DialogPortal hostName={portalHost}>
|
||||
<DialogOverlay>
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'max-w-lg gap-4 border border-border web:cursor-default bg-background p-6 shadow-lg web:duration-200 rounded-lg',
|
||||
open
|
||||
? 'web:animate-in web:fade-in-0 web:zoom-in-95'
|
||||
: 'web:animate-out web:fade-out-0 web:zoom-out-95',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<DialogPrimitive.Close
|
||||
className={
|
||||
'absolute right-4 top-4 p-0.5 web:group rounded-sm opacity-70 web:ring-offset-background web:transition-opacity web:hover:opacity-100 web:focus:outline-none web:focus:ring-2 web:focus:ring-ring web:focus:ring-offset-2 web:disabled:pointer-events-none'
|
||||
}
|
||||
>
|
||||
<X
|
||||
size={Platform.OS === 'web' ? 16 : 18}
|
||||
className={cn('text-muted-foreground', open && 'text-accent-foreground')}
|
||||
/>
|
||||
</DialogPrimitive.Close>
|
||||
</DialogPrimitive.Content>
|
||||
</DialogOverlay>
|
||||
</DialogPortal>
|
||||
);
|
||||
});
|
||||
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
||||
|
||||
const DialogHeader = ({ className, ...props }: ViewProps) => (
|
||||
<View className={cn('flex flex-col gap-1.5 text-center sm:text-left', className)} {...props} />
|
||||
);
|
||||
DialogHeader.displayName = 'DialogHeader';
|
||||
|
||||
const DialogFooter = ({ className, ...props }: ViewProps) => (
|
||||
<View
|
||||
className={cn('flex flex-col-reverse sm:flex-row sm:justify-end gap-2', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
DialogFooter.displayName = 'DialogFooter';
|
||||
|
||||
const DialogTitle = React.forwardRef<DialogPrimitive.TitleRef, DialogPrimitive.TitleProps>(
|
||||
({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'text-lg native:text-xl text-foreground font-semibold leading-none tracking-tight',
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
);
|
||||
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
||||
|
||||
const DialogDescription = React.forwardRef<
|
||||
DialogPrimitive.DescriptionRef,
|
||||
DialogPrimitive.DescriptionProps
|
||||
>(({ className, ...props }, ref) => (
|
||||
<DialogPrimitive.Description
|
||||
ref={ref}
|
||||
className={cn('text-sm native:text-base text-muted-foreground', className)}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
||||
|
||||
export {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
DialogContent,
|
||||
DialogDescription,
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogOverlay,
|
||||
DialogPortal,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
};
|
||||
@@ -1,9 +1,10 @@
|
||||
import { createAuthClient } from "better-auth/react";
|
||||
import { expoClient } from "better-auth/client/plugins";
|
||||
import * as SecureStorage from "expo-secure-store";
|
||||
|
||||
import * as Constant from "expo-constants";
|
||||
console.log(Constant);
|
||||
export const authClient = createAuthClient({
|
||||
baseURL: "http://192.168.1.7:3000",
|
||||
baseURL: "http://172.20.10.3:3000",
|
||||
disableDefaultFetchPlugins: true,
|
||||
plugins: [
|
||||
expoClient({
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
import Constants from "expo-constants";
|
||||
|
||||
/**
|
||||
* Extend this function when going to production by
|
||||
* setting the baseUrl to your production API URL.
|
||||
*/
|
||||
export const getBaseUrl = () => {
|
||||
const debuggerHost = Constants.expoConfig?.hostUri;
|
||||
const localhost = debuggerHost?.split(":")[0];
|
||||
|
||||
if (!localhost) {
|
||||
// return "https://turbo.t3.gg";
|
||||
throw new Error(
|
||||
"Failed to get localhost. Please point to your production server.",
|
||||
);
|
||||
}
|
||||
return `http://${localhost}:3000`;
|
||||
};
|
||||
4
examples/expo-example/src/lib/icons/X.tsx
Normal file
4
examples/expo-example/src/lib/icons/X.tsx
Normal file
@@ -0,0 +1,4 @@
|
||||
import { X } from 'lucide-react-native';
|
||||
import { iconWithClassName } from './iconWithClassName';
|
||||
iconWithClassName(X);
|
||||
export { X };
|
||||
14
examples/expo-example/src/lib/icons/iconWithClassName.ts
Normal file
14
examples/expo-example/src/lib/icons/iconWithClassName.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import type { LucideIcon } from 'lucide-react-native';
|
||||
import { cssInterop } from 'nativewind';
|
||||
|
||||
export function iconWithClassName(icon: LucideIcon) {
|
||||
cssInterop(icon, {
|
||||
className: {
|
||||
target: 'style',
|
||||
nativeStyleToProp: {
|
||||
color: true,
|
||||
opacity: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -73,6 +73,7 @@ export const auth = betterAuth({
|
||||
sendOnSignUp: true,
|
||||
},
|
||||
account: {
|
||||
enabled: true,
|
||||
accountLinking: {
|
||||
trustedProviders: ["google", "github"],
|
||||
},
|
||||
@@ -99,8 +100,8 @@ export const auth = betterAuth({
|
||||
google: {
|
||||
clientId: process.env.GOOGLE_CLIENT_ID || "",
|
||||
clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
|
||||
accessType: "offline",
|
||||
prompt: "select_account",
|
||||
// accessType: "offline",
|
||||
// prompt: "select_account",
|
||||
},
|
||||
discord: {
|
||||
clientId: process.env.DISCORD_CLIENT_ID || "",
|
||||
@@ -125,5 +126,5 @@ export const auth = betterAuth({
|
||||
username(),
|
||||
expo(),
|
||||
],
|
||||
trustedOrigins: ["better-auth://"],
|
||||
trustedOrigins: ["better-auth://", "exp://"],
|
||||
});
|
||||
|
||||
@@ -229,6 +229,8 @@
|
||||
"@types/react": "^18.3.3",
|
||||
"better-sqlite3": "^11.3.0",
|
||||
"drizzle-orm": "^0.33.0",
|
||||
"expo-linking": "~6.3.1",
|
||||
"expo-secure-store": "~13.0.2",
|
||||
"expo-web-browser": "~13.0.3",
|
||||
"happy-dom": "^15.7.4",
|
||||
"hono": "^4.5.4",
|
||||
@@ -265,7 +267,6 @@
|
||||
"nanoid": "^5.0.7",
|
||||
"nanostores": "^0.11.2",
|
||||
"oslo": "^1.2.1",
|
||||
"std-env": "^3.7.0",
|
||||
"uncrypto": "^0.1.3",
|
||||
"zod": "^3.22.5"
|
||||
},
|
||||
|
||||
@@ -7,9 +7,8 @@ import { HIDE_METADATA } from "../../utils/hide-metadata";
|
||||
import { setSessionCookie } from "../../cookies";
|
||||
import { logger } from "../../utils/logger";
|
||||
import type { OAuth2Tokens } from "../../oauth2";
|
||||
import { compareHash, hmac } from "../../crypto/hash";
|
||||
import { createEmailVerificationToken } from "./email-verification";
|
||||
import { isDevelopment } from "std-env";
|
||||
import { isDevelopment } from "../../utils/env";
|
||||
|
||||
export const callbackOAuth = createAuthEndpoint(
|
||||
"/callback/:id",
|
||||
@@ -115,6 +114,7 @@ export const callbackOAuth = createAuthEndpoint(
|
||||
});
|
||||
|
||||
let user = dbUser?.user;
|
||||
|
||||
if (dbUser) {
|
||||
const hasBeenLinked = dbUser.accounts.find(
|
||||
(a) => a.providerId === provider.id,
|
||||
@@ -127,7 +127,7 @@ export const callbackOAuth = createAuthEndpoint(
|
||||
);
|
||||
if (
|
||||
(!isTrustedProvider && !userInfo.emailVerified) ||
|
||||
!c.context.options.account?.accountLinking?.enabled
|
||||
c.context.options.account?.accountLinking?.enabled === false
|
||||
) {
|
||||
if (isDevelopment) {
|
||||
logger.warn(
|
||||
@@ -199,7 +199,6 @@ export const callbackOAuth = createAuthEndpoint(
|
||||
redirectOnError("unable_to_create_user");
|
||||
}
|
||||
}
|
||||
|
||||
if (!user) {
|
||||
return redirectOnError("unable_to_create_user");
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import { TimeSpan } from "oslo";
|
||||
import type { BetterAuthOptions } from "../types/options";
|
||||
import type { GenericEndpointContext } from "../types/context";
|
||||
import { BetterAuthError } from "../error";
|
||||
import { env, isProduction } from "std-env";
|
||||
import { env, isProduction } from "../utils/env";
|
||||
import type { Session, User } from "../types";
|
||||
|
||||
export function getCookies(options: BetterAuthOptions) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import { createKyselyAdapter } from "./adapters/kysely-adapter/dialect";
|
||||
import { getAdapter } from "./db/utils";
|
||||
import { hashPassword, verifyPassword } from "./crypto/password";
|
||||
import { createInternalAdapter } from "./db";
|
||||
import { env, isProduction } from "std-env";
|
||||
import { env, isProduction } from "./utils/env";
|
||||
import type {
|
||||
Adapter,
|
||||
BetterAuthOptions,
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import type { BetterAuthClientPlugin, Store } from "better-auth";
|
||||
import * as Browser from "expo-web-browser";
|
||||
import * as Linking from "expo-linking";
|
||||
import * as SecureStorage from "expo-secure-store";
|
||||
import { parseSetCookieHeader } from "../../cookies";
|
||||
|
||||
interface ExpoClientOptions {
|
||||
scheme: string;
|
||||
storage: {
|
||||
storage?: {
|
||||
getItemAsync: (key: string) => Promise<string | null> | string | null;
|
||||
setItemAsync: (key: string, value: string) => Promise<void> | void;
|
||||
deleteItemAsync: (key: string) => Promise<void> | void;
|
||||
@@ -19,10 +21,43 @@ interface StoredCookie {
|
||||
expires: Date | null;
|
||||
}
|
||||
|
||||
function getSetCookie(header: string) {
|
||||
const parsed = parseSetCookieHeader(header);
|
||||
const toSetCookie: Record<string, StoredCookie> = {};
|
||||
parsed.forEach((cookie, key) => {
|
||||
const expiresAt = cookie["expires"];
|
||||
const maxAge = cookie["max-age"];
|
||||
const expires = expiresAt
|
||||
? new Date(String(expiresAt))
|
||||
: maxAge
|
||||
? new Date(Date.now() + Number(maxAge))
|
||||
: null;
|
||||
toSetCookie[key] = {
|
||||
value: cookie["value"],
|
||||
expires,
|
||||
};
|
||||
});
|
||||
return JSON.stringify(toSetCookie);
|
||||
}
|
||||
|
||||
function getCookie(cookie: string) {
|
||||
let parsed = {} as Record<string, StoredCookie>;
|
||||
try {
|
||||
parsed = JSON.parse(cookie) as Record<string, StoredCookie>;
|
||||
} catch (e) {}
|
||||
const toSend = Object.entries(parsed).reduce((acc, [key, value]) => {
|
||||
if (value.expires && value.expires < new Date()) {
|
||||
return acc;
|
||||
}
|
||||
return `${acc}; ${key}=${value.value}`;
|
||||
}, "");
|
||||
return toSend;
|
||||
}
|
||||
|
||||
export const expoClient = (opts: ExpoClientOptions) => {
|
||||
let store: Store | null = null;
|
||||
const cookieName = opts.cookies?.name || "better-auth_cookie";
|
||||
const storage = opts.storage;
|
||||
const storage = opts.storage || SecureStorage;
|
||||
const scheme = opts.scheme;
|
||||
if (!scheme) {
|
||||
throw new Error(
|
||||
@@ -43,68 +78,40 @@ export const expoClient = (opts: ExpoClientOptions) => {
|
||||
hooks: {
|
||||
async onSuccess(context) {
|
||||
const setCookie = context.response.headers.get("set-cookie");
|
||||
if (setCookie) {
|
||||
const parsed = parseSetCookieHeader(setCookie);
|
||||
const toSetCookie: Record<string, StoredCookie> = {};
|
||||
parsed.forEach((cookie, key) => {
|
||||
const expiresAt = cookie["expires"];
|
||||
const maxAge = cookie["max-age"];
|
||||
const expires = expiresAt
|
||||
? new Date(String(expiresAt))
|
||||
: maxAge
|
||||
? new Date(Date.now() + Number(maxAge))
|
||||
: null;
|
||||
toSetCookie[key] = {
|
||||
value: cookie["value"],
|
||||
expires,
|
||||
};
|
||||
});
|
||||
await storage.setItemAsync(
|
||||
cookieName,
|
||||
JSON.stringify(toSetCookie),
|
||||
);
|
||||
}
|
||||
const toSetCookie = getSetCookie(setCookie || "");
|
||||
await storage.setItemAsync(cookieName, toSetCookie);
|
||||
if (
|
||||
context.data.redirect &&
|
||||
context.request.url.toString().includes("/sign-in")
|
||||
) {
|
||||
const callbackURL = JSON.parse(context.request.body)?.callbackURL;
|
||||
const to = callbackURL;
|
||||
const signInURL = context.data?.url;
|
||||
const result = await Browser.openAuthSessionAsync(
|
||||
signInURL,
|
||||
callbackURL,
|
||||
);
|
||||
const result = await Browser.openAuthSessionAsync(signInURL, to);
|
||||
if (result.type !== "success") return;
|
||||
const url = new URL(result.url);
|
||||
const cookie = String(url.searchParams.get("cookie"));
|
||||
if (!cookie) return;
|
||||
await storage.setItemAsync(cookieName, cookie);
|
||||
await storage.setItemAsync(cookieName, getSetCookie(cookie));
|
||||
store?.notify("$sessionSignal");
|
||||
}
|
||||
},
|
||||
},
|
||||
async init(url, options) {
|
||||
options = options || {};
|
||||
const cookie = await storage.getItemAsync(cookieName);
|
||||
const parsed = cookie
|
||||
? (JSON.parse(cookie) as Record<string, StoredCookie>)
|
||||
: {};
|
||||
const toSend = Object.entries(parsed).reduce((acc, [key, value]) => {
|
||||
if (value.expires && value.expires < new Date()) {
|
||||
return acc;
|
||||
}
|
||||
return `${acc}; ${key}=${value.value}`;
|
||||
}, "");
|
||||
|
||||
const storedCookie = await storage.getItemAsync(cookieName);
|
||||
const cookie = getCookie(storedCookie || "{}");
|
||||
options.credentials = "omit";
|
||||
options.headers = {
|
||||
...options.headers,
|
||||
cookie: toSend,
|
||||
cookie,
|
||||
origin: schemeURL,
|
||||
};
|
||||
if (options.body?.callbackURL) {
|
||||
if (options.body.callbackURL.startsWith("/")) {
|
||||
const url = `${schemeURL}${options.body.callbackURL}`;
|
||||
const url = Linking.createURL(options.body.callbackURL, {
|
||||
scheme,
|
||||
});
|
||||
options.body.callbackURL = url;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,19 @@
|
||||
import type { BetterAuthPlugin } from "better-auth";
|
||||
import { isDevelopment } from "../../utils/env";
|
||||
|
||||
export const expo = () => {
|
||||
return {
|
||||
id: "expo",
|
||||
init: (ctx) => {
|
||||
return {
|
||||
options: {
|
||||
/**
|
||||
* Add expo go as a trusted origin on dev
|
||||
*/
|
||||
trustedOrigins: isDevelopment ? ["exp://"] : [],
|
||||
},
|
||||
};
|
||||
},
|
||||
hooks: {
|
||||
after: [
|
||||
{
|
||||
@@ -13,7 +24,6 @@ export const expo = () => {
|
||||
const response = ctx.context.returned as Response;
|
||||
if (response.status === 302) {
|
||||
const location = response.headers.get("location");
|
||||
|
||||
if (!location) {
|
||||
return;
|
||||
}
|
||||
@@ -33,6 +43,7 @@ export const expo = () => {
|
||||
const url = new URL(location);
|
||||
url.searchParams.set("cookie", cookie);
|
||||
response.headers.set("location", url.toString());
|
||||
console.log("Redirecting to", url.toString());
|
||||
return {
|
||||
response,
|
||||
};
|
||||
|
||||
@@ -20,7 +20,7 @@ import type { BetterAuthPlugin } from "../../types/plugins";
|
||||
import { setSessionCookie } from "../../cookies";
|
||||
import { BetterAuthError } from "../../error";
|
||||
import { generateId } from "../../utils/id";
|
||||
import { env } from "std-env";
|
||||
import { env } from "../../utils/env";
|
||||
|
||||
interface WebAuthnChallengeValue {
|
||||
expectedChallenge: string;
|
||||
|
||||
57
packages/better-auth/src/utils/env.ts
Normal file
57
packages/better-auth/src/utils/env.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
//https://github.com/unjs/std-env/blob/main/src/env.ts
|
||||
|
||||
const _envShim = Object.create(null);
|
||||
|
||||
export type EnvObject = Record<string, string | undefined>;
|
||||
|
||||
const _getEnv = (useShim?: boolean) =>
|
||||
globalThis.process?.env ||
|
||||
//@ts-expect-error
|
||||
globalThis.Deno?.env.toObject() ||
|
||||
//@ts-expect-error
|
||||
globalThis.__env__ ||
|
||||
(useShim ? _envShim : globalThis);
|
||||
|
||||
export const env = new Proxy<EnvObject>(_envShim, {
|
||||
get(_, prop) {
|
||||
const env = _getEnv();
|
||||
return env[prop as any] ?? _envShim[prop];
|
||||
},
|
||||
has(_, prop) {
|
||||
const env = _getEnv();
|
||||
return prop in env || prop in _envShim;
|
||||
},
|
||||
set(_, prop, value) {
|
||||
const env = _getEnv(true);
|
||||
env[prop as any] = value;
|
||||
return true;
|
||||
},
|
||||
deleteProperty(_, prop) {
|
||||
if (!prop) {
|
||||
return false;
|
||||
}
|
||||
const env = _getEnv(true);
|
||||
delete env[prop as any];
|
||||
return true;
|
||||
},
|
||||
ownKeys() {
|
||||
const env = _getEnv(true);
|
||||
return Object.keys(env);
|
||||
},
|
||||
});
|
||||
|
||||
function toBoolean(val: boolean | string | undefined) {
|
||||
return val ? val !== "false" : false;
|
||||
}
|
||||
|
||||
export const nodeENV =
|
||||
(typeof process !== "undefined" && process.env && process.env.NODE_ENV) || "";
|
||||
|
||||
/** Detect if `NODE_ENV` environment variable is `production` */
|
||||
export const isProduction = nodeENV === "production";
|
||||
|
||||
/** Detect if `NODE_ENV` environment variable is `dev` or `development` */
|
||||
export const isDevelopment = nodeENV === "dev" || nodeENV === "development";
|
||||
|
||||
/** Detect if `NODE_ENV` environment variable is `test` */
|
||||
export const isTest = nodeENV === "test" || toBoolean(env.TEST);
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isTest } from "std-env";
|
||||
import { isTest } from "../utils/env";
|
||||
|
||||
export function getIp(req: Request | Headers): string | null {
|
||||
const testIP = "127.0.0.1";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// import { env } from "std-env";
|
||||
import { env } from "../utils/env";
|
||||
import { BetterAuthError } from "../error";
|
||||
|
||||
function checkHasPath(url: string): boolean {
|
||||
@@ -20,7 +20,6 @@ function withPath(url: string, path = "/api/auth") {
|
||||
path = path.startsWith("/") ? path : `/${path}`;
|
||||
return `${url}${path}`;
|
||||
}
|
||||
const env = process.env;
|
||||
|
||||
export function getBaseURL(url?: string, path?: string) {
|
||||
if (url) {
|
||||
|
||||
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -1617,9 +1617,6 @@ importers:
|
||||
oslo:
|
||||
specifier: ^1.2.1
|
||||
version: 1.2.1
|
||||
std-env:
|
||||
specifier: ^3.7.0
|
||||
version: 3.7.0
|
||||
uncrypto:
|
||||
specifier: ^0.1.3
|
||||
version: 0.1.3
|
||||
@@ -1651,9 +1648,12 @@ importers:
|
||||
drizzle-orm:
|
||||
specifier: ^0.33.0
|
||||
version: 0.33.0(@cloudflare/workers-types@4.20241011.0)(@libsql/client@0.12.0)(@prisma/client@5.20.0(prisma@5.20.0))(@types/better-sqlite3@7.6.11)(@types/pg@8.11.10)(@types/react@18.3.9)(better-sqlite3@11.3.0)(bun-types@1.1.32)(kysely@0.27.4)(mysql2@3.11.3)(pg@8.13.0)(postgres@3.4.4)(prisma@5.20.0)(react@18.3.1)
|
||||
expo-constants:
|
||||
specifier: ~16.0.2
|
||||
version: 16.0.2(expo@51.0.38(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13))
|
||||
expo-linking:
|
||||
specifier: ~6.3.1
|
||||
version: 6.3.1(expo@51.0.38(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13))
|
||||
expo-secure-store:
|
||||
specifier: ~13.0.2
|
||||
version: 13.0.2(expo@51.0.38(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13))
|
||||
expo-web-browser:
|
||||
specifier: ~13.0.3
|
||||
version: 13.0.3(expo@51.0.38(@babel/core@7.26.0)(@babel/preset-env@7.26.0(@babel/core@7.26.0))(encoding@0.1.13))
|
||||
|
||||
Reference in New Issue
Block a user