@tern-secure/nextjs 3.4.0 → 3.4.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.
Files changed (196) hide show
  1. package/dist/cjs/app-router/client/TernSecureProvider.js +33 -0
  2. package/dist/cjs/app-router/client/TernSecureProvider.js.map +1 -0
  3. package/dist/cjs/app-router/client/actions.js +180 -0
  4. package/dist/cjs/app-router/client/actions.js.map +1 -0
  5. package/dist/cjs/app-router/route-handler/internal-route.js +45 -0
  6. package/dist/cjs/app-router/route-handler/internal-route.js.map +1 -0
  7. package/dist/cjs/app-router/server/auth.js +71 -0
  8. package/dist/cjs/app-router/server/auth.js.map +1 -0
  9. package/dist/cjs/app-router/server/index.js +42 -0
  10. package/dist/cjs/app-router/server/index.js.map +1 -0
  11. package/dist/cjs/app-router/server/sessionTernSecure.js +159 -0
  12. package/dist/cjs/app-router/server/sessionTernSecure.js.map +1 -0
  13. package/dist/cjs/app-router/server/ternSecureMiddleware.js +50 -0
  14. package/dist/cjs/app-router/server/ternSecureMiddleware.js.map +1 -0
  15. package/dist/cjs/boundary/TernSecureClientProvider.js +107 -0
  16. package/dist/cjs/boundary/TernSecureClientProvider.js.map +1 -0
  17. package/dist/cjs/boundary/TernSecureCtx.js +49 -0
  18. package/dist/cjs/boundary/TernSecureCtx.js.map +1 -0
  19. package/dist/cjs/boundary/hooks/useAuth.js +51 -0
  20. package/dist/cjs/boundary/hooks/useAuth.js.map +1 -0
  21. package/dist/cjs/boundary/hooks/useSignUp.js +40 -0
  22. package/dist/cjs/boundary/hooks/useSignUp.js.map +1 -0
  23. package/dist/cjs/boundary/hooks/useUser.js +44 -0
  24. package/dist/cjs/boundary/hooks/useUser.js.map +1 -0
  25. package/dist/cjs/components/background.js +65 -0
  26. package/dist/cjs/components/background.js.map +1 -0
  27. package/dist/cjs/components/sign-in.js +242 -0
  28. package/dist/cjs/components/sign-in.js.map +1 -0
  29. package/dist/cjs/components/sign-out.js +69 -0
  30. package/dist/cjs/components/sign-out.js.map +1 -0
  31. package/dist/cjs/components/sign-up.js +328 -0
  32. package/dist/cjs/components/sign-up.js.map +1 -0
  33. package/dist/cjs/components/ui/alert.js +88 -0
  34. package/dist/cjs/components/ui/alert.js.map +1 -0
  35. package/dist/cjs/components/ui/button.js +84 -0
  36. package/dist/cjs/components/ui/button.js.map +1 -0
  37. package/dist/cjs/components/ui/card.js +101 -0
  38. package/dist/cjs/components/ui/card.js.map +1 -0
  39. package/dist/cjs/components/ui/input.js +58 -0
  40. package/dist/cjs/components/ui/input.js.map +1 -0
  41. package/dist/cjs/components/ui/label.js +55 -0
  42. package/dist/cjs/components/ui/label.js.map +1 -0
  43. package/dist/cjs/components/ui/separator.js +59 -0
  44. package/dist/cjs/components/ui/separator.js.map +1 -0
  45. package/dist/cjs/components/verify.js +195 -0
  46. package/dist/cjs/components/verify.js.map +1 -0
  47. package/dist/cjs/errors.js +41 -0
  48. package/dist/cjs/errors.js.map +1 -0
  49. package/dist/cjs/index.js +59 -0
  50. package/dist/cjs/index.js.map +1 -0
  51. package/dist/cjs/lib/utils.d.js +17 -0
  52. package/dist/cjs/lib/utils.d.js.map +1 -0
  53. package/dist/cjs/lib/utils.js +33 -0
  54. package/dist/cjs/lib/utils.js.map +1 -0
  55. package/dist/cjs/types.js +17 -0
  56. package/dist/cjs/types.js.map +1 -0
  57. package/dist/cjs/utils/admin-init.js +57 -0
  58. package/dist/cjs/utils/admin-init.js.map +1 -0
  59. package/dist/cjs/utils/client-init.js +49 -0
  60. package/dist/cjs/utils/client-init.js.map +1 -0
  61. package/dist/cjs/utils/config.js +113 -0
  62. package/dist/cjs/utils/config.js.map +1 -0
  63. package/dist/cjs/utils/construct.js +63 -0
  64. package/dist/cjs/utils/construct.js.map +1 -0
  65. package/dist/cjs/utils/create-styles.js +149 -0
  66. package/dist/cjs/utils/create-styles.js.map +1 -0
  67. package/dist/esm/app-router/client/TernSecureProvider.js +9 -0
  68. package/dist/esm/app-router/client/TernSecureProvider.js.map +1 -0
  69. package/dist/esm/app-router/client/actions.js +151 -0
  70. package/dist/esm/app-router/client/actions.js.map +1 -0
  71. package/dist/esm/app-router/route-handler/internal-route.js +20 -0
  72. package/dist/esm/app-router/route-handler/internal-route.js.map +1 -0
  73. package/dist/esm/app-router/server/auth.js +47 -0
  74. package/dist/esm/app-router/server/auth.js.map +1 -0
  75. package/dist/esm/app-router/server/index.js +13 -0
  76. package/dist/esm/app-router/server/index.js.map +1 -0
  77. package/dist/esm/app-router/server/sessionTernSecure.js +129 -0
  78. package/dist/esm/app-router/server/sessionTernSecure.js.map +1 -0
  79. package/dist/esm/app-router/server/ternSecureMiddleware.js +26 -0
  80. package/dist/esm/app-router/server/ternSecureMiddleware.js.map +1 -0
  81. package/dist/esm/boundary/TernSecureClientProvider.js +83 -0
  82. package/dist/esm/boundary/TernSecureClientProvider.js.map +1 -0
  83. package/dist/esm/boundary/TernSecureCtx.js +23 -0
  84. package/dist/esm/boundary/TernSecureCtx.js.map +1 -0
  85. package/dist/esm/boundary/hooks/useAuth.js +27 -0
  86. package/dist/esm/boundary/hooks/useAuth.js.map +1 -0
  87. package/dist/esm/boundary/hooks/useSignUp.js +16 -0
  88. package/dist/esm/boundary/hooks/useSignUp.js.map +1 -0
  89. package/dist/esm/boundary/hooks/useUser.js +20 -0
  90. package/dist/esm/boundary/hooks/useUser.js.map +1 -0
  91. package/dist/esm/components/background.js +41 -0
  92. package/dist/esm/components/background.js.map +1 -0
  93. package/dist/esm/components/sign-in.js +218 -0
  94. package/dist/esm/components/sign-in.js.map +1 -0
  95. package/dist/esm/components/sign-out.js +45 -0
  96. package/dist/esm/components/sign-out.js.map +1 -0
  97. package/dist/esm/components/sign-up.js +294 -0
  98. package/dist/esm/components/sign-up.js.map +1 -0
  99. package/dist/esm/components/ui/alert.js +52 -0
  100. package/dist/esm/components/ui/alert.js.map +1 -0
  101. package/dist/esm/components/ui/button.js +49 -0
  102. package/dist/esm/components/ui/button.js.map +1 -0
  103. package/dist/esm/components/ui/card.js +62 -0
  104. package/dist/esm/components/ui/card.js.map +1 -0
  105. package/dist/esm/components/ui/input.js +24 -0
  106. package/dist/esm/components/ui/input.js.map +1 -0
  107. package/dist/esm/components/ui/label.js +21 -0
  108. package/dist/esm/components/ui/label.js.map +1 -0
  109. package/dist/esm/components/ui/separator.js +25 -0
  110. package/dist/esm/components/ui/separator.js.map +1 -0
  111. package/dist/esm/components/verify.js +161 -0
  112. package/dist/esm/components/verify.js.map +1 -0
  113. package/dist/esm/errors.js +16 -0
  114. package/dist/esm/errors.js.map +1 -0
  115. package/dist/esm/index.js +24 -0
  116. package/dist/esm/index.js.map +1 -0
  117. package/dist/esm/lib/utils.d.js +1 -0
  118. package/dist/esm/lib/utils.d.js.map +1 -0
  119. package/dist/esm/lib/utils.js +9 -0
  120. package/dist/esm/lib/utils.js.map +1 -0
  121. package/dist/esm/types.js +1 -0
  122. package/dist/esm/types.js.map +1 -0
  123. package/dist/esm/utils/admin-init.js +22 -0
  124. package/dist/esm/utils/admin-init.js.map +1 -0
  125. package/dist/esm/utils/client-init.js +22 -0
  126. package/dist/esm/utils/client-init.js.map +1 -0
  127. package/dist/esm/utils/config.js +84 -0
  128. package/dist/esm/utils/config.js.map +1 -0
  129. package/dist/esm/utils/construct.js +37 -0
  130. package/dist/esm/utils/construct.js.map +1 -0
  131. package/dist/esm/utils/create-styles.js +123 -0
  132. package/dist/esm/utils/create-styles.js.map +1 -0
  133. package/dist/types/app-router/client/TernSecureProvider.d.ts +26 -0
  134. package/dist/types/app-router/client/TernSecureProvider.d.ts.map +1 -0
  135. package/dist/types/app-router/client/actions.d.ts +49 -0
  136. package/dist/types/app-router/client/actions.d.ts.map +1 -0
  137. package/dist/types/app-router/route-handler/internal-route.d.ts +9 -0
  138. package/dist/types/app-router/route-handler/internal-route.d.ts.map +1 -0
  139. package/dist/types/app-router/server/auth.d.ts +7 -0
  140. package/dist/types/app-router/server/auth.d.ts.map +1 -0
  141. package/dist/types/app-router/server/index.d.ts +5 -0
  142. package/dist/types/app-router/server/index.d.ts.map +1 -0
  143. package/dist/types/app-router/server/sessionTernSecure.d.ts +37 -0
  144. package/dist/types/app-router/server/sessionTernSecure.d.ts.map +1 -0
  145. package/dist/types/app-router/server/ternSecureMiddleware.d.ts +7 -0
  146. package/dist/types/app-router/server/ternSecureMiddleware.d.ts.map +1 -0
  147. package/dist/types/boundary/TernSecureClientProvider.d.ts +11 -0
  148. package/dist/types/boundary/TernSecureClientProvider.d.ts.map +1 -0
  149. package/dist/types/boundary/TernSecureCtx.d.ts +17 -0
  150. package/dist/types/boundary/TernSecureCtx.d.ts.map +1 -0
  151. package/dist/types/boundary/hooks/useAuth.d.ts +11 -0
  152. package/dist/types/boundary/hooks/useAuth.d.ts.map +1 -0
  153. package/dist/types/boundary/hooks/useSignUp.d.ts +5 -0
  154. package/dist/types/boundary/hooks/useSignUp.d.ts.map +1 -0
  155. package/dist/types/boundary/hooks/useUser.d.ts +7 -0
  156. package/dist/types/boundary/hooks/useUser.d.ts.map +1 -0
  157. package/dist/types/components/background.d.ts +2 -0
  158. package/dist/types/components/background.d.ts.map +1 -0
  159. package/dist/types/components/sign-in.d.ts +18 -0
  160. package/dist/types/components/sign-in.d.ts.map +1 -0
  161. package/dist/types/components/sign-out.d.ts +10 -0
  162. package/dist/types/components/sign-out.d.ts.map +1 -0
  163. package/dist/types/components/sign-up.d.ts +7 -0
  164. package/dist/types/components/sign-up.d.ts.map +1 -0
  165. package/dist/types/components/ui/alert.d.ts +9 -0
  166. package/dist/types/components/ui/alert.d.ts.map +1 -0
  167. package/dist/types/components/ui/button.d.ts +12 -0
  168. package/dist/types/components/ui/button.d.ts.map +1 -0
  169. package/dist/types/components/ui/card.d.ts +9 -0
  170. package/dist/types/components/ui/card.d.ts.map +1 -0
  171. package/dist/types/components/ui/input.d.ts +4 -0
  172. package/dist/types/components/ui/input.d.ts.map +1 -0
  173. package/dist/types/components/ui/label.d.ts +6 -0
  174. package/dist/types/components/ui/label.d.ts.map +1 -0
  175. package/dist/types/components/ui/separator.d.ts +5 -0
  176. package/dist/types/components/ui/separator.d.ts.map +1 -0
  177. package/dist/types/components/verify.d.ts +2 -0
  178. package/dist/types/components/verify.d.ts.map +1 -0
  179. package/dist/types/errors.d.ts +9 -0
  180. package/dist/types/errors.d.ts.map +1 -0
  181. package/dist/types/index.d.ts.map +1 -0
  182. package/dist/types/lib/utils.d.ts +3 -0
  183. package/dist/types/lib/utils.d.ts.map +1 -0
  184. package/dist/types/types.d.ts +63 -0
  185. package/dist/types/types.d.ts.map +1 -0
  186. package/dist/types/utils/admin-init.d.ts +4 -0
  187. package/dist/types/utils/admin-init.d.ts.map +1 -0
  188. package/dist/types/utils/client-init.d.ts +5 -0
  189. package/dist/types/utils/client-init.d.ts.map +1 -0
  190. package/dist/types/utils/config.d.ts +35 -0
  191. package/dist/types/utils/config.d.ts.map +1 -0
  192. package/dist/types/utils/construct.d.ts +22 -0
  193. package/dist/types/utils/construct.d.ts.map +1 -0
  194. package/dist/types/utils/create-styles.d.ts +99 -0
  195. package/dist/types/utils/create-styles.d.ts.map +1 -0
  196. package/package.json +1 -1
