@reliverse/rse
Version:
@reliverse/rse is your all-in-one companion for bootstrapping and improving any kind of projects (especially web apps built with frameworks like Next.js) — whether you're kicking off something new or upgrading an existing app. It is also a little AI-power
174 lines (173 loc) • 6.24 kB
JavaScript
import babelPresetReact from "@babel/preset-react";
import babelPresetTypeScript from "@babel/preset-typescript";
import { pathExists } from "@reliverse/relifso";
import { logger } from "better-auth";
import { BetterAuthError } from "better-auth";
import { loadConfig } from "c12";
import path from "path";
import { addSvelteKitEnvModules } from "./add-svelte-kit-env-modules.js";
import { getTsconfigInfo } from "./get-tsconfig-info.js";
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}`)
];
async function getPathAliases(cwd) {
const tsConfigPath = path.join(cwd, "tsconfig.json");
if (!await pathExists(tsConfigPath)) {
return null;
}
try {
const tsConfig = await getTsconfigInfo(cwd);
const { paths = {}, baseUrl = "." } = tsConfig.compilerOptions || {};
const result = {};
const obj = Object.entries(paths);
for (const [alias, aliasPaths] of obj) {
for (const aliasedPath of aliasPaths) {
const resolvedBaseUrl = path.join(cwd, baseUrl);
const finalAlias = alias.endsWith("*") ? alias.slice(0, -1) : alias;
const finalAliasedPath = aliasedPath.endsWith("*") ? 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");
}
}
const jitiOptions = async (cwd) => {
const alias = await 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
}) {
try {
let configFile = null;
if (configPath) {
let resolvedPath = path.join(cwd, configPath);
if (await pathExists(configPath)) resolvedPath = configPath;
const { config } = await loadConfig({
configFile: resolvedPath,
dotenv: true,
jitiOptions: await 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({
configFile: possiblePath,
jitiOptions: await 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 };