@tern-secure/nextjs 4.2.10 → 5.0.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 (232) hide show
  1. package/README.md +33 -33
  2. package/dist/cjs/app-router/admin/index.js +5 -8
  3. package/dist/cjs/app-router/admin/index.js.map +1 -1
  4. package/dist/cjs/app-router/admin/sessionTernSecure.js +3 -6
  5. package/dist/cjs/app-router/admin/sessionTernSecure.js.map +1 -1
  6. package/dist/cjs/app-router/client/TernSecureProvider.js +10 -18
  7. package/dist/cjs/app-router/client/TernSecureProvider.js.map +1 -1
  8. package/dist/cjs/app-router/client/actions.js +1 -177
  9. package/dist/cjs/app-router/client/actions.js.map +1 -1
  10. package/dist/cjs/app-router/route-handler/internal-route.js +4 -35
  11. package/dist/cjs/app-router/route-handler/internal-route.js.map +1 -1
  12. package/dist/cjs/boundary/{hooks/useSignUp.js → components.js} +16 -16
  13. package/dist/cjs/boundary/components.js.map +1 -0
  14. package/dist/cjs/{lib/utils.js → boundary/hooks.js} +9 -11
  15. package/dist/cjs/boundary/hooks.js.map +1 -0
  16. package/dist/cjs/{boundary/TernSecureCtx.js → components/uiComponents.js} +17 -24
  17. package/dist/cjs/components/uiComponents.js.map +1 -0
  18. package/dist/cjs/errors.js +1 -0
  19. package/dist/cjs/errors.js.map +1 -1
  20. package/dist/cjs/index.js +13 -27
  21. package/dist/cjs/index.js.map +1 -1
  22. package/dist/cjs/server/auth.js +4 -5
  23. package/dist/cjs/server/auth.js.map +1 -1
  24. package/dist/cjs/server/crypto.js.map +1 -1
  25. package/dist/cjs/server/ctx-store.js +1 -2
  26. package/dist/cjs/server/ctx-store.js.map +1 -1
  27. package/dist/cjs/server/edge-session.js +6 -7
  28. package/dist/cjs/server/edge-session.js.map +1 -1
  29. package/dist/cjs/server/index.js.map +1 -1
  30. package/dist/cjs/server/jwt-edge.js.map +1 -1
  31. package/dist/cjs/server/jwt.js.map +1 -1
  32. package/dist/cjs/server/session-store.js +3 -1
  33. package/dist/cjs/server/session-store.js.map +1 -1
  34. package/dist/cjs/server/ternSecureMiddleware.js.map +1 -1
  35. package/dist/cjs/server/types.js.map +1 -1
  36. package/dist/cjs/server/utils.js.map +1 -1
  37. package/dist/cjs/types.js.map +1 -1
  38. package/dist/cjs/utils/admin-init.js +3 -0
  39. package/dist/cjs/utils/admin-init.js.map +1 -1
  40. package/dist/cjs/utils/allNextProviderProps.js +108 -0
  41. package/dist/cjs/utils/allNextProviderProps.js.map +1 -0
  42. package/dist/cjs/utils/client-init.js +2 -47
  43. package/dist/cjs/utils/client-init.js.map +1 -1
  44. package/dist/cjs/utils/config.js.map +1 -1
  45. package/dist/cjs/utils/construct.js.map +1 -1
  46. package/dist/cjs/utils/create-styles.js.map +1 -1
  47. package/dist/cjs/utils/redirect.js.map +1 -1
  48. package/dist/cjs/{components/ui/separator.js → utils/tern-ui-script.js} +41 -24
  49. package/dist/cjs/utils/tern-ui-script.js.map +1 -0
  50. package/dist/esm/app-router/admin/index.js +6 -4
  51. package/dist/esm/app-router/admin/index.js.map +1 -1
  52. package/dist/esm/app-router/admin/sessionTernSecure.js +3 -6
  53. package/dist/esm/app-router/admin/sessionTernSecure.js.map +1 -1
  54. package/dist/esm/app-router/client/TernSecureProvider.js +13 -19
  55. package/dist/esm/app-router/client/TernSecureProvider.js.map +1 -1
  56. package/dist/esm/app-router/client/actions.js +1 -157
  57. package/dist/esm/app-router/client/actions.js.map +1 -1
  58. package/dist/esm/app-router/route-handler/internal-route.js +5 -30
  59. package/dist/esm/app-router/route-handler/internal-route.js.map +1 -1
  60. package/dist/esm/boundary/components.js +18 -0
  61. package/dist/esm/boundary/components.js.map +1 -0
  62. package/dist/esm/boundary/hooks.js +9 -0
  63. package/dist/esm/boundary/hooks.js.map +1 -0
  64. package/dist/esm/components/uiComponents.js +21 -0
  65. package/dist/esm/components/uiComponents.js.map +1 -0
  66. package/dist/esm/errors.js +1 -0
  67. package/dist/esm/errors.js.map +1 -1
  68. package/dist/esm/index.js +15 -16
  69. package/dist/esm/index.js.map +1 -1
  70. package/dist/esm/server/auth.js +4 -5
  71. package/dist/esm/server/auth.js.map +1 -1
  72. package/dist/esm/server/crypto.js.map +1 -1
  73. package/dist/esm/server/ctx-store.js +1 -2
  74. package/dist/esm/server/ctx-store.js.map +1 -1
  75. package/dist/esm/server/edge-session.js +6 -7
  76. package/dist/esm/server/edge-session.js.map +1 -1
  77. package/dist/esm/server/index.js.map +1 -1
  78. package/dist/esm/server/jwt-edge.js.map +1 -1
  79. package/dist/esm/server/jwt.js.map +1 -1
  80. package/dist/esm/server/session-store.js +3 -1
  81. package/dist/esm/server/session-store.js.map +1 -1
  82. package/dist/esm/server/ternSecureMiddleware.js.map +1 -1
  83. package/dist/esm/server/utils.js.map +1 -1
  84. package/dist/esm/types.js.map +1 -1
  85. package/dist/esm/utils/admin-init.js +2 -0
  86. package/dist/esm/utils/admin-init.js.map +1 -1
  87. package/dist/esm/utils/allNextProviderProps.js +84 -0
  88. package/dist/esm/utils/allNextProviderProps.js.map +1 -0
  89. package/dist/esm/utils/client-init.js +2 -21
  90. package/dist/esm/utils/client-init.js.map +1 -1
  91. package/dist/esm/utils/config.js.map +1 -1
  92. package/dist/esm/utils/construct.js.map +1 -1
  93. package/dist/esm/utils/create-styles.js.map +1 -1
  94. package/dist/esm/utils/redirect.js.map +1 -1
  95. package/dist/esm/utils/tern-ui-script.js +42 -0
  96. package/dist/esm/utils/tern-ui-script.js.map +1 -0
  97. package/dist/types/app-router/admin/index.d.ts +1 -2
  98. package/dist/types/app-router/admin/index.d.ts.map +1 -1
  99. package/dist/types/app-router/client/TernSecureProvider.d.ts +2 -14
  100. package/dist/types/app-router/client/TernSecureProvider.d.ts.map +1 -1
  101. package/dist/types/app-router/client/actions.d.ts +1 -54
  102. package/dist/types/app-router/client/actions.d.ts.map +1 -1
  103. package/dist/types/app-router/route-handler/internal-route.d.ts +1 -15
  104. package/dist/types/app-router/route-handler/internal-route.d.ts.map +1 -1
  105. package/dist/types/boundary/components.d.ts +2 -0
  106. package/dist/types/boundary/components.d.ts.map +1 -0
  107. package/dist/types/boundary/hooks.d.ts +2 -0
  108. package/dist/types/boundary/hooks.d.ts.map +1 -0
  109. package/dist/types/components/uiComponents.d.ts +6 -0
  110. package/dist/types/components/uiComponents.d.ts.map +1 -0
  111. package/dist/types/errors.d.ts +1 -1
  112. package/dist/types/errors.d.ts.map +1 -1
  113. package/dist/types/index.d.ts +3 -9
  114. package/dist/types/index.d.ts.map +1 -1
  115. package/dist/types/server/ternSecureMiddleware.d.ts.map +1 -1
  116. package/dist/types/types.d.ts +6 -13
  117. package/dist/types/types.d.ts.map +1 -1
  118. package/dist/types/utils/admin-init.d.ts +2 -1
  119. package/dist/types/utils/admin-init.d.ts.map +1 -1
  120. package/dist/types/utils/allNextProviderProps.d.ts +6 -0
  121. package/dist/types/utils/allNextProviderProps.d.ts.map +1 -0
  122. package/dist/types/utils/client-init.d.ts +1 -4
  123. package/dist/types/utils/client-init.d.ts.map +1 -1
  124. package/dist/types/utils/config.d.ts +1 -1
  125. package/dist/types/utils/config.d.ts.map +1 -1
  126. package/dist/types/utils/construct.d.ts.map +1 -1
  127. package/dist/types/utils/tern-ui-script.d.ts +8 -0
  128. package/dist/types/utils/tern-ui-script.d.ts.map +1 -0
  129. package/package.json +41 -51
  130. package/dist/cjs/boundary/TernSecureClientProvider.js +0 -240
  131. package/dist/cjs/boundary/TernSecureClientProvider.js.map +0 -1
  132. package/dist/cjs/boundary/TernSecureCtx.js.map +0 -1
  133. package/dist/cjs/boundary/hooks/useAuth.js +0 -63
  134. package/dist/cjs/boundary/hooks/useAuth.js.map +0 -1
  135. package/dist/cjs/boundary/hooks/useSignUp.js.map +0 -1
  136. package/dist/cjs/components/background.js +0 -65
  137. package/dist/cjs/components/background.js.map +0 -1
  138. package/dist/cjs/components/sign-in.js +0 -368
  139. package/dist/cjs/components/sign-in.js.map +0 -1
  140. package/dist/cjs/components/sign-out-button.js +0 -84
  141. package/dist/cjs/components/sign-out-button.js.map +0 -1
  142. package/dist/cjs/components/sign-out.js +0 -99
  143. package/dist/cjs/components/sign-out.js.map +0 -1
  144. package/dist/cjs/components/sign-up.js +0 -332
  145. package/dist/cjs/components/sign-up.js.map +0 -1
  146. package/dist/cjs/components/ui/alert.js +0 -88
  147. package/dist/cjs/components/ui/alert.js.map +0 -1
  148. package/dist/cjs/components/ui/button.js +0 -84
  149. package/dist/cjs/components/ui/button.js.map +0 -1
  150. package/dist/cjs/components/ui/card.js +0 -101
  151. package/dist/cjs/components/ui/card.js.map +0 -1
  152. package/dist/cjs/components/ui/input.js +0 -58
  153. package/dist/cjs/components/ui/input.js.map +0 -1
  154. package/dist/cjs/components/ui/label.js +0 -55
  155. package/dist/cjs/components/ui/label.js.map +0 -1
  156. package/dist/cjs/components/ui/separator.js.map +0 -1
  157. package/dist/cjs/components/verify.js +0 -195
  158. package/dist/cjs/components/verify.js.map +0 -1
  159. package/dist/cjs/lib/utils.d.js +0 -17
  160. package/dist/cjs/lib/utils.d.js.map +0 -1
  161. package/dist/cjs/lib/utils.js.map +0 -1
  162. package/dist/esm/boundary/TernSecureClientProvider.js +0 -216
  163. package/dist/esm/boundary/TernSecureClientProvider.js.map +0 -1
  164. package/dist/esm/boundary/TernSecureCtx.js +0 -23
  165. package/dist/esm/boundary/TernSecureCtx.js.map +0 -1
  166. package/dist/esm/boundary/hooks/useAuth.js +0 -39
  167. package/dist/esm/boundary/hooks/useAuth.js.map +0 -1
  168. package/dist/esm/boundary/hooks/useSignUp.js +0 -16
  169. package/dist/esm/boundary/hooks/useSignUp.js.map +0 -1
  170. package/dist/esm/components/background.js +0 -41
  171. package/dist/esm/components/background.js.map +0 -1
  172. package/dist/esm/components/sign-in.js +0 -344
  173. package/dist/esm/components/sign-in.js.map +0 -1
  174. package/dist/esm/components/sign-out-button.js +0 -60
  175. package/dist/esm/components/sign-out-button.js.map +0 -1
  176. package/dist/esm/components/sign-out.js +0 -65
  177. package/dist/esm/components/sign-out.js.map +0 -1
  178. package/dist/esm/components/sign-up.js +0 -298
  179. package/dist/esm/components/sign-up.js.map +0 -1
  180. package/dist/esm/components/ui/alert.js +0 -52
  181. package/dist/esm/components/ui/alert.js.map +0 -1
  182. package/dist/esm/components/ui/button.js +0 -49
  183. package/dist/esm/components/ui/button.js.map +0 -1
  184. package/dist/esm/components/ui/card.js +0 -62
  185. package/dist/esm/components/ui/card.js.map +0 -1
  186. package/dist/esm/components/ui/input.js +0 -24
  187. package/dist/esm/components/ui/input.js.map +0 -1
  188. package/dist/esm/components/ui/label.js +0 -21
  189. package/dist/esm/components/ui/label.js.map +0 -1
  190. package/dist/esm/components/ui/separator.js +0 -25
  191. package/dist/esm/components/ui/separator.js.map +0 -1
  192. package/dist/esm/components/verify.js +0 -161
  193. package/dist/esm/components/verify.js.map +0 -1
  194. package/dist/esm/lib/utils.d.js +0 -1
  195. package/dist/esm/lib/utils.d.js.map +0 -1
  196. package/dist/esm/lib/utils.js +0 -9
  197. package/dist/esm/lib/utils.js.map +0 -1
  198. package/dist/types/boundary/TernSecureClientProvider.d.ts +0 -27
  199. package/dist/types/boundary/TernSecureClientProvider.d.ts.map +0 -1
  200. package/dist/types/boundary/TernSecureCtx.d.ts +0 -11
  201. package/dist/types/boundary/TernSecureCtx.d.ts.map +0 -1
  202. package/dist/types/boundary/hooks/useAuth.d.ts +0 -15
  203. package/dist/types/boundary/hooks/useAuth.d.ts.map +0 -1
  204. package/dist/types/boundary/hooks/useSignUp.d.ts +0 -5
  205. package/dist/types/boundary/hooks/useSignUp.d.ts.map +0 -1
  206. package/dist/types/components/background.d.ts +0 -2
  207. package/dist/types/components/background.d.ts.map +0 -1
  208. package/dist/types/components/sign-in.d.ts +0 -18
  209. package/dist/types/components/sign-in.d.ts.map +0 -1
  210. package/dist/types/components/sign-out-button.d.ts +0 -14
  211. package/dist/types/components/sign-out-button.d.ts.map +0 -1
  212. package/dist/types/components/sign-out.d.ts +0 -12
  213. package/dist/types/components/sign-out.d.ts.map +0 -1
  214. package/dist/types/components/sign-up.d.ts +0 -11
  215. package/dist/types/components/sign-up.d.ts.map +0 -1
  216. package/dist/types/components/ui/alert.d.ts +0 -9
  217. package/dist/types/components/ui/alert.d.ts.map +0 -1
  218. package/dist/types/components/ui/button.d.ts +0 -12
  219. package/dist/types/components/ui/button.d.ts.map +0 -1
  220. package/dist/types/components/ui/card.d.ts +0 -9
  221. package/dist/types/components/ui/card.d.ts.map +0 -1
  222. package/dist/types/components/ui/input.d.ts +0 -4
  223. package/dist/types/components/ui/input.d.ts.map +0 -1
  224. package/dist/types/components/ui/label.d.ts +0 -6
  225. package/dist/types/components/ui/label.d.ts.map +0 -1
  226. package/dist/types/components/ui/separator.d.ts +0 -5
  227. package/dist/types/components/ui/separator.d.ts.map +0 -1
  228. package/dist/types/components/verify.d.ts +0 -2
  229. package/dist/types/components/verify.d.ts.map +0 -1
  230. package/dist/types/lib/utils.d.ts +0 -3
  231. package/dist/types/lib/utils.d.ts.map +0 -1
  232. package/server/package.json +0 -5
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/jwt-edge.ts"],"sourcesContent":["import { jwtVerify, createRemoteJWKSet } from \"jose\"\nimport { cache } from \"react\"\n\ninterface FirebaseIdTokenPayload {\n iss: string\n aud: string\n auth_time: number\n user_id: string\n sub: string\n iat: number\n exp: number\n email?: string\n email_verified?: boolean\n firebase: {\n identities: {\n [key: string]: any\n }\n sign_in_provider: string\n }\n}\n\n// Firebase public key endpoints\nconst FIREBASE_ID_TOKEN_URL = \"https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com\"\nconst FIREBASE_SESSION_CERT_URL = \"https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys\"\n\n// Cache the JWKS using React cache\nconst getIdTokenJWKS = cache(() => {\n return createRemoteJWKSet(new URL(FIREBASE_ID_TOKEN_URL), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n })\n})\n\nconst getSessionJWKS = cache(() => {\n return createRemoteJWKSet(new URL(FIREBASE_SESSION_CERT_URL), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n })\n})\n\n// Helper to decode JWT without verification\nfunction decodeJwt(token: string) {\n try {\n const [headerB64, payloadB64] = token.split(\".\")\n const header = JSON.parse(Buffer.from(headerB64, \"base64\").toString())\n const payload = JSON.parse(Buffer.from(payloadB64, \"base64\").toString())\n return { header, payload }\n } catch (error) {\n console.error(\"Error decoding JWT:\", error)\n return null\n }\n}\n\nexport async function verifyFirebaseToken(token: string, isSessionCookie = false) {\n try {\n const projectId = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID\n if (!projectId) {\n throw new Error(\"Firebase Project ID is not configured\")\n }\n\n // Decode token for debugging and type checking\n const decoded = decodeJwt(token)\n if (!decoded) {\n throw new Error(\"Invalid token format\")\n }\n\n console.log(\"Token details:\", {\n header: decoded.header,\n type: isSessionCookie ? \"session_cookie\" : \"id_token\",\n })\n\n\n // Use different JWKS based on token type\n const JWKS = isSessionCookie ? await getSessionJWKS() : await getIdTokenJWKS()\n\n const { payload } = await jwtVerify(token, JWKS, {\n issuer: isSessionCookie\n ? \"https://session.firebase.google.com/\" + projectId\n : \"https://securetoken.google.com/\" + projectId,\n audience: projectId,\n algorithms: [\"RS256\"],\n })\n\n const firebasePayload = payload as unknown as FirebaseIdTokenPayload\n const now = Math.floor(Date.now() / 1000)\n\n\n if (!firebasePayload.sub) {\n throw new Error(\"Token subject is empty\")\n }\n\n return {\n valid: true,\n uid: firebasePayload.sub,\n email: firebasePayload.email,\n emailVerified: firebasePayload.email_verified,\n authTime: firebasePayload.auth_time,\n issuedAt: firebasePayload.iat,\n expiresAt: firebasePayload.exp,\n }\n } catch (error) {\n console.error(\"Token verification details:\", {\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : error,\n decoded: decodeJwt(token),\n //projectId,\n isSessionCookie,\n })\n \n return {\n valid: false,\n error: error instanceof Error ? error.message : \"Invalid token\",\n }\n }\n }"],"mappings":"AAAA,SAAS,WAAW,0BAA0B;AAC9C,SAAS,aAAa;AAqBtB,MAAM,wBAAwB;AAC9B,MAAM,4BAA4B;AAGlC,MAAM,iBAAiB,MAAM,MAAM;AACjC,SAAO,mBAAmB,IAAI,IAAI,qBAAqB,GAAG;AAAA,IACxD,aAAa;AAAA;AAAA,IACb,iBAAiB;AAAA;AAAA,IACjB,kBAAkB;AAAA;AAAA,EACpB,CAAC;AACH,CAAC;AAED,MAAM,iBAAiB,MAAM,MAAM;AACjC,SAAO,mBAAmB,IAAI,IAAI,yBAAyB,GAAG;AAAA,IAC5D,aAAa;AAAA;AAAA,IACb,iBAAiB;AAAA;AAAA,IACjB,kBAAkB;AAAA;AAAA,EACpB,CAAC;AACH,CAAC;AAGD,SAAS,UAAU,OAAe;AAChC,MAAI;AACF,UAAM,CAAC,WAAW,UAAU,IAAI,MAAM,MAAM,GAAG;AAC/C,UAAM,SAAS,KAAK,MAAM,OAAO,KAAK,WAAW,QAAQ,EAAE,SAAS,CAAC;AACrE,UAAM,UAAU,KAAK,MAAM,OAAO,KAAK,YAAY,QAAQ,EAAE,SAAS,CAAC;AACvE,WAAO,EAAE,QAAQ,QAAQ;AAAA,EAC3B,SAAS,OAAO;AACd,YAAQ,MAAM,uBAAuB,KAAK;AAC1C,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,oBAAoB,OAAe,kBAAkB,OAAO;AAChF,MAAI;AACF,UAAM,YAAY,QAAQ,IAAI;AAC9B,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAGA,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,sBAAsB;AAAA,IACxC;AAEA,YAAQ,IAAI,kBAAkB;AAAA,MAC5B,QAAQ,QAAQ;AAAA,MAChB,MAAM,kBAAkB,mBAAmB;AAAA,IAC7C,CAAC;AAID,UAAM,OAAO,kBAAkB,MAAM,eAAe,IAAI,MAAM,eAAe;AAE7E,UAAM,EAAE,QAAQ,IAAI,MAAM,UAAU,OAAO,MAAM;AAAA,MAC3C,QAAQ,kBACJ,yCAAyC,YACzC,oCAAoC;AAAA,MACxC,UAAU;AAAA,MACV,YAAY,CAAC,OAAO;AAAA,IAC1B,CAAC;AAED,UAAM,kBAAkB;AACxB,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAGxC,QAAI,CAAC,gBAAgB,KAAK;AACpB,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC9C;AAEA,WAAO;AAAA,MACD,OAAO;AAAA,MACP,KAAK,gBAAgB;AAAA,MACrB,OAAO,gBAAgB;AAAA,MACvB,eAAe,gBAAgB;AAAA,MAC/B,UAAU,gBAAgB;AAAA,MAC1B,UAAU,gBAAgB;AAAA,MAC1B,WAAW,gBAAgB;AAAA,IAC7B;AAAA,EACJ,SAAS,OAAO;AACZ,YAAQ,MAAM,+BAA+B;AAAA,MAC3C,OACE,iBAAiB,QACb;AAAA,QACE,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM;AAAA,QACf,OAAO,MAAM;AAAA,MACf,IACA;AAAA,MACN,SAAS,UAAU,KAAK;AAAA;AAAA,MAExB;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAClD;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/server/jwt-edge.ts"],"sourcesContent":["import { jwtVerify, createRemoteJWKSet } from \"jose\"\r\nimport { cache } from \"react\"\r\n\r\ninterface FirebaseIdTokenPayload {\r\n iss: string\r\n aud: string\r\n auth_time: number\r\n user_id: string\r\n sub: string\r\n iat: number\r\n exp: number\r\n email?: string\r\n email_verified?: boolean\r\n firebase: {\r\n identities: {\r\n [key: string]: any\r\n }\r\n sign_in_provider: string\r\n }\r\n}\r\n\r\n// Firebase public key endpoints\r\nconst FIREBASE_ID_TOKEN_URL = \"https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com\"\r\nconst FIREBASE_SESSION_CERT_URL = \"https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys\"\r\n\r\n// Cache the JWKS using React cache\r\nconst getIdTokenJWKS = cache(() => {\r\n return createRemoteJWKSet(new URL(FIREBASE_ID_TOKEN_URL), {\r\n cacheMaxAge: 3600000, // 1 hour\r\n timeoutDuration: 5000, // 5 seconds\r\n cooldownDuration: 30000, // 30 seconds between retries\r\n })\r\n})\r\n\r\nconst getSessionJWKS = cache(() => {\r\n return createRemoteJWKSet(new URL(FIREBASE_SESSION_CERT_URL), {\r\n cacheMaxAge: 3600000, // 1 hour\r\n timeoutDuration: 5000, // 5 seconds\r\n cooldownDuration: 30000, // 30 seconds between retries\r\n })\r\n})\r\n\r\n// Helper to decode JWT without verification\r\nfunction decodeJwt(token: string) {\r\n try {\r\n const [headerB64, payloadB64] = token.split(\".\")\r\n const header = JSON.parse(Buffer.from(headerB64, \"base64\").toString())\r\n const payload = JSON.parse(Buffer.from(payloadB64, \"base64\").toString())\r\n return { header, payload }\r\n } catch (error) {\r\n console.error(\"Error decoding JWT:\", error)\r\n return null\r\n }\r\n}\r\n\r\nexport async function verifyFirebaseToken(token: string, isSessionCookie = false) {\r\n try {\r\n const projectId = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID\r\n if (!projectId) {\r\n throw new Error(\"Firebase Project ID is not configured\")\r\n }\r\n\r\n // Decode token for debugging and type checking\r\n const decoded = decodeJwt(token)\r\n if (!decoded) {\r\n throw new Error(\"Invalid token format\")\r\n }\r\n\r\n console.log(\"Token details:\", {\r\n header: decoded.header,\r\n type: isSessionCookie ? \"session_cookie\" : \"id_token\",\r\n })\r\n\r\n\r\n // Use different JWKS based on token type\r\n const JWKS = isSessionCookie ? await getSessionJWKS() : await getIdTokenJWKS()\r\n\r\n const { payload } = await jwtVerify(token, JWKS, {\r\n issuer: isSessionCookie\r\n ? \"https://session.firebase.google.com/\" + projectId\r\n : \"https://securetoken.google.com/\" + projectId,\r\n audience: projectId,\r\n algorithms: [\"RS256\"],\r\n })\r\n\r\n const firebasePayload = payload as unknown as FirebaseIdTokenPayload\r\n const now = Math.floor(Date.now() / 1000)\r\n\r\n\r\n if (!firebasePayload.sub) {\r\n throw new Error(\"Token subject is empty\")\r\n }\r\n\r\n return {\r\n valid: true,\r\n uid: firebasePayload.sub,\r\n email: firebasePayload.email,\r\n emailVerified: firebasePayload.email_verified,\r\n authTime: firebasePayload.auth_time,\r\n issuedAt: firebasePayload.iat,\r\n expiresAt: firebasePayload.exp,\r\n }\r\n } catch (error) {\r\n console.error(\"Token verification details:\", {\r\n error:\r\n error instanceof Error\r\n ? {\r\n name: error.name,\r\n message: error.message,\r\n stack: error.stack,\r\n }\r\n : error,\r\n decoded: decodeJwt(token),\r\n //projectId,\r\n isSessionCookie,\r\n })\r\n \r\n return {\r\n valid: false,\r\n error: error instanceof Error ? error.message : \"Invalid token\",\r\n }\r\n }\r\n }"],"mappings":"AAAA,SAAS,WAAW,0BAA0B;AAC9C,SAAS,aAAa;AAqBtB,MAAM,wBAAwB;AAC9B,MAAM,4BAA4B;AAGlC,MAAM,iBAAiB,MAAM,MAAM;AACjC,SAAO,mBAAmB,IAAI,IAAI,qBAAqB,GAAG;AAAA,IACxD,aAAa;AAAA;AAAA,IACb,iBAAiB;AAAA;AAAA,IACjB,kBAAkB;AAAA;AAAA,EACpB,CAAC;AACH,CAAC;AAED,MAAM,iBAAiB,MAAM,MAAM;AACjC,SAAO,mBAAmB,IAAI,IAAI,yBAAyB,GAAG;AAAA,IAC5D,aAAa;AAAA;AAAA,IACb,iBAAiB;AAAA;AAAA,IACjB,kBAAkB;AAAA;AAAA,EACpB,CAAC;AACH,CAAC;AAGD,SAAS,UAAU,OAAe;AAChC,MAAI;AACF,UAAM,CAAC,WAAW,UAAU,IAAI,MAAM,MAAM,GAAG;AAC/C,UAAM,SAAS,KAAK,MAAM,OAAO,KAAK,WAAW,QAAQ,EAAE,SAAS,CAAC;AACrE,UAAM,UAAU,KAAK,MAAM,OAAO,KAAK,YAAY,QAAQ,EAAE,SAAS,CAAC;AACvE,WAAO,EAAE,QAAQ,QAAQ;AAAA,EAC3B,SAAS,OAAO;AACd,YAAQ,MAAM,uBAAuB,KAAK;AAC1C,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,oBAAoB,OAAe,kBAAkB,OAAO;AAChF,MAAI;AACF,UAAM,YAAY,QAAQ,IAAI;AAC9B,QAAI,CAAC,WAAW;AACd,YAAM,IAAI,MAAM,uCAAuC;AAAA,IACzD;AAGA,UAAM,UAAU,UAAU,KAAK;AAC/B,QAAI,CAAC,SAAS;AACZ,YAAM,IAAI,MAAM,sBAAsB;AAAA,IACxC;AAEA,YAAQ,IAAI,kBAAkB;AAAA,MAC5B,QAAQ,QAAQ;AAAA,MAChB,MAAM,kBAAkB,mBAAmB;AAAA,IAC7C,CAAC;AAID,UAAM,OAAO,kBAAkB,MAAM,eAAe,IAAI,MAAM,eAAe;AAE7E,UAAM,EAAE,QAAQ,IAAI,MAAM,UAAU,OAAO,MAAM;AAAA,MAC3C,QAAQ,kBACJ,yCAAyC,YACzC,oCAAoC;AAAA,MACxC,UAAU;AAAA,MACV,YAAY,CAAC,OAAO;AAAA,IAC1B,CAAC;AAED,UAAM,kBAAkB;AACxB,UAAM,MAAM,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAGxC,QAAI,CAAC,gBAAgB,KAAK;AACpB,YAAM,IAAI,MAAM,wBAAwB;AAAA,IAC9C;AAEA,WAAO;AAAA,MACD,OAAO;AAAA,MACP,KAAK,gBAAgB;AAAA,MACrB,OAAO,gBAAgB;AAAA,MACvB,eAAe,gBAAgB;AAAA,MAC/B,UAAU,gBAAgB;AAAA,MAC1B,UAAU,gBAAgB;AAAA,MAC1B,WAAW,gBAAgB;AAAA,IAC7B;AAAA,EACJ,SAAS,OAAO;AACZ,YAAQ,MAAM,+BAA+B;AAAA,MAC3C,OACE,iBAAiB,QACb;AAAA,QACE,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM;AAAA,QACf,OAAO,MAAM;AAAA,MACf,IACA;AAAA,MACN,SAAS,UAAU,KAAK;AAAA;AAAA,MAExB;AAAA,IACF,CAAC;AAED,WAAO;AAAA,MACL,OAAO;AAAA,MACP,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,IAClD;AAAA,EACF;AACF;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/jwt.ts"],"sourcesContent":["import { jwtVerify, createRemoteJWKSet } from \"jose\"\nimport { cache } from \"react\"\n\ninterface FirebaseIdTokenPayload {\n iss: string\n aud: string\n auth_time: number\n user_id: string\n sub: string\n iat: number\n exp: number\n email?: string\n email_verified?: boolean\n firebase: {\n identities: {\n [key: string]: any\n }\n sign_in_provider: string\n }\n}\n\n// Firebase public key endpoints\nconst FIREBASE_ID_TOKEN_URL = \"https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com\"\nconst FIREBASE_SESSION_CERT_URL = \"https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys\"\n\n// Cache the JWKS using React cache\nconst getIdTokenJWKS = cache(() => {\n return createRemoteJWKSet(new URL(FIREBASE_ID_TOKEN_URL), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n })\n})\n\nconst getSessionJWKS = cache(() => {\n return createRemoteJWKSet(new URL(FIREBASE_SESSION_CERT_URL), {\n cacheMaxAge: 3600000, // 1 hour\n timeoutDuration: 5000, // 5 seconds\n cooldownDuration: 30000, // 30 seconds between retries\n })\n})\n\n// Helper to decode JWT without verification\nfunction decodeJwt(token: string) {\n try {\n const [headerB64, payloadB64] = token.split(\".\")\n const header = JSON.parse(Buffer.from(headerB64, \"base64\").toString())\n const payload = JSON.parse(Buffer.from(payloadB64, \"base64\").toString())\n return { header, payload }\n } catch (error) {\n console.error(\"Error decoding JWT:\", error)\n return null\n }\n}\n\nexport async function verifyFirebaseToken(token: string, isSessionCookie = false) {\n try {\n const projectId = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID\n if (!projectId) {\n throw new Error(\"Firebase Project ID is not configured\")\n }\n\n // Decode token for debugging and type checking\n const decoded = decodeJwt(token)\n if (!decoded) {\n throw new Error(\"Invalid token format\")\n }\n\n console.log(\"Token details:\", {\n header: decoded.header,\n type: isSessionCookie ? \"session_cookie\" : \"id_token\",\n })\n\n let retries = 3\n let lastError: Error | null = null\n\n while (retries > 0) {\n try {\n // Use different JWKS based on token type\n const JWKS = isSessionCookie ? await getSessionJWKS() : await getIdTokenJWKS()\n\n const { payload } = await jwtVerify(token, JWKS, {\n issuer: isSessionCookie\n ? \"https://session.firebase.google.com/\" + projectId\n : \"https://securetoken.google.com/\" + projectId,\n audience: projectId,\n algorithms: [\"RS256\"],\n })\n\n const firebasePayload = payload as unknown as FirebaseIdTokenPayload\n\n if (!firebasePayload.sub) {\n throw new Error(\"Token subject is empty\")\n }\n\n return {\n valid: true,\n uid: firebasePayload.sub,\n email: firebasePayload.email,\n emailVerified: firebasePayload.email_verified,\n authTime: firebasePayload.auth_time,\n issuedAt: firebasePayload.iat,\n expiresAt: firebasePayload.exp,\n }\n } catch (error) {\n lastError = error as Error\n if (error instanceof Error && error.name === \"JWKSNoMatchingKey\") {\n console.warn(`JWKS retry attempt ${4 - retries}:`, error.message)\n retries--\n if (retries > 0) {\n await new Promise((resolve) => setTimeout(resolve, 1000))\n continue\n }\n }\n throw error\n }\n }\n\n throw lastError || new Error(\"Failed to verify token after retries\")\n } catch (error) {\n console.error(\"Token verification details:\", {\n error:\n error instanceof Error\n ? {\n name: error.name,\n message: error.message,\n stack: error.stack,\n }\n : error,\n decoded: decodeJwt(token),\n //projectId,\n isSessionCookie,\n })\n\n return {\n valid: false,\n error: error instanceof Error ? error.message : \"Invalid token\",\n }\n }\n}"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/server/jwt.ts"],"sourcesContent":["import { jwtVerify, createRemoteJWKSet } from \"jose\"\r\nimport { cache } from \"react\"\r\n\r\ninterface FirebaseIdTokenPayload {\r\n iss: string\r\n aud: string\r\n auth_time: number\r\n user_id: string\r\n sub: string\r\n iat: number\r\n exp: number\r\n email?: string\r\n email_verified?: boolean\r\n firebase: {\r\n identities: {\r\n [key: string]: any\r\n }\r\n sign_in_provider: string\r\n }\r\n}\r\n\r\n// Firebase public key endpoints\r\nconst FIREBASE_ID_TOKEN_URL = \"https://www.googleapis.com/robot/v1/metadata/x509/securetoken@system.gserviceaccount.com\"\r\nconst FIREBASE_SESSION_CERT_URL = \"https://identitytoolkit.googleapis.com/v1/sessionCookiePublicKeys\"\r\n\r\n// Cache the JWKS using React cache\r\nconst getIdTokenJWKS = cache(() => {\r\n return createRemoteJWKSet(new URL(FIREBASE_ID_TOKEN_URL), {\r\n cacheMaxAge: 3600000, // 1 hour\r\n timeoutDuration: 5000, // 5 seconds\r\n cooldownDuration: 30000, // 30 seconds between retries\r\n })\r\n})\r\n\r\nconst getSessionJWKS = cache(() => {\r\n return createRemoteJWKSet(new URL(FIREBASE_SESSION_CERT_URL), {\r\n cacheMaxAge: 3600000, // 1 hour\r\n timeoutDuration: 5000, // 5 seconds\r\n cooldownDuration: 30000, // 30 seconds between retries\r\n })\r\n})\r\n\r\n// Helper to decode JWT without verification\r\nfunction decodeJwt(token: string) {\r\n try {\r\n const [headerB64, payloadB64] = token.split(\".\")\r\n const header = JSON.parse(Buffer.from(headerB64, \"base64\").toString())\r\n const payload = JSON.parse(Buffer.from(payloadB64, \"base64\").toString())\r\n return { header, payload }\r\n } catch (error) {\r\n console.error(\"Error decoding JWT:\", error)\r\n return null\r\n }\r\n}\r\n\r\nexport async function verifyFirebaseToken(token: string, isSessionCookie = false) {\r\n try {\r\n const projectId = process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID\r\n if (!projectId) {\r\n throw new Error(\"Firebase Project ID is not configured\")\r\n }\r\n\r\n // Decode token for debugging and type checking\r\n const decoded = decodeJwt(token)\r\n if (!decoded) {\r\n throw new Error(\"Invalid token format\")\r\n }\r\n\r\n console.log(\"Token details:\", {\r\n header: decoded.header,\r\n type: isSessionCookie ? \"session_cookie\" : \"id_token\",\r\n })\r\n\r\n let retries = 3\r\n let lastError: Error | null = null\r\n\r\n while (retries > 0) {\r\n try {\r\n // Use different JWKS based on token type\r\n const JWKS = isSessionCookie ? await getSessionJWKS() : await getIdTokenJWKS()\r\n\r\n const { payload } = await jwtVerify(token, JWKS, {\r\n issuer: isSessionCookie\r\n ? \"https://session.firebase.google.com/\" + projectId\r\n : \"https://securetoken.google.com/\" + projectId,\r\n audience: projectId,\r\n algorithms: [\"RS256\"],\r\n })\r\n\r\n const firebasePayload = payload as unknown as FirebaseIdTokenPayload\r\n\r\n if (!firebasePayload.sub) {\r\n throw new Error(\"Token subject is empty\")\r\n }\r\n\r\n return {\r\n valid: true,\r\n uid: firebasePayload.sub,\r\n email: firebasePayload.email,\r\n emailVerified: firebasePayload.email_verified,\r\n authTime: firebasePayload.auth_time,\r\n issuedAt: firebasePayload.iat,\r\n expiresAt: firebasePayload.exp,\r\n }\r\n } catch (error) {\r\n lastError = error as Error\r\n if (error instanceof Error && error.name === \"JWKSNoMatchingKey\") {\r\n console.warn(`JWKS retry attempt ${4 - retries}:`, error.message)\r\n retries--\r\n if (retries > 0) {\r\n await new Promise((resolve) => setTimeout(resolve, 1000))\r\n continue\r\n }\r\n }\r\n throw error\r\n }\r\n }\r\n\r\n throw lastError || new Error(\"Failed to verify token after retries\")\r\n } catch (error) {\r\n console.error(\"Token verification details:\", {\r\n error:\r\n error instanceof Error\r\n ? {\r\n name: error.name,\r\n message: error.message,\r\n stack: error.stack,\r\n }\r\n : error,\r\n decoded: decodeJwt(token),\r\n //projectId,\r\n isSessionCookie,\r\n })\r\n\r\n return {\r\n valid: false,\r\n error: error instanceof Error ? error.message : \"Invalid token\",\r\n }\r\n }\r\n}"],"mappings":"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","names":[]}
@@ -1,7 +1,9 @@
1
1
  import { cache } from "react";
