@dyrected/core 2.5.17 → 2.5.18

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/index.cjs CHANGED
@@ -2313,11 +2313,37 @@ function buildWelcomeEmail(config, args) {
2313
2313
  return {
2314
2314
  subject: custom?.subject ?? "Welcome \u2014 your account is ready",
2315
2315
  html: custom?.html ?? `
2316
- <div style="font-family:sans-serif;max-width:600px;margin:0 auto">
2317
- <h2>Welcome!</h2>
2318
- <p>Your account has been created. You can now log in with:</p>
2319
- <p><strong>${args.email}</strong></p>
2320
- </div>`
2316
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f9fafb;table-layout:fixed">
2317
+ <tr>
2318
+ <td align="center" style="padding:40px 16px">
2319
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;max-width:600px;background-color:#ffffff;border-radius:12px;border:1px solid #e5e7eb;table-layout:fixed">
2320
+ <tr>
2321
+ <td style="padding:32px 32px 0">
2322
+ <p style="margin:0 0 4px;font-size:12px;font-weight:600;color:#6b7280;font-family:sans-serif;text-transform:uppercase;letter-spacing:0.05em">Dyrected</p>
2323
+ <h1 style="margin:0 0 24px;font-size:22px;font-weight:700;color:#111827;font-family:sans-serif">Welcome!</h1>
2324
+ </td>
2325
+ </tr>
2326
+ <tr>
2327
+ <td style="padding:0 32px">
2328
+ <p style="margin:0 0 12px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">Your account has been created. You can now log in with:</p>
2329
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f3f4f6;border-radius:6px;table-layout:fixed">
2330
+ <tr>
2331
+ <td style="padding:12px 16px;font-size:14px;font-weight:600;color:#111827;font-family:sans-serif;word-break:break-all">
2332
+ ${args.email}
2333
+ </td>
2334
+ </tr>
2335
+ </table>
2336
+ </td>
2337
+ </tr>
2338
+ <tr>
2339
+ <td style="padding:32px">
2340
+ <p style="margin:0;font-size:12px;color:#9ca3af;font-family:sans-serif">If you didn't create this account, you can safely ignore this email.</p>
2341
+ </td>
2342
+ </tr>
2343
+ </table>
2344
+ </td>
2345
+ </tr>
2346
+ </table>`
2321
2347
  };
2322
2348
  }
2323
2349
  function buildInviteEmail(config, args) {
@@ -2325,24 +2351,89 @@ function buildInviteEmail(config, args) {
2325
2351
  return {
2326
2352
  subject: custom?.subject ?? "You've been invited",
2327
2353
  html: custom?.html ?? `
2328
- <div style="font-family:sans-serif;max-width:600px;margin:0 auto">
2329
- <h2>You've been invited</h2>
2330
- ${args.invitedByEmail ? `<p>Invited by <strong>${args.invitedByEmail}</strong>.</p>` : ""}
2331
- <p>Use the token below to accept your invitation. It expires in 7 days.</p>
2332
- <pre style="background:#f4f4f4;padding:12px;border-radius:4px;word-break:break-all">${args.token}</pre>
2333
- </div>`
2354
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f9fafb;table-layout:fixed">
2355
+ <tr>
2356
+ <td align="center" style="padding:40px 16px">
2357
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;max-width:600px;background-color:#ffffff;border-radius:12px;border:1px solid #e5e7eb;table-layout:fixed">
2358
+ <tr>
2359
+ <td style="padding:32px 32px 0">
2360
+ <p style="margin:0 0 4px;font-size:12px;font-weight:600;color:#6b7280;font-family:sans-serif;text-transform:uppercase;letter-spacing:0.05em">Dyrected</p>
2361
+ <h1 style="margin:0 0 24px;font-size:22px;font-weight:700;color:#111827;font-family:sans-serif">You've been invited</h1>
2362
+ </td>
2363
+ </tr>
2364
+ <tr>
2365
+ <td style="padding:0 32px">
2366
+ ${args.invitedByEmail ? `<p style="margin:0 0 12px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">You were invited by <strong style="color:#111827">${args.invitedByEmail}</strong>.</p>` : ""}
2367
+ <p style="margin:0 0 16px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">Use the token below to accept your invitation. It expires in 7 days.</p>
2368
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f3f4f6;border-radius:6px;table-layout:fixed">
2369
+ <tr>
2370
+ <td style="padding:12px 16px;font-family:monospace;font-size:12px;color:#374151;word-break:break-all;white-space:normal;line-height:1.4">
2371
+ ${args.token}
2372
+ </td>
2373
+ </tr>
2374
+ </table>
2375
+ </td>
2376
+ </tr>
2377
+ <tr>
2378
+ <td style="padding:32px">
2379
+ <p style="margin:0;font-size:12px;color:#9ca3af;font-family:sans-serif">If you weren't expecting this invitation, you can safely ignore this email.</p>
2380
+ </td>
2381
+ </tr>
2382
+ </table>
2383
+ </td>
2384
+ </tr>
2385
+ </table>`
2334
2386
  };
2335
2387
  }
