better-auth-studio 1.0.59-beta.12 → 1.0.59-beta.14

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.
@@ -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,CA4wLR"}
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
@@ -5122,14 +5122,11 @@ export const authClient = createAuthClient({
5122
5122
  }
5123
5123
  const envPath = join(process.cwd(), '.env');
5124
5124
  const envLocalPath = join(process.cwd(), '.env.local');
5125
- // Try .env.local first, then .env
5126
5125
  const targetPath = existsSync(envLocalPath) ? envLocalPath : envPath;
5127
5126
  const envContent = existsSync(targetPath) ? readFileSync(targetPath, 'utf-8') : '';
5128
- // Generate environment variable names
5129
5127
  const providerUpper = provider.toUpperCase();
5130
5128
  const clientIdKey = `${providerUpper}_CLIENT_ID`;
5131
5129
  const clientSecretKey = `${providerUpper}_CLIENT_SECRET`;
5132
- // Parse existing .env file
5133
5130
  const envLines = envContent.split('\n');
5134
5131
  const existingCredentials = {};
5135
5132
  envLines.forEach((line) => {
@@ -5291,7 +5288,6 @@ export const authClient = createAuthClient({
5291
5288
  });
5292
5289
  }
5293
5290
  });
5294
- // Apply org invitation email template into examples auth.ts
5295
5291
  router.post('/api/tools/apply-email-template', async (req, res) => {
5296
5292
  try {
5297
5293
  const { subject, html, templateId } = req.body || {};
@@ -5307,13 +5303,10 @@ export const authClient = createAuthClient({
5307
5303
  let fileContent = readFileSync(authPath, 'utf-8');
5308
5304
  const escapedSubject = subject.replace(/`/g, '\\`').replace(/\${/g, '\\${');
5309
5305
  const escapedHtml = html.replace(/`/g, '\\`').replace(/\${/g, '\\${');
5310
- // Ensure Resend import
5311
5306
  if (!fileContent.includes("from 'resend'")) {
5312
5307
  fileContent = `import { Resend } from 'resend';\n` + fileContent;
5313
5308
  }
5314
- // Ensure resend instance
5315
5309
  if (!fileContent.includes('const resend = new Resend(')) {
5316
- // place after imports
5317
5310
  const importBlockEnd = fileContent.indexOf('\n', fileContent.lastIndexOf('import'));
5318
5311
  if (importBlockEnd > -1) {
5319
5312
  fileContent =
@@ -5329,60 +5322,107 @@ export const authClient = createAuthClient({
5329
5322
  'password-reset': {
5330
5323
  regex: /sendResetPassword\s*:\s*async\s*\([^)]*\)\s*=>\s*\{[\s\S]*?\},?/,
5331
5324
  fn: `sendResetPassword: async ({ user, url, token }, request) => {
5325
+ const subject = \\\`${escapedSubject}\\\`
5326
+ .replace(/{{user.name}}/g, user?.name || '')
5327
+ .replace(/{{user.email}}/g, user?.email || '');
5328
+
5329
+ const html = \\\`${escapedHtml}\\\`
5330
+ .replace(/{{user.name}}/g, user?.name || '')
5331
+ .replace(/{{user.email}}/g, user?.email || '')
5332
+ .replace(/{{url}}/g, url || '')
5333
+ .replace(/{{token}}/g, token || '');
5334
+
5332
5335
  void sendEmail({
5333
5336
  to: user.email,
5334
- subject: "Reset your password",
5335
- text: \\\`Click the link to reset your password: \\\${url}\\\`,
5337
+ subject,
5338
+ html,
5336
5339
  });
5337
5340
  }`,
5338
5341
  },
5339
5342
  'email-verification': {
5340
5343
  regex: /sendVerificationEmail\s*:\s*async\s*\([^)]*\)\s*=>\s*\{[\s\S]*?\},?/,
5341
5344
  fn: `sendVerificationEmail: async ({ user, url, token }, request) => {
5345
+ const subject = \\\`${escapedSubject}\\\`
5346
+ .replace(/{{user.name}}/g, user?.name || '')
5347
+ .replace(/{{user.email}}/g, user?.email || '');
5348
+
5349
+ const html = \\\`${escapedHtml}\\\`
5350
+ .replace(/{{user.name}}/g, user?.name || '')
5351
+ .replace(/{{user.email}}/g, user?.email || '')
5352
+ .replace(/{{url}}/g, url || '')
5353
+ .replace(/{{token}}/g, token || '');
5354
+
5342
5355
  void sendEmail({
5343
5356
  to: user.email,
5344
- subject: "Verify your email address",
5345
- text: \\\`Click the link to verify your email: \\\${url}\\\`,
5357
+ subject,
5358
+ html,
5346
5359
  });
5347
5360
  }`,
5348
5361
  },
5349
5362
  'magic-link': {
5350
5363
  regex: /sendMagicLink\s*:\s*async\s*\([^)]*\)\s*=>\s*\{[\s\S]*?\},?/,
5351
5364
  fn: `sendMagicLink: async ({ email, token, url }, ctx) => {
5365
+ const subject = \\\`${escapedSubject}\\\`
5366
+ .replace(/{{user.email}}/g, email || '');
5367
+
5368
+ const html = \\\`${escapedHtml}\\\`
5369
+ .replace(/{{user.email}}/g, email || '')
5370
+ .replace(/{{url}}/g, url || '')
5371
+ .replace(/{{token}}/g, token || '');
5372
+
5352
5373
  void sendEmail({
5353
5374
  to: email,
5354
- subject: "Sign in to your account",
5355
- text: \\\`Click the link to sign in: \\\${url}\\\`,
5375
+ subject,
5376
+ html,
5356
5377
  });
5357
5378
  }`,
5358
5379
  },
5359
5380
  'org-invitation': {
5360
5381
  regex: /sendInvitationEmail\s*:\s*async\s*\([^)]*\)\s*=>\s*\{[\s\S]*?\},?/,
5361
- fn: `sendInvitationEmail: async ({ data, request }) => {
5382
+ fn: `sendInvitationEmail: async ({ data, request }: {
5383
+ data: {
5384
+ invitation: {
5385
+ id: string;
5386
+ organizationId: string;
5387
+ email: string;
5388
+ role: string;
5389
+ status: "pending" | "accepted" | "rejected" | "canceled";
5390
+ inviterId: string;
5391
+ expiresAt: Date;
5392
+ createdAt: Date;
5393
+ teamId?: string | null | undefined;
5394
+ };
5395
+ organization: { name?: string; slug?: string };
5396
+ inviter: { user: { name?: string; email?: string } };
5397
+ };
5398
+ request?: Request;
5399
+ }) => {
5362
5400
  const { invitation, organization, inviter } = data;
5363
- const url =
5364
- (invitation as any)?.url ||
5365
- (invitation as any)?.link ||
5366
- request?.url ||
5367
- invitation.id;
5401
+ const baseUrl = process.env.BETTER_AUTH_URL || 'http://localhost:3000';
5402
+ const url = \\\`\\\${baseUrl}/accept-invitation?id=\\\${invitation.id}\\\`;
5368
5403
 
5369
5404
  const subject = \\\`${escapedSubject}\\\`
5370
5405
  .replace(/{{organization.name}}/g, organization?.name || '')
5371
5406
  .replace(/{{invitation.role}}/g, invitation.role || '')
5372
5407
  .replace(/{{inviter.user.name}}/g, inviter?.user?.name || '')
5373
- .replace(/{{inviter.user.email}}/g, inviter?.user?.email || '');
5408
+ .replace(/{{inviter.user.email}}/g, inviter?.user?.email || '')
5409
+ .replace(/{{invitation.email}}/g, invitation.email || '');
5374
5410
 
5375
5411
  const html = \\\`${escapedHtml}\\\`
5376
5412
  .replace(/{{invitation.url}}/g, url)
5377
5413
  .replace(/{{invitation.role}}/g, invitation.role || '')
5378
5414
  .replace(/{{organization.name}}/g, organization?.name || '')
5415
+ .replace(/{{organization.slug}}/g, organization?.slug || '')
5379
5416
  .replace(/{{inviter.user.name}}/g, inviter?.user?.name || '')
5380
- .replace(/{{inviter.user.email}}/g, inviter?.user?.email || '');
5417
+ .replace(/{{inviter.user.email}}/g, inviter?.user?.email || '')
5418
+ .replace(/{{invitation.email}}/g, invitation.email || '')
5419
+ .replace(/{{invitation.expiresAt}}/g, invitation.expiresAt?.toLocaleString() || '')
5420
+ .replace(/{{expiresIn}}/g, invitation.expiresAt ? \\\`\\\${Math.ceil((invitation.expiresAt.getTime() - Date.now()) / (1000 * 60 * 60 * 24))} days\\\` : '');
5381
5421
 
5382
- await sendEmail({
5422
+ void sendEmail({
5383
5423
  to: invitation.email,
5384
5424
  subject,
5385
- text: url,
5425
+ html,
5386
5426
  });
5387
5427
  }`,
5388
5428
  },
@@ -5393,19 +5433,17 @@ export const authClient = createAuthClient({
5393
5433
  .status(400)
5394
5434
  .json({ success: false, message: 'Unsupported templateId for apply' });
5395
5435
  }
5396
- // ensure sendEmail helper exists
5397
5436
  if (!fileContent.includes('const sendEmail = async')) {
5398
5437
  const insertPoint = fileContent.indexOf('export const auth');
5399
5438
  fileContent =
5400
5439
  fileContent.slice(0, insertPoint) +
5401
- `const sendEmail = async ({ to, subject, text }: { to: string; subject: string; text: string }) => {\n console.log(\`Sending email to \${to} | \${subject} | \${text}\`);\n};\n\n` +
5440
+ `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` +
5402
5441
  fileContent.slice(insertPoint);
5403
5442
  }
5404
5443
  if (handler.regex.test(fileContent)) {
5405
5444
  fileContent = fileContent.replace(handler.regex, `${handler.fn},`);
5406
5445
  }
5407
5446
  else {
5408
- // try to inject into emailAndPassword or organization plugin based on template
5409
5447
  if (templateId === 'org-invitation') {
5410
5448
  const orgPluginRegex = /organization\(\s*\{\s*/;
5411
5449
  if (!orgPluginRegex.test(fileContent)) {