2
2
  class SessionStore {
3
+ static instance;
4
+ sessions;
5
+ currentSessionId = null;
3
6
  constructor() {
4
- this.currentSessionId = null;
5
7
  this.sessions = /* @__PURE__ */ new Map();
6
8
  }
7
9
  static getInstance() {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/session-store.ts"],"sourcesContent":["import { cache } from \"react\"\nimport type { User } from \"./types\"\n\n/**\n * Simple in-memory session store\n * In a real app, this would be backed by Redis/etc\n */\nclass SessionStore {\n private static instance: SessionStore\n private sessions: Map<string, User>\n private currentSessionId: string | null = null\n\n private constructor() {\n this.sessions = new Map()\n }\n\n static getInstance(): SessionStore {\n if (!SessionStore.instance) {\n SessionStore.instance = new SessionStore()\n }\n return SessionStore.instance\n }\n\n setUser(sessionId: string, user: User) {\n console.log(\"SessionStore: Setting user:\", { sessionId, user })\n this.sessions.set(sessionId, user)\n this.currentSessionId = sessionId\n }\n\n getUser(sessionId: string): User | null {\n return this.sessions.get(sessionId) || null\n }\n\n getCurrentUser(): User | null {\n if (!this.currentSessionId) return null\n return this.sessions.get(this.currentSessionId) || null\n }\n\n removeUser(sessionId: string) {\n this.sessions.delete(sessionId)\n }\n\n clear() {\n this.sessions.clear()\n }\n\n debug() {\n return {\n sessionsCount: this.sessions.size,\n currentSessionId: this.currentSessionId,\n sessions: Array.from(this.sessions.entries())\n }\n}\n}\n\n// Export singleton instance\nexport const sessionStore = SessionStore.getInstance()\n\n/**\n * Cached function to get user from session store\n * Uses React cache for SSR optimization\n */\nexport const getVerifiedUser = cache((sessionId: string): User | null => {\n return sessionStore.getUser(sessionId)\n})\n\n"],"mappings":"AAAA,SAAS,aAAa;AAOtB,MAAM,aAAa;AAAA,EAKT,cAAc;AAFtB,SAAQ,mBAAkC;AAGxC,SAAK,WAAW,oBAAI,IAAI;AAAA,EAC1B;AAAA,EAEA,OAAO,cAA4B;AACjC,QAAI,CAAC,aAAa,UAAU;AAC1B,mBAAa,WAAW,IAAI,aAAa;AAAA,IAC3C;AACA,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,QAAQ,WAAmB,MAAY;AACrC,YAAQ,IAAI,+BAA+B,EAAE,WAAW,KAAK,CAAC;AAC9D,SAAK,SAAS,IAAI,WAAW,IAAI;AACjC,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,QAAQ,WAAgC;AACtC,WAAO,KAAK,SAAS,IAAI,SAAS,KAAK;AAAA,EACzC;AAAA,EAEA,iBAA8B;AAC5B,QAAI,CAAC,KAAK,iBAAkB,QAAO;AACnC,WAAO,KAAK,SAAS,IAAI,KAAK,gBAAgB,KAAK;AAAA,EACrD;AAAA,EAEA,WAAW,WAAmB;AAC5B,SAAK,SAAS,OAAO,SAAS;AAAA,EAChC;AAAA,EAEA,QAAQ;AACN,SAAK,SAAS,MAAM;AAAA,EACtB;AAAA,EAEA,QAAQ;AACN,WAAO;AAAA,MACL,eAAe,KAAK,SAAS;AAAA,MAC7B,kBAAkB,KAAK;AAAA,MACvB,UAAU,MAAM,KAAK,KAAK,SAAS,QAAQ,CAAC;AAAA,IAC9C;AAAA,EACJ;AACA;AAGO,MAAM,eAAe,aAAa,YAAY;AAM9C,MAAM,kBAAkB,MAAM,CAAC,cAAmC;AACvE,SAAO,aAAa,QAAQ,SAAS;AACvC,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/server/session-store.ts"],"sourcesContent":["import { cache } from \"react\"\r\nimport type { User } from \"./types\"\r\n\r\n/**\r\n * Simple in-memory session store\r\n * In a real app, this would be backed by Redis/etc\r\n */\r\nclass SessionStore {\r\n private static instance: SessionStore\r\n private sessions: Map<string, User>\r\n private currentSessionId: string | null = null\r\n\r\n private constructor() {\r\n this.sessions = new Map()\r\n }\r\n\r\n static getInstance(): SessionStore {\r\n if (!SessionStore.instance) {\r\n SessionStore.instance = new SessionStore()\r\n }\r\n return SessionStore.instance\r\n }\r\n\r\n setUser(sessionId: string, user: User) {\r\n console.log(\"SessionStore: Setting user:\", { sessionId, user })\r\n this.sessions.set(sessionId, user)\r\n this.currentSessionId = sessionId\r\n }\r\n\r\n getUser(sessionId: string): User | null {\r\n return this.sessions.get(sessionId) || null\r\n }\r\n\r\n getCurrentUser(): User | null {\r\n if (!this.currentSessionId) return null\r\n return this.sessions.get(this.currentSessionId) || null\r\n }\r\n\r\n removeUser(sessionId: string) {\r\n this.sessions.delete(sessionId)\r\n }\r\n\r\n clear() {\r\n this.sessions.clear()\r\n }\r\n\r\n debug() {\r\n return {\r\n sessionsCount: this.sessions.size,\r\n currentSessionId: this.currentSessionId,\r\n sessions: Array.from(this.sessions.entries())\r\n }\r\n}\r\n}\r\n\r\n// Export singleton instance\r\nexport const sessionStore = SessionStore.getInstance()\r\n\r\n/**\r\n * Cached function to get user from session store\r\n * Uses React cache for SSR optimization\r\n */\r\nexport const getVerifiedUser = cache((sessionId: string): User | null => {\r\n return sessionStore.getUser(sessionId)\r\n})\r\n\r\n"],"mappings":"AAAA,SAAS,aAAa;AAOtB,MAAM,aAAa;AAAA,EACjB,OAAe;AAAA,EACP;AAAA,EACA,mBAAkC;AAAA,EAElC,cAAc;AACpB,SAAK,WAAW,oBAAI,IAAI;AAAA,EAC1B;AAAA,EAEA,OAAO,cAA4B;AACjC,QAAI,CAAC,aAAa,UAAU;AAC1B,mBAAa,WAAW,IAAI,aAAa;AAAA,IAC3C;AACA,WAAO,aAAa;AAAA,EACtB;AAAA,EAEA,QAAQ,WAAmB,MAAY;AACrC,YAAQ,IAAI,+BAA+B,EAAE,WAAW,KAAK,CAAC;AAC9D,SAAK,SAAS,IAAI,WAAW,IAAI;AACjC,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEA,QAAQ,WAAgC;AACtC,WAAO,KAAK,SAAS,IAAI,SAAS,KAAK;AAAA,EACzC;AAAA,EAEA,iBAA8B;AAC5B,QAAI,CAAC,KAAK,iBAAkB,QAAO;AACnC,WAAO,KAAK,SAAS,IAAI,KAAK,gBAAgB,KAAK;AAAA,EACrD;AAAA,EAEA,WAAW,WAAmB;AAC5B,SAAK,SAAS,OAAO,SAAS;AAAA,EAChC;AAAA,EAEA,QAAQ;AACN,SAAK,SAAS,MAAM;AAAA,EACtB;AAAA,EAEA,QAAQ;AACN,WAAO;AAAA,MACL,eAAe,KAAK,SAAS;AAAA,MAC7B,kBAAkB,KAAK;AAAA,MACvB,UAAU,MAAM,KAAK,KAAK,SAAS,QAAQ,CAAC;AAAA,IAC9C;AAAA,EACJ;AACA;AAGO,MAAM,eAAe,aAAa,YAAY;AAM9C,MAAM,kBAAkB,MAAM,CAAC,cAAmC;AACvE,SAAO,aAAa,QAAQ,SAAS;AACvC,CAAC;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/ternSecureMiddleware.ts"],"sourcesContent":["import { NextResponse, type NextMiddleware, type NextRequest } from 'next/server';\nimport type { User } from './types'\n\nexport const runtime = \"edge\"\n\ninterface Auth {\n user: User | null\n sessionId: string | null\n protect: () => Promise<void | Response>\n}\n\ntype MiddlewareCallback = (\n auth: Auth,\n request: NextRequest\n) => Promise<void | Response>\n\n\n/**\n * Create a route matcher function for public paths\n */\nexport function createRouteMatcher(patterns: string[]) {\n return (request: NextRequest): boolean => {\n const { pathname } = request.nextUrl\n return patterns.some((pattern) => {\n // Convert route pattern to regex\n const regexPattern = new RegExp(`^${pattern.replace(/\\*/g, \".*\").replace(/$$(.*)$$/, \"(?:$1)?\")}$`)\n return regexPattern.test(pathname)\n })\n }\n}\n\n\n/**\n * Middleware factory that handles authentication and custom logic\n * @param customHandler Optional function for additional custom logic\n */\n\nexport function ternSecureMiddleware(callback?: MiddlewareCallback): NextMiddleware {\n return async function middleware(request: NextRequest) {\n try {\n\n const sessionCookie = request.cookies.get(\"_session_cookie\")\n const idToken = request.cookies.get(\"_session_token\")\n const hasCookies = !!sessionCookie || !!idToken\n\n const auth: Auth = {\n user: null,\n sessionId: null,\n protect: async () => {\n if (!hasCookies) {\n const currentPath = request.nextUrl.pathname\n if (currentPath !== '/sign-in') {\n const redirectUrl = new URL('/sign-in', request.url)\n redirectUrl.searchParams.set('redirect', currentPath)\n return NextResponse.redirect(redirectUrl)\n }\n }\n },\n }\n\n if (callback) {\n const result = await callback(auth, request)\n if (result instanceof Response) {\n return result\n }\n }\n\n\n // Continue to the next middleware or route handler\n return NextResponse.next()\n } catch (error) {\n console.error(\"Middleware error:\", error)\n const redirectUrl = new URL(\"/sign-in\", request.url)\n return NextResponse.redirect(redirectUrl)\n }\n }\n}"],"mappings":"AAAA,SAAS,oBAA2D;AAG7D,MAAM,UAAU;AAiBhB,SAAS,mBAAmB,UAAoB;AACrD,SAAO,CAAC,YAAkC;AACxC,UAAM,EAAE,SAAS,IAAI,QAAQ;AAC7B,WAAO,SAAS,KAAK,CAAC,YAAY;AAEhC,YAAM,eAAe,IAAI,OAAO,IAAI,QAAQ,QAAQ,OAAO,IAAI,EAAE,QAAQ,YAAY,SAAS,CAAC,GAAG;AAClG,aAAO,aAAa,KAAK,QAAQ;AAAA,IACnC,CAAC;AAAA,EACH;AACF;AAQO,SAAS,qBAAqB,UAA+C;AAClF,SAAO,eAAe,WAAW,SAAsB;AACrD,QAAI;AAEF,YAAM,gBAAgB,QAAQ,QAAQ,IAAI,iBAAiB;AAC3D,YAAM,UAAU,QAAQ,QAAQ,IAAI,gBAAgB;AACpD,YAAM,aAAa,CAAC,CAAC,iBAAiB,CAAC,CAAC;AAExC,YAAM,OAAa;AAAA,QACjB,MAAM;AAAA,QACN,WAAW;AAAA,QACX,SAAS,YAAY;AACnB,cAAI,CAAC,YAAY;AACf,kBAAM,cAAc,QAAQ,QAAQ;AACpC,gBAAI,gBAAgB,YAAY;AAC9B,oBAAM,cAAc,IAAI,IAAI,YAAY,QAAQ,GAAG;AACnD,0BAAY,aAAa,IAAI,YAAY,WAAW;AACpD,qBAAO,aAAa,SAAS,WAAW;AAAA,YAC1C;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEF,UAAI,UAAU;AACV,cAAM,SAAS,MAAM,SAAS,MAAM,OAAO;AAC3C,YAAI,kBAAkB,UAAU;AAC9B,iBAAO;AAAA,QACT;AAAA,MACJ;AAIE,aAAQ,aAAa,KAAK;AAAA,IAC5B,SAAS,OAAO;AACd,cAAQ,MAAM,qBAAqB,KAAK;AACxC,YAAM,cAAc,IAAI,IAAI,YAAY,QAAQ,GAAG;AACnD,aAAO,aAAa,SAAS,WAAW;AAAA,IAC1C;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/server/ternSecureMiddleware.ts"],"sourcesContent":["import { NextResponse, type NextMiddleware, type NextRequest } from 'next/server';\r\nimport type { User } from './types'\r\n\r\nexport const runtime = \"edge\"\r\n\r\ninterface Auth {\r\n user: User | null\r\n sessionId: string | null\r\n protect: () => Promise<void | Response>\r\n}\r\n\r\ntype MiddlewareCallback = (\r\n auth: Auth,\r\n request: NextRequest\r\n) => Promise<void | Response>\r\n\r\n\r\n/**\r\n * Create a route matcher function for public paths\r\n */\r\nexport function createRouteMatcher(patterns: string[]) {\r\n return (request: NextRequest): boolean => {\r\n const { pathname } = request.nextUrl\r\n return patterns.some((pattern) => {\r\n // Convert route pattern to regex\r\n const regexPattern = new RegExp(`^${pattern.replace(/\\*/g, \".*\").replace(/$$(.*)$$/, \"(?:$1)?\")}$`)\r\n return regexPattern.test(pathname)\r\n })\r\n }\r\n}\r\n\r\n\r\n/**\r\n * Middleware factory that handles authentication and custom logic\r\n * @param customHandler Optional function for additional custom logic\r\n */\r\n\r\nexport function ternSecureMiddleware(callback?: MiddlewareCallback): NextMiddleware {\r\n return async function middleware(request: NextRequest) {\r\n try {\r\n\r\n const sessionCookie = request.cookies.get(\"_session_cookie\")\r\n const idToken = request.cookies.get(\"_session_token\")\r\n const hasCookies = !!sessionCookie || !!idToken\r\n\r\n const auth: Auth = {\r\n user: null,\r\n sessionId: null,\r\n protect: async () => {\r\n if (!hasCookies) {\r\n const currentPath = request.nextUrl.pathname\r\n if (currentPath !== '/sign-in') {\r\n const redirectUrl = new URL('/sign-in', request.url)\r\n redirectUrl.searchParams.set('redirect', currentPath)\r\n return NextResponse.redirect(redirectUrl)\r\n }\r\n }\r\n },\r\n }\r\n\r\n if (callback) {\r\n const result = await callback(auth, request)\r\n if (result instanceof Response) {\r\n return result\r\n }\r\n }\r\n\r\n\r\n // Continue to the next middleware or route handler\r\n return NextResponse.next()\r\n } catch (error) {\r\n console.error(\"Middleware error:\", error)\r\n const redirectUrl = new URL(\"/sign-in\", request.url)\r\n return NextResponse.redirect(redirectUrl)\r\n }\r\n }\r\n}"],"mappings":"AAAA,SAAS,oBAA2D;AAG7D,MAAM,UAAU;AAiBhB,SAAS,mBAAmB,UAAoB;AACrD,SAAO,CAAC,YAAkC;AACxC,UAAM,EAAE,SAAS,IAAI,QAAQ;AAC7B,WAAO,SAAS,KAAK,CAAC,YAAY;AAEhC,YAAM,eAAe,IAAI,OAAO,IAAI,QAAQ,QAAQ,OAAO,IAAI,EAAE,QAAQ,YAAY,SAAS,CAAC,GAAG;AAClG,aAAO,aAAa,KAAK,QAAQ;AAAA,IACnC,CAAC;AAAA,EACH;AACF;AAQO,SAAS,qBAAqB,UAA+C;AAClF,SAAO,eAAe,WAAW,SAAsB;AACrD,QAAI;AAEF,YAAM,gBAAgB,QAAQ,QAAQ,IAAI,iBAAiB;AAC3D,YAAM,UAAU,QAAQ,QAAQ,IAAI,gBAAgB;AACpD,YAAM,aAAa,CAAC,CAAC,iBAAiB,CAAC,CAAC;AAExC,YAAM,OAAa;AAAA,QACjB,MAAM;AAAA,QACN,WAAW;AAAA,QACX,SAAS,YAAY;AACnB,cAAI,CAAC,YAAY;AACf,kBAAM,cAAc,QAAQ,QAAQ;AACpC,gBAAI,gBAAgB,YAAY;AAC9B,oBAAM,cAAc,IAAI,IAAI,YAAY,QAAQ,GAAG;AACnD,0BAAY,aAAa,IAAI,YAAY,WAAW;AACpD,qBAAO,aAAa,SAAS,WAAW;AAAA,YAC1C;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAEF,UAAI,UAAU;AACV,cAAM,SAAS,MAAM,SAAS,MAAM,OAAO;AAC3C,YAAI,kBAAkB,UAAU;AAC9B,iBAAO;AAAA,QACT;AAAA,MACJ;AAIE,aAAQ,aAAa,KAAK;AAAA,IAC5B,SAAS,OAAO;AACd,cAAQ,MAAM,qBAAqB,KAAK;AACxC,YAAM,cAAc,IAAI,IAAI,YAAY,QAAQ,GAAG;AACnD,aAAO,aAAa,SAAS,WAAW;AAAA,IAC1C;AAAA,EACF;AACF;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/server/utils.ts"],"sourcesContent":["import type { User } from \"./types\"\n\ninterface RequestContext {\n user: User\n sessionId: string\n}\n\n// Use process.env in Node.js and globalThis in Edge\nconst getGlobalObject = () => {\n if (typeof process !== 'undefined') {\n return process\n }\n return globalThis\n}\n\nconst STORE_KEY = '__TERN_AUTH_STORE__'\n\nexport class Store {\n private static getStore() {\n const global = getGlobalObject() as any\n \n if (!global[STORE_KEY]) {\n global[STORE_KEY] = {\n contexts: new Map<string, RequestContext>(),\n sessions: new Map<string, User>(),\n currentSession: null as RequestContext | null\n }\n }\n \n return global[STORE_KEY]\n }\n\n static setContext(context: RequestContext) {\n const store = this.getStore()\n const { user, sessionId } = context\n \n console.log(\"Store: Setting context:\", { sessionId, user })\n \n // Store in both maps\n store.contexts.set(sessionId, context)\n store.sessions.set(sessionId, user)\n \n // Set as current session\n store.currentSession = context\n \n console.log(\"Store: Updated state:\", {\n contextsSize: store.contexts.size,\n sessionsSize: store.sessions.size,\n currentSession: store.currentSession\n })\n }\n\n static getContext(): RequestContext | null {\n const store = this.getStore()\n \n // First try current session\n if (store.currentSession) {\n const session = this.getSession(store.currentSession.sessionId)\n if (session && session.uid === store.currentSession.user.uid) {\n return store.currentSession\n }\n }\n \n // Then try to find any valid context\n for (const [sessionId, user] of store.sessions.entries()) {\n const context = store.contexts.get(sessionId)\n if (context && context.user.uid === user.uid) {\n // Update current session\n store.currentSession = context\n return context\n }\n }\n \n return null\n }\n\n static setSession(sessionId: string, user: User) {\n const store = this.getStore()\n store.sessions.set(sessionId, user)\n }\n\n static getSession(sessionId: string): User | null {\n const store = this.getStore()\n return store.sessions.get(sessionId) || null\n }\n\n static debug() {\n const store = this.getStore()\n return {\n contextsSize: store.contexts.size,\n sessionsSize: store.sessions.size,\n currentSession: store.currentSession,\n contexts: Array.from(store.contexts.entries()),\n sessions: Array.from(store.sessions.entries())\n }\n }\n\n static cleanup() {\n const store = this.getStore()\n const MAX_ENTRIES = 1000\n \n if (store.contexts.size > MAX_ENTRIES) {\n const keys = Array.from(store.contexts.keys())\n const toDelete = keys.slice(0, keys.length - MAX_ENTRIES)\n \n toDelete.forEach(key => {\n store.contexts.delete(key)\n store.sessions.delete(key)\n })\n }\n }\n}"],"mappings":"AAQA,MAAM,kBAAkB,MAAM;AAC5B,MAAI,OAAO,YAAY,aAAa;AAClC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,MAAM,YAAY;AAEX,MAAM,MAAM;AAAA,EACjB,OAAe,WAAW;AACxB,UAAM,SAAS,gBAAgB;AAE/B,QAAI,CAAC,OAAO,SAAS,GAAG;AACtB,aAAO,SAAS,IAAI;AAAA,QAClB,UAAU,oBAAI,IAA4B;AAAA,QAC1C,UAAU,oBAAI,IAAkB;AAAA,QAChC,gBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,WAAO,OAAO,SAAS;AAAA,EACzB;AAAA,EAEA,OAAO,WAAW,SAAyB;AACzC,UAAM,QAAQ,KAAK,SAAS;AAC5B,UAAM,EAAE,MAAM,UAAU,IAAI;AAE5B,YAAQ,IAAI,2BAA2B,EAAE,WAAW,KAAK,CAAC;AAG1D,UAAM,SAAS,IAAI,WAAW,OAAO;AACrC,UAAM,SAAS,IAAI,WAAW,IAAI;AAGlC,UAAM,iBAAiB;AAEvB,YAAQ,IAAI,yBAAyB;AAAA,MACnC,cAAc,MAAM,SAAS;AAAA,MAC7B,cAAc,MAAM,SAAS;AAAA,MAC7B,gBAAgB,MAAM;AAAA,IACxB,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,aAAoC;AACzC,UAAM,QAAQ,KAAK,SAAS;AAG5B,QAAI,MAAM,gBAAgB;AACxB,YAAM,UAAU,KAAK,WAAW,MAAM,eAAe,SAAS;AAC9D,UAAI,WAAW,QAAQ,QAAQ,MAAM,eAAe,KAAK,KAAK;AAC5D,eAAO,MAAM;AAAA,MACf;AAAA,IACF;AAGA,eAAW,CAAC,WAAW,IAAI,KAAK,MAAM,SAAS,QAAQ,GAAG;AACxD,YAAM,UAAU,MAAM,SAAS,IAAI,SAAS;AAC5C,UAAI,WAAW,QAAQ,KAAK,QAAQ,KAAK,KAAK;AAE5C,cAAM,iBAAiB;AACvB,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,WAAW,WAAmB,MAAY;AAC/C,UAAM,QAAQ,KAAK,SAAS;AAC5B,UAAM,SAAS,IAAI,WAAW,IAAI;AAAA,EACpC;AAAA,EAEA,OAAO,WAAW,WAAgC;AAChD,UAAM,QAAQ,KAAK,SAAS;AAC5B,WAAO,MAAM,SAAS,IAAI,SAAS,KAAK;AAAA,EAC1C;AAAA,EAEA,OAAO,QAAQ;AACb,UAAM,QAAQ,KAAK,SAAS;AAC5B,WAAO;AAAA,MACL,cAAc,MAAM,SAAS;AAAA,MAC7B,cAAc,MAAM,SAAS;AAAA,MAC7B,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM,KAAK,MAAM,SAAS,QAAQ,CAAC;AAAA,MAC7C,UAAU,MAAM,KAAK,MAAM,SAAS,QAAQ,CAAC;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,OAAO,UAAU;AACf,UAAM,QAAQ,KAAK,SAAS;AAC5B,UAAM,cAAc;AAEpB,QAAI,MAAM,SAAS,OAAO,aAAa;AACrC,YAAM,OAAO,MAAM,KAAK,MAAM,SAAS,KAAK,CAAC;AAC7C,YAAM,WAAW,KAAK,MAAM,GAAG,KAAK,SAAS,WAAW;AAExD,eAAS,QAAQ,SAAO;AACtB,cAAM,SAAS,OAAO,GAAG;AACzB,cAAM,SAAS,OAAO,GAAG;AAAA,MAC3B,CAAC;AAAA,IACH;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/server/utils.ts"],"sourcesContent":["import type { User } from \"./types\"\r\n\r\ninterface RequestContext {\r\n user: User\r\n sessionId: string\r\n}\r\n\r\n// Use process.env in Node.js and globalThis in Edge\r\nconst getGlobalObject = () => {\r\n if (typeof process !== 'undefined') {\r\n return process\r\n }\r\n return globalThis\r\n}\r\n\r\nconst STORE_KEY = '__TERN_AUTH_STORE__'\r\n\r\nexport class Store {\r\n private static getStore() {\r\n const global = getGlobalObject() as any\r\n \r\n if (!global[STORE_KEY]) {\r\n global[STORE_KEY] = {\r\n contexts: new Map<string, RequestContext>(),\r\n sessions: new Map<string, User>(),\r\n currentSession: null as RequestContext | null\r\n }\r\n }\r\n \r\n return global[STORE_KEY]\r\n }\r\n\r\n static setContext(context: RequestContext) {\r\n const store = this.getStore()\r\n const { user, sessionId } = context\r\n \r\n console.log(\"Store: Setting context:\", { sessionId, user })\r\n \r\n // Store in both maps\r\n store.contexts.set(sessionId, context)\r\n store.sessions.set(sessionId, user)\r\n \r\n // Set as current session\r\n store.currentSession = context\r\n \r\n console.log(\"Store: Updated state:\", {\r\n contextsSize: store.contexts.size,\r\n sessionsSize: store.sessions.size,\r\n currentSession: store.currentSession\r\n })\r\n }\r\n\r\n static getContext(): RequestContext | null {\r\n const store = this.getStore()\r\n \r\n // First try current session\r\n if (store.currentSession) {\r\n const session = this.getSession(store.currentSession.sessionId)\r\n if (session && session.uid === store.currentSession.user.uid) {\r\n return store.currentSession\r\n }\r\n }\r\n \r\n // Then try to find any valid context\r\n for (const [sessionId, user] of store.sessions.entries()) {\r\n const context = store.contexts.get(sessionId)\r\n if (context && context.user.uid === user.uid) {\r\n // Update current session\r\n store.currentSession = context\r\n return context\r\n }\r\n }\r\n \r\n return null\r\n }\r\n\r\n static setSession(sessionId: string, user: User) {\r\n const store = this.getStore()\r\n store.sessions.set(sessionId, user)\r\n }\r\n\r\n static getSession(sessionId: string): User | null {\r\n const store = this.getStore()\r\n return store.sessions.get(sessionId) || null\r\n }\r\n\r\n static debug() {\r\n const store = this.getStore()\r\n return {\r\n contextsSize: store.contexts.size,\r\n sessionsSize: store.sessions.size,\r\n currentSession: store.currentSession,\r\n contexts: Array.from(store.contexts.entries()),\r\n sessions: Array.from(store.sessions.entries())\r\n }\r\n }\r\n\r\n static cleanup() {\r\n const store = this.getStore()\r\n const MAX_ENTRIES = 1000\r\n \r\n if (store.contexts.size > MAX_ENTRIES) {\r\n const keys = Array.from(store.contexts.keys())\r\n const toDelete = keys.slice(0, keys.length - MAX_ENTRIES)\r\n \r\n toDelete.forEach(key => {\r\n store.contexts.delete(key)\r\n store.sessions.delete(key)\r\n })\r\n }\r\n }\r\n}"],"mappings":"AAQA,MAAM,kBAAkB,MAAM;AAC5B,MAAI,OAAO,YAAY,aAAa;AAClC,WAAO;AAAA,EACT;AACA,SAAO;AACT;AAEA,MAAM,YAAY;AAEX,MAAM,MAAM;AAAA,EACjB,OAAe,WAAW;AACxB,UAAM,SAAS,gBAAgB;AAE/B,QAAI,CAAC,OAAO,SAAS,GAAG;AACtB,aAAO,SAAS,IAAI;AAAA,QAClB,UAAU,oBAAI,IAA4B;AAAA,QAC1C,UAAU,oBAAI,IAAkB;AAAA,QAChC,gBAAgB;AAAA,MAClB;AAAA,IACF;AAEA,WAAO,OAAO,SAAS;AAAA,EACzB;AAAA,EAEA,OAAO,WAAW,SAAyB;AACzC,UAAM,QAAQ,KAAK,SAAS;AAC5B,UAAM,EAAE,MAAM,UAAU,IAAI;AAE5B,YAAQ,IAAI,2BAA2B,EAAE,WAAW,KAAK,CAAC;AAG1D,UAAM,SAAS,IAAI,WAAW,OAAO;AACrC,UAAM,SAAS,IAAI,WAAW,IAAI;AAGlC,UAAM,iBAAiB;AAEvB,YAAQ,IAAI,yBAAyB;AAAA,MACnC,cAAc,MAAM,SAAS;AAAA,MAC7B,cAAc,MAAM,SAAS;AAAA,MAC7B,gBAAgB,MAAM;AAAA,IACxB,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,aAAoC;AACzC,UAAM,QAAQ,KAAK,SAAS;AAG5B,QAAI,MAAM,gBAAgB;AACxB,YAAM,UAAU,KAAK,WAAW,MAAM,eAAe,SAAS;AAC9D,UAAI,WAAW,QAAQ,QAAQ,MAAM,eAAe,KAAK,KAAK;AAC5D,eAAO,MAAM;AAAA,MACf;AAAA,IACF;AAGA,eAAW,CAAC,WAAW,IAAI,KAAK,MAAM,SAAS,QAAQ,GAAG;AACxD,YAAM,UAAU,MAAM,SAAS,IAAI,SAAS;AAC5C,UAAI,WAAW,QAAQ,KAAK,QAAQ,KAAK,KAAK;AAE5C,cAAM,iBAAiB;AACvB,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,OAAO,WAAW,WAAmB,MAAY;AAC/C,UAAM,QAAQ,KAAK,SAAS;AAC5B,UAAM,SAAS,IAAI,WAAW,IAAI;AAAA,EACpC;AAAA,EAEA,OAAO,WAAW,WAAgC;AAChD,UAAM,QAAQ,KAAK,SAAS;AAC5B,WAAO,MAAM,SAAS,IAAI,SAAS,KAAK;AAAA,EAC1C;AAAA,EAEA,OAAO,QAAQ;AACb,UAAM,QAAQ,KAAK,SAAS;AAC5B,WAAO;AAAA,MACL,cAAc,MAAM,SAAS;AAAA,MAC7B,cAAc,MAAM,SAAS;AAAA,MAC7B,gBAAgB,MAAM;AAAA,MACtB,UAAU,MAAM,KAAK,MAAM,SAAS,QAAQ,CAAC;AAAA,MAC7C,UAAU,MAAM,KAAK,MAAM,SAAS,QAAQ,CAAC;AAAA,IAC/C;AAAA,EACF;AAAA,EAEA,OAAO,UAAU;AACf,UAAM,QAAQ,KAAK,SAAS;AAC5B,UAAM,cAAc;AAEpB,QAAI,MAAM,SAAS,OAAO,aAAa;AACrC,YAAM,OAAO,MAAM,KAAK,MAAM,SAAS,KAAK,CAAC;AAC7C,YAAM,WAAW,KAAK,MAAM,GAAG,KAAK,SAAS,WAAW;AAExD,eAAS,QAAQ,SAAO;AACtB,cAAM,SAAS,OAAO,GAAG;AACzB,cAAM,SAAS,OAAO,GAAG;AAAA,MAC3B,CAAC;AAAA,IACH;AAAA,EACF;AACF;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/types.ts"],"sourcesContent":["import { FirebaseOptions } from 'firebase/app'\nimport { User as FirebaseUser } from 'firebase/auth'\nimport { ERRORS } from './errors'\n\n\n/**\n * TernSecure User\n */\nexport type TernSecureUser = FirebaseUser\n\nexport type TernSecureUserData = {\n uid: string\n email: string | null\n emailVerified?: boolean\n displayName?: string | null\n}\n\n\n/**\n * TernSecure Firebase configuration interface\n * Extends Firebase's base configuration options\n */\nexport interface TernSecureConfig extends FirebaseOptions {\n apiKey: string\n authDomain: string\n projectId: string\n storageBucket: string\n messagingSenderId: string\n appId: string\n measurementId?: string // Optional for analytics\n}\n\n/**\n * TernSecure initialization options\n */\nexport interface TernSecureOptions {\n /** Environment setting for different configurations */\n environment?: 'development' | 'production'\n /** Geographic region for data storage */\n region?: string\n /** Custom error handler */\n onError?: (error: Error) => void\n /** Debug mode flag */\n debug?: boolean\n}\n\n/**\n * Firebase initialization state\n */\nexport interface FirebaseState {\n /** Whether Firebase has been initialized */\n initialized: boolean\n /** Any initialization errors */\n error: Error | null\n /** Timestamp of last initialization attempt */\n lastInitAttempt?: number\n}\n\n/**\n * Configuration validation result\n */\nexport interface ConfigValidationResult {\n isValid: boolean\n errors: string[]\n config: TernSecureConfig\n}\n\n/**\n * Firebase Admin configuration interface\n */\nexport interface TernSecureAdminConfig {\n projectId: string\n clientEmail: string\n privateKey: string\n}\n\n/**\n * Firebase Admin configuration validation result\n */\nexport interface AdminConfigValidationResult {\n isValid: boolean\n errors: string[]\n config: TernSecureAdminConfig\n}\n\n\nexport interface SignInResponse {\n success: boolean;\n message?: string;\n error?: keyof typeof ERRORS | undefined; \n user?: any;\n}\n\nexport interface AuthError extends Error {\n code?: string\n message: string\n response?: SignInResponse\n}\n\nexport function isSignInResponse(value: any): value is SignInResponse {\n return typeof value === \"object\" && \"success\" in value && typeof value.success === \"boolean\"\n}\n\n\nexport interface TernSecureState {\n userId: string | null\n isLoaded: boolean\n error: Error | null\n isValid: boolean\n isVerified: boolean\n isAuthenticated: boolean\n token: any | null\n email: string | null\n status: \"loading\" | \"authenticated\" | \"unauthenticated\" | \"unverified\"\n requiresVerification: boolean\n}\n\nexport interface RedirectConfig {\n // URL to redirect to after successful authentication\n redirectUrl?: string\n // Whether this is a return visit (e.g. after sign out)\n isReturn?: boolean\n // Priority of the redirect (higher number = higher priority)\n priority?: number\n}\n\n\nexport interface SignInProps extends RedirectConfig {\n onError?: (error: Error) => void\n onSuccess?: () => void\n className?: string\n customStyles?: {\n card?: string\n input?: string\n button?: string\n label?: string\n separator?: string\n title?: string\n description?: string\n socialButton?: string\n }\n}\n\n\n"],"mappings":"AAmGO,SAAS,iBAAiB,OAAqC;AACpE,SAAO,OAAO,UAAU,YAAY,aAAa,SAAS,OAAO,MAAM,YAAY;AACrF;","names":[]}
