better-auth-studio 1.0.59-beta.2 → 1.0.59-beta.4
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/routes.d.ts.map +1 -1
- package/dist/routes.js +143 -22
- package/dist/routes.js.map +1 -1
- package/package.json +1 -1
- package/public/assets/{main-CRDG8Se2.js → main-C3xyC-c_.js} +125 -125
- package/public/assets/main-CD1JTPhw.css +1 -0
- package/public/index.html +2 -2
- package/public/assets/main-KBM4GS4q.css +0 -1
package/dist/routes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAOA,OAAO,EAA+B,MAAM,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAOA,OAAO,EAA+B,MAAM,EAAE,MAAM,SAAS,CAAC;AAa9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA8D9C,wBAAsB,oBAAoB,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAyLhG;AAwBD,wBAAgB,YAAY,CAC1B,UAAU,EAAE,UAAU,EACtB,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAilLR"}
|
package/dist/routes.js
CHANGED
|
@@ -7,6 +7,10 @@ import { hex } from '@better-auth/utils/hex';
|
|
|
7
7
|
import { scryptAsync } from '@noble/hashes/scrypt.js';
|
|
8
8
|
import { Router } from 'express';
|
|
9
9
|
import { createJiti } from 'jiti';
|
|
10
|
+
import { execSync } from 'node:child_process';
|
|
11
|
+
import { writeFileSync as writeFile, unlinkSync, readFileSync as readFile } from 'node:fs';
|
|
12
|
+
import { tmpdir } from 'node:os';
|
|
13
|
+
import { join as pathJoin } from 'node:path';
|
|
10
14
|
import { createMockAccount, createMockSession, createMockUser, createMockVerification, getAuthAdapter, } from './auth-adapter.js';
|
|
11
15
|
import { getAuthData } from './data.js';
|
|
12
16
|
import { initializeGeoService, resolveIPLocation, setGeoDbPath } from './geo-service.js';
|
|
@@ -4355,13 +4359,9 @@ export function createRoutes(authConfig, configPath, geoDbPath) {
|
|
|
4355
4359
|
?.filter((f) => f.name.trim())
|
|
4356
4360
|
.map((field) => {
|
|
4357
4361
|
const attrs = [`type: "${field.type}"`];
|
|
4358
|
-
// Always include required (default to false)
|
|
4359
4362
|
attrs.push(`required: ${field.required ? 'true' : 'false'}`);
|
|
4360
|
-
// Always include unique (default to false)
|
|
4361
4363
|
attrs.push(`unique: ${field.unique ? 'true' : 'false'}`);
|
|
4362
|
-
// Always include input (default to false)
|
|
4363
4364
|
attrs.push('input: false');
|
|
4364
|
-
// Add defaultValue for boolean fields
|
|
4365
4365
|
if (field.type === 'boolean') {
|
|
4366
4366
|
attrs.push('defaultValue: false');
|
|
4367
4367
|
}
|
|
@@ -4369,7 +4369,6 @@ export function createRoutes(authConfig, configPath, geoDbPath) {
|
|
|
4369
4369
|
return ` ${field.name}: {\n ${attrStr}\n }`;
|
|
4370
4370
|
})
|
|
4371
4371
|
.join(',\n') || '';
|
|
4372
|
-
// If extending an existing table, use the extended table name
|
|
4373
4372
|
const tableName = table.isExtending && table.extendedTableName
|
|
4374
4373
|
? table.extendedTableName.trim()
|
|
4375
4374
|
: table.name.trim();
|
|
@@ -4381,7 +4380,6 @@ ${fields}
|
|
|
4381
4380
|
})
|
|
4382
4381
|
.join(',\n')
|
|
4383
4382
|
: '';
|
|
4384
|
-
// Generate hooks
|
|
4385
4383
|
const beforeHooks = hooks
|
|
4386
4384
|
.filter((h) => h.timing === 'before')
|
|
4387
4385
|
.map((hook) => {
|
|
@@ -4404,7 +4402,6 @@ ${fields}
|
|
|
4404
4402
|
return ` {
|
|
4405
4403
|
matcher: ${matcher},
|
|
4406
4404
|
handler: createAuthMiddleware(async (ctx) => {
|
|
4407
|
-
// ${hook.name || `${hook.timing} ${hook.action} hook`}
|
|
4408
4405
|
${hook.hookLogic || '// Hook logic here'}
|
|
4409
4406
|
}),
|
|
4410
4407
|
}`;
|
|
@@ -4431,7 +4428,6 @@ ${fields}
|
|
|
4431
4428
|
return ` {
|
|
4432
4429
|
matcher: ${matcher},
|
|
4433
4430
|
handler: createAuthMiddleware(async (ctx) => {
|
|
4434
|
-
// ${hook.name || `${hook.timing} ${hook.action} hook`}
|
|
4435
4431
|
${hook.hookLogic || '// Hook logic here'}
|
|
4436
4432
|
}),
|
|
4437
4433
|
}`;
|
|
@@ -4441,13 +4437,11 @@ ${fields}
|
|
|
4441
4437
|
return ` {
|
|
4442
4438
|
path: "${mw.path}",
|
|
4443
4439
|
middleware: createAuthMiddleware(async (ctx) => {
|
|
4444
|
-
// ${mw.name || 'Middleware'}
|
|
4445
4440
|
${mw.middlewareLogic || '// Middleware logic here'}
|
|
4446
4441
|
}),
|
|
4447
4442
|
}`;
|
|
4448
4443
|
})
|
|
4449
4444
|
.join(',\n');
|
|
4450
|
-
// Generate endpoints
|
|
4451
4445
|
const endpointsCode = endpoints.length > 0
|
|
4452
4446
|
? endpoints
|
|
4453
4447
|
.map((endpoint) => {
|
|
@@ -4475,7 +4469,6 @@ ${fields}
|
|
|
4475
4469
|
method: "${endpoint.method || 'POST'}",
|
|
4476
4470
|
},
|
|
4477
4471
|
async (ctx) => {
|
|
4478
|
-
// ${endpoint.name || sanitizedName}
|
|
4479
4472
|
${formattedHandlerLogic}
|
|
4480
4473
|
},
|
|
4481
4474
|
),`;
|
|
@@ -4518,6 +4511,33 @@ ${formattedHandlerLogic}
|
|
|
4518
4511
|
.replace(/\n{3,}/g, '\n\n')
|
|
4519
4512
|
.trim();
|
|
4520
4513
|
};
|
|
4514
|
+
const formatCode = (code) => {
|
|
4515
|
+
try {
|
|
4516
|
+
const tempFile = pathJoin(tmpdir(), `biome-format-${Date.now()}-${Math.random().toString(36).substring(7)}.ts`);
|
|
4517
|
+
writeFile(tempFile, code, 'utf-8');
|
|
4518
|
+
try {
|
|
4519
|
+
execSync(`npx @biomejs/biome format --write ${tempFile}`, {
|
|
4520
|
+
stdio: 'pipe',
|
|
4521
|
+
cwd: process.cwd(),
|
|
4522
|
+
});
|
|
4523
|
+
const formatted = readFile(tempFile, 'utf-8');
|
|
4524
|
+
unlinkSync(tempFile);
|
|
4525
|
+
return formatted;
|
|
4526
|
+
}
|
|
4527
|
+
catch (formatError) {
|
|
4528
|
+
try {
|
|
4529
|
+
unlinkSync(tempFile);
|
|
4530
|
+
}
|
|
4531
|
+
catch {
|
|
4532
|
+
// Ignore cleanup errors
|
|
4533
|
+
}
|
|
4534
|
+
return code;
|
|
4535
|
+
}
|
|
4536
|
+
}
|
|
4537
|
+
catch (error) {
|
|
4538
|
+
return code;
|
|
4539
|
+
}
|
|
4540
|
+
};
|
|
4521
4541
|
const pluginParts = [];
|
|
4522
4542
|
if (schemaCode) {
|
|
4523
4543
|
pluginParts.push(` schema: {\n${schemaCode}\n }`);
|
|
@@ -4541,7 +4561,6 @@ ${formattedHandlerLogic}
|
|
|
4541
4561
|
if (rateLimitCode) {
|
|
4542
4562
|
pluginParts.push(` rateLimit: {\n${rateLimitCode}\n }`);
|
|
4543
4563
|
}
|
|
4544
|
-
// Generate server plugin code
|
|
4545
4564
|
const imports = ['import type { BetterAuthPlugin } from "@better-auth/core"'];
|
|
4546
4565
|
if (hooks.length > 0 || middleware.length > 0 || endpoints.length > 0) {
|
|
4547
4566
|
imports.push('import { createAuthEndpoint, createAuthMiddleware } from "@better-auth/core/api"');
|
|
@@ -4549,7 +4568,7 @@ ${formattedHandlerLogic}
|
|
|
4549
4568
|
const serverPluginBody = pluginParts.length > 0
|
|
4550
4569
|
? ` id: "${camelCaseName}",\n${pluginParts.join(',\n')}`
|
|
4551
4570
|
: ` id: "${camelCaseName}"`;
|
|
4552
|
-
const serverPluginCode = cleanCode(`import type { BetterAuthPlugin } from "@better-auth/core";
|
|
4571
|
+
const serverPluginCode = formatCode(cleanCode(`import type { BetterAuthPlugin } from "@better-auth/core";
|
|
4553
4572
|
${imports.join('\n')}
|
|
4554
4573
|
|
|
4555
4574
|
${description ? `/**\n * ${description.replace(/\n/g, '\n * ')}\n */` : ''}
|
|
@@ -4558,7 +4577,7 @@ export const ${camelCaseName} = (options?: Record<string, any>) => {
|
|
|
4558
4577
|
${serverPluginBody}
|
|
4559
4578
|
} satisfies BetterAuthPlugin;
|
|
4560
4579
|
};
|
|
4561
|
-
`);
|
|
4580
|
+
`));
|
|
4562
4581
|
const pathMethods = endpoints.length > 0
|
|
4563
4582
|
? endpoints
|
|
4564
4583
|
.map((endpoint) => {
|
|
@@ -4583,7 +4602,7 @@ ${serverPluginBody}
|
|
|
4583
4602
|
const atomListenersCode = sessionAffectingPaths.length > 0
|
|
4584
4603
|
? `\n atomListeners: [\n${sessionAffectingPaths.join(',\n')}\n ],`
|
|
4585
4604
|
: '';
|
|
4586
|
-
const clientPluginCode = cleanCode(`import type { BetterAuthClientPlugin } from "@better-auth/core";
|
|
4605
|
+
const clientPluginCode = formatCode(cleanCode(`import type { BetterAuthClientPlugin } from "@better-auth/core";
|
|
4587
4606
|
import type { ${camelCaseName} } from "..";
|
|
4588
4607
|
|
|
4589
4608
|
export const ${camelCaseName}Client = () => {
|
|
@@ -4592,9 +4611,8 @@ export const ${camelCaseName}Client = () => {
|
|
|
4592
4611
|
$InferServerPlugin: {} as ReturnType<typeof ${camelCaseName}>,${pathMethods ? `\n pathMethods: {\n${pathMethods}\n },` : ''}${atomListenersCode}
|
|
4593
4612
|
} satisfies BetterAuthClientPlugin;
|
|
4594
4613
|
};
|
|
4595
|
-
`);
|
|
4596
|
-
|
|
4597
|
-
const serverSetupCode = cleanCode(`import { betterAuth } from "@better-auth/core";
|
|
4614
|
+
`));
|
|
4615
|
+
const serverSetupCode = formatCode(cleanCode(`import { betterAuth } from "@better-auth/core";
|
|
4598
4616
|
import { ${camelCaseName} } from "./plugin/${camelCaseName}";
|
|
4599
4617
|
|
|
4600
4618
|
export const auth = betterAuth({
|
|
@@ -4603,7 +4621,7 @@ export const auth = betterAuth({
|
|
|
4603
4621
|
${camelCaseName}(),
|
|
4604
4622
|
],
|
|
4605
4623
|
});
|
|
4606
|
-
`);
|
|
4624
|
+
`));
|
|
4607
4625
|
const frameworkImportMap = {
|
|
4608
4626
|
react: 'better-auth/react',
|
|
4609
4627
|
svelte: 'better-auth/svelte',
|
|
@@ -4611,7 +4629,6 @@ export const auth = betterAuth({
|
|
|
4611
4629
|
vue: 'better-auth/vue',
|
|
4612
4630
|
};
|
|
4613
4631
|
const frameworkImport = frameworkImportMap[clientFramework] || 'better-auth/react';
|
|
4614
|
-
// Get baseURL based on framework
|
|
4615
4632
|
const baseURLMap = {
|
|
4616
4633
|
react: 'process.env.NEXT_PUBLIC_BETTER_AUTH_URL || "http://localhost:3000"',
|
|
4617
4634
|
svelte: 'import.meta.env.PUBLIC_BETTER_AUTH_URL || "http://localhost:5173"',
|
|
@@ -4620,7 +4637,7 @@ export const auth = betterAuth({
|
|
|
4620
4637
|
};
|
|
4621
4638
|
const baseURL = baseURLMap[clientFramework] ||
|
|
4622
4639
|
'process.env.NEXT_PUBLIC_BETTER_AUTH_URL || "http://localhost:3000"';
|
|
4623
|
-
const clientSetupCode = cleanCode(`import { createAuthClient } from "${frameworkImport}";
|
|
4640
|
+
const clientSetupCode = formatCode(cleanCode(`import { createAuthClient } from "${frameworkImport}";
|
|
4624
4641
|
import { ${camelCaseName}Client } from "./plugin/${camelCaseName}/client";
|
|
4625
4642
|
|
|
4626
4643
|
export const authClient = createAuthClient({
|
|
@@ -4629,7 +4646,7 @@ export const authClient = createAuthClient({
|
|
|
4629
4646
|
${camelCaseName}Client(),
|
|
4630
4647
|
],
|
|
4631
4648
|
});
|
|
4632
|
-
`);
|
|
4649
|
+
`));
|
|
4633
4650
|
return res.json({
|
|
4634
4651
|
success: true,
|
|
4635
4652
|
plugin: {
|
|
@@ -4995,6 +5012,110 @@ export const authClient = createAuthClient({
|
|
|
4995
5012
|
});
|
|
4996
5013
|
}
|
|
4997
5014
|
});
|
|
5015
|
+
router.post('/api/tools/check-env-secret', async (_req, res) => {
|
|
5016
|
+
try {
|
|
5017
|
+
const envPath = join(process.cwd(), '.env');
|
|
5018
|
+
const envLocalPath = join(process.cwd(), '.env.local');
|
|
5019
|
+
const targetPath = existsSync(envLocalPath) ? envLocalPath : envPath;
|
|
5020
|
+
const envContent = existsSync(targetPath) ? readFileSync(targetPath, 'utf-8') : '';
|
|
5021
|
+
const envLines = envContent.split('\n');
|
|
5022
|
+
let existingSecret;
|
|
5023
|
+
envLines.forEach((line) => {
|
|
5024
|
+
const trimmed = line.trim();
|
|
5025
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
5026
|
+
return;
|
|
5027
|
+
const match = trimmed.match(/^BETTER_AUTH_SECRET\s*=\s*(.*)$/i);
|
|
5028
|
+
if (match) {
|
|
5029
|
+
let value = match[1].trim();
|
|
5030
|
+
if (value.length >= 2) {
|
|
5031
|
+
if ((value.startsWith('"') && value.endsWith('"')) ||
|
|
5032
|
+
(value.startsWith("'") && value.endsWith("'"))) {
|
|
5033
|
+
value = value.slice(1, -1).trim();
|
|
5034
|
+
}
|
|
5035
|
+
}
|
|
5036
|
+
if (value && value.trim() !== '') {
|
|
5037
|
+
existingSecret = value;
|
|
5038
|
+
}
|
|
5039
|
+
}
|
|
5040
|
+
});
|
|
5041
|
+
const hasExisting = !!existingSecret && existingSecret.trim() !== '';
|
|
5042
|
+
res.json({
|
|
5043
|
+
success: true,
|
|
5044
|
+
hasExisting,
|
|
5045
|
+
existingSecret: hasExisting ? existingSecret : undefined,
|
|
5046
|
+
path: targetPath,
|
|
5047
|
+
});
|
|
5048
|
+
}
|
|
5049
|
+
catch (error) {
|
|
5050
|
+
res.status(500).json({
|
|
5051
|
+
success: false,
|
|
5052
|
+
message: error instanceof Error ? error.message : 'Failed to check secret',
|
|
5053
|
+
});
|
|
5054
|
+
}
|
|
5055
|
+
});
|
|
5056
|
+
router.post('/api/tools/write-env-secret', async (req, res) => {
|
|
5057
|
+
try {
|
|
5058
|
+
const { secret, action = 'override' } = req.body || {};
|
|
5059
|
+
if (!secret) {
|
|
5060
|
+
return res.status(400).json({
|
|
5061
|
+
success: false,
|
|
5062
|
+
message: 'Secret is required',
|
|
5063
|
+
});
|
|
5064
|
+
}
|
|
5065
|
+
const envPath = join(process.cwd(), '.env');
|
|
5066
|
+
const envLocalPath = join(process.cwd(), '.env.local');
|
|
5067
|
+
const targetPath = existsSync(envLocalPath) ? envLocalPath : envPath;
|
|
5068
|
+
const envContent = existsSync(targetPath) ? readFileSync(targetPath, 'utf-8') : '';
|
|
5069
|
+
const envLines = envContent.split('\n');
|
|
5070
|
+
const envMap = new Map();
|
|
5071
|
+
const newLines = [];
|
|
5072
|
+
envLines.forEach((line, index) => {
|
|
5073
|
+
const trimmed = line.trim();
|
|
5074
|
+
if (!trimmed || trimmed.startsWith('#')) {
|
|
5075
|
+
newLines.push(line);
|
|
5076
|
+
return;
|
|
5077
|
+
}
|
|
5078
|
+
const match = trimmed.match(/^([^=#]+)\s*=\s*(.*)$/);
|
|
5079
|
+
if (match) {
|
|
5080
|
+
const key = match[1].trim();
|
|
5081
|
+
if (key.toUpperCase() === 'BETTER_AUTH_SECRET') {
|
|
5082
|
+
envMap.set('BETTER_AUTH_SECRET', { line, index });
|
|
5083
|
+
if (action === 'override') {
|
|
5084
|
+
newLines.push(`BETTER_AUTH_SECRET=${secret}`);
|
|
5085
|
+
}
|
|
5086
|
+
else {
|
|
5087
|
+
newLines.push(line);
|
|
5088
|
+
}
|
|
5089
|
+
}
|
|
5090
|
+
else {
|
|
5091
|
+
newLines.push(line);
|
|
5092
|
+
}
|
|
5093
|
+
}
|
|
5094
|
+
else {
|
|
5095
|
+
newLines.push(line);
|
|
5096
|
+
}
|
|
5097
|
+
});
|
|
5098
|
+
if (!envMap.has('BETTER_AUTH_SECRET')) {
|
|
5099
|
+
if (newLines.length > 0 && newLines[newLines.length - 1].trim() !== '') {
|
|
5100
|
+
newLines.push('');
|
|
5101
|
+
}
|
|
5102
|
+
newLines.push(`BETTER_AUTH_SECRET=${secret}`);
|
|
5103
|
+
}
|
|
5104
|
+
const newContent = newLines.join('\n');
|
|
5105
|
+
writeFileSync(targetPath, newContent, 'utf-8');
|
|
5106
|
+
res.json({
|
|
5107
|
+
success: true,
|
|
5108
|
+
message: 'Secret written successfully',
|
|
5109
|
+
path: targetPath,
|
|
5110
|
+
});
|
|
5111
|
+
}
|
|
5112
|
+
catch (error) {
|
|
5113
|
+
res.status(500).json({
|
|
5114
|
+
success: false,
|
|
5115
|
+
message: error instanceof Error ? error.message : 'Failed to write secret to .env',
|
|
5116
|
+
});
|
|
5117
|
+
}
|
|
5118
|
+
});
|
|
4998
5119
|
router.post('/api/tools/check-env-credentials', async (req, res) => {
|
|
4999
5120
|
try {
|
|
5000
5121
|
const { provider } = req.body || {};
|