better-auth-studio 1.0.20-beta.9 → 1.0.21
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/dist/add-svelte-kit-env-modules.d.ts +2 -0
- package/dist/add-svelte-kit-env-modules.d.ts.map +1 -0
- package/dist/add-svelte-kit-env-modules.js +8 -0
- package/dist/add-svelte-kit-env-modules.js.map +1 -0
- package/dist/auth-adapter.js +2 -2
- package/dist/auth-adapter.js.map +1 -1
- package/dist/config.d.ts +9 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +230 -620
- package/dist/config.js.map +1 -1
- package/dist/data.js +2 -2
- package/dist/data.js.map +1 -1
- package/dist/get-tsconfig-info.d.ts +13 -0
- package/dist/get-tsconfig-info.d.ts.map +1 -0
- package/dist/get-tsconfig-info.js +17 -0
- package/dist/get-tsconfig-info.js.map +1 -0
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +12 -1
- package/dist/routes.js.map +1 -1
- package/package.json +4 -1
- package/public/assets/{main-Dy9SWsHh.js → main-CfQsAV2A.js} +84 -53
- package/public/assets/main-D5tWCeX4.css +1 -0
- package/public/index.html +2 -2
- package/public/assets/main-x1I77urX.css +0 -1
package/dist/config.js
CHANGED
|
@@ -1,666 +1,276 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
1
|
+
// @ts-expect-error
|
|
2
|
+
import babelPresetReact from '@babel/preset-react';
|
|
3
|
+
// @ts-expect-error
|
|
4
|
+
import babelPresetTypeScript from '@babel/preset-typescript';
|
|
5
|
+
import { BetterAuthError, logger } from 'better-auth';
|
|
6
|
+
import { loadConfig } from 'c12';
|
|
7
|
+
import fs, { existsSync } from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import { addSvelteKitEnvModules } from './add-svelte-kit-env-modules.js';
|
|
10
|
+
import { getTsconfigInfo } from './get-tsconfig-info.js';
|
|
11
|
+
let possiblePaths = [
|
|
12
|
+
'auth.ts',
|
|
13
|
+
'auth.tsx',
|
|
14
|
+
'auth.js',
|
|
15
|
+
'auth.jsx',
|
|
16
|
+
'auth.server.js',
|
|
17
|
+
'auth.server.ts',
|
|
18
|
+
];
|
|
19
|
+
possiblePaths = [
|
|
20
|
+
...possiblePaths,
|
|
21
|
+
...possiblePaths.map((it) => `lib/server/${it}`),
|
|
22
|
+
...possiblePaths.map((it) => `server/${it}`),
|
|
23
|
+
...possiblePaths.map((it) => `lib/${it}`),
|
|
24
|
+
...possiblePaths.map((it) => `utils/${it}`),
|
|
25
|
+
];
|
|
26
|
+
possiblePaths = [
|
|
27
|
+
...possiblePaths,
|
|
28
|
+
...possiblePaths.map((it) => `src/${it}`),
|
|
29
|
+
...possiblePaths.map((it) => `app/${it}`),
|
|
30
|
+
];
|
|
31
|
+
function resolveReferencePath(configDir, refPath) {
|
|
32
|
+
const resolvedPath = path.resolve(configDir, refPath);
|
|
33
|
+
// If it ends with .json, treat as direct file reference
|
|
34
|
+
if (refPath.endsWith('.json')) {
|
|
35
|
+
return resolvedPath;
|
|
8
36
|
}
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
37
|
+
// If the exact path exists and is a file, use it
|
|
38
|
+
if (fs.existsSync(resolvedPath)) {
|
|
39
|
+
try {
|
|
40
|
+
const stats = fs.statSync(resolvedPath);
|
|
41
|
+
if (stats.isFile()) {
|
|
42
|
+
return resolvedPath;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
// Fall through to directory handling
|
|
16
47
|
}
|
|
17
48
|
}
|
|
18
|
-
|
|
49
|
+
// Otherwise, assume directory reference
|
|
50
|
+
return path.resolve(configDir, refPath, 'tsconfig.json');
|
|
19
51
|
}
|
|
20
|
-
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const config = await loadConfig(resolvedPath);
|
|
42
|
-
if (config) {
|
|
43
|
-
return config;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
catch (error) {
|
|
47
|
-
console.warn(`Failed to load config from ${resolvedPath}:`, error);
|
|
52
|
+
function getPathAliasesRecursive(tsconfigPath, visited = new Set()) {
|
|
53
|
+
if (visited.has(tsconfigPath)) {
|
|
54
|
+
return {};
|
|
55
|
+
}
|
|
56
|
+
visited.add(tsconfigPath);
|
|
57
|
+
if (!fs.existsSync(tsconfigPath)) {
|
|
58
|
+
logger.warn(`Referenced tsconfig not found: ${tsconfigPath}`);
|
|
59
|
+
return {};
|
|
60
|
+
}
|
|
61
|
+
try {
|
|
62
|
+
const tsConfig = getTsconfigInfo(undefined, tsconfigPath);
|
|
63
|
+
const { paths = {}, baseUrl = '.' } = tsConfig.compilerOptions || {};
|
|
64
|
+
const result = {};
|
|
65
|
+
const configDir = path.dirname(tsconfigPath);
|
|
66
|
+
const obj = Object.entries(paths);
|
|
67
|
+
for (const [alias, aliasPaths] of obj) {
|
|
68
|
+
for (const aliasedPath of aliasPaths) {
|
|
69
|
+
const resolvedBaseUrl = path.resolve(configDir, baseUrl);
|
|
70
|
+
const finalAlias = alias.slice(-1) === '*' ? alias.slice(0, -1) : alias;
|
|
71
|
+
const finalAliasedPath = aliasedPath.slice(-1) === '*' ? aliasedPath.slice(0, -1) : aliasedPath;
|
|
72
|
+
result[finalAlias || ''] = path.join(resolvedBaseUrl, finalAliasedPath);
|
|
48
73
|
}
|
|
49
74
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
join(cwd, 'packages', 'backend', 'src', 'auth.ts'),
|
|
58
|
-
join(cwd, 'packages', 'backend', 'auth.ts'),
|
|
59
|
-
join(cwd, 'src', 'auth.ts'),
|
|
60
|
-
join(cwd, 'auth.ts'),
|
|
61
|
-
];
|
|
62
|
-
for (const path of commonPaths) {
|
|
63
|
-
if (existsSync(path)) {
|
|
64
|
-
console.log(`Found config file at: ${path}`);
|
|
65
|
-
try {
|
|
66
|
-
const config = await loadConfig(path);
|
|
67
|
-
if (config) {
|
|
68
|
-
return config;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
catch (error) {
|
|
72
|
-
console.warn(`Failed to load config from ${path}:`, error);
|
|
75
|
+
if (tsConfig.references) {
|
|
76
|
+
for (const ref of tsConfig.references) {
|
|
77
|
+
const refPath = resolveReferencePath(configDir, ref.path);
|
|
78
|
+
const refAliases = getPathAliasesRecursive(refPath, visited);
|
|
79
|
+
for (const [alias, aliasPath] of Object.entries(refAliases)) {
|
|
80
|
+
if (!(alias in result)) {
|
|
81
|
+
result[alias] = aliasPath;
|
|
73
82
|
}
|
|
74
83
|
}
|
|
75
84
|
}
|
|
76
85
|
}
|
|
77
|
-
return
|
|
86
|
+
return result;
|
|
78
87
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
'auth.js',
|
|
83
|
-
'src/auth.ts',
|
|
84
|
-
'src/auth.js',
|
|
85
|
-
'lib/auth.ts',
|
|
86
|
-
'lib/auth.js',
|
|
87
|
-
'better-auth.config.ts',
|
|
88
|
-
'better-auth.config.js',
|
|
89
|
-
'better-auth.config.json',
|
|
90
|
-
'auth.config.ts',
|
|
91
|
-
'auth.config.js',
|
|
92
|
-
'auth.config.json',
|
|
93
|
-
];
|
|
94
|
-
let currentDir = process.cwd();
|
|
95
|
-
const maxDepth = 10;
|
|
96
|
-
let depth = 0;
|
|
97
|
-
while (currentDir && depth < maxDepth) {
|
|
98
|
-
for (const configFile of possibleConfigFiles) {
|
|
99
|
-
const configPath = join(currentDir, configFile);
|
|
100
|
-
if (existsSync(configPath)) {
|
|
101
|
-
try {
|
|
102
|
-
const config = await loadConfig(configPath);
|
|
103
|
-
if (config) {
|
|
104
|
-
return config;
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
catch (error) {
|
|
108
|
-
console.warn(`Failed to load config from ${configPath}:`, error);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
const parentDir = dirname(currentDir);
|
|
113
|
-
if (parentDir === currentDir) {
|
|
114
|
-
break;
|
|
115
|
-
}
|
|
116
|
-
currentDir = parentDir;
|
|
117
|
-
depth++;
|
|
88
|
+
catch (error) {
|
|
89
|
+
logger.warn(`Error parsing tsconfig at ${tsconfigPath}: ${error}`);
|
|
90
|
+
return {};
|
|
118
91
|
}
|
|
119
|
-
return null;
|
|
120
92
|
}
|
|
121
|
-
|
|
122
|
-
const
|
|
93
|
+
function getPathAliases(cwd) {
|
|
94
|
+
const tsConfigPath = path.join(cwd, 'tsconfig.json');
|
|
95
|
+
if (!fs.existsSync(tsConfigPath)) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
123
98
|
try {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
else if (ext === 'js' || ext === 'ts') {
|
|
129
|
-
return await loadTypeScriptConfig(configPath);
|
|
130
|
-
}
|
|
99
|
+
const result = getPathAliasesRecursive(tsConfigPath);
|
|
100
|
+
addSvelteKitEnvModules(result);
|
|
101
|
+
return result;
|
|
131
102
|
}
|
|
132
103
|
catch (error) {
|
|
133
|
-
console.
|
|
104
|
+
console.error(error);
|
|
105
|
+
throw new BetterAuthError('Error parsing tsconfig.json');
|
|
134
106
|
}
|
|
135
|
-
return null;
|
|
136
107
|
}
|
|
137
|
-
|
|
108
|
+
/**
|
|
109
|
+
* .tsx files are not supported by Jiti.
|
|
110
|
+
*/
|
|
111
|
+
const jitiOptions = (cwd) => {
|
|
112
|
+
const alias = getPathAliases(cwd) || {};
|
|
113
|
+
return {
|
|
114
|
+
transformOptions: {
|
|
115
|
+
babel: {
|
|
116
|
+
presets: [
|
|
117
|
+
[
|
|
118
|
+
babelPresetTypeScript,
|
|
119
|
+
{
|
|
120
|
+
isTSX: true,
|
|
121
|
+
allExtensions: true,
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
[babelPresetReact, { runtime: 'automatic' }],
|
|
125
|
+
],
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
extensions: ['.ts', '.tsx', '.js', '.jsx'],
|
|
129
|
+
alias,
|
|
130
|
+
};
|
|
131
|
+
};
|
|
132
|
+
const isDefaultExport = (object) => {
|
|
133
|
+
return (typeof object === 'object' &&
|
|
134
|
+
object !== null &&
|
|
135
|
+
!Array.isArray(object) &&
|
|
136
|
+
Object.keys(object).length > 0 &&
|
|
137
|
+
'options' in object);
|
|
138
|
+
};
|
|
139
|
+
export async function getConfig({ cwd, configPath, shouldThrowOnError = false, }) {
|
|
138
140
|
try {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
foundImports.add(match[1]);
|
|
153
|
-
}
|
|
154
|
-
for (const importPath of foundImports) {
|
|
155
|
-
const importName = importPath.replace('./', '');
|
|
156
|
-
const possiblePaths = [
|
|
157
|
-
join(configDir, importName + '.ts'),
|
|
158
|
-
join(configDir, importName + '.js'),
|
|
159
|
-
join(configDir, importName + '.mjs'),
|
|
160
|
-
join(configDir, importName + '.cjs'),
|
|
161
|
-
join(configDir, importName, 'index.ts'),
|
|
162
|
-
join(configDir, importName, 'index.js'),
|
|
163
|
-
join(configDir, importName, 'index.mjs'),
|
|
164
|
-
join(configDir, importName, 'index.cjs'),
|
|
165
|
-
];
|
|
166
|
-
for (const path of possiblePaths) {
|
|
167
|
-
if (existsSync(path)) {
|
|
168
|
-
aliases[importPath] = pathToFileURL(path).href;
|
|
169
|
-
break;
|
|
170
|
-
}
|
|
171
|
-
}
|
|
141
|
+
let configFile = null;
|
|
142
|
+
if (configPath) {
|
|
143
|
+
let resolvedPath = path.join(cwd, configPath);
|
|
144
|
+
if (existsSync(configPath))
|
|
145
|
+
resolvedPath = configPath; // If the configPath is a file, use it as is, as it means the path wasn't relative.
|
|
146
|
+
const { config } = await loadConfig({
|
|
147
|
+
configFile: resolvedPath,
|
|
148
|
+
dotenv: true,
|
|
149
|
+
jitiOptions: jitiOptions(cwd),
|
|
150
|
+
});
|
|
151
|
+
if (!('auth' in config) && !isDefaultExport(config)) {
|
|
152
|
+
if (shouldThrowOnError) {
|
|
153
|
+
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.`);
|
|
172
154
|
}
|
|
155
|
+
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.`);
|
|
156
|
+
process.exit(1);
|
|
157
|
+
}
|
|
158
|
+
configFile = 'auth' in config ? config.auth?.options : config.options;
|
|
159
|
+
}
|
|
160
|
+
if (!configFile) {
|
|
161
|
+
for (const possiblePath of possiblePaths) {
|
|
173
162
|
try {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
console.log({ importPath });
|
|
179
|
-
const jitiInstance = createJiti(importPath, {
|
|
180
|
-
debug: true,
|
|
181
|
-
fsCache: true,
|
|
182
|
-
moduleCache: true,
|
|
183
|
-
interopDefault: true,
|
|
163
|
+
const { config } = await loadConfig({
|
|
164
|
+
configFile: possiblePath,
|
|
165
|
+
jitiOptions: jitiOptions(cwd),
|
|
184
166
|
});
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
if (auth.$context) {
|
|
192
|
-
console.log('Found auth.$context, attempting to await...');
|
|
193
|
-
const context = await auth.$context;
|
|
194
|
-
const options = context.options;
|
|
195
|
-
console.log({ context });
|
|
196
|
-
if (!options) {
|
|
197
|
-
console.warn('No options found in auth context');
|
|
198
|
-
return null;
|
|
199
|
-
}
|
|
200
|
-
const config = {
|
|
201
|
-
database: {
|
|
202
|
-
type: options.database ? 'drizzle' : 'unknown',
|
|
203
|
-
adapter: 'drizzle-adapter',
|
|
204
|
-
...options.database,
|
|
205
|
-
},
|
|
206
|
-
emailAndPassword: {
|
|
207
|
-
enabled: options.emailAndPassword?.enabled || false,
|
|
208
|
-
...options.emailAndPassword,
|
|
209
|
-
},
|
|
210
|
-
socialProviders: options.socialProviders
|
|
211
|
-
? Object.keys(options.socialProviders).map((provider) => ({
|
|
212
|
-
id: provider,
|
|
213
|
-
name: provider,
|
|
214
|
-
enabled: true,
|
|
215
|
-
}))
|
|
216
|
-
: [],
|
|
217
|
-
trustedOrigins: options.trustedOrigins || ['http://localhost:3000'],
|
|
218
|
-
advanced: {
|
|
219
|
-
defaultCookieAttributes: options.advanced?.defaultCookieAttributes || {
|
|
220
|
-
sameSite: 'none',
|
|
221
|
-
secure: true,
|
|
222
|
-
httpOnly: true,
|
|
223
|
-
},
|
|
224
|
-
...options.advanced,
|
|
225
|
-
},
|
|
226
|
-
};
|
|
227
|
-
console.log('Returning config from auth.$context:', config);
|
|
228
|
-
return config;
|
|
167
|
+
const hasConfig = Object.keys(config).length > 0;
|
|
168
|
+
if (hasConfig) {
|
|
169
|
+
configFile = config.auth?.options || config.default?.options || null;
|
|
170
|
+
if (!configFile) {
|
|
171
|
+
if (shouldThrowOnError) {
|
|
172
|
+
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.");
|
|
229
173
|
}
|
|
174
|
+
logger.error("[#better-auth]: Couldn't read your auth config.");
|
|
175
|
+
console.log('');
|
|
176
|
+
logger.info('[#better-auth]: Make sure to default export your auth instance or to export as a variable named auth.');
|
|
177
|
+
process.exit(1);
|
|
230
178
|
}
|
|
231
|
-
|
|
232
|
-
console.warn('Failed to await auth.$context:', contextError.message);
|
|
233
|
-
}
|
|
179
|
+
break;
|
|
234
180
|
}
|
|
235
181
|
}
|
|
236
|
-
catch (
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
emailAndPassword: {
|
|
245
|
-
enabled: true,
|
|
246
|
-
},
|
|
247
|
-
trustedOrigins: ['http://localhost:3000'],
|
|
248
|
-
advanced: {
|
|
249
|
-
defaultCookieAttributes: {
|
|
250
|
-
sameSite: 'none',
|
|
251
|
-
secure: true,
|
|
252
|
-
httpOnly: true,
|
|
253
|
-
},
|
|
254
|
-
},
|
|
255
|
-
};
|
|
256
|
-
return config;
|
|
257
|
-
}
|
|
258
|
-
catch (importError) {
|
|
259
|
-
console.warn(`Failed to import auth config from ${configPath}:`, importError.message);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
const content = readFileSync(configPath, 'utf-8');
|
|
263
|
-
const authConfig = extractBetterAuthConfig(content);
|
|
264
|
-
if (authConfig) {
|
|
265
|
-
return authConfig;
|
|
266
|
-
}
|
|
267
|
-
if (configPath.endsWith('.js')) {
|
|
268
|
-
return await evaluateJSConfig(configPath);
|
|
269
|
-
}
|
|
270
|
-
return null;
|
|
271
|
-
}
|
|
272
|
-
catch (error) {
|
|
273
|
-
console.warn(`Error loading TypeScript config from ${configPath}:`, error);
|
|
274
|
-
return null;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
function detectDatabaseAdapter(content) {
|
|
278
|
-
const database = {};
|
|
279
|
-
if (content.includes('drizzleAdapter')) {
|
|
280
|
-
database.adapter = 'drizzle';
|
|
281
|
-
const providerMatch = content.match(/drizzleAdapter\s*\(\s*\w+\s*,\s*\{[^}]*provider\s*:\s*["']([^"']+)["'][^}]*\}/);
|
|
282
|
-
if (providerMatch) {
|
|
283
|
-
const provider = providerMatch[1];
|
|
284
|
-
database.provider = provider;
|
|
285
|
-
database.type = provider === 'pg' ? 'postgresql' : provider;
|
|
286
|
-
}
|
|
287
|
-
else {
|
|
288
|
-
database.provider = 'postgresql';
|
|
289
|
-
database.type = 'postgresql';
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
else if (content.includes('prismaAdapter')) {
|
|
293
|
-
database.adapter = 'prisma';
|
|
294
|
-
const providerMatch = content.match(/prismaAdapter\s*\(\s*\w+\s*,\s*\{[^}]*provider\s*:\s*["']([^"']+)["'][^}]*\}/);
|
|
295
|
-
if (providerMatch) {
|
|
296
|
-
database.provider = providerMatch[1];
|
|
297
|
-
database.type = providerMatch[1];
|
|
298
|
-
}
|
|
299
|
-
else {
|
|
300
|
-
database.provider = 'postgresql';
|
|
301
|
-
database.type = 'postgresql';
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
else if (content.includes('better-sqlite3') || content.includes('new Database(')) {
|
|
305
|
-
database.adapter = 'sqlite';
|
|
306
|
-
database.type = 'sqlite';
|
|
307
|
-
database.provider = 'sqlite';
|
|
308
|
-
const dbPathMatch = content.match(/new\s+Database\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
309
|
-
if (dbPathMatch) {
|
|
310
|
-
database.name = dbPathMatch[1];
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
const urlMatch = content.match(/DATABASE_URL|DB_URL|DB_CONNECTION_STRING/);
|
|
314
|
-
if (urlMatch) {
|
|
315
|
-
database.url = `process.env.${urlMatch[0]}`;
|
|
316
|
-
}
|
|
317
|
-
return database;
|
|
318
|
-
}
|
|
319
|
-
function cleanConfigString(configStr) {
|
|
320
|
-
let cleaned = configStr;
|
|
321
|
-
cleaned = cleaned.replace(/:\s*prismaAdapter\s*\(\s*\w+\s*,\s*\{[^}]*\}\s*\)/g, ':"prisma-adapter"');
|
|
322
|
-
cleaned = cleaned.replace(/:\s*prismaAdapter\s*\(\s*\w+\s*\)/g, ':"prisma-adapter"');
|
|
323
|
-
cleaned = cleaned.replace(/:\s*drizzleAdapter\s*\(\s*\w+\s*,\s*\{[^}]*\}\s*\)/g, ':"drizzle-adapter"');
|
|
324
|
-
cleaned = cleaned.replace(/:\s*drizzleAdapter\s*\(\s*\w+\s*\)/g, ':"drizzle-adapter"');
|
|
325
|
-
cleaned = cleaned.replace(/:\s*betterSqlite3\s*\(\s*[^)]*\)/g, ':"better-sqlite3"');
|
|
326
|
-
cleaned = cleaned.replace(/:\s*postgres\s*\(\s*[^)]*\)/g, ':"postgres"');
|
|
327
|
-
cleaned = cleaned.replace(/:\s*mysql2\s*\(\s*[^)]*\)/g, ':"mysql2"');
|
|
328
|
-
cleaned = cleaned.replace(/:\s*bun:sqlite\s*\(\s*[^)]*\)/g, ':"bun-sqlite"');
|
|
329
|
-
cleaned = cleaned.replace(/:\s*new\s+Database\s*\(\s*[^)]*\)/g, ':"sqlite-database"');
|
|
330
|
-
cleaned = cleaned.replace(/new\s+Database\s*\(\s*[^)]*\)/g, '"sqlite-database"');
|
|
331
|
-
cleaned = cleaned.replace(/:\s*(\w+)\s*\(\s*[^)]*\)/g, ':"$1-function"');
|
|
332
|
-
cleaned = cleaned.replace(/:\s*\[[^\]]*\]/g, ':"array"');
|
|
333
|
-
cleaned = cleaned.replace(/:\s*\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}/g, ':"object"');
|
|
334
|
-
cleaned = cleaned.replace(/:\s*process\.env\.(\w+)(\s*\|\|\s*"[^"]*")?/g, ':"$1"');
|
|
335
|
-
cleaned = cleaned.replace(/:\s*`([^`]*)`/g, ':"$1"');
|
|
336
|
-
cleaned = cleaned.replace(/:\s*"([^"]*)"/g, ':"$1"');
|
|
337
|
-
cleaned = cleaned.replace(/:\s*'([^']*)'/g, ':"$1"');
|
|
338
|
-
cleaned = cleaned.replace(/:\s*([a-zA-Z_][a-zA-Z0-9_]*)(?=\s*[,}])/g, ':"$1"');
|
|
339
|
-
cleaned = cleaned.replace(/([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, '"$1":');
|
|
340
|
-
cleaned = cleaned.replace(/,\s*}/g, '}');
|
|
341
|
-
cleaned = cleaned.replace(/,\s*]/g, ']');
|
|
342
|
-
cleaned = cleaned.replace(/\/\/.*$/gm, '');
|
|
343
|
-
cleaned = cleaned.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
344
|
-
cleaned = cleaned.replace(/\s+/g, ' ');
|
|
345
|
-
cleaned = cleaned.replace(/:\s*(\d+\.?\d*)/g, ':$1');
|
|
346
|
-
cleaned = cleaned.replace(/:\s*(true|false)/g, ':$1');
|
|
347
|
-
cleaned = cleaned.replace(/:\s*null/g, ':null');
|
|
348
|
-
return cleaned.trim();
|
|
349
|
-
}
|
|
350
|
-
export function extractBetterAuthConfig(content) {
|
|
351
|
-
const pluginsMatch = content.match(/plugins\s*:\s*(?:\[)?(\w+)(?:\])?/);
|
|
352
|
-
if (pluginsMatch) {
|
|
353
|
-
const pluginsVar = pluginsMatch[1];
|
|
354
|
-
const varMatch = content.match(new RegExp(`const\\s+${pluginsVar}\\s*=\\s*[^\\[]*\\[([^\\]]*)\\]`));
|
|
355
|
-
if (varMatch) {
|
|
356
|
-
const pluginsContent = varMatch[1];
|
|
357
|
-
const plugins = [];
|
|
358
|
-
const pluginMatches = pluginsContent.match(/(\w+)\(\)/g);
|
|
359
|
-
if (pluginMatches) {
|
|
360
|
-
for (const pluginMatch of pluginMatches) {
|
|
361
|
-
const pluginName = pluginMatch.replace(/\(\)/, '');
|
|
362
|
-
const plugin = {
|
|
363
|
-
id: pluginName,
|
|
364
|
-
name: pluginName,
|
|
365
|
-
version: 'unknown',
|
|
366
|
-
description: `${pluginName} plugin for Better Auth`,
|
|
367
|
-
enabled: true,
|
|
368
|
-
};
|
|
369
|
-
if (pluginName === 'organization') {
|
|
370
|
-
const orgConfigMatch = content.match(/organization\s*\(\s*\{[^}]*teams[^}]*enabled[^}]*\}/);
|
|
371
|
-
if (orgConfigMatch) {
|
|
372
|
-
plugin.teams = { enabled: true };
|
|
182
|
+
catch (e) {
|
|
183
|
+
if (typeof e === 'object' &&
|
|
184
|
+
e &&
|
|
185
|
+
'message' in e &&
|
|
186
|
+
typeof e.message === 'string' &&
|
|
187
|
+
e.message.includes('This module cannot be imported from a Client Component module')) {
|
|
188
|
+
if (shouldThrowOnError) {
|
|
189
|
+
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.`);
|
|
373
190
|
}
|
|
191
|
+
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.`);
|
|
192
|
+
process.exit(1);
|
|
374
193
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
}
|
|
378
|
-
if (plugins.length > 0) {
|
|
379
|
-
const database = detectDatabaseAdapter(content);
|
|
380
|
-
return {
|
|
381
|
-
plugins: plugins,
|
|
382
|
-
baseURL: 'http://localhost:3000',
|
|
383
|
-
database: database,
|
|
384
|
-
};
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
const directPluginsMatch = content.match(/plugins\s*:\s*\[([^\]]*)\]/);
|
|
389
|
-
if (directPluginsMatch) {
|
|
390
|
-
const pluginsContent = directPluginsMatch[1];
|
|
391
|
-
const plugins = [];
|
|
392
|
-
const pluginMatches = pluginsContent.match(/(\w+)\(\)/g);
|
|
393
|
-
if (pluginMatches) {
|
|
394
|
-
for (const pluginMatch of pluginMatches) {
|
|
395
|
-
const pluginName = pluginMatch.replace(/\(\)/, '');
|
|
396
|
-
const plugin = {
|
|
397
|
-
id: pluginName,
|
|
398
|
-
name: pluginName,
|
|
399
|
-
version: 'unknown',
|
|
400
|
-
description: `${pluginName} plugin for Better Auth`,
|
|
401
|
-
enabled: true,
|
|
402
|
-
};
|
|
403
|
-
if (pluginName === 'organization') {
|
|
404
|
-
const orgConfigMatch = content.match(/organization\s*\(\s*\{[^}]*teams[^}]*enabled[^}]*\}/);
|
|
405
|
-
if (orgConfigMatch) {
|
|
406
|
-
plugin.teams = { enabled: true };
|
|
194
|
+
if (shouldThrowOnError) {
|
|
195
|
+
throw e;
|
|
407
196
|
}
|
|
197
|
+
logger.error("[#better-auth]: Couldn't read your auth config.", e);
|
|
198
|
+
process.exit(1);
|
|
408
199
|
}
|
|
409
|
-
plugins.push(plugin);
|
|
410
200
|
}
|
|
411
201
|
}
|
|
412
|
-
|
|
413
|
-
const database = detectDatabaseAdapter(content);
|
|
414
|
-
return {
|
|
415
|
-
plugins: plugins,
|
|
416
|
-
baseURL: 'http://localhost:3000',
|
|
417
|
-
database: database,
|
|
418
|
-
};
|
|
419
|
-
}
|
|
202
|
+
return configFile;
|
|
420
203
|
}
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
/module\.exports\s*=\s*BetterAuth\s*\(\s*({[^{}]*(?:{[^{}]*}[^{}]*)*})\s*\)/,
|
|
430
|
-
/betterAuth\s*\(\s*({[^{}]*(?:{[^{}]*}[^{}]*)*})\s*\)/,
|
|
431
|
-
/BetterAuth\s*\(\s*({[^{}]*(?:{[^{}]*}[^{}]*)*})\s*\)/,
|
|
432
|
-
/betterAuth\s*\(\s*({[\s\S]*?})\s*\)/,
|
|
433
|
-
/BetterAuth\s*\(\s*({[\s\S]*?})\s*\)/,
|
|
434
|
-
/betterAuth\s*\(\s*({[^{}]*baseURL[^{}]*database[^{}]*})\s*\)/,
|
|
435
|
-
/BetterAuth\s*\(\s*({[^{}]*baseURL[^{}]*database[^{}]*})\s*\)/,
|
|
436
|
-
];
|
|
437
|
-
for (let i = 0; i < patterns.length; i++) {
|
|
438
|
-
const pattern = patterns[i];
|
|
439
|
-
const match = content.match(pattern);
|
|
440
|
-
if (match) {
|
|
441
|
-
try {
|
|
442
|
-
let configStr = match[1];
|
|
443
|
-
configStr = configStr
|
|
444
|
-
.replace(/(\d+\s*\*\s*\d+\s*\*\s*\d+\s*\*\s*\d+)/g, (match) => {
|
|
445
|
-
try {
|
|
446
|
-
return eval(match).toString();
|
|
447
|
-
}
|
|
448
|
-
catch {
|
|
449
|
-
return match;
|
|
450
|
-
}
|
|
451
|
-
})
|
|
452
|
-
.replace(/(\d+\s*\*\s*\d+\s*\*\s*\d+)/g, (match) => {
|
|
453
|
-
try {
|
|
454
|
-
return eval(match).toString();
|
|
455
|
-
}
|
|
456
|
-
catch {
|
|
457
|
-
return match;
|
|
458
|
-
}
|
|
459
|
-
})
|
|
460
|
-
.replace(/(\d+\s*\*\s*\d+)/g, (match) => {
|
|
461
|
-
try {
|
|
462
|
-
return eval(match).toString();
|
|
463
|
-
}
|
|
464
|
-
catch {
|
|
465
|
-
return match;
|
|
466
|
-
}
|
|
467
|
-
});
|
|
468
|
-
configStr = cleanConfigString(configStr);
|
|
469
|
-
let config;
|
|
470
|
-
try {
|
|
471
|
-
config = JSON.parse(configStr);
|
|
472
|
-
}
|
|
473
|
-
catch (error) {
|
|
474
|
-
console.warn(`Failed to parse config: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
475
|
-
console.warn('Config string that failed:', configStr.substring(0, 200) + '...');
|
|
476
|
-
return null;
|
|
477
|
-
}
|
|
478
|
-
const authConfig = extractBetterAuthFields(config);
|
|
479
|
-
if (authConfig) {
|
|
480
|
-
const detectedDatabase = detectDatabaseAdapter(content);
|
|
481
|
-
if (detectedDatabase.adapter) {
|
|
482
|
-
authConfig.database = { ...authConfig.database, ...detectedDatabase };
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
return authConfig;
|
|
486
|
-
}
|
|
487
|
-
catch (error) {
|
|
488
|
-
console.warn(`Failed to parse config pattern: ${error instanceof Error ? error.message : 'Unknown error'}`);
|
|
204
|
+
catch (e) {
|
|
205
|
+
if (typeof e === 'object' &&
|
|
206
|
+
e &&
|
|
207
|
+
'message' in e &&
|
|
208
|
+
typeof e.message === 'string' &&
|
|
209
|
+
e.message.includes('This module cannot be imported from a Client Component module')) {
|
|
210
|
+
if (shouldThrowOnError) {
|
|
211
|
+
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.`);
|
|
489
212
|
}
|
|
213
|
+
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.`);
|
|
214
|
+
process.exit(1);
|
|
490
215
|
}
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
}
|
|
494
|
-
function extractBetterAuthFields(config) {
|
|
495
|
-
const authConfig = {};
|
|
496
|
-
if (config.database) {
|
|
497
|
-
let dbType = 'postgresql';
|
|
498
|
-
let dbName = config.database.name;
|
|
499
|
-
let adapter = 'unknown';
|
|
500
|
-
if (typeof config.database === 'function') {
|
|
501
|
-
if (config.database.options?.adapterId) {
|
|
502
|
-
adapter = config.database.options.adapterId;
|
|
503
|
-
if (config.database.options.provider) {
|
|
504
|
-
const provider = config.database.options.provider;
|
|
505
|
-
dbType = provider === 'pg' ? 'postgresql' : provider;
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
else if (config.database.options?.provider) {
|
|
509
|
-
const provider = config.database.options.provider;
|
|
510
|
-
if (provider === 'pg' || provider === 'mysql' || provider === 'sqlite') {
|
|
511
|
-
adapter = 'drizzle';
|
|
512
|
-
dbType = provider === 'pg' ? 'postgresql' : provider;
|
|
513
|
-
}
|
|
514
|
-
else {
|
|
515
|
-
adapter = 'prisma';
|
|
516
|
-
dbType = 'postgresql';
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
else if (config.database.provider) {
|
|
520
|
-
const provider = config.database.provider;
|
|
521
|
-
if (provider === 'pg' || provider === 'mysql' || provider === 'sqlite') {
|
|
522
|
-
adapter = 'drizzle';
|
|
523
|
-
dbType = provider === 'pg' ? 'postgresql' : provider;
|
|
524
|
-
}
|
|
525
|
-
else {
|
|
526
|
-
adapter = 'prisma';
|
|
527
|
-
dbType = 'postgresql';
|
|
528
|
-
}
|
|
529
|
-
}
|
|
530
|
-
else {
|
|
531
|
-
adapter = 'prisma';
|
|
532
|
-
dbType = 'postgresql';
|
|
533
|
-
}
|
|
216
|
+
if (shouldThrowOnError) {
|
|
217
|
+
throw e;
|
|
534
218
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
config.database.constructor &&
|
|
538
|
-
config.database.constructor.name === 'Database')) {
|
|
539
|
-
dbType = 'sqlite';
|
|
540
|
-
dbName = config.database.name || './better-auth.db';
|
|
541
|
-
adapter = 'sqlite';
|
|
542
|
-
}
|
|
543
|
-
else if (config.database.name?.endsWith('.db') ||
|
|
544
|
-
(typeof config.database === 'string' && config.database.endsWith('.db'))) {
|
|
545
|
-
dbType = 'sqlite';
|
|
546
|
-
adapter = 'sqlite';
|
|
547
|
-
}
|
|
548
|
-
else if (config.database.provider) {
|
|
549
|
-
const provider = config.database.provider;
|
|
550
|
-
if (provider === 'pg' ||
|
|
551
|
-
provider === 'postgresql' ||
|
|
552
|
-
provider === 'mysql' ||
|
|
553
|
-
provider === 'sqlite') {
|
|
554
|
-
adapter = 'drizzle';
|
|
555
|
-
dbType = provider === 'pg' ? 'postgresql' : provider;
|
|
556
|
-
}
|
|
557
|
-
else {
|
|
558
|
-
adapter = 'prisma';
|
|
559
|
-
dbType = provider;
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
else if (config.database.adapter) {
|
|
563
|
-
adapter = config.database.adapter;
|
|
564
|
-
if (config.database.provider) {
|
|
565
|
-
const provider = config.database.provider;
|
|
566
|
-
if (provider === 'pg' ||
|
|
567
|
-
provider === 'postgresql' ||
|
|
568
|
-
provider === 'mysql' ||
|
|
569
|
-
provider === 'sqlite') {
|
|
570
|
-
adapter = 'drizzle';
|
|
571
|
-
dbType = provider === 'pg' ? 'postgresql' : provider;
|
|
572
|
-
}
|
|
573
|
-
else {
|
|
574
|
-
dbType = provider;
|
|
575
|
-
}
|
|
576
|
-
}
|
|
577
|
-
else {
|
|
578
|
-
dbType = adapter;
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
else if (config.database.type) {
|
|
582
|
-
dbType = config.database.type;
|
|
583
|
-
adapter = config.database.type;
|
|
584
|
-
}
|
|
585
|
-
if (config.database.provider &&
|
|
586
|
-
(config.database.provider === 'postgresql' ||
|
|
587
|
-
config.database.provider === 'pg' ||
|
|
588
|
-
config.database.provider === 'mysql' ||
|
|
589
|
-
config.database.provider === 'sqlite')) {
|
|
590
|
-
adapter = 'drizzle';
|
|
591
|
-
dbType = config.database.provider === 'pg' ? 'postgresql' : config.database.provider;
|
|
592
|
-
}
|
|
593
|
-
authConfig.database = {
|
|
594
|
-
url: config.database.url || config.database.connectionString,
|
|
595
|
-
name: dbName,
|
|
596
|
-
type: adapter === 'drizzle' ? `${dbType} (${adapter})` : dbType,
|
|
597
|
-
adapter: adapter,
|
|
598
|
-
dialect: config.database.dialect,
|
|
599
|
-
provider: config.database.provider,
|
|
600
|
-
casing: config.database.casing,
|
|
601
|
-
};
|
|
602
|
-
}
|
|
603
|
-
if (config.socialProviders) {
|
|
604
|
-
if (typeof config.socialProviders === 'object' && !Array.isArray(config.socialProviders)) {
|
|
605
|
-
authConfig.socialProviders = config.socialProviders;
|
|
606
|
-
authConfig.providers = Object.entries(config.socialProviders).map(([provider, config]) => ({
|
|
607
|
-
type: provider,
|
|
608
|
-
clientId: config.clientId,
|
|
609
|
-
clientSecret: config.clientSecret,
|
|
610
|
-
redirectUri: config.redirectUri,
|
|
611
|
-
...config,
|
|
612
|
-
}));
|
|
613
|
-
}
|
|
614
|
-
else if (Array.isArray(config.socialProviders)) {
|
|
615
|
-
authConfig.socialProviders = config.socialProviders;
|
|
616
|
-
authConfig.providers = config.socialProviders;
|
|
617
|
-
}
|
|
618
|
-
}
|
|
619
|
-
if (config.providers && Array.isArray(config.providers)) {
|
|
620
|
-
authConfig.providers = config.providers.map((provider) => ({
|
|
621
|
-
type: provider.type || provider.id,
|
|
622
|
-
clientId: provider.clientId || provider.client_id,
|
|
623
|
-
clientSecret: provider.clientSecret || provider.client_secret,
|
|
624
|
-
...provider,
|
|
625
|
-
}));
|
|
219
|
+
logger.error("Couldn't read your auth config.", e);
|
|
220
|
+
process.exit(1);
|
|
626
221
|
}
|
|
627
|
-
if (config.emailAndPassword) {
|
|
628
|
-
authConfig.emailAndPassword = config.emailAndPassword;
|
|
629
|
-
}
|
|
630
|
-
if (config.session) {
|
|
631
|
-
authConfig.session = config.session;
|
|
632
|
-
}
|
|
633
|
-
if (config.secret) {
|
|
634
|
-
authConfig.secret = config.secret;
|
|
635
|
-
}
|
|
636
|
-
if (config.rateLimit) {
|
|
637
|
-
authConfig.rateLimit = config.rateLimit;
|
|
638
|
-
}
|
|
639
|
-
if (config.telemetry) {
|
|
640
|
-
authConfig.telemetry = config.telemetry;
|
|
641
|
-
}
|
|
642
|
-
if (config.plugins) {
|
|
643
|
-
authConfig.plugins = config.plugins.map((plugin) => plugin.id);
|
|
644
|
-
}
|
|
645
|
-
return authConfig;
|
|
646
222
|
}
|
|
647
|
-
|
|
223
|
+
export { possiblePaths };
|
|
224
|
+
// Legacy function for backward compatibility - kept for routes.ts
|
|
225
|
+
export function extractBetterAuthConfig(content) {
|
|
226
|
+
// This is a simplified version that returns null
|
|
227
|
+
// The actual config loading is now handled by the better-auth getConfig function
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
export async function findAuthConfig(configPath) {
|
|
648
231
|
try {
|
|
649
|
-
const
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
}
|
|
654
|
-
if (
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
232
|
+
const betterAuthConfig = await getConfig({
|
|
233
|
+
cwd: process.cwd(),
|
|
234
|
+
configPath,
|
|
235
|
+
shouldThrowOnError: false,
|
|
236
|
+
});
|
|
237
|
+
if (betterAuthConfig) {
|
|
238
|
+
// Convert BetterAuthOptions to AuthConfig format
|
|
239
|
+
const authConfig = {
|
|
240
|
+
database: {
|
|
241
|
+
type: betterAuthConfig.database ? 'drizzle' : 'unknown',
|
|
242
|
+
adapter: 'drizzle-adapter',
|
|
243
|
+
...betterAuthConfig.database,
|
|
244
|
+
},
|
|
245
|
+
emailAndPassword: {
|
|
246
|
+
enabled: betterAuthConfig.emailAndPassword?.enabled || false,
|
|
247
|
+
...betterAuthConfig.emailAndPassword,
|
|
248
|
+
},
|
|
249
|
+
socialProviders: betterAuthConfig.socialProviders
|
|
250
|
+
? Object.keys(betterAuthConfig.socialProviders).map((provider) => ({
|
|
251
|
+
id: provider,
|
|
252
|
+
name: provider,
|
|
253
|
+
enabled: true,
|
|
254
|
+
}))
|
|
255
|
+
: [],
|
|
256
|
+
trustedOrigins: Array.isArray(betterAuthConfig.trustedOrigins)
|
|
257
|
+
? betterAuthConfig.trustedOrigins
|
|
258
|
+
: ['http://localhost:3000'],
|
|
259
|
+
advanced: {
|
|
260
|
+
defaultCookieAttributes: betterAuthConfig.advanced?.defaultCookieAttributes || {
|
|
261
|
+
sameSite: 'none',
|
|
262
|
+
secure: true,
|
|
263
|
+
httpOnly: true,
|
|
264
|
+
},
|
|
265
|
+
...betterAuthConfig.advanced,
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
return authConfig;
|
|
659
269
|
}
|
|
660
270
|
return null;
|
|
661
271
|
}
|
|
662
272
|
catch (error) {
|
|
663
|
-
console.warn(`
|
|
273
|
+
console.warn(`Failed to load config:`, error);
|
|
664
274
|
return null;
|
|
665
275
|
}
|
|
666
276
|
}
|