1
+ {"version":3,"sources":["../../src/types.ts"],"sourcesContent":["//import { FirebaseOptions } from 'firebase/app'\r\n//import { User as FirebaseUser } from 'firebase/auth'\r\nimport { ERRORS } from './errors'\r\nimport type { TernSecureProviderProps } from '@tern-secure/react'\r\n\r\n\r\n/**\r\n * TernSecure User\r\n */\r\n//export type TernSecureUser = FirebaseUser\r\n\r\nexport type TernSecureUserData = {\r\n uid: string\r\n email: string | null\r\n emailVerified?: boolean\r\n displayName?: string | null\r\n}\r\n\r\n\r\n/**\r\n * TernSecure Firebase configuration interface\r\n * Extends Firebase's base configuration options\r\n */\r\n//export interface TernSecureConfig extends FirebaseOptions {\r\n// apiKey: string\r\n// authDomain: string\r\n// projectId: string\r\n// storageBucket: string\r\n// messagingSenderId: string\r\n// appId: string\r\n// measurementId?: string // Optional for analytics\r\n//}\r\n\r\n/**\r\n * TernSecure initialization options\r\n */\r\nexport interface TernSecureOptions {\r\n /** Environment setting for different configurations */\r\n environment?: 'development' | 'production'\r\n /** Geographic region for data storage */\r\n region?: string\r\n /** Custom error handler */\r\n onError?: (error: Error) => void\r\n /** Debug mode flag */\r\n debug?: boolean\r\n}\r\n\r\n/**\r\n * Firebase initialization state\r\n */\r\nexport interface FirebaseState {\r\n /** Whether Firebase has been initialized */\r\n initialized: boolean\r\n /** Any initialization errors */\r\n error: Error | null\r\n /** Timestamp of last initialization attempt */\r\n lastInitAttempt?: number\r\n}\r\n\r\n/**\r\n * Configuration validation result\r\n */\r\nexport interface ConfigValidationResult {\r\n isValid: boolean\r\n errors: string[]\r\n //config: TernSecureConfig\r\n}\r\n\r\n/**\r\n * Firebase Admin configuration interface\r\n */\r\nexport interface TernSecureAdminConfig {\r\n projectId: string\r\n clientEmail: string\r\n privateKey: string\r\n}\r\n\r\n/**\r\n * Firebase Admin configuration validation result\r\n */\r\nexport interface AdminConfigValidationResult {\r\n isValid: boolean\r\n errors: string[]\r\n config: TernSecureAdminConfig\r\n}\r\n\r\n\r\nexport interface SignInResponse {\r\n success: boolean;\r\n message?: string;\r\n error?: keyof typeof ERRORS | undefined; \r\n user?: any;\r\n}\r\n\r\nexport interface AuthError extends Error {\r\n code?: string\r\n message: string\r\n response?: SignInResponse\r\n}\r\n\r\nexport function isSignInResponse(value: any): value is SignInResponse {\r\n return typeof value === \"object\" && \"success\" in value && typeof value.success === \"boolean\"\r\n}\r\n\r\n\r\nexport interface TernSecureState {\r\n userId: string | null\r\n isLoaded: boolean\r\n error: Error | null\r\n isValid: boolean\r\n isVerified: boolean\r\n isAuthenticated: boolean\r\n token: any | null\r\n email: string | null\r\n status: \"loading\" | \"authenticated\" | \"unauthenticated\" | \"unverified\"\r\n requiresVerification: boolean\r\n}\r\n\r\nexport interface RedirectConfig {\r\n // URL to redirect to after successful authentication\r\n redirectUrl?: string\r\n // Whether this is a return visit (e.g. after sign out)\r\n isReturn?: boolean\r\n // Priority of the redirect (higher number = higher priority)\r\n priority?: number\r\n}\r\n\r\n\r\nexport interface SignInProps extends RedirectConfig {\r\n onError?: (error: Error) => void\r\n onSuccess?: () => void\r\n className?: string\r\n customStyles?: {\r\n card?: string\r\n input?: string\r\n button?: string\r\n label?: string\r\n separator?: string\r\n title?: string\r\n description?: string\r\n socialButton?: string\r\n }\r\n}\r\n\r\n\r\nexport type TernSecureNextProps = TernSecureProviderProps & {\r\n apiKey?: string\r\n requiresVerification?: boolean\r\n loadingComponent?: React.ReactNode\r\n}\r\n\r\n\r\n"],"mappings":"AAoGO,SAAS,iBAAiB,OAAqC;AACpE,SAAO,OAAO,UAAU,YAAY,aAAa,SAAS,OAAO,MAAM,YAAY;AACrF;","names":[]}
@@ -15,7 +15,9 @@ if (!admin.apps.length) {
15
15
  }