2336
2388
  function buildResetPasswordEmail(config, args) {
2337
2389
  const custom = config.email?.templates?.resetPassword?.(args);
2390
+ const resetLink = args.url;
2338
2391
  return {
2339
2392
  subject: custom?.subject ?? "Reset your password",
2340
2393
  html: custom?.html ?? `
2341
- <div style="font-family:sans-serif;max-width:600px;margin:0 auto">
2342
- <h2>Reset your password</h2>
2343
- <p>Use the token below to reset your password. It expires in 1 hour.</p>
2344
- <pre style="background:#f4f4f4;padding:12px;border-radius:4px;word-break:break-all">${args.token}</pre>
2345
- </div>`
2394
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f9fafb;table-layout:fixed">
2395
+ <tr>
2396
+ <td align="center" style="padding:40px 16px">
2397
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;max-width:600px;background-color:#ffffff;border-radius:12px;border:1px solid #e5e7eb;table-layout:fixed">
2398
+ <tr>
2399
+ <td style="padding:32px 32px 0">
2400
+ <p style="margin:0 0 4px;font-size:12px;font-weight:600;color:#6b7280;font-family:sans-serif;text-transform:uppercase;letter-spacing:0.05em">Dyrected</p>
2401
+ <h1 style="margin:0 0 24px;font-size:22px;font-weight:700;color:#111827;font-family:sans-serif">Reset your password</h1>
2402
+ </td>
2403
+ </tr>
2404
+ <tr>
2405
+ <td style="padding:0 32px">
2406
+ <p style="margin:0 0 24px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">We received a request to reset your password. Use the button below to set a new password. It will expire in 1 hour.</p>
2407
+ ${resetLink ? `
2408
+ <table cellpadding="0" cellspacing="0" border="0" style="margin-bottom:24px">
2409
+ <tr>
2410
+ <td style="border-radius:6px;background-color:#111827">
2411
+ <a href="${resetLink}" style="display:inline-block;padding:12px 28px;font-size:14px;font-weight:600;color:#ffffff;text-decoration:none;font-family:sans-serif;border-radius:6px">
2412
+ Reset Password
2413
+ </a>
2414
+ </td>
2415
+ </tr>
2416
+ </table>
2417
+ ` : ""}
2418
+ <p style="margin:0 0 8px;font-size:12px;color:#9ca3af;font-family:sans-serif">Or copy and paste this token manually in the admin dashboard:</p>
2419
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f3f4f6;border-radius:6px;table-layout:fixed">
2420
+ <tr>
2421
+ <td style="padding:12px 16px;font-family:monospace;font-size:12px;color:#374151;word-break:break-all;white-space:normal;line-height:1.4">
2422
+ ${args.token}
2423
+ </td>
2424
+ </tr>
2425
+ </table>
2426
+ </td>
2427
+ </tr>
2428
+ <tr>
2429
+ <td style="padding:32px">
2430
+ <p style="margin:0;font-size:12px;color:#9ca3af;font-family:sans-serif">If you didn't request a password reset, you can safely ignore this email.</p>
2431
+ </td>
2432
+ </tr>
2433
+ </table>
2434
+ </td>
2435
+ </tr>
2436
+ </table>`
2346
2437
  };
2347
2438
  }
2348
2439
  function buildPasswordChangedEmail(config, args) {
@@ -2350,11 +2441,44 @@ function buildPasswordChangedEmail(config, args) {
2350
2441
  return {
2351
2442
  subject: custom?.subject ?? "Your password has been changed",
2352
2443
  html: custom?.html ?? `
2353
- <div style="font-family:sans-serif;max-width:600px;margin:0 auto">
2354
- <h2>Password changed</h2>
2355
- <p>The password for <strong>${args.email}</strong> was just changed.</p>
2356
- <p>If you did not make this change, please contact support immediately.</p>
2357
- </div>`
2444
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f9fafb;table-layout:fixed">
2445
+ <tr>
2446
+ <td align="center" style="padding:40px 16px">
2447
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;max-width:600px;background-color:#ffffff;border-radius:12px;border:1px solid #e5e7eb;table-layout:fixed">
2448
+ <tr>
2449
+ <td style="padding:32px 32px 0">
2450
+ <p style="margin:0 0 4px;font-size:12px;font-weight:600;color:#6b7280;font-family:sans-serif;text-transform:uppercase;letter-spacing:0.05em">Dyrected</p>
2451
+ <h1 style="margin:0 0 24px;font-size:22px;font-weight:700;color:#111827;font-family:sans-serif">Password changed</h1>
2452
+ </td>
2453
+ </tr>
2454
+ <tr>
2455
+ <td style="padding:0 32px">
2456
+ <p style="margin:0 0 12px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">The password for your account was just changed:</p>
2457
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f3f4f6;border-radius:6px;table-layout:fixed">
2458
+ <tr>
2459
+ <td style="padding:12px 16px;font-size:14px;font-weight:600;color:#111827;font-family:sans-serif;word-break:break-all">
2460
+ ${args.email}
2461
+ </td>
2462
+ </tr>
2463
+ </table>
2464
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;margin-top:16px;background-color:#fef2f2;border-radius:6px;border:1px solid #fecaca;table-layout:fixed">
2465
+ <tr>
2466
+ <td style="padding:12px 16px;font-size:13px;color:#b91c1c;line-height:1.5;font-family:sans-serif">
2467
+ If you did not make this change, please contact support immediately.
2468
+ </td>
2469
+ </tr>
2470
+ </table>
2471
+ </td>
2472
+ </tr>
2473
+ <tr>
2474
+ <td style="padding:32px">
2475
+ <p style="margin:0;font-size:12px;color:#9ca3af;font-family:sans-serif">This is an automated security notification.</p>
2476
+ </td>
2477
+ </tr>
2478
+ </table>
2479
+ </td>
2480
+ </tr>
2481
+ </table>`
2358
2482
  };
2359
2483
  }
