better-auth-studio 1.0.59-beta.8 → 1.0.59
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 +195 -8
- package/dist/routes.js.map +1 -1
- package/package.json +1 -1
- package/public/assets/main-p2dU6WGq.js +1140 -0
- package/public/index.html +1 -1
- package/public/assets/main-GLVvDN7r.js +0 -1104
package/dist/routes.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAeA,OAAO,EAA+B,MAAM,EAAE,MAAM,SAAS,CAAC;AAS9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAeA,OAAO,EAA+B,MAAM,EAAE,MAAM,SAAS,CAAC;AAS9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA+D9C,wBAAsB,oBAAoB,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,UAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAqLhG;AAeD,wBAAgB,YAAY,CAC1B,UAAU,EAAE,UAAU,EACtB,UAAU,CAAC,EAAE,MAAM,EACnB,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAkzLR"}
|
package/dist/routes.js
CHANGED
|
@@ -8,10 +8,10 @@ import { scryptAsync } from '@noble/hashes/scrypt.js';
|
|
|
8
8
|
import { Router } from 'express';
|
|
9
9
|
import { createJiti } from 'jiti';
|
|
10
10
|
import { createMockAccount, createMockSession, createMockUser, createMockVerification, getAuthAdapter, } from './auth-adapter.js';
|
|
11
|
+
import { possiblePaths } from './config.js';
|
|
11
12
|
import { getAuthData } from './data.js';
|
|
12
13
|
import { initializeGeoService, resolveIPLocation, setGeoDbPath } from './geo-service.js';
|
|
13
14
|
import { detectDatabaseWithDialect } from './utils/database-detection.js';
|
|
14
|
-
import { possiblePaths } from './config.js';
|
|
15
15
|
const config = {
|
|
16
16
|
N: 16384,
|
|
17
17
|
r: 16,
|
|
@@ -4348,7 +4348,9 @@ export function createRoutes(authConfig, configPath, geoDbPath) {
|
|
|
4348
4348
|
attrs.push(`unique: ${field.unique ? 'true' : 'false'}`);
|
|
4349
4349
|
attrs.push('input: false');
|
|
4350
4350
|
// Handle defaultValue
|
|
4351
|
-
if (field.defaultValue !== undefined &&
|
|
4351
|
+
if (field.defaultValue !== undefined &&
|
|
4352
|
+
field.defaultValue !== null &&
|
|
4353
|
+
field.defaultValue !== '') {
|
|
4352
4354
|
if (field.type === 'string') {
|
|
4353
4355
|
attrs.push(`defaultValue: "${field.defaultValue}"`);
|
|
4354
4356
|
}
|
|
@@ -4390,15 +4392,15 @@ ${fields}
|
|
|
4390
4392
|
if (!code.trim())
|
|
4391
4393
|
return '';
|
|
4392
4394
|
const lines = code.split('\n');
|
|
4393
|
-
const nonEmptyLines = lines.filter(line => line.trim());
|
|
4395
|
+
const nonEmptyLines = lines.filter((line) => line.trim());
|
|
4394
4396
|
if (nonEmptyLines.length === 0)
|
|
4395
4397
|
return '';
|
|
4396
|
-
const minIndent = Math.min(...nonEmptyLines.map(line => {
|
|
4398
|
+
const minIndent = Math.min(...nonEmptyLines.map((line) => {
|
|
4397
4399
|
const match = line.match(/^(\s*)/);
|
|
4398
4400
|
return match ? match[1].length : 0;
|
|
4399
4401
|
}));
|
|
4400
4402
|
return lines
|
|
4401
|
-
.map(line => {
|
|
4403
|
+
.map((line) => {
|
|
4402
4404
|
if (!line.trim())
|
|
4403
4405
|
return '';
|
|
4404
4406
|
const currentIndent = line.match(/^(\s*)/)?.[1] || '';
|
|
@@ -5120,14 +5122,11 @@ export const authClient = createAuthClient({
|
|
|
5120
5122
|
}
|
|
5121
5123
|
const envPath = join(process.cwd(), '.env');
|
|
5122
5124
|
const envLocalPath = join(process.cwd(), '.env.local');
|
|
5123
|
-
// Try .env.local first, then .env
|
|
5124
5125
|
const targetPath = existsSync(envLocalPath) ? envLocalPath : envPath;
|
|
5125
5126
|
const envContent = existsSync(targetPath) ? readFileSync(targetPath, 'utf-8') : '';
|
|
5126
|
-
// Generate environment variable names
|
|
5127
5127
|
const providerUpper = provider.toUpperCase();
|
|
5128
5128
|
const clientIdKey = `${providerUpper}_CLIENT_ID`;
|
|
5129
5129
|
const clientSecretKey = `${providerUpper}_CLIENT_SECRET`;
|
|
5130
|
-
// Parse existing .env file
|
|
5131
5130
|
const envLines = envContent.split('\n');
|
|
5132
5131
|
const existingCredentials = {};
|
|
5133
5132
|
envLines.forEach((line) => {
|
|
@@ -5289,6 +5288,194 @@ export const authClient = createAuthClient({
|
|
|
5289
5288
|
});
|
|
5290
5289
|
}
|
|
5291
5290
|
});
|
|
5291
|
+
router.post('/api/tools/apply-email-template', async (req, res) => {
|
|
5292
|
+
try {
|
|
5293
|
+
const { subject, html, templateId } = req.body || {};
|
|
5294
|
+
if (!subject || !html || !templateId) {
|
|
5295
|
+
return res
|
|
5296
|
+
.status(400)
|
|
5297
|
+
.json({ success: false, message: 'templateId, subject and html are required' });
|
|
5298
|
+
}
|
|
5299
|
+
const authPath = join(process.cwd(), 'examples/nextjs/prisma/lib/auth.ts');
|
|
5300
|
+
if (!existsSync(authPath)) {
|
|
5301
|
+
return res.status(404).json({ success: false, message: 'auth.ts not found' });
|
|
5302
|
+
}
|
|
5303
|
+
let fileContent = readFileSync(authPath, 'utf-8');
|
|
5304
|
+
const escapedSubject = subject.replace(/`/g, '\\`').replace(/\${/g, '\\${');
|
|
5305
|
+
const escapedHtml = html.replace(/`/g, '\\`').replace(/\${/g, '\\${');
|
|
5306
|
+
if (!fileContent.includes("from 'resend'")) {
|
|
5307
|
+
fileContent = `import { Resend } from 'resend';\n` + fileContent;
|
|
5308
|
+
}
|
|
5309
|
+
if (!fileContent.includes('const resend = new Resend(')) {
|
|
5310
|
+
const importBlockEnd = fileContent.indexOf('\n', fileContent.lastIndexOf('import'));
|
|
5311
|
+
if (importBlockEnd > -1) {
|
|
5312
|
+
fileContent =
|
|
5313
|
+
fileContent.slice(0, importBlockEnd + 1) +
|
|
5314
|
+
`const resend = new Resend(process.env.RESEND_API_KEY || '');\n` +
|
|
5315
|
+
fileContent.slice(importBlockEnd + 1);
|
|
5316
|
+
}
|
|
5317
|
+
else {
|
|
5318
|
+
fileContent =
|
|
5319
|
+
`const resend = new Resend(process.env.RESEND_API_KEY || '');\n` + fileContent;
|
|
5320
|
+
}
|
|
5321
|
+
}
|
|
5322
|
+
const handlers = {
|
|
5323
|
+
'password-reset': {
|
|
5324
|
+
regex: /sendResetPassword\s*:\s*async\s*\([^)]*\)\s*=>\s*\{[\s\S]*?\},?/,
|
|
5325
|
+
fn: `sendResetPassword: async ({ user, url, token }, request) => {
|
|
5326
|
+
const subject = \\\`${escapedSubject}\\\`
|
|
5327
|
+
.replace(/{{user.name}}/g, user?.name || '')
|
|
5328
|
+
.replace(/{{user.email}}/g, user?.email || '');
|
|
5329
|
+
|
|
5330
|
+
const html = \\\`${escapedHtml}\\\`
|
|
5331
|
+
.replace(/{{user.name}}/g, user?.name || '')
|
|
5332
|
+
.replace(/{{user.email}}/g, user?.email || '')
|
|
5333
|
+
.replace(/{{url}}/g, url || '')
|
|
5334
|
+
.replace(/{{token}}/g, token || '');
|
|
5335
|
+
|
|
5336
|
+
void sendEmail({
|
|
5337
|
+
to: user.email,
|
|
5338
|
+
subject,
|
|
5339
|
+
html,
|
|
5340
|
+
});
|
|
5341
|
+
}`,
|
|
5342
|
+
},
|
|
5343
|
+
'email-verification': {
|
|
5344
|
+
regex: /sendVerificationEmail\s*:\s*async\s*\([^)]*\)\s*=>\s*\{[\s\S]*?\},?/,
|
|
5345
|
+
fn: `sendVerificationEmail: async ({ user, url, token }, request) => {
|
|
5346
|
+
const subject = \\\`${escapedSubject}\\\`
|
|
5347
|
+
.replace(/{{user.name}}/g, user?.name || '')
|
|
5348
|
+
.replace(/{{user.email}}/g, user?.email || '');
|
|
5349
|
+
|
|
5350
|
+
const html = \\\`${escapedHtml}\\\`
|
|
5351
|
+
.replace(/{{user.name}}/g, user?.name || '')
|
|
5352
|
+
.replace(/{{user.email}}/g, user?.email || '')
|
|
5353
|
+
.replace(/{{url}}/g, url || '')
|
|
5354
|
+
.replace(/{{token}}/g, token || '');
|
|
5355
|
+
|
|
5356
|
+
void sendEmail({
|
|
5357
|
+
to: user.email,
|
|
5358
|
+
subject,
|
|
5359
|
+
html,
|
|
5360
|
+
});
|
|
5361
|
+
}`,
|
|
5362
|
+
},
|
|
5363
|
+
'magic-link': {
|
|
5364
|
+
regex: /sendMagicLink\s*:\s*async\s*\([^)]*\)\s*=>\s*\{[\s\S]*?\},?/,
|
|
5365
|
+
fn: `sendMagicLink: async ({ email, token, url }, ctx) => {
|
|
5366
|
+
const subject = \\\`${escapedSubject}\\\`
|
|
5367
|
+
.replace(/{{user.email}}/g, email || '');
|
|
5368
|
+
|
|
5369
|
+
const html = \\\`${escapedHtml}\\\`
|
|
5370
|
+
.replace(/{{user.email}}/g, email || '')
|
|
5371
|
+
.replace(/{{url}}/g, url || '')
|
|
5372
|
+
.replace(/{{token}}/g, token || '');
|
|
5373
|
+
|
|
5374
|
+
void sendEmail({
|
|
5375
|
+
to: email,
|
|
5376
|
+
subject,
|
|
5377
|
+
html,
|
|
5378
|
+
});
|
|
5379
|
+
}`,
|
|
5380
|
+
},
|
|
5381
|
+
'org-invitation': {
|
|
5382
|
+
regex: /sendInvitationEmail\s*:\s*async\s*\([^)]*\)\s*=>\s*\{[\s\S]*?\},?/,
|
|
5383
|
+
fn: `sendInvitationEmail: async ({ data, request }: {
|
|
5384
|
+
data: {
|
|
5385
|
+
invitation: {
|
|
5386
|
+
id: string;
|
|
5387
|
+
organizationId: string;
|
|
5388
|
+
email: string;
|
|
5389
|
+
role: string;
|
|
5390
|
+
status: "pending" | "accepted" | "rejected" | "canceled";
|
|
5391
|
+
inviterId: string;
|
|
5392
|
+
expiresAt: Date;
|
|
5393
|
+
createdAt: Date;
|
|
5394
|
+
teamId?: string | null | undefined;
|
|
5395
|
+
};
|
|
5396
|
+
organization: { name?: string; slug?: string };
|
|
5397
|
+
inviter: { user: { name?: string; email?: string } };
|
|
5398
|
+
};
|
|
5399
|
+
request?: Request;
|
|
5400
|
+
}) => {
|
|
5401
|
+
const { invitation, organization, inviter } = data;
|
|
5402
|
+
const baseUrl = process.env.BETTER_AUTH_URL || 'http://localhost:3000';
|
|
5403
|
+
const url = \\\`\\\${baseUrl}/accept-invitation?id=\\\${invitation.id}\\\`;
|
|
5404
|
+
|
|
5405
|
+
const subject = \\\`${escapedSubject}\\\`
|
|
5406
|
+
.replace(/{{organization.name}}/g, organization?.name || '')
|
|
5407
|
+
.replace(/{{invitation.role}}/g, invitation.role || '')
|
|
5408
|
+
.replace(/{{inviter.user.name}}/g, inviter?.user?.name || '')
|
|
5409
|
+
.replace(/{{inviter.user.email}}/g, inviter?.user?.email || '')
|
|
5410
|
+
.replace(/{{invitation.email}}/g, invitation.email || '');
|
|
5411
|
+
|
|
5412
|
+
const html = \\\`${escapedHtml}\\\`
|
|
5413
|
+
.replace(/{{invitation.url}}/g, url)
|
|
5414
|
+
.replace(/{{invitation.role}}/g, invitation.role || '')
|
|
5415
|
+
.replace(/{{organization.name}}/g, organization?.name || '')
|
|
5416
|
+
.replace(/{{organization.slug}}/g, organization?.slug || '')
|
|
5417
|
+
.replace(/{{inviter.user.name}}/g, inviter?.user?.name || '')
|
|
5418
|
+
.replace(/{{inviter.user.email}}/g, inviter?.user?.email || '')
|
|
5419
|
+
.replace(/{{invitation.email}}/g, invitation.email || '')
|
|
5420
|
+
.replace(/{{invitation.expiresAt}}/g, invitation.expiresAt?.toLocaleString() || '')
|
|
5421
|
+
.replace(/{{expiresIn}}/g, invitation.expiresAt ? \\\`\\\${Math.ceil((invitation.expiresAt.getTime() - Date.now()) / (1000 * 60 * 60 * 24))} days\\\` : '');
|
|
5422
|
+
|
|
5423
|
+
void sendEmail({
|
|
5424
|
+
to: invitation.email,
|
|
5425
|
+
subject,
|
|
5426
|
+
html,
|
|
5427
|
+
});
|
|
5428
|
+
}`,
|
|
5429
|
+
},
|
|
5430
|
+
};
|
|
5431
|
+
const handler = handlers[templateId];
|
|
5432
|
+
if (!handler) {
|
|
5433
|
+
return res
|
|
5434
|
+
.status(400)
|
|
5435
|
+
.json({ success: false, message: 'Unsupported templateId for apply' });
|
|
5436
|
+
}
|
|
5437
|
+
if (!fileContent.includes('const sendEmail = async')) {
|
|
5438
|
+
const insertPoint = fileContent.indexOf('export const auth');
|
|
5439
|
+
fileContent =
|
|
5440
|
+
fileContent.slice(0, insertPoint) +
|
|
5441
|
+
`const sendEmail = async ({ to, subject, text, html }: { to: string; subject: string; text?: string; html?: string }) => {\n console.log(\`Sending email to \${to} | \${subject}\`);\n if (text) console.log('Text content:', text);\n if (html) console.log('HTML content:', html);\n};\n\n` +
|
|
5442
|
+
fileContent.slice(insertPoint);
|
|
5443
|
+
}
|
|
5444
|
+
if (handler.regex.test(fileContent)) {
|
|
5445
|
+
fileContent = fileContent.replace(handler.regex, `${handler.fn},`);
|
|
5446
|
+
}
|
|
5447
|
+
else {
|
|
5448
|
+
if (templateId === 'org-invitation') {
|
|
5449
|
+
const orgPluginRegex = /organization\(\s*\{\s*/;
|
|
5450
|
+
if (!orgPluginRegex.test(fileContent)) {
|
|
5451
|
+
return res.status(400).json({
|
|
5452
|
+
success: false,
|
|
5453
|
+
message: 'organization plugin config not found in auth.ts',
|
|
5454
|
+
});
|
|
5455
|
+
}
|
|
5456
|
+
fileContent = fileContent.replace(orgPluginRegex, (m) => `${m}${handler.fn},\n `);
|
|
5457
|
+
}
|
|
5458
|
+
else {
|
|
5459
|
+
const emailAndPasswordRegex = /emailAndPassword\s*:\s*\{\s*/;
|
|
5460
|
+
if (!emailAndPasswordRegex.test(fileContent)) {
|
|
5461
|
+
return res.status(400).json({
|
|
5462
|
+
success: false,
|
|
5463
|
+
message: 'emailAndPassword config not found in auth.ts',
|
|
5464
|
+
});
|
|
5465
|
+
}
|
|
5466
|
+
fileContent = fileContent.replace(emailAndPasswordRegex, (m) => `${m}${handler.fn},\n `);
|
|
5467
|
+
}
|
|
5468
|
+
}
|
|
5469
|
+
writeFileSync(authPath, fileContent, 'utf-8');
|
|
5470
|
+
res.json({ success: true, path: authPath });
|
|
5471
|
+
}
|
|
5472
|
+
catch (error) {
|
|
5473
|
+
res.status(500).json({
|
|
5474
|
+
success: false,
|
|
5475
|
+
message: error?.message || 'Failed to apply invitation template',
|
|
5476
|
+
});
|
|
5477
|
+
}
|
|
5478
|
+
});
|
|
5292
5479
|
return router;
|
|
5293
5480
|
}
|
|
5294
5481
|
//# sourceMappingURL=routes.js.map
|