@@ -0,0 +1,161 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useState, useEffect } from "react";
4
+ import { useRouter } from "next/navigation";
5
+ import Link from "next/link";
6
+ import { Loader2, MailCheck, ChevronLeft, RefreshCw, ArrowRight } from "lucide-react";
7
+ import { Button } from "./ui/button";
8
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "./ui/card";
9
+ import { Alert, AlertDescription } from "./ui/alert";
10
+ import { Separator } from "./ui/separator";
11
+ import { AuthBackground } from "./background";
12
+ import { cn } from "../lib/utils";
13
+ import { useSignUp } from "../boundary/hooks/useSignUp";
14
+ import { resendEmailVerification } from "../app-router/client/actions";
15
+ const RESEND_COOLDOWN = 59;
16
+ const MAX_RESEND_ATTEMPTS = 3;
17
+ function Verify() {
18
+ const router = useRouter();
19
+ const { email } = useSignUp();
20
+ const [error, setError] = useState("");
21
+ const [success, setSuccess] = useState("");
22
+ const [resendCooldown, setResendCooldown] = useState(0);
23
+ const [isResending, setIsResending] = useState(false);
24
+ const [resendAttempts, setResendAttempts] = useState(0);
25
+ useEffect(() => {
26
+ if (!email) {
27
+ router.push("/sign-in");
28
+ }
29
+ }, [email, router]);
30
+ useEffect(() => {
31
+ let timer;
32
+ if (resendCooldown > 0) {
33
+ timer = setInterval(() => {
34
+ setResendCooldown((prev) => prev - 1);
35
+ }, 1e3);
36
+ }
37
+ return () => clearInterval(timer);
38
+ }, [resendCooldown]);
39
+ const handleResendVerification = async () => {
40
+ if (!email || isResending || resendCooldown > 0 || resendAttempts >= MAX_RESEND_ATTEMPTS) return;
41
+ try {
42
+ setIsResending(true);
43
+ setError("");
44
+ setSuccess("");
45
+ const result = await resendEmailVerification();
46
+ if (result.success) {
47
+ if (result.isVerified) {
48
+ setSuccess(result.message);
49
+ setTimeout(() => {
50
+ router.push("/sign-in");
51
+ }, 2e3);
52
+ } else {
53
+ setSuccess(result.message);
54
+ setResendAttempts((prev) => prev + 1);
55
+ setResendCooldown(RESEND_COOLDOWN);
56
+ }
57
+ }
58
+ } catch (error2) {
59
+ setError("Failed to resend verification email. Please try again.");
60
+ } finally {
61
+ setIsResending(false);
62
+ }
63
+ };
64
+ const handleRedirectToSignIn = () => {
65
+ router.push("/sign-in");
66
+ };
67
+ if (!email) {
68
+ return null;
69
+ }
70
+ return /* @__PURE__ */ jsxs("div", { className: "relative min-h-screen flex flex-col items-center justify-center py-12 px-4 sm:px-6 lg:px-8", children: [
71
+ /* @__PURE__ */ jsx(AuthBackground, {}),
72
+ /* @__PURE__ */ jsxs(
73
+ Link,
74
+ {
75
+ href: "/sign-in",
76
+ className: cn(
77
+ "absolute top-8 left-8 flex items-center text-sm font-medium text-muted-foreground",
78
+ "transition-colors hover:text-primary"
79
+ ),
80
+ children: [
81
+ /* @__PURE__ */ jsx(ChevronLeft, { className: "mr-2 h-4 w-4" }),
82
+ "Back to sign in"
83
+ ]
84
+ }
85
+ ),
86
+ /* @__PURE__ */ jsxs(Card, { className: "w-full max-w-md mx-auto", children: [
87
+ /* @__PURE__ */ jsxs(CardHeader, { className: "space-y-1", children: [
88
+ /* @__PURE__ */ jsx("div", { className: "flex justify-center mb-4", children: /* @__PURE__ */ jsxs("div", { className: "relative", children: [
89
+ /* @__PURE__ */ jsx("div", { className: "absolute -inset-1 rounded-full bg-primary/20 blur-lg" }),
90
+ /* @__PURE__ */ jsx("div", { className: "relative rounded-full bg-primary/10 p-3", children: /* @__PURE__ */ jsx(MailCheck, { className: "h-8 w-8 text-primary" }) })
91
+ ] }) }),
92
+ /* @__PURE__ */ jsx(CardTitle, { className: "text-2xl font-bold tracking-tight text-center", children: "Check your email" }),
93
+ /* @__PURE__ */ jsxs(CardDescription, { className: "text-center", children: [
94
+ "We've sent a verification link to",
95
+ /* @__PURE__ */ jsx("br", {}),
96
+ /* @__PURE__ */ jsx("span", { className: "font-medium", children: email })
97
+ ] })
98
+ ] }),
99
+ /* @__PURE__ */ jsxs(CardContent, { className: "p-6 space-y-6", children: [
100
+ error && /* @__PURE__ */ jsx(Alert, { variant: "destructive", className: "animate-in fade-in-50", children: /* @__PURE__ */ jsx(AlertDescription, { children: error }) }),
101
+ success && /* @__PURE__ */ jsx(
102
+ Alert,
103
+ {
104
+ variant: "default",
105
+ className: cn(
106
+ "animate-in fade-in-50",
107
+ success.includes("already verified") ? "bg-green-50" : "bg-blue-50"
108
+ ),
109
+ children: /* @__PURE__ */ jsx(
110
+ AlertDescription,
111
+ {
112
+ className: success.includes("already verified") ? "text-green-800" : "text-blue-800",
113
+ children: success
114
+ }
115
+ )
116
+ }
117
+ ),
118
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
119
+ /* @__PURE__ */ jsx("div", { className: "p-4 rounded-lg bg-muted/50", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start space-x-4", children: [
120
+ /* @__PURE__ */ jsx("div", { className: "mt-1", children: /* @__PURE__ */ jsx(MailCheck, { className: "h-5 w-5 text-muted-foreground" }) }),
121
+ /* @__PURE__ */ jsxs("div", { className: "flex-1 space-y-1", children: [
122
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium", children: "Already verified?" }),
123
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "If you've already clicked the verification link in your email, you can proceed to sign in." })
124
+ ] })
125
+ ] }) }),
126
+ /* @__PURE__ */ jsxs(Button, { onClick: handleRedirectToSignIn, className: "w-full", variant: "outline", children: [
127
+ "Continue to sign in",
128
+ /* @__PURE__ */ jsx(ArrowRight, { className: "ml-2 h-4 w-4" })
129
+ ] }),
130
+ /* @__PURE__ */ jsx(Separator, {}),
131
+ /* @__PURE__ */ jsx("div", { className: "space-y-2", children: /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
132
+ /* @__PURE__ */ jsxs("p", { className: "text-sm text-center text-muted-foreground", children: [
133
+ "Didn't receive the email? Check your spam folder or request a new link",
134
+ resendCooldown > 0 && ` in ${resendCooldown}s`
135
+ ] }),
136
+ resendAttempts >= MAX_RESEND_ATTEMPTS ? /* @__PURE__ */ jsx(Alert, { children: /* @__PURE__ */ jsx(AlertDescription, { children: "Maximum resend attempts reached. Please try signing up again or contact support." }) }) : /* @__PURE__ */ jsx(
137
+ Button,
138
+ {
139
+ onClick: handleResendVerification,
140
+ className: "w-full",
141
+ disabled: isResending || resendCooldown > 0 || resendAttempts >= MAX_RESEND_ATTEMPTS,
142
+ children: isResending ? /* @__PURE__ */ jsxs(Fragment, { children: [
143
+ /* @__PURE__ */ jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }),
144
+ "Sending..."
145
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
146
+ /* @__PURE__ */ jsx(RefreshCw, { className: "mr-2 h-4 w-4" }),
147
+ "Resend verification email",
148
+ resendAttempts > 0 && ` (${MAX_RESEND_ATTEMPTS - resendAttempts} left)`
149
+ ] })
150
+ }
151
+ )
152
+ ] }) })
153
+ ] })
154
+ ] })
155
+ ] })
156
+ ] });
157
+ }
158
+ export {
159
+ Verify
160
+ };
161
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/components/verify.tsx"],"sourcesContent":["\"use client\"\n\nimport { useState, useEffect } from \"react\"\nimport { useRouter } from \"next/navigation\"\nimport Link from \"next/link\"\nimport { Loader2, MailCheck, ChevronLeft, RefreshCw, ArrowRight } from 'lucide-react'\nimport { Button } from \"./ui/button\"\nimport { Card, CardContent, CardDescription, CardHeader, CardTitle } from \"./ui/card\"\nimport { Alert, AlertDescription } from \"./ui/alert\"\nimport { Separator } from \"./ui/separator\"\nimport { AuthBackground } from \"./background\"\nimport { cn } from \"../lib/utils\"\nimport { useSignUp } from '../boundary/hooks/useSignUp'\nimport { resendEmailVerification } from '../app-router/client/actions'\n\nconst RESEND_COOLDOWN = 59 // 59 seconds cooldown for resend\nconst MAX_RESEND_ATTEMPTS = 3\n\n\nexport function Verify() {\n const router = useRouter()\n const { email } = useSignUp()\n \n const [error, setError] = useState(\"\")\n const [success, setSuccess] = useState(\"\")\n const [resendCooldown, setResendCooldown] = useState(0)\n const [isResending, setIsResending] = useState(false)\n const [resendAttempts, setResendAttempts] = useState(0)\n \n // Redirect if no email in context\n useEffect(() => {\n if (!email) {\n router.push(\"/sign-in\")\n }\n }, [email, router])\n \n useEffect(() => {\n let timer: NodeJS.Timeout\n if (resendCooldown > 0) {\n timer = setInterval(() => {\n setResendCooldown((prev) => prev - 1)\n }, 1000)\n }\n return () => clearInterval(timer)\n }, [resendCooldown])\n \n const handleResendVerification = async () => {\n if (!email || isResending || resendCooldown > 0 || resendAttempts >= MAX_RESEND_ATTEMPTS) return\n \n try {\n setIsResending(true)\n setError(\"\")\n setSuccess(\"\")\n\n const result = await resendEmailVerification()\n\n if (result.success) {\n if (result.isVerified) {\n // If already verified, show success message and redirect after delay\n setSuccess(result.message)\n setTimeout(() => {\n router.push('/sign-in')\n }, 2000)\n } else {\n // If not verified, increment attempts and start cooldown\n setSuccess(result.message)\n setResendAttempts((prev) => prev + 1)\n setResendCooldown(RESEND_COOLDOWN)\n }\n }\n\n } catch (error) {\n setError(\"Failed to resend verification email. Please try again.\")\n } finally {\n setIsResending(false)\n }\n }\n \n const handleRedirectToSignIn = () => {\n router.push(\"/sign-in\")\n }\n \n if (!email) {\n return null // Will redirect in useEffect\n }\n \n return (\n <div className=\"relative min-h-screen flex flex-col items-center justify-center py-12 px-4 sm:px-6 lg:px-8\">\n <AuthBackground />\n \n <Link\n href=\"/sign-in\"\n className={cn(\n \"absolute top-8 left-8 flex items-center text-sm font-medium text-muted-foreground\",\n \"transition-colors hover:text-primary\",\n )}\n >\n <ChevronLeft className=\"mr-2 h-4 w-4\" />\n Back to sign in\n </Link>\n \n <Card className=\"w-full max-w-md mx-auto\">\n <CardHeader className=\"space-y-1\">\n <div className=\"flex justify-center mb-4\">\n <div className=\"relative\">\n <div className=\"absolute -inset-1 rounded-full bg-primary/20 blur-lg\" />\n <div className=\"relative rounded-full bg-primary/10 p-3\">\n <MailCheck className=\"h-8 w-8 text-primary\" />\n </div>\n </div>\n </div>\n <CardTitle className=\"text-2xl font-bold tracking-tight text-center\">Check your email</CardTitle>\n <CardDescription className=\"text-center\">\n We&apos;ve sent a verification link to\n <br />\n <span className=\"font-medium\">{email}</span>\n </CardDescription>\n </CardHeader>\n \n <CardContent className=\"p-6 space-y-6\">\n {error && (\n <Alert variant=\"destructive\" className=\"animate-in fade-in-50\">\n <AlertDescription>{error}</AlertDescription>\n </Alert>\n )}\n\n{success && (\n <Alert \n variant=\"default\" \n className={cn(\n \"animate-in fade-in-50\",\n success.includes(\"already verified\") ? \"bg-green-50\" : \"bg-blue-50\"\n )}\n >\n <AlertDescription \n className={success.includes(\"already verified\") ? \"text-green-800\" : \"text-blue-800\"}\n >\n {success}\n </AlertDescription>\n </Alert>\n)}\n \n <div className=\"space-y-4\">\n <div className=\"p-4 rounded-lg bg-muted/50\">\n <div className=\"flex items-start space-x-4\">\n <div className=\"mt-1\">\n <MailCheck className=\"h-5 w-5 text-muted-foreground\" />\n </div>\n <div className=\"flex-1 space-y-1\">\n <p className=\"text-sm font-medium\">Already verified?</p>\n <p className=\"text-sm text-muted-foreground\">\n If you&apos;ve already clicked the verification link in your email, you can proceed to sign in.\n </p>\n </div>\n </div>\n </div>\n \n <Button onClick={handleRedirectToSignIn} className=\"w-full\" variant=\"outline\">\n Continue to sign in\n <ArrowRight className=\"ml-2 h-4 w-4\" />\n </Button>\n \n <Separator />\n \n <div className=\"space-y-2\">\n <div className=\"space-y-2\">\n <p className=\"text-sm text-center text-muted-foreground\">\n Didn&apos;t receive the email? Check your spam folder or request a new link\n {resendCooldown > 0 && ` in ${resendCooldown}s`}\n </p>\n {resendAttempts >= MAX_RESEND_ATTEMPTS ? (\n <Alert>\n <AlertDescription>\n Maximum resend attempts reached. Please try signing up again or contact support.\n </AlertDescription>\n </Alert>\n ) : (\n <Button\n onClick={handleResendVerification}\n className=\"w-full\"\n disabled={isResending || resendCooldown > 0 || resendAttempts >= MAX_RESEND_ATTEMPTS}\n >\n {isResending ? (\n <>\n <Loader2 className=\"mr-2 h-4 w-4 animate-spin\" />\n Sending...\n </>\n ) : (\n <>\n <RefreshCw className=\"mr-2 h-4 w-4\" />\n Resend verification email\n {resendAttempts > 0 && ` (${MAX_RESEND_ATTEMPTS - resendAttempts} left)`}\n </>\n )}\n </Button>\n )}\n </div>\n </div>\n </div>\n </CardContent>\n </Card>\n </div>\n )\n }"],"mappings":"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","names":["error"]}
@@ -0,0 +1,16 @@
1
+ const ERRORS = {
2
+ SERVER_SIDE_INITIALIZATION: "TernSecure must be initialized on the client side",
3
+ NOT_INITIALIZED: "TernSecure services are not initialized. Call initializeTernSecure() first",
4
+ HOOK_CONTEXT: (hookName) => `${hookName} must be used within TernSecureProvider`
5
+ };
6
+ class TernSecureError extends Error {
7
+ constructor(message) {
8
+ super(message);
9
+ this.name = "TernSecureError";
10
+ }
11
+ }
12
+ export {
13
+ ERRORS,
14
+ TernSecureError
15
+ };
16
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/errors.ts"],"sourcesContent":["export const ERRORS = {\n SERVER_SIDE_INITIALIZATION: 'TernSecure must be initialized on the client side',\n NOT_INITIALIZED: 'TernSecure services are not initialized. Call initializeTernSecure() first',\n HOOK_CONTEXT: (hookName: string) => `${hookName} must be used within TernSecureProvider`,\n } as const;\n \n export class TernSecureError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'TernSecureError';\n }\n }"],"mappings":"AAAO,MAAM,SAAS;AAAA,EAClB,4BAA4B;AAAA,EAC5B,iBAAiB;AAAA,EACjB,cAAc,CAAC,aAAqB,GAAG,QAAQ;AACjD;AAEO,MAAM,wBAAwB,MAAM;AAAA,EACzC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;","names":[]}
@@ -0,0 +1,24 @@
1
+ import { TernSecureAuth, TernSecureFirestore, ternSecureAuth } from "./utils/client-init";
2
+ import { loadFireConfig, validateConfig } from "./utils/config";
3
+ import { signInWithEmail } from "./app-router/client/actions";
4
+ import { TernSecureProvider } from "./app-router/client/TernSecureProvider";
5
+ import { useAuth } from "./boundary/hooks/useAuth";
6
+ import { useUser } from "./boundary/hooks/useUser";
7
+ import { SignIn } from "./components/sign-in";
8
+ import { SignOut } from "./components/sign-out";
9
+ import { SignUp } from "./components/sign-up";
10
+ export {
11
+ SignIn,
12
+ SignOut,
13
+ SignUp,
14
+ TernSecureAuth,
15
+ TernSecureFirestore,
16
+ TernSecureProvider,
17
+ loadFireConfig,
18
+ signInWithEmail,
19
+ ternSecureAuth,
20
+ useAuth,
21
+ useUser,
22
+ validateConfig
23
+ };
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/index.ts"],"sourcesContent":["\n//import { TernSecureServerProvider } from './app-router/server/TernSecureServerProvider'\n//import type { TernSecureState } from './app-router/client/TernSecureProvider'\nexport { TernSecureAuth, TernSecureFirestore, ternSecureAuth } from './utils/client-init'\nexport { loadFireConfig, validateConfig } from './utils/config'\nexport { signInWithEmail } from './app-router/client/actions'\n//export { useInternalContext } from './boundary/TernSecureCtx'\n//export { TernSecureClientProvider } from './app-router/client/TernSecureProvider'\nexport { TernSecureProvider } from './app-router/client/TernSecureProvider'\nexport { useAuth } from './boundary/hooks/useAuth' \nexport { useUser } from './boundary/hooks/useUser'\nexport { SignIn } from './components/sign-in'\nexport { SignOut } from './components/sign-out'\nexport { SignUp } from './components/sign-up'\n\n//export const TernSecureProvider = TernSecureServerProvider\n//export type { TernSecureState }"],"mappings":"AAGA,SAAS,gBAAgB,qBAAqB,sBAAsB;AACpE,SAAS,gBAAgB,sBAAsB;AAC/C,SAAS,uBAAuB;AAGhC,SAAS,0BAA0B;AACnC,SAAS,eAAe;AACxB,SAAS,eAAe;AACxB,SAAS,cAAc;AACvB,SAAS,eAAe;AACxB,SAAS,cAAc;","names":[]}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=utils.d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,9 @@
1
+ import { clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+ function cn(...inputs) {
4
+ return twMerge(clsx(inputs));
5
+ }
6
+ export {
7
+ cn
8
+ };
9
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/lib/utils.ts"],"sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n"],"mappings":"AAAA,SAAS,YAA6B;AACtC,SAAS,eAAe;AAEjB,SAAS,MAAM,QAAsB;AAC1C,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;","names":[]}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,22 @@
1
+ import admin from "firebase-admin";
2
+ import { initializeAdminConfig } from "./config";
3
+ if (!admin.apps.length) {
4
+ try {
5
+ const config = initializeAdminConfig();
6
+ admin.initializeApp({
7
+ credential: admin.credential.cert({
8
+ ...config,
9
+ privateKey: config.privateKey.replace(/\\n/g, "\n")
10
+ })
11
+ });
12
+ } catch (error) {
13
+ console.error("Firebase admin initialization error", error);
14
+ }
15
+ }
16
+ const adminTernSecureAuth = admin.auth();
17
+ const adminTernSecureDb = admin.firestore();
18
+ export {
19
+ adminTernSecureAuth,
20
+ adminTernSecureDb
21
+ };
22
+ //# sourceMappingURL=admin-init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/admin-init.ts"],"sourcesContent":["import admin from 'firebase-admin';\nimport { initializeAdminConfig } from './config';\n\nif (!admin.apps.length) {\n try {\n const config = initializeAdminConfig();\n admin.initializeApp({\n credential: admin.credential.cert({\n ...config,\n privateKey: config.privateKey.replace(/\\\\n/g, '\\n'),\n }),\n });\n } catch (error) {\n console.error('Firebase admin initialization error', error);\n }\n}\n\nexport const adminTernSecureAuth = admin.auth();\nexport const adminTernSecureDb = admin.firestore();"],"mappings":"AAAA,OAAO,WAAW;AAClB,SAAS,6BAA6B;AAEtC,IAAI,CAAC,MAAM,KAAK,QAAQ;AACtB,MAAI;AACF,UAAM,SAAS,sBAAsB;AACrC,UAAM,cAAc;AAAA,MAClB,YAAY,MAAM,WAAW,KAAK;AAAA,QAChC,GAAG;AAAA,QACH,YAAY,OAAO,WAAW,QAAQ,QAAQ,IAAI;AAAA,MACpD,CAAC;AAAA,IACH,CAAC;AAAA,EACH,SAAS,OAAO;AACd,YAAQ,MAAM,uCAAuC,KAAK;AAAA,EAC5D;AACF;AAEO,MAAM,sBAAsB,MAAM,KAAK;AACvC,MAAM,oBAAoB,MAAM,UAAU;","names":[]}
@@ -0,0 +1,22 @@
1
+ import { initializeApp, getApps } from "firebase/app";
2
+ import { getAuth, setPersistence, browserSessionPersistence } from "firebase/auth";
3
+ import { getFirestore } from "firebase/firestore";
4
+ import { getStorage } from "firebase/storage";
5
+ import { initializeConfig } from "./config";
6
+ const APP_NAME = process.env.NEXT_PUBLIC_APP_NAME;
7
+ const config = initializeConfig();
8
+ const clientApp = getApps().length === 0 ? initializeApp(config, APP_NAME) : getApps()[0];
9
+ const ternSecureAuth = getAuth(clientApp);
10
+ setPersistence(ternSecureAuth, browserSessionPersistence);
11
+ const firestore = getFirestore(clientApp);
12
+ const storage = getStorage(clientApp);
13
+ const TernSecureAuth = () => ternSecureAuth;
14
+ const TernSecureFirestore = () => firestore;
15
+ const TernSecureStorage = () => storage;
16
+ export {
17
+ TernSecureAuth,
18
+ TernSecureFirestore,
19
+ TernSecureStorage,
20
+ ternSecureAuth
21
+ };
22
+ //# sourceMappingURL=client-init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/client-init.ts"],"sourcesContent":["import { initializeApp, getApps } from 'firebase/app';\nimport { getAuth, setPersistence, browserSessionPersistence } from 'firebase/auth';\nimport { getFirestore } from 'firebase/firestore';\nimport { getStorage } from 'firebase/storage';\nimport { initializeConfig} from './config';\n\nconst APP_NAME = process.env.NEXT_PUBLIC_APP_NAME;\n\n// Initialize immediately\nconst config = initializeConfig();\nconst clientApp = getApps().length === 0 ? initializeApp(config, APP_NAME) : getApps()[0];\nexport const ternSecureAuth = getAuth(clientApp);\nsetPersistence(ternSecureAuth, browserSessionPersistence); //to change later user should be able to choose persistance\nconst firestore = getFirestore(clientApp);\nconst storage = getStorage(clientApp);\n\n\n\nexport const TernSecureAuth = () => ternSecureAuth;\nexport const TernSecureFirestore = () => firestore;\nexport const TernSecureStorage = () => storage;\n"],"mappings":"AAAA,SAAS,eAAe,eAAe;AACvC,SAAS,SAAS,gBAAgB,iCAAiC;AACnE,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;AAC3B,SAAS,wBAAuB;AAEhC,MAAM,WAAW,QAAQ,IAAI;AAG7B,MAAM,SAAS,iBAAiB;AAChC,MAAM,YAAY,QAAQ,EAAE,WAAW,IAAI,cAAc,QAAQ,QAAQ,IAAI,QAAQ,EAAE,CAAC;AACjF,MAAM,iBAAiB,QAAQ,SAAS;AAC/C,eAAe,gBAAgB,yBAAyB;AACxD,MAAM,YAAY,aAAa,SAAS;AACxC,MAAM,UAAU,WAAW,SAAS;AAI7B,MAAM,iBAAiB,MAAM;AAC7B,MAAM,sBAAsB,MAAM;AAClC,MAAM,oBAAoB,MAAM;","names":[]}
@@ -0,0 +1,84 @@
1
+ const loadFireConfig = () => ({
2
+ apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY || "",
3
+ authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN || "",
4
+ projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID || "",
5
+ storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET || "",
6
+ messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID || "",
7
+ appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID || "",
8
+ measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID || void 0
9
+ });
10
+ const validateConfig = (config) => {
11
+ const requiredFields = [
12
+ "apiKey",
13
+ "authDomain",
14
+ "projectId",
15
+ "storageBucket",
16
+ "messagingSenderId",
17
+ "appId"
18
+ ];
19
+ const errors = [];
20
+ requiredFields.forEach((field) => {
21
+ if (!config[field]) {
22
+ errors.push(`Missing required field: NEXT_PUBLIC_FIREBASE_${String(field).toUpperCase()}`);
23
+ }
24
+ });
25
+ return {
26
+ isValid: errors.length === 0,
27
+ errors,
28
+ config
29
+ };
30
+ };
31
+ const initializeConfig = () => {
32
+ const config = loadFireConfig();
33
+ const validationResult = validateConfig(config);
34
+ if (!validationResult.isValid) {
35
+ throw new Error(
36
+ `Firebase configuration validation failed:
37
+ ${validationResult.errors.join("\n")}`
38
+ );
39
+ }
40
+ return config;
41
+ };
42
+ const loadAdminConfig = () => ({
43
+ projectId: process.env.FIREBASE_PROJECT_ID || "",
44
+ clientEmail: process.env.FIREBASE_CLIENT_EMAIL || "",
45
+ privateKey: process.env.FIREBASE_PRIVATE_KEY || ""
46
+ });
47
+ const validateAdminConfig = (config) => {
48
+ const requiredFields = [
49
+ "projectId",
50
+ "clientEmail",
51
+ "privateKey"
52
+ ];
53
+ const errors = [];
54
+ requiredFields.forEach((field) => {
55
+ if (!config[field]) {
56
+ errors.push(`Missing required field: FIREBASE_${String(field).toUpperCase()}`);
57
+ }
58
+ });
59
+ return {
60
+ isValid: errors.length === 0,
61
+ errors,
62
+ config
63
+ };
64
+ };
65
+ const initializeAdminConfig = () => {
66
+ const config = loadAdminConfig();
67
+ const validationResult = validateAdminConfig(config);
68
+ if (!validationResult.isValid) {
69
+ throw new Error(
70
+ `Firebase Admin configuration validation failed:
71
+ ${validationResult.errors.join("\n")}`
72
+ );
73
+ }
74
+ return config;
75
+ };
76
+ export {
77
+ initializeAdminConfig,
78
+ initializeConfig,
79
+ loadAdminConfig,
80
+ loadFireConfig,
81
+ validateAdminConfig,
82
+ validateConfig
83
+ };
84
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/config.ts"],"sourcesContent":["import { TernSecureConfig, ConfigValidationResult, TernSecureAdminConfig, AdminConfigValidationResult } from '../types'\n\n/**\n * Loads Firebase configuration from environment variables\n * @returns {TernSecureConfig} Firebase configuration object\n */\nexport const loadFireConfig = (): TernSecureConfig => ({\n apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY || '',\n authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN || '',\n projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID || '',\n storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET || '',\n messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID || '',\n appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID || '',\n measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID || undefined,\n})\n\n/**\n * Validates Firebase configuration\n * @param {TernSecureConfig} config - Firebase configuration object\n * @throws {Error} If required configuration values are missing\n * @returns {TernSecureConfig} Validated configuration object\n */\nexport const validateConfig = (config: TernSecureConfig): ConfigValidationResult => {\n const requiredFields: (keyof TernSecureConfig)[] = [\n 'apiKey',\n 'authDomain',\n 'projectId',\n 'storageBucket',\n 'messagingSenderId',\n 'appId'\n ]\n\n const errors: string[] = []\n \n requiredFields.forEach(field => {\n if (!config[field]) {\n errors.push(`Missing required field: NEXT_PUBLIC_FIREBASE_${String(field).toUpperCase()}`)\n }\n })\n\n return {\n isValid: errors.length === 0,\n errors,\n config\n }\n}\n\n/**\n * Initializes configuration with validation\n * @throws {Error} If configuration is invalid\n */\nexport const initializeConfig = (): TernSecureConfig => {\n const config = loadFireConfig()\n const validationResult = validateConfig(config)\n\n if (!validationResult.isValid) {\n throw new Error(\n `Firebase configuration validation failed:\\n${validationResult.errors.join('\\n')}`\n )\n }\n\n return config\n}\n\n/**\n * Loads Firebase Admin configuration from environment variables\n * @returns {AdminConfig} Firebase Admin configuration object\n */\nexport const loadAdminConfig = (): TernSecureAdminConfig => ({\n projectId: process.env.FIREBASE_PROJECT_ID || '',\n clientEmail: process.env.FIREBASE_CLIENT_EMAIL || '',\n privateKey: process.env.FIREBASE_PRIVATE_KEY || '',\n})\n\n/**\n * Validates Firebase Admin configuration\n * @param {AdminConfig} config - Firebase Admin configuration object\n * @returns {ConfigValidationResult} Validation result\n */\nexport const validateAdminConfig = (config: TernSecureAdminConfig): AdminConfigValidationResult => {\n const requiredFields: (keyof TernSecureAdminConfig)[] = [\n 'projectId',\n 'clientEmail',\n 'privateKey'\n ]\n\n const errors: string[] = []\n \n requiredFields.forEach(field => {\n if (!config[field]) {\n errors.push(`Missing required field: FIREBASE_${String(field).toUpperCase()}`)\n }\n })\n\n return {\n isValid: errors.length === 0,\n errors,\n config\n }\n}\n\n/**\n * Initializes admin configuration with validation\n * @throws {Error} If configuration is invalid\n */\nexport const initializeAdminConfig = (): TernSecureAdminConfig => {\n const config = loadAdminConfig()\n const validationResult = validateAdminConfig(config)\n\n if (!validationResult.isValid) {\n throw new Error(\n `Firebase Admin configuration validation failed:\\n${validationResult.errors.join('\\n')}`\n )\n }\n\n return config\n}"],"mappings":"AAMO,MAAM,iBAAiB,OAAyB;AAAA,EACrD,QAAQ,QAAQ,IAAI,gCAAgC;AAAA,EACpD,YAAY,QAAQ,IAAI,oCAAoC;AAAA,EAC5D,WAAW,QAAQ,IAAI,mCAAmC;AAAA,EAC1D,eAAe,QAAQ,IAAI,uCAAuC;AAAA,EAClE,mBAAmB,QAAQ,IAAI,4CAA4C;AAAA,EAC3E,OAAO,QAAQ,IAAI,+BAA+B;AAAA,EAClD,eAAe,QAAQ,IAAI,uCAAuC;AACpE;AAQO,MAAM,iBAAiB,CAAC,WAAqD;AAClF,QAAM,iBAA6C;AAAA,IACjD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,SAAmB,CAAC;AAE1B,iBAAe,QAAQ,WAAS;AAC9B,QAAI,CAAC,OAAO,KAAK,GAAG;AAClB,aAAO,KAAK,gDAAgD,OAAO,KAAK,EAAE,YAAY,CAAC,EAAE;AAAA,IAC3F;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA;AAAA,EACF;AACF;AAMO,MAAM,mBAAmB,MAAwB;AACtD,QAAM,SAAS,eAAe;AAC9B,QAAM,mBAAmB,eAAe,MAAM;AAE9C,MAAI,CAAC,iBAAiB,SAAS;AAC7B,UAAM,IAAI;AAAA,MACR;AAAA,EAA8C,iBAAiB,OAAO,KAAK,IAAI,CAAC;AAAA,IAClF;AAAA,EACF;AAEA,SAAO;AACT;AAMO,MAAM,kBAAkB,OAA8B;AAAA,EAC3D,WAAW,QAAQ,IAAI,uBAAuB;AAAA,EAC9C,aAAa,QAAQ,IAAI,yBAAyB;AAAA,EAClD,YAAY,QAAQ,IAAI,wBAAwB;AAClD;AAOO,MAAM,sBAAsB,CAAC,WAA+D;AACjG,QAAM,iBAAkD;AAAA,IACtD;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,SAAmB,CAAC;AAE1B,iBAAe,QAAQ,WAAS;AAC9B,QAAI,CAAC,OAAO,KAAK,GAAG;AAClB,aAAO,KAAK,oCAAoC,OAAO,KAAK,EAAE,YAAY,CAAC,EAAE;AAAA,IAC/E;AAAA,EACF,CAAC;AAED,SAAO;AAAA,IACL,SAAS,OAAO,WAAW;AAAA,IAC3B;AAAA,IACA;AAAA,EACF;AACF;AAMO,MAAM,wBAAwB,MAA6B;AAChE,QAAM,SAAS,gBAAgB;AAC/B,QAAM,mBAAmB,oBAAoB,MAAM;AAEnD,MAAI,CAAC,iBAAiB,SAAS;AAC7B,UAAM,IAAI;AAAA,MACR;AAAA,EAAoD,iBAAiB,OAAO,KAAK,IAAI,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}
@@ -0,0 +1,37 @@
1
+ const constructFullUrl = (path) => {
2
+ const baseUrl = window.location.origin;
3
+ if (path.startsWith("http")) {
4
+ return path;
5
+ }
6
+ return `${baseUrl}${path.startsWith("/") ? path : `/${path}`}`;
7
+ };
8
+ const constructUrlWithRedirect = (path, redirectUrl, loginPath) => {
9
+ const url = new URL(path, window.location.origin);
10
+ if (redirectUrl && !redirectUrl.startsWith(loginPath)) {
11
+ const fullRedirectUrl = redirectUrl.startsWith("http") ? redirectUrl : constructFullUrl(redirectUrl);
12
+ url.searchParams.set("redirect_url", fullRedirectUrl);
13
+ }
14
+ return url.toString();
15
+ };
16
+ const getValidRedirectUrl = (redirectUrl, searchParams) => {
17
+ const redirect = redirectUrl || searchParams.get("redirect_url") || "/";
18
+ try {
19
+ if (redirect.startsWith("http")) {
20
+ const url = new URL(redirect);
21
+ if (url.origin === window.location.origin) {
22
+ return redirect;
23
+ }
24
+ return "/";
25
+ }
26
+ return constructFullUrl(redirect);
27
+ } catch (e) {
28
+ console.error("Invalid redirect URL:", e);
29
+ return constructFullUrl("/");
30
+ }
31
+ };
32
+ export {
33
+ constructFullUrl,
34
+ constructUrlWithRedirect,
35
+ getValidRedirectUrl
36
+ };
37
+ //# sourceMappingURL=construct.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/construct.ts"],"sourcesContent":["/**\n * Constructs a full URL with the current origin\n * @param path - The path to construct the URL for\n * @returns The full URL with origin\n */\nexport const constructFullUrl = (path: string) => {\n const baseUrl = window.location.origin\n if (path.startsWith('http')) {\n return path\n }\n return `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`\n }\n \n /**\n * Constructs a URL with redirect parameters\n * @param path - The base path (usually login path)\n * @param redirectUrl - The URL to redirect to after action completes\n * @param loginPath - The login path to check against\n * @returns The full URL with redirect parameters\n */\n export const constructUrlWithRedirect = (path: string, redirectUrl: string, loginPath: string) => {\n // Create the URL with the full origin\n const url = new URL(path, window.location.origin)\n \n // Add redirect parameter if provided and not redirecting to login\n if (redirectUrl && !redirectUrl.startsWith(loginPath)) {\n // Ensure redirect URL is also absolute if it's not already\n const fullRedirectUrl = redirectUrl.startsWith('http') \n ? redirectUrl \n : constructFullUrl(redirectUrl)\n \n url.searchParams.set('redirect_url', fullRedirectUrl)\n }\n \n return url.toString()\n }\n \n /**\n * Gets a validated redirect URL ensuring it's from the same origin\n * @param redirectUrl - The URL to validate\n * @param searchParams - The search parameters to check for redirect_url\n * @returns A validated redirect URL\n */\n export const getValidRedirectUrl = (\n redirectUrl: string | undefined,\n searchParams: URLSearchParams\n ): string => {\n const redirect = redirectUrl || searchParams.get('redirect_url') || '/'\n \n try {\n if (redirect.startsWith('http')) {\n const url = new URL(redirect)\n if (url.origin === window.location.origin) {\n return redirect\n }\n return '/'\n }\n return constructFullUrl(redirect)\n } catch (e) {\n console.error('Invalid redirect URL:', e)\n return constructFullUrl('/')\n }\n }\n \n "],"mappings":"AAKO,MAAM,mBAAmB,CAAC,SAAiB;AAC9C,QAAM,UAAU,OAAO,SAAS;AAChC,MAAI,KAAK,WAAW,MAAM,GAAG;AAC3B,WAAO;AAAA,EACT;AACA,SAAO,GAAG,OAAO,GAAG,KAAK,WAAW,GAAG,IAAI,OAAO,IAAI,IAAI,EAAE;AAC9D;AASO,MAAM,2BAA2B,CAAC,MAAc,aAAqB,cAAsB;AAEhG,QAAM,MAAM,IAAI,IAAI,MAAM,OAAO,SAAS,MAAM;AAGhD,MAAI,eAAe,CAAC,YAAY,WAAW,SAAS,GAAG;AAErD,UAAM,kBAAkB,YAAY,WAAW,MAAM,IACjD,cACA,iBAAiB,WAAW;AAEhC,QAAI,aAAa,IAAI,gBAAgB,eAAe;AAAA,EACtD;AAEA,SAAO,IAAI,SAAS;AACtB;AAQO,MAAM,sBAAsB,CACjC,aACA,iBACW;AACX,QAAM,WAAW,eAAe,aAAa,IAAI,cAAc,KAAK;AAEpE,MAAI;AACF,QAAI,SAAS,WAAW,MAAM,GAAG;AAC/B,YAAM,MAAM,IAAI,IAAI,QAAQ;AAC5B,UAAI,IAAI,WAAW,OAAO,SAAS,QAAQ;AACzC,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT;AACA,WAAO,iBAAiB,QAAQ;AAAA,EAClC,SAAS,GAAG;AACV,YAAQ,MAAM,yBAAyB,CAAC;AACxC,WAAO,iBAAiB,GAAG;AAAA,EAC7B;AACF;","names":[]}
@@ -0,0 +1,123 @@
1
+ "use client";
2
+ const PREFIX = "tern";
3
+ const styleInjection = {
4
+ isInjected: false,
5
+ styleElement: null
6
+ };
7
+ const defaultClassNames = {
8
+ container: `${PREFIX}-container`,
9
+ header: `${PREFIX}-header`,
10
+ title: `${PREFIX}-title`,
11
+ formWrapper: `${PREFIX}-formWrapper`,
12
+ formContainer: `${PREFIX}-formContainer`,
13
+ form: `${PREFIX}-form`,
14
+ label: `${PREFIX}-label`,
15
+ input: `${PREFIX}-input`,
16
+ button: `${PREFIX}-button`,
17
+ error: `${PREFIX}-error`
18
+ };
19
+ function createStyleSheet(styles2) {
20
+ if (typeof window === "undefined") return defaultClassNames;
21
+ if (styleInjection.isInjected) {
22
+ return defaultClassNames;
23
+ }
24
+ let styleElement = document.querySelector("[data-tern-secure]");
25
+ if (!styleElement) {
26
+ styleElement = document.createElement("style");
27
+ styleElement.setAttribute("data-tern-secure", "");
28
+ document.head.appendChild(styleElement);
29
+ styleInjection.styleElement = styleElement;
30
+ }
31
+ const cssRules = Object.entries(styles2).map(([key, rules]) => {
32
+ const className = defaultClassNames[key];
33
+ const cssProperties = Object.entries(rules).map(([prop, value]) => {
34
+ const cssProperty = prop.replace(/([A-Z])/g, "-$1").toLowerCase();
35
+ return `${cssProperty}: ${value};`;
36
+ }).join(" ");
37
+ return `.${className} { ${cssProperties} }`;
38
+ }).join("\n");
39
+ styleElement.textContent = cssRules;
40
+ styleInjection.isInjected = true;
41
+ return defaultClassNames;
42
+ }
43
+ const styleConfig = {
44
+ container: {
45
+ display: "flex",
46
+ minHeight: "100%",
47
+ flex: "1",
48
+ flexDirection: "column",
49
+ justifyContent: "center",
50
+ padding: "3rem 1.5rem"
51
+ },
52
+ header: {
53
+ margin: "0 auto",
54
+ width: "100%",
55
+ maxWidth: "28rem"
56
+ },
57
+ title: {
58
+ marginTop: "1.5rem",
59
+ textAlign: "center",
60
+ fontSize: "1.875rem",
61
+ fontWeight: "700",
62
+ lineHeight: "2.25rem",
63
+ letterSpacing: "-0.025em",
64
+ color: "var(--tern-text-primary, #111827)"
65
+ },
66
+ formWrapper: {
67
+ marginTop: "2.5rem",
68
+ margin: "0 auto",
69
+ width: "100%",
70
+ maxWidth: "30rem"
71
+ },
72
+ formContainer: {
73
+ padding: "3rem 1.5rem",
74
+ boxShadow: "0 1px 3px 0 rgb(0 0 0 / 0.1)",
75
+ borderRadius: "0.5rem",
76
+ backgroundColor: "var(--tern-background, white)"
77
+ },
78
+ form: {
79
+ display: "flex",
80
+ flexDirection: "column",
81
+ gap: "1rem"
82
+ },
83
+ label: {
84
+ display: "block",
85
+ fontSize: "0.875rem",
86
+ fontWeight: "500",
87
+ color: "var(--tern-text-secondary, #374151)"
88
+ },
89
+ input: {
90
+ marginTop: "0.25rem",
91
+ display: "block",
92
+ width: "100%",
93
+ padding: "0.5rem 0.75rem",
94
+ borderRadius: "0.375rem",
95
+ border: "1px solid var(--tern-border, #D1D5DB)",
96
+ backgroundColor: "var(--tern-input-background, white)",
97
+ color: "var(--tern-text-primary, #111827)"
98
+ },
99
+ button: {
100
+ display: "flex",
101
+ width: "100%",
102
+ justifyContent: "center",
103
+ padding: "0.5rem 1rem",
104
+ fontSize: "0.875rem",
105
+ fontWeight: "500",
106
+ color: "white",
107
+ backgroundColor: "var(--tern-primary, #2563EB)",
108
+ border: "none",
109
+ borderRadius: "0.375rem",
110
+ cursor: "pointer"
111
+ },
112
+ error: {
113
+ color: "var(--tern-error, #DC2626)",
114
+ fontSize: "0.875rem"
115
+ }
116
+ };
117
+ const styles = createStyleSheet(styleConfig);
118
+ export {
119
+ defaultClassNames,
120
+ styleConfig,
121
+ styles
122
+ };
123
+ //# sourceMappingURL=create-styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/create-styles.ts"],"sourcesContent":["'use client'\n\nconst PREFIX = 'tern'\n\n// Singleton to track style injection\nconst styleInjection = {\n isInjected: false,\n styleElement: null as HTMLStyleElement | null\n}\n\nexport const defaultClassNames = {\n container: `${PREFIX}-container`,\n header: `${PREFIX}-header`,\n title: `${PREFIX}-title`,\n formWrapper: `${PREFIX}-formWrapper`,\n formContainer: `${PREFIX}-formContainer`,\n form: `${PREFIX}-form`,\n label: `${PREFIX}-label`,\n input: `${PREFIX}-input`,\n button: `${PREFIX}-button`,\n error: `${PREFIX}-error`\n} as const\n\n// Create styles once and cache them\nfunction createStyleSheet(styles: Record<string, React.CSSProperties>) {\n if (typeof window === 'undefined') return defaultClassNames\n\n // Return early if styles are already injected\n if (styleInjection.isInjected) {\n return defaultClassNames\n }\n\n // Find existing style element or create new one\n let styleElement = document.querySelector<HTMLStyleElement>('[data-tern-secure]')\n \n if (!styleElement) {\n styleElement = document.createElement('style')\n styleElement.setAttribute('data-tern-secure', '')\n document.head.appendChild(styleElement)\n styleInjection.styleElement = styleElement\n }\n\n // Create CSS rules\n const cssRules = Object.entries(styles).map(([key, rules]) => {\n const className = defaultClassNames[key as keyof typeof defaultClassNames]\n const cssProperties = Object.entries(rules).map(([prop, value]) => {\n const cssProperty = prop.replace(/([A-Z])/g, '-$1').toLowerCase()\n return `${cssProperty}: ${value};`\n }).join(' ')\n\n return `.${className} { ${cssProperties} }`\n }).join('\\n')\n\n // Insert styles only once\n styleElement.textContent = cssRules\n styleInjection.isInjected = true\n\n return defaultClassNames\n}\n\n// Style configuration\nexport const styleConfig = {\n container: {\n display: 'flex',\n minHeight: '100%',\n flex: '1',\n flexDirection: 'column',\n justifyContent: 'center',\n padding: '3rem 1.5rem'\n },\n header: {\n margin: '0 auto',\n width: '100%',\n maxWidth: '28rem'\n },\n title: {\n marginTop: '1.5rem',\n textAlign: 'center',\n fontSize: '1.875rem',\n fontWeight: '700',\n lineHeight: '2.25rem',\n letterSpacing: '-0.025em',\n color: 'var(--tern-text-primary, #111827)'\n },\n formWrapper: {\n marginTop: '2.5rem',\n margin: '0 auto',\n width: '100%',\n maxWidth: '30rem'\n },\n formContainer: {\n padding: '3rem 1.5rem',\n boxShadow: '0 1px 3px 0 rgb(0 0 0 / 0.1)',\n borderRadius: '0.5rem',\n backgroundColor: 'var(--tern-background, white)'\n },\n form: {\n display: 'flex',\n flexDirection: 'column',\n gap: '1rem'\n },\n label: {\n display: 'block',\n fontSize: '0.875rem',\n fontWeight: '500',\n color: 'var(--tern-text-secondary, #374151)'\n },\n input: {\n marginTop: '0.25rem',\n display: 'block',\n width: '100%',\n padding: '0.5rem 0.75rem',\n borderRadius: '0.375rem',\n border: '1px solid var(--tern-border, #D1D5DB)',\n backgroundColor: 'var(--tern-input-background, white)',\n color: 'var(--tern-text-primary, #111827)'\n },\n button: {\n display: 'flex',\n width: '100%',\n justifyContent: 'center',\n padding: '0.5rem 1rem',\n fontSize: '0.875rem',\n fontWeight: '500',\n color: 'white',\n backgroundColor: 'var(--tern-primary, #2563EB)',\n border: 'none',\n borderRadius: '0.375rem',\n cursor: 'pointer'\n },\n error: {\n color: 'var(--tern-error, #DC2626)',\n fontSize: '0.875rem'\n }\n} as const\n\n// Export pre-created styles\nexport const styles = createStyleSheet(styleConfig)\n\n"],"mappings":"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","names":["styles"]}
@@ -0,0 +1,26 @@
1
+ import React from "react";
2
+ /**
3
+ * Root Provider for TernSecure
4
+ * Use this in your Next.js App Router root layout
5
+ * Automatically handles client/server boundary and authentication state
6
+ *
7
+ * @example
8
+ * /// app/layout.tsx
9
+ * import { TernSecureProvider } from '@tern/secure'
10
+ *
11
+ * export default function RootLayout({ children }) {
12
+ * return (
13
+ * <html>
14
+ * <body>
15
+ * <TernSecureProvider>
16
+ * {children}
17
+ * </TernSecureProvider>
18
+ * </body>
19
+ * </html>
20
+ * )
21
+ * }
22
+ */
23
+ export declare function TernSecureProvider({ children }: {
24
+ children: React.ReactNode;
25
+ }): Promise<import("react/jsx-runtime").JSX.Element>;
26
+ //# sourceMappingURL=TernSecureProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TernSecureProvider.d.ts","sourceRoot":"","sources":["../../../../src/app-router/client/TernSecureProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAYzB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,kBAAkB,CAAC,EAAE,QAAQ,EAAE,EAAE;IAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAAE,oDAMnF"}