16
16
  const adminTernSecureAuth = admin.auth();
17
17
  const adminTernSecureDb = admin.firestore();
18
+ const TernSecureTenantManager = admin.auth().tenantManager();
18
19
  export {
20
+ TernSecureTenantManager,
19
21
  adminTernSecureAuth,
20
22
  adminTernSecureDb
21
23
  };
@@ -1 +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":[]}
1
+ {"version":3,"sources":["../../../src/utils/admin-init.ts"],"sourcesContent":["import admin from 'firebase-admin';\r\nimport { initializeAdminConfig } from './config';\r\n\r\n// Initialize Firebase Admin if not already initialized\r\nif (!admin.apps.length) {\r\n try {\r\n const config = initializeAdminConfig();\r\n admin.initializeApp({\r\n credential: admin.credential.cert({\r\n ...config,\r\n privateKey: config.privateKey.replace(/\\\\n/g, '\\n'),\r\n }),\r\n });\r\n } catch (error) {\r\n console.error('Firebase admin initialization error', error);\r\n }\r\n}\r\n\r\n// Add explicit type annotations using the types from the admin namespace\r\nexport const adminTernSecureAuth: admin.auth.Auth = admin.auth();\r\nexport const adminTernSecureDb: admin.firestore.Firestore = admin.firestore();\r\nexport const TernSecureTenantManager: admin.auth.TenantManager = admin.auth().tenantManager();"],"mappings":"AAAA,OAAO,WAAW;AAClB,SAAS,6BAA6B;AAGtC,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;AAGO,MAAM,sBAAuC,MAAM,KAAK;AACxD,MAAM,oBAA+C,MAAM,UAAU;AACrE,MAAM,0BAAoD,MAAM,KAAK,EAAE,cAAc;","names":[]}
@@ -0,0 +1,84 @@
1
+ const allNextProviderPropsWithEnv = (nextProps) => {
2
+ const {
3
+ signInUrl,
4
+ signUpUrl,
5
+ signInForceRedirectUrl: propsSignInForceRedirectUrl,
6
+ signUpForceRedirectUrl: propsSignUpForceRedirectUrl,
7
+ apiKey: propsApiKey,
8
+ projectId: propsProjectId,
9
+ customDomain: propsCustomDomain,
10
+ proxyUrl: propsProxyUrl,
11
+ environment: propsEnvironment,
12
+ requiresVerification: propsRequiresVerification,
13
+ loadingComponent: propsLoadingComponent,
14
+ ...baseProps
15
+ } = nextProps;
16
+ const envConfig = {
17
+ apiKey: process.env.NEXT_PUBLIC_TERN_API_KEY,
18
+ projectId: process.env.NEXT_PUBLIC_TERN_PROJECT_ID,
19
+ customDomain: process.env.NEXT_PUBLIC_TERN_CUSTOM_DOMAIN,
20
+ proxyUrl: process.env.NEXT_PUBLIC_TERN_PROXY_URL,
21
+ environment: process.env.NEXT_PUBLIC_TERN_ENVIRONMENT,
22
+ signInUrl: process.env.NEXT_PUBLIC_SIGN_IN_URL,
23
+ signUpUrl: process.env.NEXT_PUBLIC_SIGN_UP_URL,
24
+ signInForceRedirectUrl: process.env.NEXT_PUBLIC_SIGN_IN_FORCE_REDIRECT_URL,
25
+ signUpForceRedirectUrl: process.env.NEXT_PUBLIC_SIGN_UP_FORCE_REDIRECT_URL
26
+ };
27
+ const ternSecureConfig = {
28
+ apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY || "",
29
+ authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN || "",
30
+ appName: process.env.NEXT_PUBLIC_FIREBASE_APP_NAME || "",
31
+ projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID || "",
32
+ storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET || "",
33
+ messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID || "",
34
+ appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID || "",
35
+ measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENTID
36
+ };
37
+ const finalApiKey = propsApiKey ?? envConfig.apiKey;
38
+ const finalProjectId = propsProjectId ?? envConfig.projectId;
39
+ const finalCustomDomain = propsCustomDomain ?? envConfig.customDomain;
40
+ const finalProxyUrl = propsProxyUrl ?? envConfig.proxyUrl;
41
+ const finalEnvironment = propsEnvironment ?? envConfig.environment;
42
+ const finalSignInUrl = signInUrl ?? envConfig.signInUrl;
43
+ const finalSignUpUrl = signUpUrl ?? envConfig.signUpUrl;
44
+ const finalSignInForceRedirectUrl = propsSignInForceRedirectUrl ?? envConfig.signInForceRedirectUrl;
45
+ const finalSignUpForceRedirectUrl = propsSignUpForceRedirectUrl ?? envConfig.signUpForceRedirectUrl;
46
+ const result = {
47
+ ...baseProps,
48
+ // Set the merged/prioritized instance configuration properties
49
+ apiKey: finalApiKey,
50
+ projectId: finalProjectId,
51
+ customDomain: finalCustomDomain,
52
+ proxyUrl: finalProxyUrl,
53
+ environment: finalEnvironment,
54
+ // Set the Firebase configuration properties
55
+ ternSecureConfig,
56
+ // Set properties explicitly taken from TernSecureNextProps (props version)
57
+ // These are part of the TernSecureProviderProps interface.
58
+ requiresVerification: propsRequiresVerification,
59
+ loadingComponent: propsLoadingComponent,
60
+ ...propsRequiresVerification !== void 0 && { requireverification: propsRequiresVerification },
61
+ //TernSecure: baseProps.Instance,
62
+ initialState: baseProps.initialState,
63
+ bypassApiKey: baseProps.bypassApiKey,
64
+ initialSession: baseProps.initialSession,
65
+ defaultAppearance: baseProps.defaultAppearance,
66
+ signInUrl: finalSignInUrl,
67
+ signUpUrl: finalSignUpUrl,
68
+ signInForceRedirectUrl: finalSignInForceRedirectUrl,
69
+ signUpForceRedirectUrl: finalSignUpForceRedirectUrl,
70
+ mode: baseProps.mode,
71
+ onAuthStateChanged: baseProps.onAuthStateChanged,
72
+ onError: baseProps.onError
73
+ };
74
+ Object.keys(result).forEach((key) => {
75
+ if (result[key] === void 0) {
76
+ delete result[key];
77
+ }
78
+ });
79
+ return result;
80
+ };
81
+ export {
82
+ allNextProviderPropsWithEnv
83
+ };
84
+ //# sourceMappingURL=allNextProviderProps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/allNextProviderProps.ts"],"sourcesContent":["import type { TernSecureNextProps } from \"../types\";\nimport type { \n TernSecureProviderProps, \n IsomorphicTernSecureOptions \n} from \"@tern-secure/react\";\n\n// Helper type for the return value, as children are handled by the consuming component\ntype NextProviderProcessedProps = Omit<TernSecureProviderProps, 'children'>;\n\nexport const allNextProviderPropsWithEnv = (\n nextProps: Omit<TernSecureNextProps, 'children'>\n): NextProviderProcessedProps => {\n const {\n signInUrl,\n signUpUrl,\n signInForceRedirectUrl: propsSignInForceRedirectUrl,\n signUpForceRedirectUrl: propsSignUpForceRedirectUrl,\n apiKey: propsApiKey,\n projectId: propsProjectId,\n customDomain: propsCustomDomain,\n proxyUrl: propsProxyUrl,\n environment: propsEnvironment,\n requiresVerification: propsRequiresVerification,\n loadingComponent: propsLoadingComponent,\n ...baseProps \n } = nextProps;\n\n const envConfig = {\n apiKey: process.env.NEXT_PUBLIC_TERN_API_KEY,\n projectId: process.env.NEXT_PUBLIC_TERN_PROJECT_ID,\n customDomain: process.env.NEXT_PUBLIC_TERN_CUSTOM_DOMAIN,\n proxyUrl: process.env.NEXT_PUBLIC_TERN_PROXY_URL,\n environment: process.env.NEXT_PUBLIC_TERN_ENVIRONMENT,\n signInUrl: process.env.NEXT_PUBLIC_SIGN_IN_URL,\n signUpUrl: process.env.NEXT_PUBLIC_SIGN_UP_URL,\n signInForceRedirectUrl: process.env.NEXT_PUBLIC_SIGN_IN_FORCE_REDIRECT_URL,\n signUpForceRedirectUrl: process.env.NEXT_PUBLIC_SIGN_UP_FORCE_REDIRECT_URL,\n };\n\n const ternSecureConfig = {\n apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY || '',\n authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN || '',\n appName: process.env.NEXT_PUBLIC_FIREBASE_APP_NAME || '',\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_MEASUREMENTID\n };\n\n // Merge config values: props take precedence over environment variables\n const finalApiKey = propsApiKey ?? envConfig.apiKey;\n const finalProjectId = propsProjectId ?? envConfig.projectId;\n const finalCustomDomain = propsCustomDomain ?? envConfig.customDomain;\n const finalProxyUrl = propsProxyUrl ?? envConfig.proxyUrl;\n const finalEnvironment = propsEnvironment ?? envConfig.environment;\n const finalSignInUrl = signInUrl ?? envConfig.signInUrl;\n const finalSignUpUrl = signUpUrl ?? envConfig.signUpUrl;\n const finalSignInForceRedirectUrl = propsSignInForceRedirectUrl ?? envConfig.signInForceRedirectUrl;\n const finalSignUpForceRedirectUrl = propsSignUpForceRedirectUrl ?? envConfig.signUpForceRedirectUrl\n\n // Construct the result, ensuring it conforms to NextProviderProcessedProps\n // (Omit<TernSecureProviderProps, 'children'>)\n const result: NextProviderProcessedProps = {\n ...(baseProps as Omit<TernSecureProviderProps, 'children' | keyof IsomorphicTernSecureOptions | 'requiresVerification' | 'loadingComponent'>),\n \n // Set the merged/prioritized instance configuration properties\n apiKey: finalApiKey,\n projectId: finalProjectId,\n customDomain: finalCustomDomain,\n proxyUrl: finalProxyUrl,\n environment: finalEnvironment,\n\n // Set the Firebase configuration properties\n ternSecureConfig,\n \n // Set properties explicitly taken from TernSecureNextProps (props version)\n // These are part of the TernSecureProviderProps interface.\n requiresVerification: propsRequiresVerification,\n loadingComponent: propsLoadingComponent,\n ...(propsRequiresVerification !== undefined && { requireverification: propsRequiresVerification }),\n\n //TernSecure: baseProps.Instance,\n initialState: baseProps.initialState,\n bypassApiKey: baseProps.bypassApiKey,\n initialSession: baseProps.initialSession,\n defaultAppearance: baseProps.defaultAppearance,\n signInUrl: finalSignInUrl,\n signUpUrl: finalSignUpUrl,\n signInForceRedirectUrl: finalSignInForceRedirectUrl,\n signUpForceRedirectUrl: finalSignUpForceRedirectUrl,\n mode: baseProps.mode,\n onAuthStateChanged: baseProps.onAuthStateChanged,\n onError: baseProps.onError,\n };\n\n // Clean up undefined keys that might have resulted from spreading if not present in baseProps\n // and also not set by merged values (e.g. if env var is also undefined)\n Object.keys(result).forEach(key => {\n if (result[key as keyof NextProviderProcessedProps] === undefined) {\n delete result[key as keyof NextProviderProcessedProps];\n }\n });\n\n return result;\n};"],"mappings":"AASO,MAAM,8BAA8B,CACzC,cAC+B;AAC/B,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,wBAAwB;AAAA,IACxB,wBAAwB;AAAA,IACxB,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,cAAc;AAAA,IACd,UAAU;AAAA,IACV,aAAa;AAAA,IACb,sBAAsB;AAAA,IACtB,kBAAkB;AAAA,IAClB,GAAG;AAAA,EACL,IAAI;AAEJ,QAAM,YAAY;AAAA,IAChB,QAAQ,QAAQ,IAAI;AAAA,IACpB,WAAW,QAAQ,IAAI;AAAA,IACvB,cAAc,QAAQ,IAAI;AAAA,IAC1B,UAAU,QAAQ,IAAI;AAAA,IACtB,aAAa,QAAQ,IAAI;AAAA,IACzB,WAAW,QAAQ,IAAI;AAAA,IACvB,WAAW,QAAQ,IAAI;AAAA,IACvB,wBAAwB,QAAQ,IAAI;AAAA,IACpC,wBAAwB,QAAQ,IAAI;AAAA,EACtC;AAEA,QAAM,mBAAmB;AAAA,IACvB,QAAQ,QAAQ,IAAI,gCAAgC;AAAA,IACpD,YAAY,QAAQ,IAAI,oCAAoC;AAAA,IAC5D,SAAS,QAAQ,IAAI,iCAAiC;AAAA,IACtD,WAAW,QAAQ,IAAI,mCAAmC;AAAA,IAC1D,eAAe,QAAQ,IAAI,uCAAuC;AAAA,IAClE,mBAAmB,QAAQ,IAAI,4CAA4C;AAAA,IAC3E,OAAO,QAAQ,IAAI,+BAA+B;AAAA,IAClD,eAAe,QAAQ,IAAI;AAAA,EAC7B;AAGA,QAAM,cAAc,eAAe,UAAU;AAC7C,QAAM,iBAAiB,kBAAkB,UAAU;AACnD,QAAM,oBAAoB,qBAAqB,UAAU;AACzD,QAAM,gBAAgB,iBAAiB,UAAU;AACjD,QAAM,mBAAmB,oBAAoB,UAAU;AACvD,QAAM,iBAAiB,aAAa,UAAU;AAC9C,QAAM,iBAAiB,aAAa,UAAU;AAC9C,QAAM,8BAA8B,+BAA+B,UAAU;AAC7E,QAAM,8BAA8B,+BAA+B,UAAU;AAI7E,QAAM,SAAqC;AAAA,IACzC,GAAI;AAAA;AAAA,IAGJ,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,cAAc;AAAA,IACd,UAAU;AAAA,IACV,aAAa;AAAA;AAAA,IAGb;AAAA;AAAA;AAAA,IAIA,sBAAsB;AAAA,IACtB,kBAAkB;AAAA,IAClB,GAAI,8BAA8B,UAAa,EAAE,qBAAqB,0BAA0B;AAAA;AAAA,IAGhG,cAAc,UAAU;AAAA,IACxB,cAAc,UAAU;AAAA,IACxB,gBAAgB,UAAU;AAAA,IAC1B,mBAAmB,UAAU;AAAA,IAC7B,WAAW;AAAA,IACX,WAAW;AAAA,IACX,wBAAwB;AAAA,IACxB,wBAAwB;AAAA,IACxB,MAAM,UAAU;AAAA,IAChB,oBAAoB,UAAU;AAAA,IAC9B,SAAS,UAAU;AAAA,EACrB;AAIA,SAAO,KAAK,MAAM,EAAE,QAAQ,SAAO;AACjC,QAAI,OAAO,GAAuC,MAAM,QAAW;AACjE,aAAO,OAAO,GAAuC;AAAA,IACvD;AAAA,EACF,CAAC;AAED,SAAO;AACT;","names":[]}
@@ -1,22 +1,3 @@
1
- import { initializeApp, getApps } from "firebase/app";
2
- import { getAuth, setPersistence, browserLocalPersistence } 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, browserLocalPersistence);
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
- };
1
+ {
2
+ }
22
3
  //# sourceMappingURL=client-init.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/client-init.ts"],"sourcesContent":["import { initializeApp, getApps } from 'firebase/app';\nimport { getAuth, setPersistence, browserSessionPersistence, browserLocalPersistence} 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, browserLocalPersistence); //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,gBAA2C,+BAA8B;AAC3F,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,uBAAuB;AACtD,MAAM,YAAY,aAAa,SAAS;AACxC,MAAM,UAAU,WAAW,SAAS;AAI7B,MAAM,iBAAiB,MAAM;AAC7B,MAAM,sBAAsB,MAAM;AAClC,MAAM,oBAAoB,MAAM;","names":[]}
