better-auth-studio 1.0.59-beta.11 → 1.0.59-beta.13
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 +159 -0
- package/dist/routes.js.map +1 -1
- package/package.json +1 -1
- package/public/assets/{main-RRrATaXc.js → main-sbtbb6Py.js} +127 -72
- package/public/index.html +1 -1
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;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,
|
|
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,CAyxLR"}
|
package/dist/routes.js
CHANGED
|
@@ -5291,6 +5291,165 @@ export const authClient = createAuthClient({
|
|
|
5291
5291
|
});
|
|
5292
5292
|
}
|
|
5293
5293
|
});
|
|
5294
|
+
router.post('/api/tools/apply-email-template', async (req, res) => {
|
|
5295
|
+
try {
|
|
5296
|
+
const { subject, html, templateId } = req.body || {};
|
|
5297
|
+
if (!subject || !html || !templateId) {
|
|
5298
|
+
return res
|
|
5299
|
+
.status(400)
|
|
5300
|
+
.json({ success: false, message: 'templateId, subject and html are required' });
|
|
5301
|
+
}
|
|
5302
|
+
const authPath = join(process.cwd(), 'examples/nextjs/prisma/lib/auth.ts');
|
|
5303
|
+
if (!existsSync(authPath)) {
|
|
5304
|
+
return res.status(404).json({ success: false, message: 'auth.ts not found' });
|
|
5305
|
+
}
|
|
5306
|
+
let fileContent = readFileSync(authPath, 'utf-8');
|
|
5307
|
+
const escapedSubject = subject.replace(/`/g, '\\`').replace(/\${/g, '\\${');
|
|
5308
|
+
const escapedHtml = html.replace(/`/g, '\\`').replace(/\${/g, '\\${');
|
|
5309
|
+
if (!fileContent.includes("from 'resend'")) {
|
|
5310
|
+
fileContent = `import { Resend } from 'resend';\n` + fileContent;
|
|
5311
|
+
}
|
|
5312
|
+
if (!fileContent.includes('const resend = new Resend(')) {
|
|
5313
|
+
const importBlockEnd = fileContent.indexOf('\n', fileContent.lastIndexOf('import'));
|
|
5314
|
+
if (importBlockEnd > -1) {
|
|
5315
|
+
fileContent =
|
|
5316
|
+
fileContent.slice(0, importBlockEnd + 1) +
|
|
5317
|
+
`const resend = new Resend(process.env.RESEND_API_KEY || '');\n` +
|
|
5318
|
+
fileContent.slice(importBlockEnd + 1);
|
|
5319
|
+
}
|
|
5320
|
+
else {
|
|
5321
|
+
fileContent = `const resend = new Resend(process.env.RESEND_API_KEY || '');\n` + fileContent;
|
|
5322
|
+
}
|
|
5323
|
+
}
|
|
5324
|
+
const handlers = {
|
|
5325
|
+
'password-reset': {
|
|
5326
|
+
regex: /sendResetPassword\s*:\s*async\s*\([^)]*\)\s*=>\s*\{[\s\S]*?\},?/,
|
|
5327
|
+
fn: `sendResetPassword: async ({ user, url, token }, request) => {
|
|
5328
|
+
void sendEmail({
|
|
5329
|
+
to: user.email,
|
|
5330
|
+
subject: "Reset your password",
|
|
5331
|
+
text: \\\`Click the link to reset your password: \\\${url}\\\`,
|
|
5332
|
+
});
|
|
5333
|
+
}`,
|
|
5334
|
+
},
|
|
5335
|
+
'email-verification': {
|
|
5336
|
+
regex: /sendVerificationEmail\s*:\s*async\s*\([^)]*\)\s*=>\s*\{[\s\S]*?\},?/,
|
|
5337
|
+
fn: `sendVerificationEmail: async ({ user, url, token }, request) => {
|
|
5338
|
+
void sendEmail({
|
|
5339
|
+
to: user.email,
|
|
5340
|
+
subject: "Verify your email address",
|
|
5341
|
+
text: \\\`Click the link to verify your email: \\\${url}\\\`,
|
|
5342
|
+
});
|
|
5343
|
+
}`,
|
|
5344
|
+
},
|
|
5345
|
+
'magic-link': {
|
|
5346
|
+
regex: /sendMagicLink\s*:\s*async\s*\([^)]*\)\s*=>\s*\{[\s\S]*?\},?/,
|
|
5347
|
+
fn: `sendMagicLink: async ({ email, token, url }, ctx) => {
|
|
5348
|
+
void sendEmail({
|
|
5349
|
+
to: email,
|
|
5350
|
+
subject: "Sign in to your account",
|
|
5351
|
+
text: \\\`Click the link to sign in: \\\${url}\\\`,
|
|
5352
|
+
});
|
|
5353
|
+
}`,
|
|
5354
|
+
},
|
|
5355
|
+
'org-invitation': {
|
|
5356
|
+
regex: /sendInvitationEmail\s*:\s*async\s*\([^)]*\)\s*=>\s*\{[\s\S]*?\},?/,
|
|
5357
|
+
fn: `sendInvitationEmail: async ({ data, request }: {
|
|
5358
|
+
data: {
|
|
5359
|
+
invitation: {
|
|
5360
|
+
id: string;
|
|
5361
|
+
organizationId: string;
|
|
5362
|
+
email: string;
|
|
5363
|
+
role: string;
|
|
5364
|
+
status: "pending" | "accepted" | "rejected" | "canceled";
|
|
5365
|
+
inviterId: string;
|
|
5366
|
+
expiresAt: Date;
|
|
5367
|
+
createdAt: Date;
|
|
5368
|
+
teamId?: string | null | undefined;
|
|
5369
|
+
};
|
|
5370
|
+
organization: { name?: string; slug?: string };
|
|
5371
|
+
inviter: { user: { name?: string; email?: string } };
|
|
5372
|
+
};
|
|
5373
|
+
request?: Request;
|
|
5374
|
+
}) => {
|
|
5375
|
+
const { invitation, organization, inviter } = data;
|
|
5376
|
+
const baseUrl = process.env.BETTER_AUTH_URL || 'http://localhost:3000';
|
|
5377
|
+
const url = \\\`\\\${baseUrl}/accept-invitation?id=\\\${invitation.id}\\\`;
|
|
5378
|
+
|
|
5379
|
+
const subject = \\\`${escapedSubject}\\\`
|
|
5380
|
+
.replace(/{{organization.name}}/g, organization?.name || '')
|
|
5381
|
+
.replace(/{{invitation.role}}/g, invitation.role || '')
|
|
5382
|
+
.replace(/{{inviter.user.name}}/g, inviter?.user?.name || '')
|
|
5383
|
+
.replace(/{{inviter.user.email}}/g, inviter?.user?.email || '')
|
|
5384
|
+
.replace(/{{invitation.email}}/g, invitation.email || '');
|
|
5385
|
+
|
|
5386
|
+
const html = \\\`${escapedHtml}\\\`
|
|
5387
|
+
.replace(/{{invitation.url}}/g, url)
|
|
5388
|
+
.replace(/{{invitation.role}}/g, invitation.role || '')
|
|
5389
|
+
.replace(/{{organization.name}}/g, organization?.name || '')
|
|
5390
|
+
.replace(/{{organization.slug}}/g, organization?.slug || '')
|
|
5391
|
+
.replace(/{{inviter.user.name}}/g, inviter?.user?.name || '')
|
|
5392
|
+
.replace(/{{inviter.user.email}}/g, inviter?.user?.email || '')
|
|
5393
|
+
.replace(/{{invitation.email}}/g, invitation.email || '')
|
|
5394
|
+
.replace(/{{invitation.expiresAt}}/g, invitation.expiresAt?.toLocaleString() || '')
|
|
5395
|
+
.replace(/{{expiresIn}}/g, invitation.expiresAt ? \\\`\\\${Math.ceil((invitation.expiresAt.getTime() - Date.now()) / (1000 * 60 * 60 * 24))} days\\\` : '');
|
|
5396
|
+
|
|
5397
|
+
void sendEmail({
|
|
5398
|
+
to: invitation.email,
|
|
5399
|
+
subject,
|
|
5400
|
+
html,
|
|
5401
|
+
});
|
|
5402
|
+
}`,
|
|
5403
|
+
},
|
|
5404
|
+
};
|
|
5405
|
+
const handler = handlers[templateId];
|
|
5406
|
+
if (!handler) {
|
|
5407
|
+
return res
|
|
5408
|
+
.status(400)
|
|
5409
|
+
.json({ success: false, message: 'Unsupported templateId for apply' });
|
|
5410
|
+
}
|
|
5411
|
+
if (!fileContent.includes('const sendEmail = async')) {
|
|
5412
|
+
const insertPoint = fileContent.indexOf('export const auth');
|
|
5413
|
+
fileContent =
|
|
5414
|
+
fileContent.slice(0, insertPoint) +
|
|
5415
|
+
`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` +
|
|
5416
|
+
fileContent.slice(insertPoint);
|
|
5417
|
+
}
|
|
5418
|
+
if (handler.regex.test(fileContent)) {
|
|
5419
|
+
fileContent = fileContent.replace(handler.regex, `${handler.fn},`);
|
|
5420
|
+
}
|
|
5421
|
+
else {
|
|
5422
|
+
if (templateId === 'org-invitation') {
|
|
5423
|
+
const orgPluginRegex = /organization\(\s*\{\s*/;
|
|
5424
|
+
if (!orgPluginRegex.test(fileContent)) {
|
|
5425
|
+
return res.status(400).json({
|
|
5426
|
+
success: false,
|
|
5427
|
+
message: 'organization plugin config not found in auth.ts',
|
|
5428
|
+
});
|
|
5429
|
+
}
|
|
5430
|
+
fileContent = fileContent.replace(orgPluginRegex, (m) => `${m}${handler.fn},\n `);
|
|
5431
|
+
}
|
|
5432
|
+
else {
|
|
5433
|
+
const emailAndPasswordRegex = /emailAndPassword\s*:\s*\{\s*/;
|
|
5434
|
+
if (!emailAndPasswordRegex.test(fileContent)) {
|
|
5435
|
+
return res.status(400).json({
|
|
5436
|
+
success: false,
|
|
5437
|
+
message: 'emailAndPassword config not found in auth.ts',
|
|
5438
|
+
});
|
|
5439
|
+
}
|
|
5440
|
+
fileContent = fileContent.replace(emailAndPasswordRegex, (m) => `${m}${handler.fn},\n `);
|
|
5441
|
+
}
|
|
5442
|
+
}
|
|
5443
|
+
writeFileSync(authPath, fileContent, 'utf-8');
|
|
5444
|
+
res.json({ success: true, path: authPath });
|
|
5445
|
+
}
|
|
5446
|
+
catch (error) {
|
|
5447
|
+
res.status(500).json({
|
|
5448
|
+
success: false,
|
|
5449
|
+
message: error?.message || 'Failed to apply invitation template',
|
|
5450
|
+
});
|
|
5451
|
+
}
|
|
5452
|
+
});
|
|
5294
5453
|
return router;
|
|
5295
5454
|
}
|
|
5296
5455
|
//# sourceMappingURL=routes.js.map
|