@tracked/emails 0.1.0

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 (116) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +211 -0
  3. package/dist/emails/bodyweight-goal-reached.d.ts +14 -0
  4. package/dist/emails/bodyweight-goal-reached.d.ts.map +1 -0
  5. package/dist/emails/bodyweight-goal-reached.js +177 -0
  6. package/dist/emails/bodyweight-goal-reached.js.map +1 -0
  7. package/dist/emails/client-accepted-invitation.d.ts +10 -0
  8. package/dist/emails/client-accepted-invitation.d.ts.map +1 -0
  9. package/dist/emails/client-accepted-invitation.js +99 -0
  10. package/dist/emails/client-accepted-invitation.js.map +1 -0
  11. package/dist/emails/coach-invite.d.ts +10 -0
  12. package/dist/emails/coach-invite.d.ts.map +1 -0
  13. package/dist/emails/coach-invite.js +126 -0
  14. package/dist/emails/coach-invite.js.map +1 -0
  15. package/dist/emails/coach-removed-client.d.ts +8 -0
  16. package/dist/emails/coach-removed-client.d.ts.map +1 -0
  17. package/dist/emails/coach-removed-client.js +80 -0
  18. package/dist/emails/coach-removed-client.js.map +1 -0
  19. package/dist/emails/direct-message.d.ts +11 -0
  20. package/dist/emails/direct-message.d.ts.map +1 -0
  21. package/dist/emails/direct-message.js +103 -0
  22. package/dist/emails/direct-message.js.map +1 -0
  23. package/dist/emails/feature-discovery.d.ts +11 -0
  24. package/dist/emails/feature-discovery.d.ts.map +1 -0
  25. package/dist/emails/feature-discovery.js +121 -0
  26. package/dist/emails/feature-discovery.js.map +1 -0
  27. package/dist/emails/first-workout-assigned.d.ts +10 -0
  28. package/dist/emails/first-workout-assigned.d.ts.map +1 -0
  29. package/dist/emails/first-workout-assigned.js +98 -0
  30. package/dist/emails/first-workout-assigned.js.map +1 -0
  31. package/dist/emails/first-workout-completed.d.ts +11 -0
  32. package/dist/emails/first-workout-completed.d.ts.map +1 -0
  33. package/dist/emails/first-workout-completed.js +129 -0
  34. package/dist/emails/first-workout-completed.js.map +1 -0
  35. package/dist/emails/index.d.ts +7 -0
  36. package/dist/emails/index.d.ts.map +1 -0
  37. package/dist/emails/index.js +7 -0
  38. package/dist/emails/index.js.map +1 -0
  39. package/dist/emails/new-follower.d.ts +11 -0
  40. package/dist/emails/new-follower.d.ts.map +1 -0
  41. package/dist/emails/new-follower.js +98 -0
  42. package/dist/emails/new-follower.js.map +1 -0
  43. package/dist/emails/subscription-canceled.d.ts +10 -0
  44. package/dist/emails/subscription-canceled.d.ts.map +1 -0
  45. package/dist/emails/subscription-canceled.js +131 -0
  46. package/dist/emails/subscription-canceled.js.map +1 -0
  47. package/dist/emails/support-email.d.ts +8 -0
  48. package/dist/emails/support-email.d.ts.map +1 -0
  49. package/dist/emails/support-email.js +40 -0
  50. package/dist/emails/support-email.js.map +1 -0
  51. package/dist/emails/team-invite.d.ts +11 -0
  52. package/dist/emails/team-invite.d.ts.map +1 -0
  53. package/dist/emails/team-invite.js +100 -0
  54. package/dist/emails/team-invite.js.map +1 -0
  55. package/dist/emails/team-member-removed-email.d.ts +8 -0
  56. package/dist/emails/team-member-removed-email.d.ts.map +1 -0
  57. package/dist/emails/team-member-removed-email.js +97 -0
  58. package/dist/emails/team-member-removed-email.js.map +1 -0
  59. package/dist/emails/tracked-magic-link-activate.d.ts +7 -0
  60. package/dist/emails/tracked-magic-link-activate.d.ts.map +1 -0
  61. package/dist/emails/tracked-magic-link-activate.js +93 -0
  62. package/dist/emails/tracked-magic-link-activate.js.map +1 -0
  63. package/dist/emails/tracked-magic-link.d.ts +7 -0
  64. package/dist/emails/tracked-magic-link.d.ts.map +1 -0
  65. package/dist/emails/tracked-magic-link.js +101 -0
  66. package/dist/emails/tracked-magic-link.js.map +1 -0
  67. package/dist/emails/week-one-checkin.d.ts +10 -0
  68. package/dist/emails/week-one-checkin.d.ts.map +1 -0
  69. package/dist/emails/week-one-checkin.js +141 -0
  70. package/dist/emails/week-one-checkin.js.map +1 -0
  71. package/dist/emails/welcome.d.ts +8 -0
  72. package/dist/emails/welcome.d.ts.map +1 -0
  73. package/dist/emails/welcome.js +146 -0
  74. package/dist/emails/welcome.js.map +1 -0
  75. package/dist/index.d.ts +22 -0
  76. package/dist/index.d.ts.map +1 -0
  77. package/dist/index.js +24 -0
  78. package/dist/index.js.map +1 -0
  79. package/dist/utils/email-validation.d.ts +48 -0
  80. package/dist/utils/email-validation.d.ts.map +1 -0
  81. package/dist/utils/email-validation.js +72 -0
  82. package/dist/utils/email-validation.js.map +1 -0
  83. package/dist/utils/index.d.ts +8 -0
  84. package/dist/utils/index.d.ts.map +1 -0
  85. package/dist/utils/index.js +8 -0
  86. package/dist/utils/index.js.map +1 -0
  87. package/dist/utils/username-validation.d.ts +54 -0
  88. package/dist/utils/username-validation.d.ts.map +1 -0
  89. package/dist/utils/username-validation.js +76 -0
  90. package/dist/utils/username-validation.js.map +1 -0
  91. package/package.json +78 -0
  92. package/src/emails/bodyweight-goal-reached.tsx +396 -0
  93. package/src/emails/client-accepted-invitation.tsx +258 -0
  94. package/src/emails/coach-invite.tsx +270 -0
  95. package/src/emails/coach-removed-client.tsx +212 -0
  96. package/src/emails/direct-message.tsx +249 -0
  97. package/src/emails/feature-discovery.tsx +289 -0
  98. package/src/emails/first-workout-assigned.tsx +255 -0
  99. package/src/emails/first-workout-completed.tsx +312 -0
  100. package/src/emails/index.tsx +6 -0
  101. package/src/emails/new-follower.tsx +260 -0
  102. package/src/emails/subscription-canceled.tsx +311 -0
  103. package/src/emails/support-email.tsx +80 -0
  104. package/src/emails/team-invite.tsx +262 -0
  105. package/src/emails/team-member-removed-email.tsx +240 -0
  106. package/src/emails/tracked-magic-link-activate.tsx +252 -0
  107. package/src/emails/tracked-magic-link.tsx +264 -0
  108. package/src/emails/week-one-checkin.tsx +353 -0
  109. package/src/emails/welcome.tsx +341 -0
  110. package/src/index.ts +57 -0
  111. package/src/utils/email-validation.test.ts +78 -0
  112. package/src/utils/email-validation.ts +80 -0
  113. package/src/utils/index.ts +13 -0
  114. package/src/utils/username-validation.test.ts +118 -0
  115. package/src/utils/username-validation.ts +89 -0
  116. package/static/tracked-logo.png +0 -0
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Username Validation Utilities
3
+ *
4
+ * Handles validation for usernames to determine if they're user-chosen or
5
+ * auto-generated UUIDs. Auto-generated usernames should not be displayed in emails.
6
+ */
7
+
8
+ /**
9
+ * Check if username is a generated UUID (not user-chosen)
10
+ *
11
+ * The database schema uses UUIDv7 as the default for usernames when users
12
+ * don't provide one. Format: 01944f9e-8e64-7a78-9e1e-3daba7b13e9f
13
+ *
14
+ * UUIDv7/v4 pattern: 8-4-4-4-12 hex characters separated by hyphens
15
+ *
16
+ * @param username - The username to check
17
+ * @returns true if the username is an auto-generated UUID
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * isAnonymousUsername("01944f9e-8e64-7a78-9e1e-3daba7b13e9f") // true
22
+ * isAnonymousUsername("john_doe") // false
23
+ * isAnonymousUsername(null) // true
24
+ * ```
25
+ */
26
+ export function isAnonymousUsername(
27
+ username: string | null | undefined,
28
+ ): boolean {
29
+ if (!username) {
30
+ return true;
31
+ }
32
+
33
+ // UUIDv7/v4 pattern: 8-4-4-4-12 hex characters
34
+ const uuidRegex =
35
+ /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
36
+ return uuidRegex.test(username);
37
+ }
38
+
39
+ /**
40
+ * Get safe display name for emails with intelligent fallback
41
+ *
42
+ * Tries to find a user-friendly display name by checking multiple sources
43
+ * in order of preference:
44
+ * 1. Real username (non-UUID)
45
+ * 2. Given name / First name
46
+ * 3. Full name
47
+ * 4. Generic fallback ("there")
48
+ *
49
+ * This ensures we never show auto-generated UUIDs in emails.
50
+ *
51
+ * @param username - The user's username (may be UUID)
52
+ * @param givenName - The user's first/given name
53
+ * @param name - The user's full name
54
+ * @param fallback - Default fallback if no good name is found (default: "there")
55
+ * @returns A safe, user-friendly display name
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * getSafeDisplayName("john_doe", "John", "John Doe") // "john_doe"
60
+ * getSafeDisplayName("01944f9e...", "John", "John Doe") // "John"
61
+ * getSafeDisplayName("01944f9e...", null, "John Doe") // "John Doe"
62
+ * getSafeDisplayName("01944f9e...", null, null) // "there"
63
+ * getSafeDisplayName(null, null, null, "friend") // "friend"
64
+ * ```
65
+ */
66
+ export function getSafeDisplayName(
67
+ username: string | null | undefined,
68
+ givenName: string | null | undefined,
69
+ name: string | null | undefined,
70
+ fallback: string = "there",
71
+ ): string {
72
+ // Try real username first (skip if it's a UUID)
73
+ if (username && !isAnonymousUsername(username)) {
74
+ return username;
75
+ }
76
+
77
+ // Try given name
78
+ if (givenName && givenName.trim().length > 0) {
79
+ return givenName;
80
+ }
81
+
82
+ // Try full name
83
+ if (name && name.trim().length > 0) {
84
+ return name;
85
+ }
86
+
87
+ // Use fallback
88
+ return fallback;
89
+ }
Binary file