1
+ {"version":3,"sources":["../../../src/utils/client-init.ts"],"sourcesContent":["{/*import { initializeApp, getApps } from 'firebase/app';\r\nimport { getAuth, setPersistence, browserSessionPersistence, browserLocalPersistence} from 'firebase/auth';\r\nimport { getFirestore } from 'firebase/firestore';\r\nimport { getStorage } from 'firebase/storage';\r\nimport { initializeConfig} from './config';\r\n\r\nconst APP_NAME = process.env.NEXT_PUBLIC_APP_NAME;\r\n\r\n// Initialize immediately\r\nconst config = initializeConfig();\r\nconst clientApp = getApps().length === 0 ? initializeApp(config, APP_NAME) : getApps()[0];\r\nexport const ternSecureAuth = getAuth(clientApp);\r\nsetPersistence(ternSecureAuth, browserLocalPersistence); //to change later user should be able to choose persistance\r\nconst firestore = getFirestore(clientApp);\r\nconst storage = getStorage(clientApp);\r\n\r\n\r\n\r\nexport const TernSecureAuth = () => ternSecureAuth;\r\nexport const TernSecureFirestore = () => firestore;\r\nexport const TernSecureStorage = () => storage;\r\n*/}"],"mappings":"AAAA;AAqBE;","names":[]}
@@ -1 +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":[]}
1
+ {"version":3,"sources":["../../../src/utils/config.ts"],"sourcesContent":["import { \r\n TernSecureConfig, \r\n ConfigValidationResult, \r\n TernSecureAdminConfig, \r\n AdminConfigValidationResult\r\n} from '@tern-secure/types'\r\n\r\n/**\r\n * Loads Firebase configuration from environment variables\r\n * @returns {TernSecureConfig} Firebase configuration object\r\n */\r\nexport const loadFireConfig = (): TernSecureConfig => ({\r\n apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY || '',\r\n authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN || '',\r\n projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID || '',\r\n storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET || '',\r\n messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID || '',\r\n appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID || '',\r\n measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID || undefined,\r\n})\r\n\r\n/**\r\n * Validates Firebase configuration\r\n * @param {TernSecureConfig} config - Firebase configuration object\r\n * @throws {Error} If required configuration values are missing\r\n * @returns {TernSecureConfig} Validated configuration object\r\n */\r\nexport const validateConfig = (config: TernSecureConfig): ConfigValidationResult => {\r\n const requiredFields: (keyof TernSecureConfig)[] = [\r\n 'apiKey',\r\n 'authDomain',\r\n 'projectId',\r\n 'storageBucket',\r\n 'messagingSenderId',\r\n 'appId'\r\n ]\r\n\r\n const errors: string[] = []\r\n \r\n requiredFields.forEach(field => {\r\n if (!config[field]) {\r\n errors.push(`Missing required field: NEXT_PUBLIC_FIREBASE_${String(field).toUpperCase()}`)\r\n }\r\n })\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n config\r\n }\r\n}\r\n\r\n/**\r\n * Initializes configuration with validation\r\n * @throws {Error} If configuration is invalid\r\n */\r\nexport const initializeConfig = (): TernSecureConfig => {\r\n const config = loadFireConfig()\r\n const validationResult = validateConfig(config)\r\n\r\n if (!validationResult.isValid) {\r\n throw new Error(\r\n `Firebase configuration validation failed:\\n${validationResult.errors.join('\\n')}`\r\n )\r\n }\r\n\r\n return config\r\n}\r\n\r\n/**\r\n * Loads Firebase Admin configuration from environment variables\r\n * @returns {AdminConfig} Firebase Admin configuration object\r\n */\r\nexport const loadAdminConfig = (): TernSecureAdminConfig => ({\r\n projectId: process.env.FIREBASE_PROJECT_ID || '',\r\n clientEmail: process.env.FIREBASE_CLIENT_EMAIL || '',\r\n privateKey: process.env.FIREBASE_PRIVATE_KEY || '',\r\n})\r\n\r\n/**\r\n * Validates Firebase Admin configuration\r\n * @param {AdminConfig} config - Firebase Admin configuration object\r\n * @returns {ConfigValidationResult} Validation result\r\n */\r\nexport const validateAdminConfig = (config: TernSecureAdminConfig): AdminConfigValidationResult => {\r\n const requiredFields: (keyof TernSecureAdminConfig)[] = [\r\n 'projectId',\r\n 'clientEmail',\r\n 'privateKey'\r\n ]\r\n\r\n const errors: string[] = []\r\n \r\n requiredFields.forEach(field => {\r\n if (!config[field]) {\r\n errors.push(`Missing required field: FIREBASE_${String(field).toUpperCase()}`)\r\n }\r\n })\r\n\r\n return {\r\n isValid: errors.length === 0,\r\n errors,\r\n config\r\n }\r\n}\r\n\r\n/**\r\n * Initializes admin configuration with validation\r\n * @throws {Error} If configuration is invalid\r\n */\r\nexport const initializeAdminConfig = (): TernSecureAdminConfig => {\r\n const config = loadAdminConfig()\r\n const validationResult = validateAdminConfig(config)\r\n\r\n if (!validationResult.isValid) {\r\n throw new Error(\r\n `Firebase Admin configuration validation failed:\\n${validationResult.errors.join('\\n')}`\r\n )\r\n }\r\n\r\n return config\r\n}"],"mappings":"AAWO,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":[]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/construct.ts"],"sourcesContent":["//v2: redict with taking priority from the sign-in page\n\nimport { isInternalRoute, isAuthRoute } from \"../app-router/route-handler/internal-route\"\n\n/**\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 if (typeof window === \"undefined\") return path\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/**\n * Checks if the current URL has a redirect loop\n * @param currentPath - The current pathname\n * @param redirectPath - The path we're trying to redirect to\n * @returns boolean indicating if there's a redirect loop\n */\nexport const hasRedirectLoop = (currentPath: string, redirectPath: string): boolean => {\n if (!currentPath || !redirectPath) return false\n\n // Remove any query parameters for comparison\n const cleanCurrentPath = currentPath.split(\"?\")[0]\n const cleanRedirectPath = redirectPath.split(\"?\")[0]\n\n return cleanCurrentPath === cleanRedirectPath\n}\n \n/**\n * Constructs a URL with redirect parameters while preventing loops\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 * @param signUpPath - The sign up path to check against\n * @returns The full URL with redirect parameters\n */\nexport const constructUrlWithRedirect = (\n path: string,\n redirectUrl: string | undefined,\n): string => {\n const url = new URL(path, typeof window !== \"undefined\" ? window.location.origin : undefined)\n \n if (redirectUrl && !isAuthRoute(redirectUrl) && !isInternalRoute(redirectUrl)) {\n url.searchParams.set(\"redirect\", redirectUrl)\n }\n \n return url.toString()\n}\n\n/**\n * Stores the current path before signing out\n */\nexport const storePreviousPath = (path: string): void => {\n if (typeof window !== \"undefined\" && !isAuthRoute(path)) {\n sessionStorage.setItem(\"previousPath\", path)\n }\n}\n\n/**\n * Gets the stored previous path\n */\nexport const getPreviousPath = (): string | null => {\n if (typeof window !== \"undefined\") {\n return sessionStorage.getItem(\"previousPath\")\n }\n return null\n}\n\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\n * @returns A validated redirect URL\n */\nexport const getValidRedirectUrl = (\n searchParams: URLSearchParams,\n configuredRedirect?: string,\n): string => {\n // Check URL search param first (highest priority)\n const urlRedirect = searchParams.get(\"redirect\")\n if (urlRedirect) {\n return validateUrl(urlRedirect)\n }\n\n // Then check configured redirect (for first visits)\n if (configuredRedirect) {\n return validateUrl(configuredRedirect)\n }\n\n // Default fallback\n return \"/\"\n}\n\n/**\n * Validates and sanitizes URLs\n */\nconst validateUrl = (url: string): string => {\n try {\n // For absolute URLs\n if (url.startsWith(\"http\")) {\n const urlObj = new URL(url)\n if (typeof window !== \"undefined\" && urlObj.origin !== window.location.origin) {\n return \"/\"\n }\n return !isAuthRoute(urlObj.pathname) && !isInternalRoute(urlObj.pathname) \n ? urlObj.pathname \n : \"/\"\n }\n \n // For relative URLs\n return !isAuthRoute(url) && !isInternalRoute(url) ? url : \"/\"\n } catch {\n return \"/\"\n }\n}\n\n\n\n\n\n\n\n"],"mappings":"AAEA,SAAS,iBAAiB,mBAAmB;AAOtC,MAAM,mBAAmB,CAAC,SAAiB;AAChD,MAAI,OAAO,WAAW,YAAa,QAAO;AACxC,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;AASK,MAAM,kBAAkB,CAAC,aAAqB,iBAAkC;AACrF,MAAI,CAAC,eAAe,CAAC,aAAc,QAAO;AAG1C,QAAM,mBAAmB,YAAY,MAAM,GAAG,EAAE,CAAC;AACjD,QAAM,oBAAoB,aAAa,MAAM,GAAG,EAAE,CAAC;AAEnD,SAAO,qBAAqB;AAC9B;AAUO,MAAM,2BAA2B,CACtC,MACA,gBACW;AACX,QAAM,MAAM,IAAI,IAAI,MAAM,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS,MAAS;AAE5F,MAAI,eAAe,CAAC,YAAY,WAAW,KAAK,CAAC,gBAAgB,WAAW,GAAG;AAC7E,QAAI,aAAa,IAAI,YAAY,WAAW;AAAA,EAC9C;AAEA,SAAO,IAAI,SAAS;AACtB;AAKO,MAAM,oBAAoB,CAAC,SAAuB;AACvD,MAAI,OAAO,WAAW,eAAe,CAAC,YAAY,IAAI,GAAG;AACvD,mBAAe,QAAQ,gBAAgB,IAAI;AAAA,EAC7C;AACF;AAKO,MAAM,kBAAkB,MAAqB;AAClD,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,eAAe,QAAQ,cAAc;AAAA,EAC9C;AACA,SAAO;AACT;AAUO,MAAM,sBAAsB,CACjC,cACA,uBACW;AAEX,QAAM,cAAc,aAAa,IAAI,UAAU;AAC/C,MAAI,aAAa;AACf,WAAO,YAAY,WAAW;AAAA,EAChC;AAGA,MAAI,oBAAoB;AACtB,WAAO,YAAY,kBAAkB;AAAA,EACvC;AAGA,SAAO;AACT;AAKA,MAAM,cAAc,CAAC,QAAwB;AAC3C,MAAI;AAEF,QAAI,IAAI,WAAW,MAAM,GAAG;AAC1B,YAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,UAAI,OAAO,WAAW,eAAe,OAAO,WAAW,OAAO,SAAS,QAAQ;AAC7E,eAAO;AAAA,MACT;AACA,aAAO,CAAC,YAAY,OAAO,QAAQ,KAAK,CAAC,gBAAgB,OAAO,QAAQ,IACpE,OAAO,WACP;AAAA,IACN;AAGA,WAAO,CAAC,YAAY,GAAG,KAAK,CAAC,gBAAgB,GAAG,IAAI,MAAM;AAAA,EAC5D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/utils/construct.ts"],"sourcesContent":["//v2: redict with taking priority from the sign-in page\r\n\r\nimport { isInternalRoute, isAuthRoute } from \"../app-router/route-handler/internal-route\"\r\n\r\n/**\r\n * Constructs a full URL with the current origin\r\n * @param path - The path to construct the URL for\r\n * @returns The full URL with origin\r\n */\r\nexport const constructFullUrl = (path: string) => {\r\n if (typeof window === \"undefined\") return path\r\n const baseUrl = window.location.origin\r\n if (path.startsWith('http')) {\r\n return path\r\n }\r\n return `${baseUrl}${path.startsWith('/') ? path : `/${path}`}`\r\n }\r\n\r\n\r\n/**\r\n * Checks if the current URL has a redirect loop\r\n * @param currentPath - The current pathname\r\n * @param redirectPath - The path we're trying to redirect to\r\n * @returns boolean indicating if there's a redirect loop\r\n */\r\nexport const hasRedirectLoop = (currentPath: string, redirectPath: string): boolean => {\r\n if (!currentPath || !redirectPath) return false\r\n\r\n // Remove any query parameters for comparison\r\n const cleanCurrentPath = currentPath.split(\"?\")[0]\r\n const cleanRedirectPath = redirectPath.split(\"?\")[0]\r\n\r\n return cleanCurrentPath === cleanRedirectPath\r\n}\r\n \r\n/**\r\n * Constructs a URL with redirect parameters while preventing loops\r\n * @param path - The base path (usually login path)\r\n * @param redirectUrl - The URL to redirect to after action completes\r\n * @param loginPath - The login path to check against\r\n * @param signUpPath - The sign up path to check against\r\n * @returns The full URL with redirect parameters\r\n */\r\nexport const constructUrlWithRedirect = (\r\n path: string,\r\n redirectUrl: string | undefined,\r\n): string => {\r\n const url = new URL(path, typeof window !== \"undefined\" ? window.location.origin : undefined)\r\n \r\n if (redirectUrl && !isAuthRoute(redirectUrl) && !isInternalRoute(redirectUrl)) {\r\n url.searchParams.set(\"redirect\", redirectUrl)\r\n }\r\n \r\n return url.toString()\r\n}\r\n\r\n/**\r\n * Stores the current path before signing out\r\n */\r\nexport const storePreviousPath = (path: string): void => {\r\n if (typeof window !== \"undefined\" && !isAuthRoute(path)) {\r\n sessionStorage.setItem(\"previousPath\", path)\r\n }\r\n}\r\n\r\n/**\r\n * Gets the stored previous path\r\n */\r\nexport const getPreviousPath = (): string | null => {\r\n if (typeof window !== \"undefined\") {\r\n return sessionStorage.getItem(\"previousPath\")\r\n }\r\n return null\r\n}\r\n\r\n\r\n \r\n/**\r\n * Gets a validated redirect URL ensuring it's from the same origin\r\n * @param redirectUrl - The URL to validate\r\n * @param searchParams - The search parameters to check for redirect\r\n * @returns A validated redirect URL\r\n */\r\nexport const getValidRedirectUrl = (\r\n searchParams: URLSearchParams,\r\n configuredRedirect?: string,\r\n): string => {\r\n // Check URL search param first (highest priority)\r\n const urlRedirect = searchParams.get(\"redirect\")\r\n if (urlRedirect) {\r\n return validateUrl(urlRedirect)\r\n }\r\n\r\n // Then check configured redirect (for first visits)\r\n if (configuredRedirect) {\r\n return validateUrl(configuredRedirect)\r\n }\r\n\r\n // Default fallback\r\n return \"/\"\r\n}\r\n\r\n/**\r\n * Validates and sanitizes URLs\r\n */\r\nconst validateUrl = (url: string): string => {\r\n try {\r\n // For absolute URLs\r\n if (url.startsWith(\"http\")) {\r\n const urlObj = new URL(url)\r\n if (typeof window !== \"undefined\" && urlObj.origin !== window.location.origin) {\r\n return \"/\"\r\n }\r\n return !isAuthRoute(urlObj.pathname) && !isInternalRoute(urlObj.pathname) \r\n ? urlObj.pathname \r\n : \"/\"\r\n }\r\n \r\n // For relative URLs\r\n return !isAuthRoute(url) && !isInternalRoute(url) ? url : \"/\"\r\n } catch {\r\n return \"/\"\r\n }\r\n}\r\n\r\n\r\n\r\n\r\n\r\n\r\n\r\n"],"mappings":"AAEA,SAAS,iBAAiB,mBAAmB;AAOtC,MAAM,mBAAmB,CAAC,SAAiB;AAChD,MAAI,OAAO,WAAW,YAAa,QAAO;AACxC,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;AASK,MAAM,kBAAkB,CAAC,aAAqB,iBAAkC;AACrF,MAAI,CAAC,eAAe,CAAC,aAAc,QAAO;AAG1C,QAAM,mBAAmB,YAAY,MAAM,GAAG,EAAE,CAAC;AACjD,QAAM,oBAAoB,aAAa,MAAM,GAAG,EAAE,CAAC;AAEnD,SAAO,qBAAqB;AAC9B;AAUO,MAAM,2BAA2B,CACtC,MACA,gBACW;AACX,QAAM,MAAM,IAAI,IAAI,MAAM,OAAO,WAAW,cAAc,OAAO,SAAS,SAAS,MAAS;AAE5F,MAAI,eAAe,CAAC,YAAY,WAAW,KAAK,CAAC,gBAAgB,WAAW,GAAG;AAC7E,QAAI,aAAa,IAAI,YAAY,WAAW;AAAA,EAC9C;AAEA,SAAO,IAAI,SAAS;AACtB;AAKO,MAAM,oBAAoB,CAAC,SAAuB;AACvD,MAAI,OAAO,WAAW,eAAe,CAAC,YAAY,IAAI,GAAG;AACvD,mBAAe,QAAQ,gBAAgB,IAAI;AAAA,EAC7C;AACF;AAKO,MAAM,kBAAkB,MAAqB;AAClD,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO,eAAe,QAAQ,cAAc;AAAA,EAC9C;AACA,SAAO;AACT;AAUO,MAAM,sBAAsB,CACjC,cACA,uBACW;AAEX,QAAM,cAAc,aAAa,IAAI,UAAU;AAC/C,MAAI,aAAa;AACf,WAAO,YAAY,WAAW;AAAA,EAChC;AAGA,MAAI,oBAAoB;AACtB,WAAO,YAAY,kBAAkB;AAAA,EACvC;AAGA,SAAO;AACT;AAKA,MAAM,cAAc,CAAC,QAAwB;AAC3C,MAAI;AAEF,QAAI,IAAI,WAAW,MAAM,GAAG;AAC1B,YAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,UAAI,OAAO,WAAW,eAAe,OAAO,WAAW,OAAO,SAAS,QAAQ;AAC7E,eAAO;AAAA,MACT;AACA,aAAO,CAAC,YAAY,OAAO,QAAQ,KAAK,CAAC,gBAAgB,OAAO,QAAQ,IACpE,OAAO,WACP;AAAA,IACN;AAGA,WAAO,CAAC,YAAY,GAAG,KAAK,CAAC,gBAAgB,GAAG,IAAI,MAAM;AAAA,EAC5D,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -1 +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"]}
1
+ {"version":3,"sources":["../../../src/utils/create-styles.ts"],"sourcesContent":["'use client'\r\n\r\nconst PREFIX = 'tern'\r\n\r\n// Singleton to track style injection\r\nconst styleInjection = {\r\n isInjected: false,\r\n styleElement: null as HTMLStyleElement | null\r\n}\r\n\r\nexport const defaultClassNames = {\r\n container: `${PREFIX}-container`,\r\n header: `${PREFIX}-header`,\r\n title: `${PREFIX}-title`,\r\n formWrapper: `${PREFIX}-formWrapper`,\r\n formContainer: `${PREFIX}-formContainer`,\r\n form: `${PREFIX}-form`,\r\n label: `${PREFIX}-label`,\r\n input: `${PREFIX}-input`,\r\n button: `${PREFIX}-button`,\r\n error: `${PREFIX}-error`\r\n} as const\r\n\r\n// Create styles once and cache them\r\nfunction createStyleSheet(styles: Record<string, React.CSSProperties>) {\r\n if (typeof window === 'undefined') return defaultClassNames\r\n\r\n // Return early if styles are already injected\r\n if (styleInjection.isInjected) {\r\n return defaultClassNames\r\n }\r\n\r\n // Find existing style element or create new one\r\n let styleElement = document.querySelector<HTMLStyleElement>('[data-tern-secure]')\r\n \r\n if (!styleElement) {\r\n styleElement = document.createElement('style')\r\n styleElement.setAttribute('data-tern-secure', '')\r\n document.head.appendChild(styleElement)\r\n styleInjection.styleElement = styleElement\r\n }\r\n\r\n // Create CSS rules\r\n const cssRules = Object.entries(styles).map(([key, rules]) => {\r\n const className = defaultClassNames[key as keyof typeof defaultClassNames]\r\n const cssProperties = Object.entries(rules).map(([prop, value]) => {\r\n const cssProperty = prop.replace(/([A-Z])/g, '-$1').toLowerCase()\r\n return `${cssProperty}: ${value};`\r\n }).join(' ')\r\n\r\n return `.${className} { ${cssProperties} }`\r\n }).join('\\n')\r\n\r\n // Insert styles only once\r\n styleElement.textContent = cssRules\r\n styleInjection.isInjected = true\r\n\r\n return defaultClassNames\r\n}\r\n\r\n// Style configuration\r\nexport const styleConfig = {\r\n container: {\r\n display: 'flex',\r\n minHeight: '100%',\r\n flex: '1',\r\n flexDirection: 'column',\r\n justifyContent: 'center',\r\n padding: '3rem 1.5rem'\r\n },\r\n header: {\r\n margin: '0 auto',\r\n width: '100%',\r\n maxWidth: '28rem'\r\n },\r\n title: {\r\n marginTop: '1.5rem',\r\n textAlign: 'center',\r\n fontSize: '1.875rem',\r\n fontWeight: '700',\r\n lineHeight: '2.25rem',\r\n letterSpacing: '-0.025em',\r\n color: 'var(--tern-text-primary, #111827)'\r\n },\r\n formWrapper: {\r\n marginTop: '2.5rem',\r\n margin: '0 auto',\r\n width: '100%',\r\n maxWidth: '30rem'\r\n },\r\n formContainer: {\r\n padding: '3rem 1.5rem',\r\n boxShadow: '0 1px 3px 0 rgb(0 0 0 / 0.1)',\r\n borderRadius: '0.5rem',\r\n backgroundColor: 'var(--tern-background, white)'\r\n },\r\n form: {\r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: '1rem'\r\n },\r\n label: {\r\n display: 'block',\r\n fontSize: '0.875rem',\r\n fontWeight: '500',\r\n color: 'var(--tern-text-secondary, #374151)'\r\n },\r\n input: {\r\n marginTop: '0.25rem',\r\n display: 'block',\r\n width: '100%',\r\n padding: '0.5rem 0.75rem',\r\n borderRadius: '0.375rem',\r\n border: '1px solid var(--tern-border, #D1D5DB)',\r\n backgroundColor: 'var(--tern-input-background, white)',\r\n color: 'var(--tern-text-primary, #111827)'\r\n },\r\n button: {\r\n display: 'flex',\r\n width: '100%',\r\n justifyContent: 'center',\r\n padding: '0.5rem 1rem',\r\n fontSize: '0.875rem',\r\n fontWeight: '500',\r\n color: 'white',\r\n backgroundColor: 'var(--tern-primary, #2563EB)',\r\n border: 'none',\r\n borderRadius: '0.375rem',\r\n cursor: 'pointer'\r\n },\r\n error: {\r\n color: 'var(--tern-error, #DC2626)',\r\n fontSize: '0.875rem'\r\n }\r\n} as const\r\n\r\n// Export pre-created styles\r\nexport const styles = createStyleSheet(styleConfig)\r\n\r\n"],"mappings":"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","names":["styles"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/redirect.ts"],"sourcesContent":["import { headers } from \"next/headers\"\n\n/**\n * Validates and sanitizes redirect URLs\n */\nexport async function validateRedirectUrl(url: string | null): Promise<string> {\n if (!url) return \"/\"\n\n try {\n // Check if it's a relative path\n if (url.startsWith(\"/\")) {\n // Basic validation to ensure the path exists in your app\n // Add more paths as needed\n const validPaths = [\"/\"]\n return validPaths.includes(url) ? url : \"/\"\n }\n\n // If it's an absolute URL, ensure it's from your domain\n const headersList = await headers()\n const currentHost = headersList.get(\"host\")\n const urlObj = new URL(url)\n if (urlObj.host === currentHost) {\n return urlObj.pathname\n }\n } catch {\n // Invalid URL format\n }\n\n return \"/\"\n}\n\n/**\n * Gets the current path for redirect purposes\n */\nexport async function getCurrentPath(): Promise<string> {\n try {\n const headersList = await headers()\n const pathname = headersList.get(\"x-pathname\") || \"/\"\n return pathname\n } catch {\n return \"/\"\n }\n}\n\n"],"mappings":"AAAA,SAAS,eAAe;AAKxB,eAAsB,oBAAoB,KAAqC;AAC7E,MAAI,CAAC,IAAK,QAAO;AAEjB,MAAI;AAEF,QAAI,IAAI,WAAW,GAAG,GAAG;AAGvB,YAAM,aAAa,CAAC,GAAG;AACvB,aAAO,WAAW,SAAS,GAAG,IAAI,MAAM;AAAA,IAC1C;AAGC,UAAM,cAAc,MAAM,QAAQ;AACnC,UAAM,cAAc,YAAY,IAAI,MAAM;AAC1C,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,QAAI,OAAO,SAAS,aAAa;AAC/B,aAAO,OAAO;AAAA,IAChB;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAKA,eAAsB,iBAAkC;AACtD,MAAI;AACF,UAAM,cAAc,MAAM,QAAQ;AAClC,UAAM,WAAW,YAAY,IAAI,YAAY,KAAK;AAClD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
1
+ {"version":3,"sources":["../../../src/utils/redirect.ts"],"sourcesContent":["import { headers } from \"next/headers\"\r\n\r\n/**\r\n * Validates and sanitizes redirect URLs\r\n */\r\nexport async function validateRedirectUrl(url: string | null): Promise<string> {\r\n if (!url) return \"/\"\r\n\r\n try {\r\n // Check if it's a relative path\r\n if (url.startsWith(\"/\")) {\r\n // Basic validation to ensure the path exists in your app\r\n // Add more paths as needed\r\n const validPaths = [\"/\"]\r\n return validPaths.includes(url) ? url : \"/\"\r\n }\r\n\r\n // If it's an absolute URL, ensure it's from your domain\r\n const headersList = await headers()\r\n const currentHost = headersList.get(\"host\")\r\n const urlObj = new URL(url)\r\n if (urlObj.host === currentHost) {\r\n return urlObj.pathname\r\n }\r\n } catch {\r\n // Invalid URL format\r\n }\r\n\r\n return \"/\"\r\n}\r\n\r\n/**\r\n * Gets the current path for redirect purposes\r\n */\r\nexport async function getCurrentPath(): Promise<string> {\r\n try {\r\n const headersList = await headers()\r\n const pathname = headersList.get(\"x-pathname\") || \"/\"\r\n return pathname\r\n } catch {\r\n return \"/\"\r\n }\r\n}\r\n\r\n"],"mappings":"AAAA,SAAS,eAAe;AAKxB,eAAsB,oBAAoB,KAAqC;AAC7E,MAAI,CAAC,IAAK,QAAO;AAEjB,MAAI;AAEF,QAAI,IAAI,WAAW,GAAG,GAAG;AAGvB,YAAM,aAAa,CAAC,GAAG;AACvB,aAAO,WAAW,SAAS,GAAG,IAAI,MAAM;AAAA,IAC1C;AAGC,UAAM,cAAc,MAAM,QAAQ;AACnC,UAAM,cAAc,YAAY,IAAI,MAAM;AAC1C,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,QAAI,OAAO,SAAS,aAAa;AAC/B,aAAO,OAAO;AAAA,IAChB;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAKA,eAAsB,iBAAkC;AACtD,MAAI;AACF,UAAM,cAAc,MAAM,QAAQ;AAClC,UAAM,WAAW,YAAY,IAAI,YAAY,KAAK;AAClD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -0,0 +1,42 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import Script from "next/script";
3
+ import { ternUIgetScriptUrl, constructScriptAttributes } from "@tern-secure/react";
4
+ const isDevelopment = process.env.NODE_ENV === "development";
5
+ const localPort = process.env.TERN_UI_PORT || "4000";
6
+ const devDomain = isDevelopment ? `http://localhost:${localPort || process.env.NEXT_PUBLIC_TERN_UI_PORT || "4000"}` : void 0;
7
+ function TernUIScript({
8
+ customDomain,
9
+ proxyUrl,
10
+ version,
11
+ nonce
12
+ }) {
13
+ const effectiveDomain = isDevelopment ? devDomain : customDomain;
14
+ console.log("[TernSecure] TernUIScript: Using effective domain:", effectiveDomain);
15
+ if (!effectiveDomain) {
16
+ console.warn("[TernSecure] TernUIScript: No custom domain or proxy URL provided. The script will not be loaded.");
17
+ return null;
18
+ }
19
+ const scriptOptions = {
20
+ customDomain: effectiveDomain,
21
+ proxyUrl,
22
+ version,
23
+ nonce
24
+ };
25
+ const scriptUrl = ternUIgetScriptUrl(scriptOptions);
26
+ const scriptAttributes = constructScriptAttributes(scriptOptions);
27
+ return /* @__PURE__ */ jsx(
28
+ Script,
29
+ {
30
+ src: scriptUrl,
31
+ "data-ternui-script": true,
32
+ async: true,
33
+ nonce,
34
+ strategy: void 0,
35
+ ...scriptAttributes
36
+ }
37
+ );
38
+ }
39
+ export {
40
+ TernUIScript
41
+ };
42
+ //# sourceMappingURL=tern-ui-script.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/utils/tern-ui-script.tsx"],"sourcesContent":["import Script from 'next/script'\nimport { ternUIgetScriptUrl, constructScriptAttributes } from '@tern-secure/react'\nimport type { TernSecureNextProps } from '../types'\n\nconst isDevelopment = process.env.NODE_ENV === 'development';\nconst localPort = process.env.TERN_UI_PORT || '4000';\n\ntype TernUIScriptProps = Pick<TernSecureNextProps, 'customDomain' | 'proxyUrl'> & {\n version?: string;\n nonce?: string;\n}\n\nconst devDomain = isDevelopment \n ? `http://localhost:${localPort || process.env.NEXT_PUBLIC_TERN_UI_PORT || '4000'}`\n : undefined\n\n\nexport function TernUIScript({\n customDomain,\n proxyUrl,\n version,\n nonce,\n}: TernUIScriptProps) {\n const effectiveDomain = isDevelopment ? devDomain : customDomain\n console.log('[TernSecure] TernUIScript: Using effective domain:', effectiveDomain);\n\n if (!effectiveDomain) {\n console.warn('[TernSecure] TernUIScript: No custom domain or proxy URL provided. The script will not be loaded.');\n return null;\n }\n\n const scriptOptions = {\n customDomain: effectiveDomain,\n proxyUrl,\n version,\n nonce,\n };\n\n const scriptUrl = ternUIgetScriptUrl(scriptOptions);\n const scriptAttributes = constructScriptAttributes(scriptOptions);\n\n return (\n <Script\n src={scriptUrl}\n data-ternui-script\n async\n nonce={nonce}\n strategy={undefined}\n {...scriptAttributes}\n //crossOrigin= {undefined}\n />\n )\n}"],"mappings":"AA0CQ;AA1CR,OAAO,YAAY;AACnB,SAAS,oBAAoB,iCAAiC;AAG9D,MAAM,gBAAgB,QAAQ,IAAI,aAAa;AAC/C,MAAM,YAAY,QAAQ,IAAI,gBAAgB;AAO9C,MAAM,YAAY,gBACZ,oBAAoB,aAAa,QAAQ,IAAI,4BAA4B,MAAM,KAC/E;AAGC,SAAS,aAAa;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACJ,GAAsB;AAClB,QAAM,kBAAkB,gBAAgB,YAAY;AACpD,UAAQ,IAAI,sDAAsD,eAAe;AAEjF,MAAI,CAAC,iBAAiB;AAClB,YAAQ,KAAK,mGAAmG;AAChH,WAAO;AAAA,EACX;AAEA,QAAM,gBAAgB;AAAA,IAClB,cAAc;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,EACJ;AAEA,QAAM,YAAY,mBAAmB,aAAa;AAClD,QAAM,mBAAmB,0BAA0B,aAAa;AAEhE,SACI;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,sBAAkB;AAAA,MAClB,OAAK;AAAA,MACL;AAAA,MACA,UAAU;AAAA,MACP,GAAG;AAAA;AAAA,EAER;AAER;","names":[]}
@@ -1,3 +1,2 @@
1
- export { verifyTernSessionCookie, createSessionCookie } from './sessionTernSecure';
2
- export { adminTernSecureAuth, adminTernSecureDb } from '../../utils/admin-init';
1
+ export { verifyTernSessionCookie, createSessionCookie, clearSessionCookie, } from '@tern-secure/backend';
3
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/app-router/admin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AAClF,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/app-router/admin/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACH,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,GACrB,MAAM,sBAAsB,CAAA"}
@@ -1,17 +1,5 @@
1
1
  import React from "react";
2
- /**
3
- * Configuration options for TernSecure authentication
4
- */
5
- export interface TernSecureConfig {
6
- /** Whether email verification is required (defaults to true) */
7
- requiresVerification?: boolean;
8
- /** Custom path for login page (defaults to /sign-in) */
9
- loginPath?: string;
10
- /** Custom path for signup page (defaults to /sign-up) */
11
- signUpPath?: string;
12
- /** Custom loading component */
13
- loadingComponent?: React.ReactNode;
14
- }
2
+ import type { TernSecureNextProps } from "../../types";
15
3
  /**
16
4
  * Root Provider for TernSecure
17
5
  * Use this in your Next.js App Router root layout
@@ -33,5 +21,5 @@ export interface TernSecureConfig {
33
21
  * )
34
22
  * }
35
23
  */
36
- export declare function TernSecureProvider({ children, requiresVerification, loginPath, signUpPath, loadingComponent, }: React.PropsWithChildren<TernSecureConfig>): Promise<import("react/jsx-runtime").JSX.Element>;
24
+ export declare function TernSecureProvider(props: React.PropsWithChildren<TernSecureNextProps>): import("react/jsx-runtime").JSX.Element;
37
25
  //# sourceMappingURL=TernSecureProvider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TernSecureProvider.d.ts","sourceRoot":"","sources":["../../../../src/app-router/client/TernSecureProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,gEAAgE;IAChE,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,wDAAwD;IACxD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,+BAA+B;IAC/B,gBAAgB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CACnC;AAUD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,QAAQ,EACR,oBAA2B,EAC3B,SAAS,EACT,UAAU,EACV,gBAAgB,GAChB,EAAE,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,oDAW5C"}
1
+ {"version":3,"file":"TernSecureProvider.d.ts","sourceRoot":"","sources":["../../../../src/app-router/client/TernSecureProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAA;AActD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,2CASrF"}