@learncard/email-templates 1.0.1
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/LICENSE +21 -0
- package/README.md +189 -0
- package/dist/branding.d.ts +36 -0
- package/dist/branding.d.ts.map +1 -0
- package/dist/branding.js +28 -0
- package/dist/branding.js.map +1 -0
- package/dist/components/CodeBlock.d.ts +16 -0
- package/dist/components/CodeBlock.d.ts.map +1 -0
- package/dist/components/CodeBlock.js +42 -0
- package/dist/components/CodeBlock.js.map +1 -0
- package/dist/components/EmailButton.d.ts +15 -0
- package/dist/components/EmailButton.d.ts.map +1 -0
- package/dist/components/EmailButton.js +20 -0
- package/dist/components/EmailButton.js.map +1 -0
- package/dist/components/IssuerLogo.d.ts +14 -0
- package/dist/components/IssuerLogo.d.ts.map +1 -0
- package/dist/components/IssuerLogo.js +23 -0
- package/dist/components/IssuerLogo.js.map +1 -0
- package/dist/components/Layout.d.ts +19 -0
- package/dist/components/Layout.d.ts.map +1 -0
- package/dist/components/Layout.js +95 -0
- package/dist/components/Layout.js.map +1 -0
- package/dist/components/LinkFallback.d.ts +12 -0
- package/dist/components/LinkFallback.d.ts.map +1 -0
- package/dist/components/LinkFallback.js +29 -0
- package/dist/components/LinkFallback.js.map +1 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/index.js.map +1 -0
- package/dist/previews/_fixtures.d.ts +12 -0
- package/dist/previews/_fixtures.d.ts.map +1 -0
- package/dist/previews/_fixtures.js +34 -0
- package/dist/previews/_fixtures.js.map +1 -0
- package/dist/previews/account-approved-scenarios.d.ts +5 -0
- package/dist/previews/account-approved-scenarios.d.ts.map +1 -0
- package/dist/previews/account-approved-scenarios.js +7 -0
- package/dist/previews/account-approved-scenarios.js.map +1 -0
- package/dist/previews/endorsement-request-scenarios.d.ts +5 -0
- package/dist/previews/endorsement-request-scenarios.d.ts.map +1 -0
- package/dist/previews/endorsement-request-scenarios.js +7 -0
- package/dist/previews/endorsement-request-scenarios.js.map +1 -0
- package/dist/previews/guardian-approval-scenarios.d.ts +5 -0
- package/dist/previews/guardian-approval-scenarios.d.ts.map +1 -0
- package/dist/previews/guardian-approval-scenarios.js +7 -0
- package/dist/previews/guardian-approval-scenarios.js.map +1 -0
- package/dist/previews/guardian-credential-scenarios.d.ts +5 -0
- package/dist/previews/guardian-credential-scenarios.d.ts.map +1 -0
- package/dist/previews/guardian-credential-scenarios.js +11 -0
- package/dist/previews/guardian-credential-scenarios.js.map +1 -0
- package/dist/previews/inbox-claim-scenarios.d.ts +8 -0
- package/dist/previews/inbox-claim-scenarios.d.ts.map +1 -0
- package/dist/previews/inbox-claim-scenarios.js +7 -0
- package/dist/previews/inbox-claim-scenarios.js.map +1 -0
- package/dist/previews/recovery-key-scenarios.d.ts +5 -0
- package/dist/previews/recovery-key-scenarios.d.ts.map +1 -0
- package/dist/previews/recovery-key-scenarios.js +7 -0
- package/dist/previews/recovery-key-scenarios.js.map +1 -0
- package/dist/previews/verification-code-scenarios.d.ts +5 -0
- package/dist/previews/verification-code-scenarios.d.ts.map +1 -0
- package/dist/previews/verification-code-scenarios.js +7 -0
- package/dist/previews/verification-code-scenarios.js.map +1 -0
- package/dist/render.d.ts +185 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +153 -0
- package/dist/render.js.map +1 -0
- package/dist/sms.d.ts +34 -0
- package/dist/sms.d.ts.map +1 -0
- package/dist/sms.js +34 -0
- package/dist/sms.js.map +1 -0
- package/dist/templates/account-approved.d.ts +17 -0
- package/dist/templates/account-approved.d.ts.map +1 -0
- package/dist/templates/account-approved.js +46 -0
- package/dist/templates/account-approved.js.map +1 -0
- package/dist/templates/credential-awaiting-guardian.d.ts +25 -0
- package/dist/templates/credential-awaiting-guardian.d.ts.map +1 -0
- package/dist/templates/credential-awaiting-guardian.js +65 -0
- package/dist/templates/credential-awaiting-guardian.js.map +1 -0
- package/dist/templates/email-verification.d.ts +21 -0
- package/dist/templates/email-verification.d.ts.map +1 -0
- package/dist/templates/email-verification.js +51 -0
- package/dist/templates/email-verification.js.map +1 -0
- package/dist/templates/endorsement-request.d.ts +28 -0
- package/dist/templates/endorsement-request.d.ts.map +1 -0
- package/dist/templates/endorsement-request.js +67 -0
- package/dist/templates/endorsement-request.js.map +1 -0
- package/dist/templates/guardian-approval.d.ts +23 -0
- package/dist/templates/guardian-approval.d.ts.map +1 -0
- package/dist/templates/guardian-approval.js +50 -0
- package/dist/templates/guardian-approval.js.map +1 -0
- package/dist/templates/guardian-approved-claim.d.ts +22 -0
- package/dist/templates/guardian-approved-claim.d.ts.map +1 -0
- package/dist/templates/guardian-approved-claim.js +49 -0
- package/dist/templates/guardian-approved-claim.js.map +1 -0
- package/dist/templates/guardian-credential-approval.d.ts +27 -0
- package/dist/templates/guardian-credential-approval.d.ts.map +1 -0
- package/dist/templates/guardian-credential-approval.js +51 -0
- package/dist/templates/guardian-credential-approval.js.map +1 -0
- package/dist/templates/guardian-email-otp.d.ts +16 -0
- package/dist/templates/guardian-email-otp.d.ts.map +1 -0
- package/dist/templates/guardian-email-otp.js +49 -0
- package/dist/templates/guardian-email-otp.js.map +1 -0
- package/dist/templates/guardian-rejected-credential.d.ts +24 -0
- package/dist/templates/guardian-rejected-credential.d.ts.map +1 -0
- package/dist/templates/guardian-rejected-credential.js +44 -0
- package/dist/templates/guardian-rejected-credential.js.map +1 -0
- package/dist/templates/inbox-claim.d.ts +28 -0
- package/dist/templates/inbox-claim.d.ts.map +1 -0
- package/dist/templates/inbox-claim.js +58 -0
- package/dist/templates/inbox-claim.js.map +1 -0
- package/dist/templates/index.d.ts +25 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +13 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/templates/recovery-key.d.ts +15 -0
- package/dist/templates/recovery-key.d.ts.map +1 -0
- package/dist/templates/recovery-key.js +46 -0
- package/dist/templates/recovery-key.js.map +1 -0
- package/dist/templates/verification-code.d.ts +24 -0
- package/dist/templates/verification-code.d.ts.map +1 -0
- package/dist/templates/verification-code.js +87 -0
- package/dist/templates/verification-code.js.map +1 -0
- package/dist/tenant-registry.d.ts +48 -0
- package/dist/tenant-registry.d.ts.map +1 -0
- package/dist/tenant-registry.js +146 -0
- package/dist/tenant-registry.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* RecoveryKey — email containing a user's account recovery key.
|
|
4
|
+
*
|
|
5
|
+
* Used by: lca-api keys.ts (templateAlias: RECOVERY_KEY_TEMPLATE_ALIAS)
|
|
6
|
+
*/
|
|
7
|
+
import { Text } from '@react-email/components';
|
|
8
|
+
import { DEFAULT_BRANDING } from '../branding';
|
|
9
|
+
import { Layout } from '../components/Layout';
|
|
10
|
+
import { CodeBlock } from '../components/CodeBlock';
|
|
11
|
+
export const RecoveryKey = ({ branding, recoveryKey, }) => (_jsxs(Layout, { branding: branding, preview: `Your ${branding.brandName} recovery key — keep this safe`, children: [_jsxs(Text, { style: heading, children: ["Your ", branding.brandName, " Recovery Key"] }), _jsx(Text, { style: paragraph, children: "Hello," }), _jsxs(Text, { style: paragraph, children: ["Keep this email safe. You can use the recovery key below to regain access to your ", branding.brandName, " account if you lose your device."] }), _jsx(CodeBlock, { code: recoveryKey, label: "Recovery Key \u2014 do NOT share this with anyone", variant: "key" }), _jsxs(Text, { style: paragraph, children: ["To recover your account, choose ", _jsx("strong", { children: "\u201CRecover via Email\u201D" }), " in the app and paste the recovery key above when prompted."] }), _jsx(Text, { style: muted, children: "If you did not request this, you can safely ignore this email." }), _jsxs(Text, { style: paragraph, children: [branding.brandName, " is your private, digital passport for learning and work. It lets you securely collect and share your verified skills and achievements online."] }), _jsxs(Text, { style: signOff, children: ["Sincerely,", _jsx("br", {}), "The ", branding.brandName, " Team"] })] }));
|
|
12
|
+
export const getRecoveryKeySubject = (branding) => `Your ${branding.brandName} recovery key`;
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Styles
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
const heading = {
|
|
17
|
+
fontSize: 24,
|
|
18
|
+
fontWeight: 600,
|
|
19
|
+
color: '#111827',
|
|
20
|
+
margin: '0 0 24px',
|
|
21
|
+
};
|
|
22
|
+
const paragraph = {
|
|
23
|
+
fontSize: 16,
|
|
24
|
+
color: '#374151',
|
|
25
|
+
lineHeight: '24px',
|
|
26
|
+
margin: '0 0 24px',
|
|
27
|
+
};
|
|
28
|
+
const muted = {
|
|
29
|
+
fontSize: 14,
|
|
30
|
+
color: '#6b7280',
|
|
31
|
+
lineHeight: '20px',
|
|
32
|
+
margin: '0 0 24px',
|
|
33
|
+
};
|
|
34
|
+
const signOff = {
|
|
35
|
+
fontSize: 14,
|
|
36
|
+
color: '#374151',
|
|
37
|
+
lineHeight: '20px',
|
|
38
|
+
margin: '24px 0 0',
|
|
39
|
+
};
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
// Preview
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
export default function Preview() {
|
|
44
|
+
return (_jsx(RecoveryKey, { branding: DEFAULT_BRANDING, recoveryKey: "mango-delta-fox-echo-bravo-seven-lima-niner" }));
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=recovery-key.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recovery-key.js","sourceRoot":"","sources":["../../src/templates/recovery-key.tsx"],"names":[],"mappings":";AAAA;;;;GAIG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAI/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAOpD,MAAM,CAAC,MAAM,WAAW,GAA+B,CAAC,EACpD,QAAQ,EACR,WAAW,GACd,EAAE,EAAE,CAAC,CACF,MAAC,MAAM,IAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,QAAQ,CAAC,SAAS,gCAAgC,aAC3F,MAAC,IAAI,IAAC,KAAK,EAAE,OAAO,sBAAQ,QAAQ,CAAC,SAAS,qBAAqB,EAEnE,KAAC,IAAI,IAAC,KAAK,EAAE,SAAS,uBAAe,EAErC,MAAC,IAAI,IAAC,KAAK,EAAE,SAAS,mGAET,QAAQ,CAAC,SAAS,yCACxB,EAEP,KAAC,SAAS,IAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAC,mDAA8C,EAAC,OAAO,EAAC,KAAK,GAAG,EAEnG,MAAC,IAAI,IAAC,KAAK,EAAE,SAAS,iDACc,6DAAgD,mEAE7E,EAEP,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,+EAEX,EAEP,MAAC,IAAI,IAAC,KAAK,EAAE,SAAS,aACjB,QAAQ,CAAC,SAAS,sJAEhB,EAEP,MAAC,IAAI,IAAC,KAAK,EAAE,OAAO,2BACN,cAAM,UAAK,QAAQ,CAAC,SAAS,aACpC,IACF,CACZ,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,QAAwB,EAAU,EAAE,CACtE,QAAQ,QAAQ,CAAC,SAAS,eAAe,CAAC;AAE9C,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E,MAAM,OAAO,GAAwB;IACjC,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE,GAAG;IACf,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,UAAU;CACrB,CAAC;AAEF,MAAM,SAAS,GAAwB;IACnC,QAAQ,EAAE,EAAE;IACZ,KAAK,EAAE,SAAS;IAChB,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,UAAU;CACrB,CAAC;AAEF,MAAM,KAAK,GAAwB;IAC/B,QAAQ,EAAE,EAAE;IACZ,KAAK,EAAE,SAAS;IAChB,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,UAAU;CACrB,CAAC;AAEF,MAAM,OAAO,GAAwB;IACjC,QAAQ,EAAE,EAAE;IACZ,KAAK,EAAE,SAAS;IAChB,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,UAAU;CACrB,CAAC;AAEF,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E,MAAM,CAAC,OAAO,UAAU,OAAO;IAC3B,OAAO,CACH,KAAC,WAAW,IACR,QAAQ,EAAE,gBAAgB,EAC1B,WAAW,EAAC,6CAA6C,GAC3D,CACL,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VerificationCode — shared template for all code-based verification emails.
|
|
3
|
+
*
|
|
4
|
+
* Used by:
|
|
5
|
+
* - login-verification-code (lca-api firebase.ts)
|
|
6
|
+
* - recovery-email-code (lca-api keys.ts)
|
|
7
|
+
* - embed-email-verification (brain-service contact-methods.ts)
|
|
8
|
+
* - contact-method-verification (brain-service contact-methods.ts)
|
|
9
|
+
*
|
|
10
|
+
* The `variant` prop controls the subject line and descriptive text.
|
|
11
|
+
*/
|
|
12
|
+
import * as React from 'react';
|
|
13
|
+
import type { TenantBranding } from '../branding';
|
|
14
|
+
export type VerificationCodeVariant = 'login' | 'recovery-email' | 'embed-verification' | 'contact-method';
|
|
15
|
+
export interface VerificationCodeProps {
|
|
16
|
+
branding: TenantBranding;
|
|
17
|
+
verificationCode: string;
|
|
18
|
+
verificationEmail?: string;
|
|
19
|
+
variant: VerificationCodeVariant;
|
|
20
|
+
}
|
|
21
|
+
export declare const VerificationCode: React.FC<VerificationCodeProps>;
|
|
22
|
+
export declare const getVerificationCodeSubject: (branding: TenantBranding, variant: VerificationCodeVariant) => string;
|
|
23
|
+
export default function Preview(): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
//# sourceMappingURL=verification-code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-code.d.ts","sourceRoot":"","sources":["../../src/templates/verification-code.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAKlD,MAAM,MAAM,uBAAuB,GAC7B,OAAO,GACP,gBAAgB,GAChB,oBAAoB,GACpB,gBAAgB,CAAC;AAEvB,MAAM,WAAW,qBAAqB;IAClC,QAAQ,EAAE,cAAc,CAAC;IACzB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,EAAE,uBAAuB,CAAC;CACpC;AAwCD,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA8B5D,CAAC;AAEF,eAAO,MAAM,0BAA0B,aACzB,cAAc,WACf,uBAAuB,KACjC,MAA6D,CAAC;AAsCjE,MAAM,CAAC,OAAO,UAAU,OAAO,4CAS9B"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* VerificationCode — shared template for all code-based verification emails.
|
|
4
|
+
*
|
|
5
|
+
* Used by:
|
|
6
|
+
* - login-verification-code (lca-api firebase.ts)
|
|
7
|
+
* - recovery-email-code (lca-api keys.ts)
|
|
8
|
+
* - embed-email-verification (brain-service contact-methods.ts)
|
|
9
|
+
* - contact-method-verification (brain-service contact-methods.ts)
|
|
10
|
+
*
|
|
11
|
+
* The `variant` prop controls the subject line and descriptive text.
|
|
12
|
+
*/
|
|
13
|
+
import { Text } from '@react-email/components';
|
|
14
|
+
import { DEFAULT_BRANDING } from '../branding';
|
|
15
|
+
import { Layout } from '../components/Layout';
|
|
16
|
+
import { CodeBlock } from '../components/CodeBlock';
|
|
17
|
+
const VARIANT_CONFIG = {
|
|
18
|
+
login: {
|
|
19
|
+
subject: (b) => `Your ${b} login code`,
|
|
20
|
+
heading: (b) => `Your ${b} Login Code`,
|
|
21
|
+
description: (email, b) => email
|
|
22
|
+
? `Here's your secure 6-digit code to log into ${b}`
|
|
23
|
+
: `Here's your secure 6-digit code to log into ${b}`,
|
|
24
|
+
expiry: 'This code will expire in 5 minutes. If you didn\u2019t request this, you can safely ignore this email.',
|
|
25
|
+
},
|
|
26
|
+
'recovery-email': {
|
|
27
|
+
subject: () => 'Verify your recovery email',
|
|
28
|
+
heading: (b) => `Your ${b} Verification Code`,
|
|
29
|
+
description: (email, b) => email
|
|
30
|
+
? `Here's your secure 6-digit code to add ${email} as a recovery method for ${b}`
|
|
31
|
+
: `Here's your secure 6-digit code to add a recovery method for ${b}`,
|
|
32
|
+
expiry: 'This code will expire in 5 minutes. If you didn\u2019t request this, you can safely ignore this email.',
|
|
33
|
+
},
|
|
34
|
+
'embed-verification': {
|
|
35
|
+
subject: (b) => `Your ${b} verification code`,
|
|
36
|
+
heading: (b) => `Your ${b} Verification Code`,
|
|
37
|
+
description: (email) => email
|
|
38
|
+
? `Enter this code to verify ${email} and claim your credential:`
|
|
39
|
+
: 'Enter this code to verify your email address and claim your credential:',
|
|
40
|
+
expiry: 'This code will expire in 10 minutes. If you didn\u2019t request this, you can safely ignore this email.',
|
|
41
|
+
},
|
|
42
|
+
'contact-method': {
|
|
43
|
+
subject: (b) => `Your ${b} verification code`,
|
|
44
|
+
heading: (b) => `Your ${b} Verification Code`,
|
|
45
|
+
description: () => 'Enter this code in the app to verify your contact information.',
|
|
46
|
+
expiry: 'This code will expire in 24 hours. If you didn\u2019t request this, you can safely ignore this email.',
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
export const VerificationCode = ({ branding, verificationCode, verificationEmail, variant, }) => {
|
|
50
|
+
const config = VARIANT_CONFIG[variant];
|
|
51
|
+
return (_jsxs(Layout, { branding: branding, preview: `Your code: ${verificationCode}`, children: [_jsx(Text, { style: headingStyle, children: config.heading(branding.brandName) }), _jsx(Text, { style: paragraph, children: "Hello," }), _jsx(Text, { style: paragraph, children: config.description(verificationEmail, branding.brandName) }), _jsx(CodeBlock, { code: verificationCode, label: "Verification code" }), _jsx(Text, { style: muted, children: config.expiry }), _jsxs(Text, { style: paragraph, children: [branding.brandName, " is your private, digital passport for learning and work. It lets you securely collect and share your verified skills and achievements online."] }), _jsxs(Text, { style: signOff, children: ["Sincerely,", _jsx("br", {}), "The ", branding.brandName, " Team"] })] }));
|
|
52
|
+
};
|
|
53
|
+
export const getVerificationCodeSubject = (branding, variant) => VARIANT_CONFIG[variant].subject(branding.brandName);
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
// Styles
|
|
56
|
+
// ---------------------------------------------------------------------------
|
|
57
|
+
const headingStyle = {
|
|
58
|
+
fontSize: 24,
|
|
59
|
+
fontWeight: 600,
|
|
60
|
+
color: '#111827',
|
|
61
|
+
margin: '0 0 24px',
|
|
62
|
+
};
|
|
63
|
+
const paragraph = {
|
|
64
|
+
fontSize: 16,
|
|
65
|
+
color: '#374151',
|
|
66
|
+
lineHeight: '24px',
|
|
67
|
+
margin: '0 0 24px',
|
|
68
|
+
};
|
|
69
|
+
const muted = {
|
|
70
|
+
fontSize: 14,
|
|
71
|
+
color: '#6b7280',
|
|
72
|
+
lineHeight: '20px',
|
|
73
|
+
margin: '0 0 24px',
|
|
74
|
+
};
|
|
75
|
+
const signOff = {
|
|
76
|
+
fontSize: 14,
|
|
77
|
+
color: '#374151',
|
|
78
|
+
lineHeight: '20px',
|
|
79
|
+
margin: '24px 0 0',
|
|
80
|
+
};
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// Preview (used by `pnpm dev` / react-email dev server)
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
export default function Preview() {
|
|
85
|
+
return (_jsx(VerificationCode, { branding: DEFAULT_BRANDING, verificationCode: "847293", verificationEmail: "jane@example.com", variant: "login" }));
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=verification-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"verification-code.js","sourceRoot":"","sources":["../../src/templates/verification-code.tsx"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,yBAAyB,CAAC;AAI/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAepD,MAAM,cAAc,GAKf;IACD,KAAK,EAAE;QACH,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,aAAa;QACtC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,aAAa;QACtC,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK;YAC5B,CAAC,CAAC,+CAA+C,CAAC,EAAE;YACpD,CAAC,CAAC,+CAA+C,CAAC,EAAE;QACxD,MAAM,EAAE,wGAAwG;KACnH;IACD,gBAAgB,EAAE;QACd,OAAO,EAAE,GAAG,EAAE,CAAC,4BAA4B;QAC3C,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,oBAAoB;QAC7C,WAAW,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK;YAC5B,CAAC,CAAC,0CAA0C,KAAK,6BAA6B,CAAC,EAAE;YACjF,CAAC,CAAC,gEAAgE,CAAC,EAAE;QACzE,MAAM,EAAE,wGAAwG;KACnH;IACD,oBAAoB,EAAE;QAClB,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,oBAAoB;QAC7C,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,oBAAoB;QAC7C,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK;YACzB,CAAC,CAAC,6BAA6B,KAAK,6BAA6B;YACjE,CAAC,CAAC,yEAAyE;QAC/E,MAAM,EAAE,yGAAyG;KACpH;IACD,gBAAgB,EAAE;QACd,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,oBAAoB;QAC7C,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,oBAAoB;QAC7C,WAAW,EAAE,GAAG,EAAE,CAAC,gEAAgE;QACnF,MAAM,EAAE,uGAAuG;KAClH;CACJ,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAoC,CAAC,EAC9D,QAAQ,EACR,gBAAgB,EAChB,iBAAiB,EACjB,OAAO,GACV,EAAE,EAAE;IACD,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAEvC,OAAO,CACH,MAAC,MAAM,IAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,gBAAgB,EAAE,aACjE,KAAC,IAAI,IAAC,KAAK,EAAE,YAAY,YAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,GAAQ,EAEtE,KAAC,IAAI,IAAC,KAAK,EAAE,SAAS,uBAAe,EAErC,KAAC,IAAI,IAAC,KAAK,EAAE,SAAS,YAAG,MAAM,CAAC,WAAW,CAAC,iBAAiB,EAAE,QAAQ,CAAC,SAAS,CAAC,GAAQ,EAE1F,KAAC,SAAS,IAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAC,mBAAmB,GAAG,EAE/D,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,YAAG,MAAM,CAAC,MAAM,GAAQ,EAE1C,MAAC,IAAI,IAAC,KAAK,EAAE,SAAS,aACjB,QAAQ,CAAC,SAAS,sJAEhB,EAEP,MAAC,IAAI,IAAC,KAAK,EAAE,OAAO,2BACN,cAAM,UAAK,QAAQ,CAAC,SAAS,aACpC,IACF,CACZ,CAAC;AACN,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,0BAA0B,GAAG,CACtC,QAAwB,EACxB,OAAgC,EAC1B,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AAEjE,8EAA8E;AAC9E,SAAS;AACT,8EAA8E;AAE9E,MAAM,YAAY,GAAwB;IACtC,QAAQ,EAAE,EAAE;IACZ,UAAU,EAAE,GAAG;IACf,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,UAAU;CACrB,CAAC;AAEF,MAAM,SAAS,GAAwB;IACnC,QAAQ,EAAE,EAAE;IACZ,KAAK,EAAE,SAAS;IAChB,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,UAAU;CACrB,CAAC;AAEF,MAAM,KAAK,GAAwB;IAC/B,QAAQ,EAAE,EAAE;IACZ,KAAK,EAAE,SAAS;IAChB,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,UAAU;CACrB,CAAC;AAEF,MAAM,OAAO,GAAwB;IACjC,QAAQ,EAAE,EAAE;IACZ,KAAK,EAAE,SAAS;IAChB,UAAU,EAAE,MAAM;IAClB,MAAM,EAAE,UAAU;CACrB,CAAC;AAEF,8EAA8E;AAC9E,wDAAwD;AACxD,8EAA8E;AAE9E,MAAM,CAAC,OAAO,UAAU,OAAO;IAC3B,OAAO,CACH,KAAC,gBAAgB,IACb,QAAQ,EAAE,gBAAgB,EAC1B,gBAAgB,EAAC,QAAQ,EACzB,iBAAiB,EAAC,kBAAkB,EACpC,OAAO,EAAC,OAAO,GACjB,CACL,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side tenant resolution for brain-service and lca-api.
|
|
3
|
+
*
|
|
4
|
+
* Resolution order (first match wins):
|
|
5
|
+
* 1. Explicit `X-Tenant-Id` header — native apps, any client that knows its tenant
|
|
6
|
+
* 2. `Origin` / `Referer` header hostname — web apps (e.g. alpha.vetpass.app → vetpass)
|
|
7
|
+
* 3. `DEFAULT_TENANT_ID` env var — per-tenant deploys, cron jobs, server-to-server
|
|
8
|
+
* 4. Fallback to 'learncard'
|
|
9
|
+
*
|
|
10
|
+
* The registry maps tenant IDs to email branding overrides. Missing fields
|
|
11
|
+
* fall back to LearnCard defaults via `resolveBranding()`.
|
|
12
|
+
*/
|
|
13
|
+
import type { TenantBranding } from './branding';
|
|
14
|
+
export interface ResolvedTenant {
|
|
15
|
+
/** Canonical tenant identifier, e.g. 'vetpass', 'learncard'. */
|
|
16
|
+
id: string;
|
|
17
|
+
/** Partial email branding — pass to `resolveBranding()` for full defaults. */
|
|
18
|
+
emailBranding: Partial<TenantBranding>;
|
|
19
|
+
/** How the tenant was resolved — useful for logging / debugging. */
|
|
20
|
+
resolvedVia: 'header' | 'origin' | 'env' | 'default';
|
|
21
|
+
}
|
|
22
|
+
export interface RequestHeaders {
|
|
23
|
+
/** Value of the X-Tenant-Id header. */
|
|
24
|
+
'x-tenant-id'?: string | undefined;
|
|
25
|
+
/** Origin header (e.g. "https://alpha.vetpass.app"). */
|
|
26
|
+
origin?: string | undefined;
|
|
27
|
+
/** Referer header (fallback for Origin). */
|
|
28
|
+
referer?: string | undefined;
|
|
29
|
+
[key: string]: string | string[] | undefined;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolve the tenant from HTTP request headers.
|
|
33
|
+
*
|
|
34
|
+
* @param headers — Request headers object. Accepts plain objects, Node IncomingHttpHeaders, etc.
|
|
35
|
+
* @param envTenantId — Override for `process.env.DEFAULT_TENANT_ID` (useful for testing).
|
|
36
|
+
*/
|
|
37
|
+
export declare const resolveTenantFromRequest: (headers: RequestHeaders, envTenantId?: string) => ResolvedTenant;
|
|
38
|
+
/**
|
|
39
|
+
* Register additional origin → tenant mappings at startup.
|
|
40
|
+
* Useful for dev/staging domains configured via env vars.
|
|
41
|
+
*/
|
|
42
|
+
export declare const registerOriginMapping: (hostname: string, tenantId: string) => void;
|
|
43
|
+
/**
|
|
44
|
+
* Register or update email branding for a tenant at startup.
|
|
45
|
+
* Merges with any existing branding (does not replace).
|
|
46
|
+
*/
|
|
47
|
+
export declare const registerTenantBranding: (tenantId: string, branding: Partial<TenantBranding>) => void;
|
|
48
|
+
//# sourceMappingURL=tenant-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-registry.d.ts","sourceRoot":"","sources":["../src/tenant-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAMjD,MAAM,WAAW,cAAc;IAC3B,gEAAgE;IAChE,EAAE,EAAE,MAAM,CAAC;IAEX,8EAA8E;IAC9E,aAAa,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IAEvC,oEAAoE;IACpE,WAAW,EAAE,QAAQ,GAAG,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;CACxD;AAED,MAAM,WAAW,cAAc;IAC3B,uCAAuC;IACvC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAEnC,wDAAwD;IACxD,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE5B,4CAA4C;IAC5C,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC;CAChD;AAkFD;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,YACxB,cAAc,gBACT,MAAM,KACrB,cAgCF,CAAC;AAsBF;;;GAGG;AACH,eAAO,MAAM,qBAAqB,aAAc,MAAM,YAAY,MAAM,KAAG,IAE1E,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,sBAAsB,aAAc,MAAM,YAAY,OAAO,CAAC,cAAc,CAAC,KAAG,IAK5F,CAAC"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side tenant resolution for brain-service and lca-api.
|
|
3
|
+
*
|
|
4
|
+
* Resolution order (first match wins):
|
|
5
|
+
* 1. Explicit `X-Tenant-Id` header — native apps, any client that knows its tenant
|
|
6
|
+
* 2. `Origin` / `Referer` header hostname — web apps (e.g. alpha.vetpass.app → vetpass)
|
|
7
|
+
* 3. `DEFAULT_TENANT_ID` env var — per-tenant deploys, cron jobs, server-to-server
|
|
8
|
+
* 4. Fallback to 'learncard'
|
|
9
|
+
*
|
|
10
|
+
* The registry maps tenant IDs to email branding overrides. Missing fields
|
|
11
|
+
* fall back to LearnCard defaults via `resolveBranding()`.
|
|
12
|
+
*/
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Origin → tenant ID mapping
|
|
15
|
+
//
|
|
16
|
+
// Add new entries when a tenant gets a web deployment.
|
|
17
|
+
// Supports exact hostname match and wildcard subdomains.
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
const ORIGIN_MAP = {
|
|
20
|
+
// VetPass
|
|
21
|
+
'vetpass.app': 'vetpass',
|
|
22
|
+
'alpha.vetpass.app': 'vetpass',
|
|
23
|
+
'staging.vetpass.app': 'vetpass',
|
|
24
|
+
// LearnCard
|
|
25
|
+
'learncard.app': 'learncard',
|
|
26
|
+
'staging.learncard.app': 'learncard',
|
|
27
|
+
'app.learncard.com': 'learncard',
|
|
28
|
+
// Local dev
|
|
29
|
+
'localhost': 'learncard',
|
|
30
|
+
};
|
|
31
|
+
// ---------------------------------------------------------------------------
|
|
32
|
+
// Tenant email branding registry
|
|
33
|
+
//
|
|
34
|
+
// Only override fields that differ from LearnCard defaults.
|
|
35
|
+
// Missing fields → resolveBranding() fills in DEFAULT_BRANDING.
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
const TENANT_EMAIL_BRANDING = {
|
|
38
|
+
learncard: {},
|
|
39
|
+
vetpass: {
|
|
40
|
+
brandName: 'VetPass',
|
|
41
|
+
logoUrl: 'https://vetpass.app/assets/icon/icon.png',
|
|
42
|
+
logoAlt: 'VetPass',
|
|
43
|
+
primaryColor: '#1B5E20',
|
|
44
|
+
primaryTextColor: '#ffffff',
|
|
45
|
+
supportEmail: 'support@vetpass.app',
|
|
46
|
+
websiteUrl: 'https://www.vetpass.app',
|
|
47
|
+
appUrl: 'https://vetpass.app',
|
|
48
|
+
fromDomain: 'vetpass.app',
|
|
49
|
+
copyrightHolder: 'VetPass',
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// Resolution
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
/**
|
|
56
|
+
* Extract a hostname from a URL string. Returns undefined if parsing fails.
|
|
57
|
+
*/
|
|
58
|
+
const extractHostname = (urlString) => {
|
|
59
|
+
try {
|
|
60
|
+
return new URL(urlString).hostname;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Look up tenant ID from a hostname, checking exact match first,
|
|
68
|
+
* then stripping subdomains progressively (e.g. "foo.bar.vetpass.app" → "vetpass.app").
|
|
69
|
+
*/
|
|
70
|
+
const tenantIdFromHostname = (hostname) => {
|
|
71
|
+
if (ORIGIN_MAP[hostname])
|
|
72
|
+
return ORIGIN_MAP[hostname];
|
|
73
|
+
// Strip subdomains: "alpha.vetpass.app" → "vetpass.app"
|
|
74
|
+
const parts = hostname.split('.');
|
|
75
|
+
for (let i = 1; i < parts.length - 1; i++) {
|
|
76
|
+
const parent = parts.slice(i).join('.');
|
|
77
|
+
if (ORIGIN_MAP[parent])
|
|
78
|
+
return ORIGIN_MAP[parent];
|
|
79
|
+
}
|
|
80
|
+
return undefined;
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* Resolve the tenant from HTTP request headers.
|
|
84
|
+
*
|
|
85
|
+
* @param headers — Request headers object. Accepts plain objects, Node IncomingHttpHeaders, etc.
|
|
86
|
+
* @param envTenantId — Override for `process.env.DEFAULT_TENANT_ID` (useful for testing).
|
|
87
|
+
*/
|
|
88
|
+
export const resolveTenantFromRequest = (headers, envTenantId) => {
|
|
89
|
+
// 1. Explicit X-Tenant-Id header (native apps, any informed client)
|
|
90
|
+
const explicit = normalizeHeader(headers['x-tenant-id']);
|
|
91
|
+
if (explicit) {
|
|
92
|
+
return buildTenant(explicit, 'header');
|
|
93
|
+
}
|
|
94
|
+
// 2. Origin / Referer header (web apps)
|
|
95
|
+
const origin = normalizeHeader(headers.origin) || normalizeHeader(headers.referer);
|
|
96
|
+
if (origin) {
|
|
97
|
+
const hostname = extractHostname(origin);
|
|
98
|
+
if (hostname) {
|
|
99
|
+
const matched = tenantIdFromHostname(hostname);
|
|
100
|
+
if (matched) {
|
|
101
|
+
return buildTenant(matched, 'origin');
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// 3. Deploy-level env var
|
|
106
|
+
const envDefault = envTenantId ?? process.env.DEFAULT_TENANT_ID;
|
|
107
|
+
if (envDefault) {
|
|
108
|
+
return buildTenant(envDefault, 'env');
|
|
109
|
+
}
|
|
110
|
+
// 4. Safe default
|
|
111
|
+
return buildTenant('learncard', 'default');
|
|
112
|
+
};
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
// Helpers
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
const normalizeHeader = (value) => {
|
|
117
|
+
if (Array.isArray(value))
|
|
118
|
+
return value[0];
|
|
119
|
+
return value || undefined;
|
|
120
|
+
};
|
|
121
|
+
const buildTenant = (id, resolvedVia) => ({
|
|
122
|
+
id,
|
|
123
|
+
emailBranding: TENANT_EMAIL_BRANDING[id] ?? {},
|
|
124
|
+
resolvedVia,
|
|
125
|
+
});
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// Admin helpers (for extending the registry at runtime via env vars)
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
/**
|
|
130
|
+
* Register additional origin → tenant mappings at startup.
|
|
131
|
+
* Useful for dev/staging domains configured via env vars.
|
|
132
|
+
*/
|
|
133
|
+
export const registerOriginMapping = (hostname, tenantId) => {
|
|
134
|
+
ORIGIN_MAP[hostname] = tenantId;
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Register or update email branding for a tenant at startup.
|
|
138
|
+
* Merges with any existing branding (does not replace).
|
|
139
|
+
*/
|
|
140
|
+
export const registerTenantBranding = (tenantId, branding) => {
|
|
141
|
+
TENANT_EMAIL_BRANDING[tenantId] = {
|
|
142
|
+
...TENANT_EMAIL_BRANDING[tenantId],
|
|
143
|
+
...branding,
|
|
144
|
+
};
|
|
145
|
+
};
|
|
146
|
+
//# sourceMappingURL=tenant-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-registry.js","sourceRoot":"","sources":["../src/tenant-registry.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@learncard/email-templates",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Git-managed, tenant-branded email and SMS templates for LearnCard services",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"files": [
|
|
8
|
+
"dist"
|
|
9
|
+
],
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@react-email/components": "^0.0.36",
|
|
12
|
+
"@react-email/render": "^1.0.5",
|
|
13
|
+
"react": "^18.3.1"
|
|
14
|
+
},
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@types/react": "^18.3.0",
|
|
17
|
+
"react-email": "^3.0.0",
|
|
18
|
+
"typescript": "^5.0.0",
|
|
19
|
+
"vitest": "^1.0.0"
|
|
20
|
+
},
|
|
21
|
+
"author": "Learning Economy Foundation (www.learningeconomy.io)",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"homepage": "https://github.com/learningeconomy/LearnCard/tree/main/packages/email-templates/README.md",
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "https://github.com/learningeconomy/LearnCard"
|
|
27
|
+
},
|
|
28
|
+
"bugs": {
|
|
29
|
+
"url": "https://github.com/learningeconomy/LearnCard/issues"
|
|
30
|
+
},
|
|
31
|
+
"sideEffects": false,
|
|
32
|
+
"scripts": {
|
|
33
|
+
"dev": "email dev --dir src --port 3333",
|
|
34
|
+
"preview": "email dev --dir src --port 3333",
|
|
35
|
+
"test": "vitest run",
|
|
36
|
+
"test:watch": "vitest",
|
|
37
|
+
"typecheck": "tsc --noEmit",
|
|
38
|
+
"build": "tsc"
|
|
39
|
+
}
|
|
40
|
+
}
|