UNPKG

@proofkit/better-auth

Version:

FileMaker adapter for Better Auth

221 lines (213 loc) 7.14 kB
import { loadConfig } from "c12"; import type { BetterAuthOptions } from "better-auth"; import { logger } from "better-auth"; import path from "path"; // @ts-expect-error not typed import babelPresetTypeScript from "@babel/preset-typescript"; // @ts-expect-error not typed import babelPresetReact from "@babel/preset-react"; import fs, { existsSync } from "fs"; import { BetterAuthError } from "better-auth"; import { addSvelteKitEnvModules } from "./add-svelte-kit-env-modules"; import { getTsconfigInfo } from "./get-tsconfig-info"; let possiblePaths = [ "auth.ts", "auth.tsx", "auth.js", "auth.jsx", "auth.server.js", "auth.server.ts", ]; possiblePaths = [ ...possiblePaths, ...possiblePaths.map((it) => `lib/server/${it}`), ...possiblePaths.map((it) => `server/${it}`), ...possiblePaths.map((it) => `lib/${it}`), ...possiblePaths.map((it) => `utils/${it}`), ]; possiblePaths = [ ...possiblePaths, ...possiblePaths.map((it) => `src/${it}`), ...possiblePaths.map((it) => `app/${it}`), ]; function getPathAliases(cwd: string): Record<string, string> | null { const tsConfigPath = path.join(cwd, "tsconfig.json"); if (!fs.existsSync(tsConfigPath)) { return null; } try { const tsConfig = getTsconfigInfo(cwd); const { paths = {}, baseUrl = "." } = tsConfig.compilerOptions || {}; const result: Record<string, string> = {}; const obj = Object.entries(paths) as [string, string[]][]; for (const [alias, aliasPaths] of obj) { for (const aliasedPath of aliasPaths) { const resolvedBaseUrl = path.join(cwd, baseUrl); const finalAlias = alias.slice(-1) === "*" ? alias.slice(0, -1) : alias; const finalAliasedPath = aliasedPath.slice(-1) === "*" ? aliasedPath.slice(0, -1) : aliasedPath; result[finalAlias || ""] = path.join(resolvedBaseUrl, finalAliasedPath); } } addSvelteKitEnvModules(result); return result; } catch (error) { console.error(error); throw new BetterAuthError("Error parsing tsconfig.json"); } } /** * .tsx files are not supported by Jiti. */ const jitiOptions = (cwd: string) => { const alias = getPathAliases(cwd) || {}; return { transformOptions: { babel: { presets: [ [ babelPresetTypeScript, { isTSX: true, allExtensions: true, }, ], [babelPresetReact, { runtime: "automatic" }], ], }, }, extensions: [".ts", ".tsx", ".js", ".jsx"], alias, }; }; export async function getConfig({ cwd, configPath, shouldThrowOnError = false, }: { cwd: string; configPath?: string; shouldThrowOnError?: boolean; }) { try { let configFile: BetterAuthOptions | null = null; if (configPath) { let resolvedPath: string = path.join(cwd, configPath); if (existsSync(configPath)) resolvedPath = configPath; // If the configPath is a file, use it as is, as it means the path wasn't relative. const { config } = await loadConfig<{ auth: { options: BetterAuthOptions; }; default?: { options: BetterAuthOptions; }; }>({ configFile: resolvedPath, dotenv: true, jitiOptions: jitiOptions(cwd), }); if (!config.auth && !config.default) { if (shouldThrowOnError) { throw new Error( `Couldn't read your auth config in ${resolvedPath}. Make sure to default export your auth instance or to export as a variable named auth.`, ); } logger.error( `[#better-auth]: Couldn't read your auth config in ${resolvedPath}. Make sure to default export your auth instance or to export as a variable named auth.`, ); process.exit(1); } configFile = config.auth?.options || config.default?.options || null; } if (!configFile) { for (const possiblePath of possiblePaths) { try { const { config } = await loadConfig<{ auth: { options: BetterAuthOptions; }; default?: { options: BetterAuthOptions; }; }>({ configFile: possiblePath, jitiOptions: jitiOptions(cwd), }); const hasConfig = Object.keys(config).length > 0; if (hasConfig) { configFile = config.auth?.options || config.default?.options || null; if (!configFile) { if (shouldThrowOnError) { throw new Error( "Couldn't read your auth config. Make sure to default export your auth instance or to export as a variable named auth.", ); } logger.error("[#better-auth]: Couldn't read your auth config."); console.log(""); logger.info( "[#better-auth]: Make sure to default export your auth instance or to export as a variable named auth.", ); process.exit(1); } break; } } catch (e) { if ( typeof e === "object" && e && "message" in e && typeof e.message === "string" && e.message.includes( "This module cannot be imported from a Client Component module", ) ) { if (shouldThrowOnError) { throw new Error( `Please remove import 'server-only' from your auth config file temporarily. The CLI cannot resolve the configuration with it included. You can re-add it after running the CLI.`, ); } logger.error( `Please remove import 'server-only' from your auth config file temporarily. The CLI cannot resolve the configuration with it included. You can re-add it after running the CLI.`, ); process.exit(1); } if (shouldThrowOnError) { throw e; } logger.error("[#better-auth]: Couldn't read your auth config.", e); process.exit(1); } } } return configFile; } catch (e) { if ( typeof e === "object" && e && "message" in e && typeof e.message === "string" && e.message.includes( "This module cannot be imported from a Client Component module", ) ) { if (shouldThrowOnError) { throw new Error( `Please remove import 'server-only' from your auth config file temporarily. The CLI cannot resolve the configuration with it included. You can re-add it after running the CLI.`, ); } logger.error( `Please remove import 'server-only' from your auth config file temporarily. The CLI cannot resolve the configuration with it included. You can re-add it after running the CLI.`, ); process.exit(1); } if (shouldThrowOnError) { throw e; } logger.error("Couldn't read your auth config.", e); process.exit(1); } } export { possiblePaths };