@nextsparkjs/core 0.1.0-beta.149 → 0.1.0-beta.150

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.
Files changed (83) hide show
  1. package/dist/components/dashboard/block-editor/block-picker.d.ts +6 -1
  2. package/dist/components/dashboard/block-editor/block-picker.d.ts.map +1 -1
  3. package/dist/components/dashboard/block-editor/block-picker.js +34 -12
  4. package/dist/components/dashboard/block-editor/block-preview-canvas.d.ts +2 -1
  5. package/dist/components/dashboard/block-editor/block-preview-canvas.d.ts.map +1 -1
  6. package/dist/components/dashboard/block-editor/block-preview-canvas.js +5 -0
  7. package/dist/components/dashboard/block-editor/builder-editor-view.d.ts.map +1 -1
  8. package/dist/components/dashboard/block-editor/builder-editor-view.js +41 -13
  9. package/dist/components/dashboard/block-editor/floating-block-toolbar.d.ts +2 -1
  10. package/dist/components/dashboard/block-editor/floating-block-toolbar.d.ts.map +1 -1
  11. package/dist/components/dashboard/block-editor/floating-block-toolbar.js +17 -1
  12. package/dist/components/dashboard/block-editor/tree-view-node.d.ts +4 -1
  13. package/dist/components/dashboard/block-editor/tree-view-node.d.ts.map +1 -1
  14. package/dist/components/dashboard/block-editor/tree-view-node.js +52 -1
  15. package/dist/components/dashboard/block-editor/tree-view.d.ts +4 -1
  16. package/dist/components/dashboard/block-editor/tree-view.d.ts.map +1 -1
  17. package/dist/components/dashboard/block-editor/tree-view.js +6 -0
  18. package/dist/components/entities/EntityTable.d.ts +1 -1
  19. package/dist/components/entities/EntityTable.d.ts.map +1 -1
  20. package/dist/components/entities/EntityTable.js +14 -1
  21. package/dist/components/entities/entity-table.types.d.ts +2 -0
  22. package/dist/components/entities/entity-table.types.d.ts.map +1 -1
  23. package/dist/components/entities/wrappers/EntityListWrapper.d.ts.map +1 -1
  24. package/dist/components/entities/wrappers/EntityListWrapper.js +19 -1
  25. package/dist/emails/otp-verification.d.ts +9 -0
  26. package/dist/emails/otp-verification.d.ts.map +1 -0
  27. package/dist/emails/otp-verification.js +72 -0
  28. package/dist/emails/reset-password.d.ts +9 -0
  29. package/dist/emails/reset-password.d.ts.map +1 -0
  30. package/dist/emails/reset-password.js +95 -0
  31. package/dist/emails/team-invitation.d.ts +9 -0
  32. package/dist/emails/team-invitation.d.ts.map +1 -0
  33. package/dist/emails/team-invitation.js +93 -0
  34. package/dist/emails/verify-email.d.ts +13 -0
  35. package/dist/emails/verify-email.d.ts.map +1 -0
  36. package/dist/emails/verify-email.js +84 -0
  37. package/dist/lib/api/entities.d.ts +6 -1
  38. package/dist/lib/api/entities.d.ts.map +1 -1
  39. package/dist/lib/api/entities.js +23 -2
  40. package/dist/lib/auth.d.ts.map +1 -1
  41. package/dist/lib/auth.js +12 -7
  42. package/dist/lib/blocks/clipboard.d.ts +11 -0
  43. package/dist/lib/blocks/clipboard.d.ts.map +1 -0
  44. package/dist/lib/blocks/clipboard.js +30 -0
  45. package/dist/lib/email/index.d.ts +1 -0
  46. package/dist/lib/email/index.d.ts.map +1 -1
  47. package/dist/lib/email/index.js +12 -0
  48. package/dist/lib/email/send.d.ts +15 -0
  49. package/dist/lib/email/send.d.ts.map +1 -0
  50. package/dist/lib/email/send.js +11 -0
  51. package/dist/lib/email/templates.d.ts +42 -29
  52. package/dist/lib/email/templates.d.ts.map +1 -1
  53. package/dist/lib/email/templates.js +8 -303
  54. package/dist/lib/email/types.d.ts +32 -0
  55. package/dist/lib/email/types.d.ts.map +1 -1
  56. package/dist/lib/services/subscription.service.d.ts +2 -2
  57. package/dist/lib/services/subscription.service.d.ts.map +1 -1
  58. package/dist/lib/services/subscription.service.js +6 -6
  59. package/dist/messages/de/email.json +58 -0
  60. package/dist/messages/en/admin.json +6 -2
  61. package/dist/messages/en/email.json +58 -0
  62. package/dist/messages/en/index.d.ts +4 -0
  63. package/dist/messages/en/index.d.ts.map +1 -1
  64. package/dist/messages/es/admin.json +6 -2
  65. package/dist/messages/es/email.json +58 -0
  66. package/dist/messages/es/index.d.ts +4 -0
  67. package/dist/messages/es/index.d.ts.map +1 -1
  68. package/dist/messages/fr/email.json +58 -0
  69. package/dist/messages/it/email.json +58 -0
  70. package/dist/messages/pt/email.json +58 -0
  71. package/dist/styles/classes.json +3 -2
  72. package/dist/templates/app/api/v1/teams/[teamId]/members/route.ts +9 -7
  73. package/dist/templates/contents/themes/starter/emails/_README.md +69 -0
  74. package/dist/templates/contents/themes/starter/emails/verify-email.ts +34 -0
  75. package/package.json +6 -2
  76. package/scripts/build/registry/discovery/emails.mjs +146 -0
  77. package/scripts/build/registry/generators/email-registry.mjs +94 -0
  78. package/scripts/build/registry.mjs +8 -4
  79. package/templates/app/api/v1/teams/[teamId]/members/route.ts +9 -7
  80. package/templates/contents/themes/starter/emails/_README.md +69 -0
  81. package/templates/contents/themes/starter/emails/verify-email.ts +34 -0
  82. package/tests/jest/__mocks__/@nextsparkjs/registries/email-registry.ts +41 -0
  83. package/tests/jest/__mocks__/next-intl-server.js +55 -0