2360
2484
 
@@ -2515,8 +2639,10 @@ var AuthController = class {
2515
2639
  { sub: user.id, email: user.email, collection: this.collection.slug, purpose: "reset" },
2516
2640
  "1h"
2517
2641
  );
2642
+ const resetUrl = body?.resetUrl;
2643
+ const url = resetUrl ? `${resetUrl}${resetUrl.includes("?") ? "&" : "?"}token=${encodeURIComponent(resetToken)}` : void 0;
2518
2644
  try {
2519
- const { subject, html } = buildResetPasswordEmail(config, { token: resetToken });
2645
+ const { subject, html } = buildResetPasswordEmail(config, { token: resetToken, url });
2520
2646
  await sendEmail(config, { to: user.email, subject, html });
2521
2647
  } catch (err) {
2522
2648
  console.error("[dyrected/core] Failed to send password reset email:", err);
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { D as DyrectedConfig, F as Field, C as CollectionConfig, P as Prettify, I as InferDocShape, S as SystemDocFields, A as AuthDocFields, U as UploadDocFields, G as GlobalConfig } from './app-BElen1tP.cjs';
2
- export { a as AccessFunction, b as AdminConfig, c as AuthenticatedUser, B as BaseDocument, d as Block, e as CollectionAfterChangeHook, f as CollectionAfterDeleteHook, g as CollectionAfterReadHook, h as CollectionBeforeChangeHook, i as CollectionBeforeDeleteHook, j as CollectionBeforeReadHook, k as DatabaseAdapter, l as DynamicOptionItem, m as DynamicOptionsConfig, n as DynamicOptionsResolver, o as DynamicOptionsResolverArgs, p as DyrectedContext, q as FieldAfterReadHook, r as FieldBeforeChangeHook, s as FieldHook, t as FieldType, u as FileData, v as GlobalAfterChangeHook, w as GlobalAfterReadHook, x as GlobalBeforeChangeHook, y as GlobalBeforeReadHook, H as HookFunction, z as HookRequestContext, E as ImageService, J as PaginatedResult, K as StorageAdapter, L as UploadConfig, M as createDyrectedApp } from './app-BElen1tP.cjs';
1
+ import { D as DyrectedConfig, F as Field, C as CollectionConfig, P as Prettify, I as InferDocShape, S as SystemDocFields, A as AuthDocFields, U as UploadDocFields, G as GlobalConfig } from './app-D0ffogDd.cjs';
2
+ export { a as AccessFunction, b as AdminConfig, c as AuthenticatedUser, B as BaseDocument, d as Block, e as CollectionAfterChangeHook, f as CollectionAfterDeleteHook, g as CollectionAfterReadHook, h as CollectionBeforeChangeHook, i as CollectionBeforeDeleteHook, j as CollectionBeforeReadHook, k as DatabaseAdapter, l as DynamicOptionItem, m as DynamicOptionsConfig, n as DynamicOptionsResolver, o as DynamicOptionsResolverArgs, p as DyrectedContext, q as FieldAfterReadHook, r as FieldBeforeChangeHook, s as FieldHook, t as FieldType, u as FileData, v as GlobalAfterChangeHook, w as GlobalAfterReadHook, x as GlobalBeforeChangeHook, y as GlobalBeforeReadHook, H as HookFunction, z as HookRequestContext, E as ImageService, J as PaginatedResult, K as StorageAdapter, L as UploadConfig, M as createDyrectedApp } from './app-D0ffogDd.cjs';
3
3
  import 'hono/types';
4
4
  import 'hono';
5
5
 
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { D as DyrectedConfig, F as Field, C as CollectionConfig, P as Prettify, I as InferDocShape, S as SystemDocFields, A as AuthDocFields, U as UploadDocFields, G as GlobalConfig } from './app-BElen1tP.js';
2
- export { a as AccessFunction, b as AdminConfig, c as AuthenticatedUser, B as BaseDocument, d as Block, e as CollectionAfterChangeHook, f as CollectionAfterDeleteHook, g as CollectionAfterReadHook, h as CollectionBeforeChangeHook, i as CollectionBeforeDeleteHook, j as CollectionBeforeReadHook, k as DatabaseAdapter, l as DynamicOptionItem, m as DynamicOptionsConfig, n as DynamicOptionsResolver, o as DynamicOptionsResolverArgs, p as DyrectedContext, q as FieldAfterReadHook, r as FieldBeforeChangeHook, s as FieldHook, t as FieldType, u as FileData, v as GlobalAfterChangeHook, w as GlobalAfterReadHook, x as GlobalBeforeChangeHook, y as GlobalBeforeReadHook, H as HookFunction, z as HookRequestContext, E as ImageService, J as PaginatedResult, K as StorageAdapter, L as UploadConfig, M as createDyrectedApp } from './app-BElen1tP.js';
1
+ import { D as DyrectedConfig, F as Field, C as CollectionConfig, P as Prettify, I as InferDocShape, S as SystemDocFields, A as AuthDocFields, U as UploadDocFields, G as GlobalConfig } from './app-D0ffogDd.js';
2
+ export { a as AccessFunction, b as AdminConfig, c as AuthenticatedUser, B as BaseDocument, d as Block, e as CollectionAfterChangeHook, f as CollectionAfterDeleteHook, g as CollectionAfterReadHook, h as CollectionBeforeChangeHook, i as CollectionBeforeDeleteHook, j as CollectionBeforeReadHook, k as DatabaseAdapter, l as DynamicOptionItem, m as DynamicOptionsConfig, n as DynamicOptionsResolver, o as DynamicOptionsResolverArgs, p as DyrectedContext, q as FieldAfterReadHook, r as FieldBeforeChangeHook, s as FieldHook, t as FieldType, u as FileData, v as GlobalAfterChangeHook, w as GlobalAfterReadHook, x as GlobalBeforeChangeHook, y as GlobalBeforeReadHook, H as HookFunction, z as HookRequestContext, E as ImageService, J as PaginatedResult, K as StorageAdapter, L as UploadConfig, M as createDyrectedApp } from './app-D0ffogDd.js';
3
3
  import 'hono/types';
4
4
  import 'hono';
5
5
 
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  executeFieldBeforeChange,
5
5
  normalizeConfig,
6
6
  runCollectionHooks
7
- } from "./chunk-YNJ3YC4N.js";
7
+ } from "./chunk-TUUHGLB5.js";
8
8
 