@@ -1,4 +1,5 @@
1
1
  export * from './types';
2
2
  export * from './factory';
3
3
  export * from './templates';
4
+ export { sendVerifyEmail, sendResetPasswordEmail, sendOtpVerificationEmail, sendTeamInvitationEmail, } from './send';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/email/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/email/index.ts"],"names":[],"mappings":"AACA,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,aAAa,CAAC;AAC5B,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,QAAQ,CAAC"}
@@ -1,3 +1,15 @@
1
1
  export * from "./types.js";
2
2
  export * from "./factory.js";
3
3
  export * from "./templates.js";
4
+ import {
5
+ sendVerifyEmail,
6
+ sendResetPasswordEmail,
7
+ sendOtpVerificationEmail,
8
+ sendTeamInvitationEmail
9
+ } from "./send.js";
10
+ export {
11
+ sendOtpVerificationEmail,
12
+ sendResetPasswordEmail,
13
+ sendTeamInvitationEmail,
14
+ sendVerifyEmail
15
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Typed convenience helpers around `EMAIL_REGISTRY`.
3
+ *
4
+ * These wrap the four core slugs so call sites can stay readable and keep
5
+ * full type safety on the data argument. For consumer-defined slugs (e.g. a
6
+ * theme's own `purchase-confirmation.ts`), call `EMAIL_REGISTRY['<slug>']`
7
+ * directly — TypeScript infers the data type from each registered function's
8
+ * signature thanks to the `as const` emission in the generated registry.
9
+ */
10
+ import type { EmailContent, VerificationEmailData, PasswordResetEmailData, OtpVerificationEmailData, TeamInvitationEmailData } from './types';
11
+ export declare const sendVerifyEmail: (data: VerificationEmailData, locale?: string) => EmailContent | Promise<EmailContent>;
12
+ export declare const sendResetPasswordEmail: (data: PasswordResetEmailData, locale?: string) => EmailContent | Promise<EmailContent>;
13
+ export declare const sendOtpVerificationEmail: (data: OtpVerificationEmailData, locale?: string) => EmailContent | Promise<EmailContent>;
14
+ export declare const sendTeamInvitationEmail: (data: TeamInvitationEmailData, locale?: string) => EmailContent | Promise<EmailContent>;
15
+ //# sourceMappingURL=send.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../../src/lib/email/send.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EACV,YAAY,EACZ,qBAAqB,EACrB,sBAAsB,EACtB,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAEjB,eAAO,MAAM,eAAe,GAC1B,MAAM,qBAAqB,EAC3B,SAAS,MAAM,KACd,YAAY,GAAG,OAAO,CAAC,YAAY,CACQ,CAAC;AAE/C,eAAO,MAAM,sBAAsB,GACjC,MAAM,sBAAsB,EAC5B,SAAS,MAAM,KACd,YAAY,GAAG,OAAO,CAAC,YAAY,CACU,CAAC;AAEjD,eAAO,MAAM,wBAAwB,GACnC,MAAM,wBAAwB,EAC9B,SAAS,MAAM,KACd,YAAY,GAAG,OAAO,CAAC,YAAY,CACY,CAAC;AAEnD,eAAO,MAAM,uBAAuB,GAClC,MAAM,uBAAuB,EAC7B,SAAS,MAAM,KACd,YAAY,GAAG,OAAO,CAAC,YAAY,CACW,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { EMAIL_REGISTRY } from "@nextsparkjs/registries/email-registry";
2
+ const sendVerifyEmail = (data, locale) => EMAIL_REGISTRY["verify-email"](data, locale);
3
+ const sendResetPasswordEmail = (data, locale) => EMAIL_REGISTRY["reset-password"](data, locale);
4
+ const sendOtpVerificationEmail = (data, locale) => EMAIL_REGISTRY["otp-verification"](data, locale);
5
+ const sendTeamInvitationEmail = (data, locale) => EMAIL_REGISTRY["team-invitation"](data, locale);
6
+ export {
7
+ sendOtpVerificationEmail,
8
+ sendResetPasswordEmail,
9
+ sendTeamInvitationEmail,
10
+ sendVerifyEmail
11
+ };
@@ -1,32 +1,45 @@
1
- import type { VerificationEmailData, PasswordResetEmailData, TeamInvitationEmailData, OtpVerificationEmailData } from './types';
1
+ /**
2
+ * Deprecated email-templates surface.
3
+ *
4
+ * Prior to the email-registry refactor (0.1.0-beta.150) this file shipped four
5
+ * monolithic English-only templates accessed via `emailTemplates.<slug>(data)`.
6
+ * That made it impossible for themes to brand or translate transactional
7
+ * emails without forking core.
8
+ *
9
+ * The replacement is the build-time `EMAIL_REGISTRY` in
10
+ * `@nextsparkjs/registries/email-registry`, with theme overrides at
11
+ * `themes/<active-theme>/emails/<slug>.ts`. Typed convenience helpers live in
12
+ * `@nextsparkjs/core/lib/email/send` (`sendVerifyEmail`, `sendResetPasswordEmail`,
13
+ * `sendOtpVerificationEmail`, `sendTeamInvitationEmail`).
14
+ *
15
+ * The exports below are kept as thin async adapters so out-of-tree consumers
16
+ * keep working for one release cycle. They will be removed in a future release.
17
+ */
18
+ import type { VerificationEmailData, PasswordResetEmailData, TeamInvitationEmailData, OtpVerificationEmailData, EmailContent } from './types';
19
+ /**
20
+ * @deprecated Use the typed helpers from `@nextsparkjs/core/lib/email/send`
21
+ * (e.g. `sendVerifyEmail`) or `EMAIL_REGISTRY['<slug>']` directly. This object
22
+ * is kept for one release cycle to avoid breaking out-of-tree consumers.
23
+ */
2
24
  export declare const emailTemplates: {
3
- verifyEmail: (data: VerificationEmailData) => {
4
- subject: string;
5
- html: string;
6
- };
7
- resetPassword: (data: PasswordResetEmailData) => {
8
- subject: string;
9
- html: string;
10
- };
11
- otpVerification: (data: OtpVerificationEmailData) => {
12
- subject: string;
13
- html: string;
14
- };
15
- teamInvitation: (data: TeamInvitationEmailData) => {
16
- subject: string;
17
- html: string;
18
- };
19
- };
20
- export declare const createVerificationEmail: (name: string | undefined, verifyUrl: string) => {
21
- subject: string;
22
- html: string;
23
- };
24
- export declare const createPasswordResetEmail: (name: string | undefined, resetUrl: string) => {
25
- subject: string;
26
- html: string;
27
- };
28
- export declare const createTeamInvitationEmail: (inviteeEmail: string, inviterName: string, teamName: string, role: string, acceptUrl: string, expiresIn?: string) => {
29
- subject: string;
30
- html: string;
25
+ verifyEmail: (data: VerificationEmailData) => Promise<EmailContent>;
26
+ resetPassword: (data: PasswordResetEmailData) => Promise<EmailContent>;
27
+ otpVerification: (data: OtpVerificationEmailData) => Promise<EmailContent>;
28
+ teamInvitation: (data: TeamInvitationEmailData) => Promise<EmailContent>;
31
29
  };
30
+ /**
31
+ * @deprecated Use `sendVerifyEmail({ userName, verificationUrl, appName })`
32
+ * from `@nextsparkjs/core/lib/email/send`.
33
+ */
34
+ export declare const createVerificationEmail: (name: string | undefined, verifyUrl: string) => any;
35
+ /**
36
+ * @deprecated Use `sendResetPasswordEmail({ userName, resetUrl, appName })`
37
+ * from `@nextsparkjs/core/lib/email/send`.
38
+ */
39
+ export declare const createPasswordResetEmail: (name: string | undefined, resetUrl: string) => any;
40
+ /**
41
+ * @deprecated Use `sendTeamInvitationEmail({ inviteeEmail, inviterName, teamName, role, acceptUrl, expiresIn, appName })`
42
+ * from `@nextsparkjs/core/lib/email/send`.
43
+ */
44
+ export declare const createTeamInvitationEmail: (inviteeEmail: string, inviterName: string, teamName: string, role: string, acceptUrl: string, expiresIn?: string) => any;
32
45
  //# sourceMappingURL=templates.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../../src/lib/email/templates.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,wBAAwB,EAAE,MAAM,SAAS,CAAC;AAIhI,eAAO,MAAM,cAAc;wBACL,qBAAqB;;;;0BA0EnB,sBAAsB;;;;4BAoFpB,wBAAwB;;;;2BA8DzB,uBAAuB;;;;CAmF/C,CAAC;AAGF,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,GAAG,SAAS,EAAE,WAAW,MAAM;;;CAK/E,CAAC;AAEL,eAAO,MAAM,wBAAwB,GAAI,MAAM,MAAM,GAAG,SAAS,EAAE,UAAU,MAAM;;;CAK/E,CAAC;AAEL,eAAO,MAAM,yBAAyB,GACpC,cAAc,MAAM,EACpB,aAAa,MAAM,EACnB,UAAU,MAAM,EAChB,MAAM,MAAM,EACZ,WAAW,MAAM,EACjB,YAAW,MAAiB;;;CAU1B,CAAC"}
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../../src/lib/email/templates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,EACV,qBAAqB,EACrB,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,EACxB,YAAY,EACb,MAAM,SAAS,CAAC;AAIjB;;;;GAIG;AACH,eAAO,MAAM,cAAc;wBACL,qBAAqB,KAAG,OAAO,CAAC,YAAY,CAAC;0BAE3C,sBAAsB,KAAG,OAAO,CAAC,YAAY,CAAC;4BAE5C,wBAAwB,KAAG,OAAO,CAAC,YAAY,CAAC;2BAEjD,uBAAuB,KAAG,OAAO,CAAC,YAAY,CAAC;CAEvE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,GAAI,MAAM,MAAM,GAAG,SAAS,EAAE,WAAW,MAAM,QAK/E,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,wBAAwB,GAAI,MAAM,MAAM,GAAG,SAAS,EAAE,UAAU,MAAM,QAK/E,CAAC;AAEL;;;GAGG;AACH,eAAO,MAAM,yBAAyB,GACpC,cAAc,MAAM,EACpB,aAAa,MAAM,EACnB,UAAU,MAAM,EAChB,MAAM,MAAM,EACZ,WAAW,MAAM,EACjB,YAAW,MAAiB,QAU1B,CAAC"}
@@ -1,317 +1,22 @@
1
+ import { EMAIL_REGISTRY } from "@nextsparkjs/registries/email-registry";
1
2
  const APP_NAME = process.env.NEXT_PUBLIC_APP_NAME || "Your App";
2
3
  const emailTemplates = {
3
- verifyEmail: (data) => ({
4
- subject: `Welcome to ${data.appName || APP_NAME} - Verify Your Email`,
5
- html: `
6
- <!DOCTYPE html>
7
- <html>
8
- <head>
9
- <meta charset="utf-8">
10
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
11
- </head>
12
- <body style="margin: 0; padding: 0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f4f4f4;">
13
- <table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
14
- <tr>
15
- <td align="center" style="padding: 40px 0;">
16
- <table role="presentation" width="600" cellspacing="0" cellpadding="0" border="0" style="background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
17
- <!-- Header -->
18
- <tr>
19
- <td style="padding: 40px 40px 20px 40px; text-align: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 8px 8px 0 0;">
20
- <h1 style="color: #ffffff; font-size: 28px; margin: 0; font-weight: 600;">${data.appName || APP_NAME}</h1>
21
- <p style="color: #ffffff; font-size: 16px; margin: 10px 0 0 0; opacity: 0.95;">Welcome to Your Account</p>
22
- </td>
23
- </tr>
24
-
25
- <!-- Content -->
26
- <tr>
27
- <td style="padding: 40px;">
28
- <h2 style="color: #333333; font-size: 24px; margin: 0 0 20px 0; font-weight: 600;">Verify Your Email Address</h2>
29
-
30
- <p style="color: #666666; font-size: 16px; line-height: 1.6; margin: 0 0 20px 0;">
31
- Hi${data.userName ? ` ${data.userName}` : ""},
32
- </p>
33
-
34
- <p style="color: #666666; font-size: 16px; line-height: 1.6; margin: 0 0 30px 0;">
35
- Thank you for signing up! We're excited to have you on board. Please verify your email address to activate your account and get started.
36
- </p>
37
-
38
- <table role="presentation" cellspacing="0" cellpadding="0" border="0" style="margin: 0 auto;">
39
- <tr>
40
- <td style="border-radius: 6px; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
41
- <a href="${data.verificationUrl}" target="_blank" style="display: inline-block; padding: 14px 32px; font-size: 16px; font-weight: 600; color: #ffffff; text-decoration: none; border-radius: 6px;">
42
- Verify Email Address
43
- </a>
44
- </td>
45
- </tr>
46
- </table>
47
-
48
- <p style="color: #999999; font-size: 14px; line-height: 1.6; margin: 30px 0 0 0; padding: 20px; background-color: #f8f8f8; border-radius: 6px;">
49
- <strong>Can't click the button?</strong><br>
50
- Copy and paste this link into your browser:<br>
51
- <span style="color: #667eea; word-break: break-all; font-size: 12px;">${data.verificationUrl}</span>
52
- </p>
53
- </td>
54
- </tr>
55
-
56
- <!-- Footer -->
57
- <tr>
58
- <td style="padding: 30px 40px; background-color: #f8f8f8; border-radius: 0 0 8px 8px; text-align: center;">
59
- <p style="color: #999999; font-size: 14px; margin: 0 0 10px 0;">
60
- \xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} ${data.appName || APP_NAME}. All rights reserved.
61
- </p>
62
- <p style="color: #999999; font-size: 12px; margin: 0;">
63
- This email was sent to you because you signed up for ${data.appName || APP_NAME}.
64
- <br>If you didn't request this, please ignore this email.
65
- </p>
66
- </td>
67
- </tr>
68
- </table>
69
- </td>
70
- </tr>
71
- </table>
72
- </body>
73
- </html>
74
- `
75
- }),
76
- resetPassword: (data) => ({
77
- subject: `Reset Your Password - ${data.appName || APP_NAME}`,
78
- html: `
79
- <!DOCTYPE html>
80
- <html>
81
- <head>
82
- <meta charset="utf-8">
83
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
84
- </head>
85
- <body style="margin: 0; padding: 0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f4f4f4;">
86
- <table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
87
- <tr>
88
- <td align="center" style="padding: 40px 0;">
89
- <table role="presentation" width="600" cellspacing="0" cellpadding="0" border="0" style="background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
90
- <!-- Header -->
91
- <tr>
92
- <td style="padding: 40px 40px 20px 40px; text-align: center; background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); border-radius: 8px 8px 0 0;">
93
- <h1 style="color: #ffffff; font-size: 28px; margin: 0; font-weight: 600;">${data.appName || APP_NAME}</h1>
94
- <p style="color: #ffffff; font-size: 16px; margin: 10px 0 0 0; opacity: 0.95;">Password Reset Request</p>
95
- </td>
96
- </tr>
97
-
98
- <!-- Content -->
99
- <tr>
100
- <td style="padding: 40px;">
101
- <h2 style="color: #333333; font-size: 24px; margin: 0 0 20px 0; font-weight: 600;">Reset Your Password</h2>
102
-
103
- <p style="color: #666666; font-size: 16px; line-height: 1.6; margin: 0 0 20px 0;">
104
- Hi${data.userName ? ` ${data.userName}` : ""},
105
- </p>
106
-
107
- <p style="color: #666666; font-size: 16px; line-height: 1.6; margin: 0 0 30px 0;">
108
- We received a request to reset your password for your account. Click the button below to create a new password:
109
- </p>
110
-
111
- <table role="presentation" cellspacing="0" cellpadding="0" border="0" style="margin: 0 auto;">
112
- <tr>
113
- <td style="border-radius: 6px; background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);">
114
- <a href="${data.resetUrl}" target="_blank" style="display: inline-block; padding: 14px 32px; font-size: 16px; font-weight: 600; color: #ffffff; text-decoration: none; border-radius: 6px;">
115
- Reset Password
116
- </a>
117
- </td>
118
- </tr>
119
- </table>
120
-
121
- <div style="margin: 30px 0; padding: 20px; background-color: #fff3cd; border-left: 4px solid #ffc107; border-radius: 4px;">
122
- <p style="color: #856404; font-size: 14px; margin: 0; font-weight: 600;">
123
- \u26A0\uFE0F Important Security Information
124
- </p>
125
- <p style="color: #856404; font-size: 14px; margin: 10px 0 0 0; line-height: 1.5;">
126
- This link will expire in <strong>${data.expiresIn || "1 hour"}</strong> for your security.<br>
127
- If you didn't request this password reset, please ignore this email and your password will remain unchanged.
128
- </p>
129
- </div>
130
-
131
- <p style="color: #999999; font-size: 14px; line-height: 1.6; margin: 20px 0 0 0; padding: 20px; background-color: #f8f8f8; border-radius: 6px;">
132
- <strong>Can't click the button?</strong><br>
133
- Copy and paste this link into your browser:<br>
134
- <span style="color: #f5576c; word-break: break-all; font-size: 12px;">${data.resetUrl}</span>
135
- </p>
136
- </td>
137
- </tr>
138
-
139
- <!-- Footer -->
140
- <tr>
141
- <td style="padding: 30px 40px; background-color: #f8f8f8; border-radius: 0 0 8px 8px; text-align: center;">
142
- <p style="color: #999999; font-size: 14px; margin: 0 0 10px 0;">
143
- \xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} ${data.appName || APP_NAME}. All rights reserved.
144
- </p>
145
- <p style="color: #999999; font-size: 12px; margin: 0;">
146
- This is an automated security email from ${data.appName || APP_NAME}.
147
- <br>For security reasons, we never ask for your password via email.
148
- </p>
149
- </td>
150
- </tr>
151
- </table>
152
- </td>
153
- </tr>
154
- </table>
155
- </body>
156
- </html>
157
- `
158
- }),
159
- otpVerification: (data) => ({
160
- subject: `${data.otp} is your verification code - ${data.appName || APP_NAME}`,
161
- html: `
162
- <!DOCTYPE html>
163
- <html>
164
- <head>
165
- <meta charset="utf-8">
166
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
167
- </head>
168
- <body style="margin: 0; padding: 0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f4f4f4;">
169
- <table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
170
- <tr>
171
- <td align="center" style="padding: 40px 0;">
172
- <table role="presentation" width="600" cellspacing="0" cellpadding="0" border="0" style="background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
173
- <!-- Header -->
174
- <tr>
175
- <td style="padding: 40px 40px 20px 40px; text-align: center; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 8px 8px 0 0;">
176
- <h1 style="color: #ffffff; font-size: 28px; margin: 0; font-weight: 600;">${data.appName || APP_NAME}</h1>
177
- <p style="color: #ffffff; font-size: 16px; margin: 10px 0 0 0; opacity: 0.95;">Verification Code</p>
178
- </td>
179
- </tr>
180
-
181
- <!-- Content -->
182
- <tr>
183
- <td style="padding: 40px; text-align: center;">
184
- <h2 style="color: #333333; font-size: 24px; margin: 0 0 20px 0; font-weight: 600;">Your verification code</h2>
185
-
186
- <p style="color: #666666; font-size: 16px; line-height: 1.6; margin: 0 0 30px 0;">
187
- Enter this code to verify your identity:
188
- </p>
189
-
190
- <div style="margin: 0 auto 30px; padding: 20px 40px; background-color: #f8f8f8; border-radius: 8px; display: inline-block;">
191
- <span style="font-size: 36px; font-weight: 700; letter-spacing: 8px; color: #333333; font-family: monospace;">${data.otp}</span>
192
- </div>
193
-
194
- <p style="color: #999999; font-size: 14px; line-height: 1.6; margin: 0;">
195
- This code expires in <strong>5 minutes</strong>.<br>
196
- If you didn't request this code, you can safely ignore this email.
197
- </p>
198
- </td>
199
- </tr>
200
-
201
- <!-- Footer -->
202
- <tr>
203
- <td style="padding: 30px 40px; background-color: #f8f8f8; border-radius: 0 0 8px 8px; text-align: center;">
204
- <p style="color: #999999; font-size: 14px; margin: 0 0 10px 0;">
205
- &copy; ${(/* @__PURE__ */ new Date()).getFullYear()} ${data.appName || APP_NAME}. All rights reserved.
206
- </p>
207
- <p style="color: #999999; font-size: 12px; margin: 0;">
208
- This is an automated email from ${data.appName || APP_NAME}.
209
- </p>
210
- </td>
211
- </tr>
212
- </table>
213
- </td>
214
- </tr>
215
- </table>
216
- </body>
217
- </html>
218
- `
219
- }),
220
- teamInvitation: (data) => ({
221
- subject: `You've been invited to join ${data.teamName} on ${data.appName || APP_NAME}`,
222
- html: `
223
- <!DOCTYPE html>
224
- <html>
225
- <head>
226
- <meta charset="utf-8">
227
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
228
- </head>
229
- <body style="margin: 0; padding: 0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background-color: #f4f4f4;">
230
- <table role="presentation" width="100%" cellspacing="0" cellpadding="0" border="0">
231
- <tr>
232
- <td align="center" style="padding: 40px 0;">
233
- <table role="presentation" width="600" cellspacing="0" cellpadding="0" border="0" style="background-color: #ffffff; border-radius: 8px; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
234
- <!-- Header -->
235
- <tr>
236
- <td style="padding: 40px 40px 20px 40px; text-align: center; background: linear-gradient(135deg, #4F46E5 0%, #7C3AED 100%); border-radius: 8px 8px 0 0;">
237
- <h1 style="color: #ffffff; font-size: 28px; margin: 0; font-weight: 600;">${data.appName || APP_NAME}</h1>
238
- <p style="color: #ffffff; font-size: 16px; margin: 10px 0 0 0; opacity: 0.95;">Team Invitation</p>
239
- </td>
240
- </tr>
241
-
242
- <!-- Content -->
243
- <tr>
244
- <td style="padding: 40px;">
245
- <h2 style="color: #333333; font-size: 24px; margin: 0 0 20px 0; font-weight: 600;">You're Invited!</h2>
246
-
247
- <p style="color: #666666; font-size: 16px; line-height: 1.6; margin: 0 0 20px 0;">
248
- <strong>${data.inviterName}</strong> has invited you to join the team <strong>${data.teamName}</strong> as a <strong>${data.role}</strong>.
249
- </p>
250
-
251
- <p style="color: #666666; font-size: 16px; line-height: 1.6; margin: 0 0 30px 0;">
252
- Click the button below to accept the invitation and join the team:
253
- </p>
254
-
255
- <table role="presentation" cellspacing="0" cellpadding="0" border="0" style="margin: 0 auto;">
256
- <tr>
257
- <td style="border-radius: 6px; background: linear-gradient(135deg, #4F46E5 0%, #7C3AED 100%);">
258
- <a href="${data.acceptUrl}" target="_blank" style="display: inline-block; padding: 14px 32px; font-size: 16px; font-weight: 600; color: #ffffff; text-decoration: none; border-radius: 6px;">
259
- Accept Invitation
260
- </a>
261
- </td>
262
- </tr>
263
- </table>
264
-
265
- <div style="margin: 30px 0; padding: 20px; background-color: #f0f9ff; border-left: 4px solid #4F46E5; border-radius: 4px;">
266
- <p style="color: #1e40af; font-size: 14px; margin: 0; font-weight: 600;">
267
- \u23F0 Invitation Details
268
- </p>
269
- <p style="color: #1e40af; font-size: 14px; margin: 10px 0 0 0; line-height: 1.5;">
270
- This invitation will expire in <strong>${data.expiresIn}</strong>.<br>
271
- If you don't have an account yet, you'll be able to create one when you accept.
272
- </p>
273
- </div>
274
-
275
- <p style="color: #999999; font-size: 14px; line-height: 1.6; margin: 20px 0 0 0; padding: 20px; background-color: #f8f8f8; border-radius: 6px;">
276
- <strong>Can't click the button?</strong><br>
277
- Copy and paste this link into your browser:<br>
278
- <span style="color: #4F46E5; word-break: break-all; font-size: 12px;">${data.acceptUrl}</span>
279
- </p>
280
- </td>
281
- </tr>
282
-
283
- <!-- Footer -->
284
- <tr>
285
- <td style="padding: 30px 40px; background-color: #f8f8f8; border-radius: 0 0 8px 8px; text-align: center;">
286
- <p style="color: #999999; font-size: 14px; margin: 0 0 10px 0;">
287
- \xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} ${data.appName || APP_NAME}. All rights reserved.
288
- </p>
289
- <p style="color: #999999; font-size: 12px; margin: 0;">
290
- This invitation was sent to ${data.inviteeEmail}.<br>
291
- If you didn't expect this invitation, you can safely ignore this email.
292
- </p>
293
- </td>
294
- </tr>
295
- </table>
296
- </td>
297
- </tr>
298
- </table>
299
- </body>
300
- </html>
301
- `
302
- })
4
+ verifyEmail: (data) => Promise.resolve(EMAIL_REGISTRY["verify-email"](data)),
5
+ resetPassword: (data) => Promise.resolve(EMAIL_REGISTRY["reset-password"](data)),
6
+ otpVerification: (data) => Promise.resolve(EMAIL_REGISTRY["otp-verification"](data)),
7
+ teamInvitation: (data) => Promise.resolve(EMAIL_REGISTRY["team-invitation"](data))
303
8
  };
304
- const createVerificationEmail = (name, verifyUrl) => emailTemplates.verifyEmail({
9
+ const createVerificationEmail = (name, verifyUrl) => EMAIL_REGISTRY["verify-email"]({
305
10
  userName: name || "",
306
11
  verificationUrl: verifyUrl,
307
12
  appName: APP_NAME
308
13
  });
309
- const createPasswordResetEmail = (name, resetUrl) => emailTemplates.resetPassword({
14
+ const createPasswordResetEmail = (name, resetUrl) => EMAIL_REGISTRY["reset-password"]({
310
15
  userName: name || "",
311
16
  resetUrl,
312
17
  appName: APP_NAME
313
18
  });
314
- const createTeamInvitationEmail = (inviteeEmail, inviterName, teamName, role, acceptUrl, expiresIn = "7 days") => emailTemplates.teamInvitation({
19
+ const createTeamInvitationEmail = (inviteeEmail, inviterName, teamName, role, acceptUrl, expiresIn = "7 days") => EMAIL_REGISTRY["team-invitation"]({
315
20
  inviteeEmail,
316
21
  inviterName,
317
22
  teamName,
@@ -27,6 +27,30 @@ export interface EmailProvider {
27
27
  export interface EmailTemplateData {
28
28
  [key: string]: string | number | boolean | undefined;
29
29
  }
30
+ /**
31
+ * Output shape every email template function returns.
32
+ *
33
+ * The shipping `EmailFactory` consumes `subject` and `html` directly when
34
+ * dispatching via Resend or the console provider. `text` is reserved for
35
+ * future plain-text fallback support and is currently optional.
36
+ */
37
+ export interface EmailContent {
38
+ subject: string;
39
+ html: string;
40
+ text?: string;
41
+ }
42
+ /**
43
+ * Contract every email template file (core default or theme override) must
44
+ * export as its default export.
45
+ *
46
+ * - `data`: template-specific input shape (e.g. `VerificationEmailData`).
47
+ * - `locale`: optional BCP47 code; templates that integrate i18n use it to
48
+ * fetch translated copy via `getTranslations({ locale, namespace })`.
49
+ *
50
+ * Returning a `Promise` is fully supported so locale-aware templates can
51
+ * `await getTranslations(...)`.
52
+ */
53
+ export type EmailTemplateFn<TData extends EmailTemplateData> = (data: TData, locale?: string) => EmailContent | Promise<EmailContent>;
30
54
  export interface VerificationEmailData extends EmailTemplateData {
31
55
  userName: string;
32
56
  verificationUrl: string;
@@ -38,6 +62,14 @@ export interface PasswordResetEmailData extends EmailTemplateData {
38
62
  appName: string;
39
63
  expiresIn?: string;
40
64
  }
65
+ /**
66
+ * @deprecated Orphaned type — no template implementation in core or any
67
+ * theme as of 0.1.0-beta.149. Either implement a `welcome-email` template
68
+ * (drop a file at `packages/core/src/emails/welcome-email.ts` exporting
69
+ * `EmailTemplateFn<WelcomeEmailData>`) or remove this interface in a
70
+ * follow-up cleanup. Kept exported for now to avoid breaking any
71
+ * out-of-tree consumer that imports the type.
72
+ */
41
73
  export interface WelcomeEmailData extends EmailTemplateData {
42
74
  userName: string;
43
75
  appName: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/email/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACpD,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CACtD;AAED,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAiB,SAAQ,iBAAiB;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAyB,SAAQ,iBAAiB;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/email/types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACpD,MAAM,CAAC,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAC;CACtD;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,eAAe,CAAC,KAAK,SAAS,iBAAiB,IAAI,CAC7D,IAAI,EAAE,KAAK,EACX,MAAM,CAAC,EAAE,MAAM,KACZ,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;AAE1C,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAuB,SAAQ,iBAAiB;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAiB,SAAQ,iBAAiB;IACzD,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAyB,SAAQ,iBAAiB;IACjE,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB"}
@@ -220,7 +220,7 @@ export declare class SubscriptionService {
220
220
  * @example
221
221
  * const hasAnalytics = await SubscriptionService.hasFeature('team-123', 'advanced_analytics')
222
222
  */
223
- static hasFeature(teamId: string, featureSlug: string): Promise<boolean>;
223
+ static hasFeature(teamId: string, featureSlug: string, userId?: string): Promise<boolean>;
224
224
  /**
225
225
  * Check quota for a specific limit
226
226
  *
@@ -234,7 +234,7 @@ export declare class SubscriptionService {
234
234
  * console.log('Quota exceeded:', quota.current, '/', quota.max)
235
235
  * }
236
236
  */
237
- static checkQuota(teamId: string, limitSlug: string): Promise<QuotaInfo>;
237
+ static checkQuota(teamId: string, limitSlug: string, userId?: string): Promise<QuotaInfo>;
238
238
  /**
239
239
  * Check if action is allowed (RBAC + feature + quota)
240
240
  *
@@ -1 +1 @@
1
- {"version":3,"file":"subscription.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/subscription.service.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"subscription.service.d.ts","sourceRoot":"","sources":["../../../src/lib/services/subscription.service.ts"],"names":[],"mappings":"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"}
@@ -664,11 +664,11 @@ class SubscriptionService {
664
664
  * @example
665
665
  * const hasAnalytics = await SubscriptionService.hasFeature('team-123', 'advanced_analytics')
666
666
  */
667
- static async hasFeature(teamId, featureSlug) {
667
+ static async hasFeature(teamId, featureSlug, userId) {
668
668
  if (!teamId || !featureSlug) {
669
669
  return false;
670
670
  }
671
- const subscription = await this.getActive(teamId);
671
+ const subscription = await this.getActive(teamId, userId);
672
672
  if (!subscription || !isSubscriptionActive(subscription.status)) {
673
673
  return false;
674
674
  }
@@ -689,7 +689,7 @@ class SubscriptionService {
689
689
  * console.log('Quota exceeded:', quota.current, '/', quota.max)
690
690
  * }
691
691
  */
692
- static async checkQuota(teamId, limitSlug) {
692
+ static async checkQuota(teamId, limitSlug, userId) {
693
693
  if (!teamId || !limitSlug) {
694
694
  return {
695
695
  allowed: false,
@@ -699,7 +699,7 @@ class SubscriptionService {
699
699
  percentUsed: 0
700
700
  };
701
701
  }
702
- const subscription = await this.getActive(teamId);
702
+ const subscription = await this.getActive(teamId, userId);
703
703
  if (!subscription || !isSubscriptionActive(subscription.status)) {
704
704
  return {
705
705
  allowed: false,
@@ -811,14 +811,14 @@ class SubscriptionService {
811
811
  }
812
812
  const requiredFeature = BILLING_REGISTRY.actionMappings.features[action];
813
813
  if (requiredFeature) {
814
- const hasFeatureAccess = await this.hasFeature(teamId, requiredFeature);
814
+ const hasFeatureAccess = await this.hasFeature(teamId, requiredFeature, userId);
815
815
  if (!hasFeatureAccess) {
816
816
  return { allowed: false, reason: "feature_not_in_plan" };
817
817
  }
818
818
  }
819
819
  const consumedLimit = BILLING_REGISTRY.actionMappings.limits[action];
820
820
  if (consumedLimit) {
821
- const quota = await this.checkQuota(teamId, consumedLimit);
821
+ const quota = await this.checkQuota(teamId, consumedLimit, userId);
822
822
  if (!quota.allowed) {
823
823
  return { allowed: false, reason: "quota_exceeded", quota };
824
824
  }