9
9
  // src/utils/setup-prompt.ts
10
10
  function buildEnvironmentSection(frameworkLabel, isSelfHosted, config) {
package/dist/server.cjs CHANGED
@@ -1184,11 +1184,37 @@ function buildWelcomeEmail(config, args) {
1184
1184
  return {
1185
1185
  subject: custom?.subject ?? "Welcome \u2014 your account is ready",
1186
1186
  html: custom?.html ?? `
1187
- <div style="font-family:sans-serif;max-width:600px;margin:0 auto">
1188
- <h2>Welcome!</h2>
1189
- <p>Your account has been created. You can now log in with:</p>
1190
- <p><strong>${args.email}</strong></p>
1191
- </div>`
1187
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f9fafb;table-layout:fixed">
1188
+ <tr>
1189
+ <td align="center" style="padding:40px 16px">
1190
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;max-width:600px;background-color:#ffffff;border-radius:12px;border:1px solid #e5e7eb;table-layout:fixed">
1191
+ <tr>
1192
+ <td style="padding:32px 32px 0">
1193
+ <p style="margin:0 0 4px;font-size:12px;font-weight:600;color:#6b7280;font-family:sans-serif;text-transform:uppercase;letter-spacing:0.05em">Dyrected</p>
1194
+ <h1 style="margin:0 0 24px;font-size:22px;font-weight:700;color:#111827;font-family:sans-serif">Welcome!</h1>
1195
+ </td>
1196
+ </tr>
1197
+ <tr>
1198
+ <td style="padding:0 32px">
1199
+ <p style="margin:0 0 12px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">Your account has been created. You can now log in with:</p>
1200
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f3f4f6;border-radius:6px;table-layout:fixed">
1201
+ <tr>
1202
+ <td style="padding:12px 16px;font-size:14px;font-weight:600;color:#111827;font-family:sans-serif;word-break:break-all">
1203
+ ${args.email}
1204
+ </td>
1205
+ </tr>
1206
+ </table>
1207
+ </td>
1208
+ </tr>
1209
+ <tr>
1210
+ <td style="padding:32px">
1211
+ <p style="margin:0;font-size:12px;color:#9ca3af;font-family:sans-serif">If you didn't create this account, you can safely ignore this email.</p>
1212
+ </td>
1213
+ </tr>
1214
+ </table>
1215
+ </td>
1216
+ </tr>
1217
+ </table>`
1192
1218
  };
1193
1219
  }
1194
1220
  function buildInviteEmail(config, args) {
@@ -1196,24 +1222,89 @@ function buildInviteEmail(config, args) {
1196
1222
  return {
1197
1223
  subject: custom?.subject ?? "You've been invited",
1198
1224
  html: custom?.html ?? `
1199
- <div style="font-family:sans-serif;max-width:600px;margin:0 auto">
1200
- <h2>You've been invited</h2>
1201
- ${args.invitedByEmail ? `<p>Invited by <strong>${args.invitedByEmail}</strong>.</p>` : ""}
1202
- <p>Use the token below to accept your invitation. It expires in 7 days.</p>
1203
- <pre style="background:#f4f4f4;padding:12px;border-radius:4px;word-break:break-all">${args.token}</pre>
1204
- </div>`
1225
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f9fafb;table-layout:fixed">
1226
+ <tr>
1227
+ <td align="center" style="padding:40px 16px">
1228
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;max-width:600px;background-color:#ffffff;border-radius:12px;border:1px solid #e5e7eb;table-layout:fixed">
1229
+ <tr>
1230
+ <td style="padding:32px 32px 0">
1231
+ <p style="margin:0 0 4px;font-size:12px;font-weight:600;color:#6b7280;font-family:sans-serif;text-transform:uppercase;letter-spacing:0.05em">Dyrected</p>
1232
+ <h1 style="margin:0 0 24px;font-size:22px;font-weight:700;color:#111827;font-family:sans-serif">You've been invited</h1>
1233
+ </td>
1234
+ </tr>
1235
+ <tr>
1236
+ <td style="padding:0 32px">
1237
+ ${args.invitedByEmail ? `<p style="margin:0 0 12px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">You were invited by <strong style="color:#111827">${args.invitedByEmail}</strong>.</p>` : ""}
1238
+ <p style="margin:0 0 16px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">Use the token below to accept your invitation. It expires in 7 days.</p>
1239
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f3f4f6;border-radius:6px;table-layout:fixed">
1240
+ <tr>
1241
+ <td style="padding:12px 16px;font-family:monospace;font-size:12px;color:#374151;word-break:break-all;white-space:normal;line-height:1.4">
1242
+ ${args.token}
1243
+ </td>
1244
+ </tr>
1245
+ </table>
1246
+ </td>
1247
+ </tr>
1248
+ <tr>
1249
+ <td style="padding:32px">
1250
+ <p style="margin:0;font-size:12px;color:#9ca3af;font-family:sans-serif">If you weren't expecting this invitation, you can safely ignore this email.</p>
1251
+ </td>
1252
+ </tr>
1253
+ </table>
1254
+ </td>
1255
+ </tr>
1256
+ </table>`
1205
1257
  };
1206
1258
  }
1207
1259
  function buildResetPasswordEmail(config, args) {
1208
1260
  const custom = config.email?.templates?.resetPassword?.(args);
1261
+ const resetLink = args.url;
1209
1262
  return {
1210
1263
  subject: custom?.subject ?? "Reset your password",
1211
1264
  html: custom?.html ?? `
1212
- <div style="font-family:sans-serif;max-width:600px;margin:0 auto">
1213
- <h2>Reset your password</h2>
1214
- <p>Use the token below to reset your password. It expires in 1 hour.</p>
1215
- <pre style="background:#f4f4f4;padding:12px;border-radius:4px;word-break:break-all">${args.token}</pre>
1216
- </div>`
1265
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f9fafb;table-layout:fixed">
1266
+ <tr>
1267
+ <td align="center" style="padding:40px 16px">
1268
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;max-width:600px;background-color:#ffffff;border-radius:12px;border:1px solid #e5e7eb;table-layout:fixed">
1269
+ <tr>
1270
+ <td style="padding:32px 32px 0">
1271
+ <p style="margin:0 0 4px;font-size:12px;font-weight:600;color:#6b7280;font-family:sans-serif;text-transform:uppercase;letter-spacing:0.05em">Dyrected</p>
1272
+ <h1 style="margin:0 0 24px;font-size:22px;font-weight:700;color:#111827;font-family:sans-serif">Reset your password</h1>
1273
+ </td>
1274
+ </tr>
1275
+ <tr>
1276
+ <td style="padding:0 32px">
1277
+ <p style="margin:0 0 24px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">We received a request to reset your password. Use the button below to set a new password. It will expire in 1 hour.</p>
1278
+ ${resetLink ? `
1279
+ <table cellpadding="0" cellspacing="0" border="0" style="margin-bottom:24px">
1280
+ <tr>
1281
+ <td style="border-radius:6px;background-color:#111827">
1282
+ <a href="${resetLink}" style="display:inline-block;padding:12px 28px;font-size:14px;font-weight:600;color:#ffffff;text-decoration:none;font-family:sans-serif;border-radius:6px">
1283
+ Reset Password
1284
+ </a>
1285
+ </td>
1286
+ </tr>
1287
+ </table>
1288
+ ` : ""}
1289
+ <p style="margin:0 0 8px;font-size:12px;color:#9ca3af;font-family:sans-serif">Or copy and paste this token manually in the admin dashboard:</p>
1290
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f3f4f6;border-radius:6px;table-layout:fixed">
1291
+ <tr>
1292
+ <td style="padding:12px 16px;font-family:monospace;font-size:12px;color:#374151;word-break:break-all;white-space:normal;line-height:1.4">
1293
+ ${args.token}
1294
+ </td>
1295
+ </tr>
1296
+ </table>
1297
+ </td>
1298
+ </tr>
1299
+ <tr>
1300
+ <td style="padding:32px">
1301
+ <p style="margin:0;font-size:12px;color:#9ca3af;font-family:sans-serif">If you didn't request a password reset, you can safely ignore this email.</p>
1302
+ </td>
1303
+ </tr>
1304
+ </table>
1305
+ </td>
1306
+ </tr>
1307
+ </table>`
1217
1308
  };
1218
1309
  }
1219
1310
  function buildPasswordChangedEmail(config, args) {
@@ -1221,11 +1312,44 @@ function buildPasswordChangedEmail(config, args) {
1221
1312
  return {
1222
1313
  subject: custom?.subject ?? "Your password has been changed",
1223
1314
  html: custom?.html ?? `
1224
- <div style="font-family:sans-serif;max-width:600px;margin:0 auto">
1225
- <h2>Password changed</h2>
1226
- <p>The password for <strong>${args.email}</strong> was just changed.</p>
1227
- <p>If you did not make this change, please contact support immediately.</p>
1228
- </div>`
1315
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f9fafb;table-layout:fixed">
1316
+ <tr>
1317
+ <td align="center" style="padding:40px 16px">
1318
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;max-width:600px;background-color:#ffffff;border-radius:12px;border:1px solid #e5e7eb;table-layout:fixed">
1319
+ <tr>
1320
+ <td style="padding:32px 32px 0">
1321
+ <p style="margin:0 0 4px;font-size:12px;font-weight:600;color:#6b7280;font-family:sans-serif;text-transform:uppercase;letter-spacing:0.05em">Dyrected</p>
1322
+ <h1 style="margin:0 0 24px;font-size:22px;font-weight:700;color:#111827;font-family:sans-serif">Password changed</h1>
1323
+ </td>
1324
+ </tr>
1325
+ <tr>
1326
+ <td style="padding:0 32px">
1327
+ <p style="margin:0 0 12px;font-size:14px;color:#4b5563;line-height:1.6;font-family:sans-serif">The password for your account was just changed:</p>
1328
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;background-color:#f3f4f6;border-radius:6px;table-layout:fixed">
1329
+ <tr>
1330
+ <td style="padding:12px 16px;font-size:14px;font-weight:600;color:#111827;font-family:sans-serif;word-break:break-all">
1331
+ ${args.email}
1332
+ </td>
1333
+ </tr>
1334
+ </table>
1335
+ <table cellpadding="0" cellspacing="0" border="0" style="width:100%;margin-top:16px;background-color:#fef2f2;border-radius:6px;border:1px solid #fecaca;table-layout:fixed">
1336
+ <tr>
1337
+ <td style="padding:12px 16px;font-size:13px;color:#b91c1c;line-height:1.5;font-family:sans-serif">
1338
+ If you did not make this change, please contact support immediately.
1339
+ </td>
1340
+ </tr>
1341
+ </table>
1342
+ </td>
1343
+ </tr>
1344
+ <tr>
1345
+ <td style="padding:32px">
1346
+ <p style="margin:0;font-size:12px;color:#9ca3af;font-family:sans-serif">This is an automated security notification.</p>
1347
+ </td>
1348
+ </tr>
1349
+ </table>
1350
+ </td>
1351
+ </tr>
1352
+ </table>`
1229
1353
  };
1230
1354
  }
1231
1355
 
@@ -1386,8 +1510,10 @@ var AuthController = class {
1386
1510
  { sub: user.id, email: user.email, collection: this.collection.slug, purpose: "reset" },
1387
1511
  "1h"
1388
1512
  );
1513
+ const resetUrl = body?.resetUrl;
1514
+ const url = resetUrl ? `${resetUrl}${resetUrl.includes("?") ? "&" : "?"}token=${encodeURIComponent(resetToken)}` : void 0;
1389
1515
  try {
1390
- const { subject, html } = buildResetPasswordEmail(config, { token: resetToken });
1516
+ const { subject, html } = buildResetPasswordEmail(config, { token: resetToken, url });
1391
1517
  await sendEmail(config, { to: user.email, subject, html });
1392
1518
  } catch (err) {
1393
1519
  console.error("[dyrected/core] Failed to send password reset email:", err);
package/dist/server.d.cts CHANGED
@@ -1,9 +1,9 @@
1
- import { p as DyrectedContext, D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-BElen1tP.cjs';
2
- export { M as createDyrectedApp } from './app-BElen1tP.cjs';
1
+ import { p as DyrectedContext, D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-D0ffogDd.cjs';
2
+ export { M as createDyrectedApp } from './app-D0ffogDd.cjs';
3
3
  import * as hono from 'hono';
4
4
  import { Hono, Context } from 'hono';
5
- import * as hono_utils_types from 'hono/utils/types';
6
5
  import * as hono_utils_http_status from 'hono/utils/http-status';
6
+ import * as hono_utils_types from 'hono/utils/types';
7
7
  import 'hono/types';
8
8
 
9
9
  /**
@@ -43,7 +43,7 @@ declare class AuthController {
43
43
  }, 400, "json">) | (Response & hono.TypedResponse<{
44
44
  token: string;
45
45
  user: {
46
- [x: string]: hono_utils_types.JSONValue;
46
+ [x: string]: any;
47
47
  id: string;
48
48
  };
49
49
  }, hono_utils_http_status.ContentfulStatusCode, "json">)>;
@@ -58,7 +58,7 @@ declare class AuthController {
58
58
  }, 401, "json">) | (Response & hono.TypedResponse<{
59
59
  token: string;
60
60
  user: {
61
- [x: string]: hono_utils_types.JSONValue;
61
+ [x: string]: any;
62
62
  };
63
63
  }, hono_utils_http_status.ContentfulStatusCode, "json">)>;
64
64
  logout(c: Context<DyrectedContext>): Promise<Response & hono.TypedResponse<{
@@ -74,7 +74,7 @@ declare class AuthController {
74
74
  error: true;
75
75
  message: string;
76
76
  }, 404, "json">) | (Response & hono.TypedResponse<{
77
- [x: string]: hono_utils_types.JSONValue;
77
+ [x: string]: any;
78
78
  id: string;
79
79
  }, hono_utils_http_status.ContentfulStatusCode, "json">)>;
80
80
  refreshToken(c: Context<DyrectedContext>): Promise<(Response & hono.TypedResponse<{
@@ -127,7 +127,7 @@ declare class AuthController {
127
127
  }, 409, "json">) | (Response & hono.TypedResponse<{
128
128
  token: string;
129
129
  user: {
130
- [x: string]: hono_utils_types.JSONValue;
130
+ [x: string]: any;
131
131
  id: string;
132
132
  };
133
133
  }, 201, "json">)>;
@@ -140,7 +140,7 @@ declare class CollectionController {
140
140
  message: string;
141
141
  }, 500, "json">) | (Response & hono.TypedResponse<{
142
142
  docs: {
143
- [x: string]: hono_utils_types.JSONValue;
143
+ [x: string]: any;
144
144
  }[];
145
145
  total: number;
146
146
  limit: number;
@@ -240,12 +240,12 @@ declare class MediaController {
240
240
  }, 500, "json">) | (Response & hono.TypedResponse<{
241
241
  message: string;
242
242
  }, 400, "json">) | (Response & hono.TypedResponse<{
243
- [x: string]: hono_utils_types.JSONValue;
243
+ [x: string]: any;
244
244
  id: string;
245
245
  }, 201, "json">)>;
246
246
  find(c: Context<DyrectedContext>): Promise<(Response & hono.TypedResponse<{
247
247
  docs: {
248
- [x: string]: hono_utils_types.JSONValue;
248
+ [x: string]: any;
249
249
  }[];
250
250
  total: number;
251
251
  limit: number;
package/dist/server.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { p as DyrectedContext, D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-BElen1tP.js';
2
- export { M as createDyrectedApp } from './app-BElen1tP.js';
1
+ import { p as DyrectedContext, D as DyrectedConfig, C as CollectionConfig, G as GlobalConfig } from './app-D0ffogDd.js';
2
+ export { M as createDyrectedApp } from './app-D0ffogDd.js';
3
3
  import * as hono from 'hono';
4
4
  import { Hono, Context } from 'hono';
5
- import * as hono_utils_types from 'hono/utils/types';
6
5
  import * as hono_utils_http_status from 'hono/utils/http-status';
6
+ import * as hono_utils_types from 'hono/utils/types';
7
7
  import 'hono/types';
8
8
 
9
9
  /**
@@ -43,7 +43,7 @@ declare class AuthController {
43
43
  }, 400, "json">) | (Response & hono.TypedResponse<{
44
44
  token: string;
45
45
  user: {
46
- [x: string]: hono_utils_types.JSONValue;
46
+ [x: string]: any;
47
47
  id: string;
48
48
  };
49
49
  }, hono_utils_http_status.ContentfulStatusCode, "json">)>;
@@ -58,7 +58,7 @@ declare class AuthController {
58
58
  }, 401, "json">) | (Response & hono.TypedResponse<{
59
59
  token: string;
60
60
  user: {
61
- [x: string]: hono_utils_types.JSONValue;
61
+ [x: string]: any;
62
62
  };
63
63
  }, hono_utils_http_status.ContentfulStatusCode, "json">)>;
64
64
  logout(c: Context<DyrectedContext>): Promise<Response & hono.TypedResponse<{
@@ -74,7 +74,7 @@ declare class AuthController {
74
74
  error: true;
75
75
  message: string;
76
76
  }, 404, "json">) | (Response & hono.TypedResponse<{
77
- [x: string]: hono_utils_types.JSONValue;
77
+ [x: string]: any;
78
78
  id: string;
79
79
  }, hono_utils_http_status.ContentfulStatusCode, "json">)>;
80
80
  refreshToken(c: Context<DyrectedContext>): Promise<(Response & hono.TypedResponse<{
@@ -127,7 +127,7 @@ declare class AuthController {
127
127
  }, 409, "json">) | (Response & hono.TypedResponse<{
128
128
  token: string;
129
129
  user: {
130
- [x: string]: hono_utils_types.JSONValue;
130
+ [x: string]: any;
131
131
  id: string;
132
132
  };
133
133
  }, 201, "json">)>;
@@ -140,7 +140,7 @@ declare class CollectionController {
140
140
  message: string;
141
141
  }, 500, "json">) | (Response & hono.TypedResponse<{
142
142
  docs: {
143
- [x: string]: hono_utils_types.JSONValue;
143
+ [x: string]: any;
144
144
  }[];
145
145
  total: number;
146
146
  limit: number;
@@ -240,12 +240,12 @@ declare class MediaController {
240
240
  }, 500, "json">) | (Response & hono.TypedResponse<{
241
241
  message: string;
242
242
  }, 400, "json">) | (Response & hono.TypedResponse<{
243
- [x: string]: hono_utils_types.JSONValue;
243
+ [x: string]: any;
244
244
  id: string;
245
245
  }, 201, "json">)>;
246
246
  find(c: Context<DyrectedContext>): Promise<(Response & hono.TypedResponse<{
247
247
  docs: {
248
- [x: string]: hono_utils_types.JSONValue;
248
+ [x: string]: any;
249
249
  }[];
250
250
  total: number;
251
251
  limit: number;
package/dist/server.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  PreviewController,
7
7
  createDyrectedApp,
8
8
  registerRoutes
9
- } from "./chunk-YNJ3YC4N.js";
9
+ } from "./chunk-TUUHGLB5.js";
10
10
  export {
11
11
  AuthController,
12
12
  CollectionController,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dyrected/core",
3
- "version": "2.5.17",
3
+ "version": "2.5.18",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",