svelte-firekit 0.1.9 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (439) hide show
  1. package/README.md +550 -354
  2. package/dist/components/AuthGuard.svelte +64 -0
  3. package/dist/components/AuthGuard.svelte.d.ts +15 -0
  4. package/dist/components/Collection.svelte +62 -0
  5. package/dist/components/Collection.svelte.d.ts +39 -0
  6. package/dist/components/CustomGuard.svelte +87 -0
  7. package/dist/components/CustomGuard.svelte.d.ts +13 -0
  8. package/dist/components/Doc.svelte +56 -0
  9. package/dist/components/Doc.svelte.d.ts +36 -0
  10. package/dist/components/DownloadURL.svelte +48 -0
  11. package/dist/components/DownloadURL.svelte.d.ts +14 -0
  12. package/dist/components/FirebaseApp.svelte +81 -0
  13. package/dist/components/FirebaseApp.svelte.d.ts +12 -0
  14. package/dist/components/Node.svelte +54 -0
  15. package/dist/components/Node.svelte.d.ts +36 -0
  16. package/dist/components/SignedIn.svelte +22 -0
  17. package/dist/components/{firekit/signed-in.svelte.d.ts → SignedIn.svelte.d.ts} +1 -4
  18. package/dist/components/SignedOut.svelte +32 -0
  19. package/dist/components/{firekit/signed-out.svelte.d.ts → SignedOut.svelte.d.ts} +3 -5
  20. package/dist/components/UploadTask.svelte +75 -0
  21. package/dist/components/UploadTask.svelte.d.ts +33 -0
  22. package/dist/config.d.ts +29 -6
  23. package/dist/config.js +37 -74
  24. package/dist/context.d.ts +46 -0
  25. package/dist/context.js +56 -0
  26. package/dist/firebase.d.ts +25 -84
  27. package/dist/firebase.js +75 -125
  28. package/dist/index.d.ts +31 -20
  29. package/dist/index.js +47 -30
  30. package/dist/services/ai.svelte.d.ts +152 -0
  31. package/dist/services/ai.svelte.js +302 -0
  32. package/dist/services/analytics.d.ts +39 -231
  33. package/dist/services/analytics.js +89 -421
  34. package/dist/services/app-check.svelte.d.ts +82 -0
  35. package/dist/services/app-check.svelte.js +159 -0
  36. package/dist/services/auth.d.ts +63 -352
  37. package/dist/services/auth.js +353 -718
  38. package/dist/services/bundles.d.ts +42 -0
  39. package/dist/services/bundles.js +57 -0
  40. package/dist/services/callable.d.ts +57 -0
  41. package/dist/services/callable.js +115 -0
  42. package/dist/services/collection.svelte.d.ts +154 -221
  43. package/dist/services/collection.svelte.js +357 -663
  44. package/dist/services/document.svelte.d.ts +73 -254
  45. package/dist/services/document.svelte.js +196 -497
  46. package/dist/services/in-app-messaging.js +4 -0
  47. package/dist/services/messaging.svelte.d.ts +75 -0
  48. package/dist/services/messaging.svelte.js +190 -0
  49. package/dist/services/mutations.d.ts +59 -282
  50. package/dist/services/mutations.js +202 -951
  51. package/dist/services/performance.d.ts +60 -0
  52. package/dist/services/performance.js +118 -0
  53. package/dist/services/presence.svelte.d.ts +21 -89
  54. package/dist/services/presence.svelte.js +232 -469
  55. package/dist/services/realtime.svelte.d.ts +54 -125
  56. package/dist/services/realtime.svelte.js +111 -175
  57. package/dist/services/remote-config.svelte.d.ts +73 -0
  58. package/dist/services/remote-config.svelte.js +204 -0
  59. package/dist/services/storage.svelte.d.ts +81 -208
  60. package/dist/services/storage.svelte.js +190 -305
  61. package/dist/services/user.svelte.d.ts +23 -244
  62. package/dist/services/user.svelte.js +129 -439
  63. package/dist/types/analytics.d.ts +2 -36
  64. package/dist/types/analytics.js +0 -5
  65. package/dist/types/auth.d.ts +15 -85
  66. package/dist/types/auth.js +0 -17
  67. package/dist/types/collection.d.ts +31 -225
  68. package/dist/types/collection.js +5 -51
  69. package/dist/types/document.d.ts +11 -236
  70. package/dist/types/document.js +2 -47
  71. package/dist/types/firebase.d.ts +10 -13
  72. package/dist/types/firebase.js +3 -9
  73. package/dist/types/index.d.ts +5 -5
  74. package/dist/types/index.js +5 -4
  75. package/dist/types/mutations.d.ts +11 -225
  76. package/dist/types/mutations.js +6 -51
  77. package/dist/types/presence.d.ts +5 -158
  78. package/dist/types/presence.js +0 -20
  79. package/dist/utils/errors.d.ts +10 -14
  80. package/dist/utils/errors.js +11 -16
  81. package/dist/utils/firestore.d.ts +3 -4
  82. package/dist/utils/firestore.js +7 -10
  83. package/dist/utils/index.d.ts +4 -4
  84. package/dist/utils/index.js +4 -8
  85. package/dist/utils/providers.d.ts +4 -13
  86. package/dist/utils/providers.js +14 -13
  87. package/dist/utils/user.d.ts +1 -3
  88. package/dist/utils/user.js +1 -3
  89. package/package.json +41 -55
  90. package/dist/components/docs/doc-content.svelte +0 -19
  91. package/dist/components/docs/doc-content.svelte.d.ts +0 -6
  92. package/dist/components/docs/doc-header.svelte +0 -24
  93. package/dist/components/docs/doc-header.svelte.d.ts +0 -13
  94. package/dist/components/docs/doc-renderer.svelte +0 -27
  95. package/dist/components/docs/doc-renderer.svelte.d.ts +0 -8
  96. package/dist/components/docs/mobile-table-of-contents.svelte +0 -42
  97. package/dist/components/docs/mobile-table-of-contents.svelte.d.ts +0 -3
  98. package/dist/components/docs/table-of-contents.svelte +0 -33
  99. package/dist/components/docs/table-of-contents.svelte.d.ts +0 -4
  100. package/dist/components/docs/toc.svelte.d.ts +0 -16
  101. package/dist/components/docs/toc.svelte.js +0 -59
  102. package/dist/components/firekit/Collection.svelte +0 -122
  103. package/dist/components/firekit/Collection.svelte.d.ts +0 -27
  104. package/dist/components/firekit/Doc.svelte +0 -140
  105. package/dist/components/firekit/Doc.svelte.d.ts +0 -28
  106. package/dist/components/firekit/Node.svelte +0 -97
  107. package/dist/components/firekit/Node.svelte.d.ts +0 -23
  108. package/dist/components/firekit/auth-guard.svelte +0 -120
  109. package/dist/components/firekit/auth-guard.svelte.d.ts +0 -26
  110. package/dist/components/firekit/custom-guard.svelte +0 -163
  111. package/dist/components/firekit/custom-guard.svelte.d.ts +0 -31
  112. package/dist/components/firekit/download-url.svelte +0 -92
  113. package/dist/components/firekit/download-url.svelte.d.ts +0 -19
  114. package/dist/components/firekit/firebase-app.svelte +0 -33
  115. package/dist/components/firekit/firebase-app.svelte.d.ts +0 -7
  116. package/dist/components/firekit/node-list.svelte +0 -102
  117. package/dist/components/firekit/node-list.svelte.d.ts +0 -27
  118. package/dist/components/firekit/signed-in.svelte +0 -42
  119. package/dist/components/firekit/signed-out.svelte +0 -42
  120. package/dist/components/firekit/storage-list.svelte +0 -97
  121. package/dist/components/firekit/storage-list.svelte.d.ts +0 -26
  122. package/dist/components/firekit/upload-task.svelte +0 -108
  123. package/dist/components/firekit/upload-task.svelte.d.ts +0 -24
  124. package/dist/components/nav/app-sidebar.svelte +0 -175
  125. package/dist/components/nav/app-sidebar.svelte.d.ts +0 -9
  126. package/dist/components/nav/auto-breadcrumb.svelte +0 -41
  127. package/dist/components/nav/auto-breadcrumb.svelte.d.ts +0 -3
  128. package/dist/components/nav/dark-mode-toggle.svelte +0 -17
  129. package/dist/components/nav/dark-mode-toggle.svelte.d.ts +0 -18
  130. package/dist/components/nav/nav-components.svelte +0 -24
  131. package/dist/components/nav/nav-components.svelte.d.ts +0 -11
  132. package/dist/components/nav/nav-main.svelte +0 -45
  133. package/dist/components/nav/nav-main.svelte.d.ts +0 -11
  134. package/dist/components/nav/nav-secondary.svelte +0 -32
  135. package/dist/components/nav/nav-secondary.svelte.d.ts +0 -14
  136. package/dist/components/nav/site-header.svelte +0 -32
  137. package/dist/components/nav/site-header.svelte.d.ts +0 -18
  138. package/dist/components/ui/avatar/avatar-fallback.svelte +0 -17
  139. package/dist/components/ui/avatar/avatar-fallback.svelte.d.ts +0 -4
  140. package/dist/components/ui/avatar/avatar-image.svelte +0 -17
  141. package/dist/components/ui/avatar/avatar-image.svelte.d.ts +0 -4
  142. package/dist/components/ui/avatar/avatar.svelte +0 -19
  143. package/dist/components/ui/avatar/avatar.svelte.d.ts +0 -4
  144. package/dist/components/ui/avatar/index.d.ts +0 -4
  145. package/dist/components/ui/avatar/index.js +0 -6
  146. package/dist/components/ui/badge/badge.svelte +0 -50
  147. package/dist/components/ui/badge/badge.svelte.d.ts +0 -32
  148. package/dist/components/ui/badge/index.d.ts +0 -2
  149. package/dist/components/ui/badge/index.js +0 -2
  150. package/dist/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +0 -23
  151. package/dist/components/ui/breadcrumb/breadcrumb-ellipsis.svelte.d.ts +0 -5
  152. package/dist/components/ui/breadcrumb/breadcrumb-item.svelte +0 -20
  153. package/dist/components/ui/breadcrumb/breadcrumb-item.svelte.d.ts +0 -5
  154. package/dist/components/ui/breadcrumb/breadcrumb-link.svelte +0 -31
  155. package/dist/components/ui/breadcrumb/breadcrumb-link.svelte.d.ts +0 -11
  156. package/dist/components/ui/breadcrumb/breadcrumb-list.svelte +0 -23
  157. package/dist/components/ui/breadcrumb/breadcrumb-list.svelte.d.ts +0 -5
  158. package/dist/components/ui/breadcrumb/breadcrumb-page.svelte +0 -23
  159. package/dist/components/ui/breadcrumb/breadcrumb-page.svelte.d.ts +0 -5
  160. package/dist/components/ui/breadcrumb/breadcrumb-separator.svelte +0 -27
  161. package/dist/components/ui/breadcrumb/breadcrumb-separator.svelte.d.ts +0 -5
  162. package/dist/components/ui/breadcrumb/breadcrumb.svelte +0 -21
  163. package/dist/components/ui/breadcrumb/breadcrumb.svelte.d.ts +0 -5
  164. package/dist/components/ui/breadcrumb/index.d.ts +0 -8
  165. package/dist/components/ui/breadcrumb/index.js +0 -10
  166. package/dist/components/ui/button/button.svelte +0 -80
  167. package/dist/components/ui/button/button.svelte.d.ts +0 -58
  168. package/dist/components/ui/button/index.d.ts +0 -2
  169. package/dist/components/ui/button/index.js +0 -4
  170. package/dist/components/ui/card/card-action.svelte +0 -20
  171. package/dist/components/ui/card/card-action.svelte.d.ts +0 -5
  172. package/dist/components/ui/card/card-content.svelte +0 -15
  173. package/dist/components/ui/card/card-content.svelte.d.ts +0 -5
  174. package/dist/components/ui/card/card-description.svelte +0 -20
  175. package/dist/components/ui/card/card-description.svelte.d.ts +0 -5
  176. package/dist/components/ui/card/card-footer.svelte +0 -20
  177. package/dist/components/ui/card/card-footer.svelte.d.ts +0 -5
  178. package/dist/components/ui/card/card-header.svelte +0 -23
  179. package/dist/components/ui/card/card-header.svelte.d.ts +0 -5
  180. package/dist/components/ui/card/card-title.svelte +0 -20
  181. package/dist/components/ui/card/card-title.svelte.d.ts +0 -5
  182. package/dist/components/ui/card/card.svelte +0 -23
  183. package/dist/components/ui/card/card.svelte.d.ts +0 -5
  184. package/dist/components/ui/card/index.d.ts +0 -8
  185. package/dist/components/ui/card/index.js +0 -10
  186. package/dist/components/ui/chart/chart-container.svelte +0 -80
  187. package/dist/components/ui/chart/chart-container.svelte.d.ts +0 -9
  188. package/dist/components/ui/chart/chart-style.svelte +0 -36
  189. package/dist/components/ui/chart/chart-style.svelte.d.ts +0 -8
  190. package/dist/components/ui/chart/chart-tooltip.svelte +0 -159
  191. package/dist/components/ui/chart/chart-tooltip.svelte.d.ts +0 -27
  192. package/dist/components/ui/chart/chart-utils.d.ts +0 -36
  193. package/dist/components/ui/chart/chart-utils.js +0 -33
  194. package/dist/components/ui/chart/index.d.ts +0 -4
  195. package/dist/components/ui/chart/index.js +0 -4
  196. package/dist/components/ui/checkbox/checkbox.svelte +0 -36
  197. package/dist/components/ui/checkbox/checkbox.svelte.d.ts +0 -4
  198. package/dist/components/ui/checkbox/index.d.ts +0 -2
  199. package/dist/components/ui/checkbox/index.js +0 -4
  200. package/dist/components/ui/data-table/data-table.svelte.d.ts +0 -40
  201. package/dist/components/ui/data-table/data-table.svelte.js +0 -110
  202. package/dist/components/ui/data-table/flex-render.svelte +0 -36
  203. package/dist/components/ui/data-table/flex-render.svelte.d.ts +0 -30
  204. package/dist/components/ui/data-table/index.d.ts +0 -3
  205. package/dist/components/ui/data-table/index.js +0 -3
  206. package/dist/components/ui/data-table/render-helpers.d.ts +0 -90
  207. package/dist/components/ui/data-table/render-helpers.js +0 -99
  208. package/dist/components/ui/dialog/dialog-close.svelte +0 -7
  209. package/dist/components/ui/dialog/dialog-close.svelte.d.ts +0 -4
  210. package/dist/components/ui/dialog/dialog-content.svelte +0 -43
  211. package/dist/components/ui/dialog/dialog-content.svelte.d.ts +0 -11
  212. package/dist/components/ui/dialog/dialog-description.svelte +0 -17
  213. package/dist/components/ui/dialog/dialog-description.svelte.d.ts +0 -4
  214. package/dist/components/ui/dialog/dialog-footer.svelte +0 -20
  215. package/dist/components/ui/dialog/dialog-footer.svelte.d.ts +0 -5
  216. package/dist/components/ui/dialog/dialog-header.svelte +0 -20
  217. package/dist/components/ui/dialog/dialog-header.svelte.d.ts +0 -5
  218. package/dist/components/ui/dialog/dialog-overlay.svelte +0 -20
  219. package/dist/components/ui/dialog/dialog-overlay.svelte.d.ts +0 -4
  220. package/dist/components/ui/dialog/dialog-title.svelte +0 -17
  221. package/dist/components/ui/dialog/dialog-title.svelte.d.ts +0 -4
  222. package/dist/components/ui/dialog/dialog-trigger.svelte +0 -7
  223. package/dist/components/ui/dialog/dialog-trigger.svelte.d.ts +0 -4
  224. package/dist/components/ui/dialog/index.d.ts +0 -11
  225. package/dist/components/ui/dialog/index.js +0 -14
  226. package/dist/components/ui/drawer/drawer-close.svelte +0 -7
  227. package/dist/components/ui/drawer/drawer-close.svelte.d.ts +0 -4
  228. package/dist/components/ui/drawer/drawer-content.svelte +0 -37
  229. package/dist/components/ui/drawer/drawer-content.svelte.d.ts +0 -7
  230. package/dist/components/ui/drawer/drawer-description.svelte +0 -17
  231. package/dist/components/ui/drawer/drawer-description.svelte.d.ts +0 -4
  232. package/dist/components/ui/drawer/drawer-footer.svelte +0 -20
  233. package/dist/components/ui/drawer/drawer-footer.svelte.d.ts +0 -5
  234. package/dist/components/ui/drawer/drawer-header.svelte +0 -20
  235. package/dist/components/ui/drawer/drawer-header.svelte.d.ts +0 -5
  236. package/dist/components/ui/drawer/drawer-nested.svelte +0 -12
  237. package/dist/components/ui/drawer/drawer-nested.svelte.d.ts +0 -3
  238. package/dist/components/ui/drawer/drawer-overlay.svelte +0 -20
  239. package/dist/components/ui/drawer/drawer-overlay.svelte.d.ts +0 -4
  240. package/dist/components/ui/drawer/drawer-title.svelte +0 -17
  241. package/dist/components/ui/drawer/drawer-title.svelte.d.ts +0 -4
  242. package/dist/components/ui/drawer/drawer-trigger.svelte +0 -7
  243. package/dist/components/ui/drawer/drawer-trigger.svelte.d.ts +0 -4
  244. package/dist/components/ui/drawer/drawer.svelte +0 -12
  245. package/dist/components/ui/drawer/drawer.svelte.d.ts +0 -3
  246. package/dist/components/ui/drawer/index.d.ts +0 -13
  247. package/dist/components/ui/drawer/index.js +0 -15
  248. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +0 -41
  249. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +0 -9
  250. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +0 -27
  251. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte.d.ts +0 -7
  252. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +0 -22
  253. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +0 -8
  254. package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte +0 -7
  255. package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte.d.ts +0 -4
  256. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +0 -27
  257. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +0 -8
  258. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +0 -24
  259. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte.d.ts +0 -8
  260. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +0 -16
  261. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +0 -4
  262. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +0 -31
  263. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +0 -4
  264. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +0 -17
  265. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte.d.ts +0 -4
  266. package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +0 -20
  267. package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +0 -5
  268. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +0 -20
  269. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +0 -4
  270. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +0 -29
  271. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +0 -7
  272. package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +0 -7
  273. package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +0 -4
  274. package/dist/components/ui/dropdown-menu/index.d.ts +0 -25
  275. package/dist/components/ui/dropdown-menu/index.js +0 -17
  276. package/dist/components/ui/input/index.d.ts +0 -2
  277. package/dist/components/ui/input/index.js +0 -4
  278. package/dist/components/ui/input/input.svelte +0 -51
  279. package/dist/components/ui/input/input.svelte.d.ts +0 -13
  280. package/dist/components/ui/label/index.d.ts +0 -2
  281. package/dist/components/ui/label/index.js +0 -4
  282. package/dist/components/ui/label/label.svelte +0 -20
  283. package/dist/components/ui/label/label.svelte.d.ts +0 -4
  284. package/dist/components/ui/scroll-area/index.d.ts +0 -3
  285. package/dist/components/ui/scroll-area/index.js +0 -5
  286. package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte +0 -31
  287. package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte.d.ts +0 -4
  288. package/dist/components/ui/scroll-area/scroll-area.svelte +0 -40
  289. package/dist/components/ui/scroll-area/scroll-area.svelte.d.ts +0 -10
  290. package/dist/components/ui/select/index.d.ts +0 -11
  291. package/dist/components/ui/select/index.js +0 -14
  292. package/dist/components/ui/select/select-content.svelte +0 -40
  293. package/dist/components/ui/select/select-content.svelte.d.ts +0 -8
  294. package/dist/components/ui/select/select-group-heading.svelte +0 -21
  295. package/dist/components/ui/select/select-group-heading.svelte.d.ts +0 -10
  296. package/dist/components/ui/select/select-group.svelte +0 -7
  297. package/dist/components/ui/select/select-group.svelte.d.ts +0 -4
  298. package/dist/components/ui/select/select-item.svelte +0 -38
  299. package/dist/components/ui/select/select-item.svelte.d.ts +0 -4
  300. package/dist/components/ui/select/select-label.svelte +0 -20
  301. package/dist/components/ui/select/select-label.svelte.d.ts +0 -6
  302. package/dist/components/ui/select/select-scroll-down-button.svelte +0 -20
  303. package/dist/components/ui/select/select-scroll-down-button.svelte.d.ts +0 -4
  304. package/dist/components/ui/select/select-scroll-up-button.svelte +0 -20
  305. package/dist/components/ui/select/select-scroll-up-button.svelte.d.ts +0 -4
  306. package/dist/components/ui/select/select-separator.svelte +0 -18
  307. package/dist/components/ui/select/select-separator.svelte.d.ts +0 -4
  308. package/dist/components/ui/select/select-trigger.svelte +0 -29
  309. package/dist/components/ui/select/select-trigger.svelte.d.ts +0 -8
  310. package/dist/components/ui/separator/index.d.ts +0 -2
  311. package/dist/components/ui/separator/index.js +0 -4
  312. package/dist/components/ui/separator/separator.svelte +0 -20
  313. package/dist/components/ui/separator/separator.svelte.d.ts +0 -4
  314. package/dist/components/ui/sheet/index.d.ts +0 -11
  315. package/dist/components/ui/sheet/index.js +0 -14
  316. package/dist/components/ui/sheet/sheet-close.svelte +0 -7
  317. package/dist/components/ui/sheet/sheet-close.svelte.d.ts +0 -4
  318. package/dist/components/ui/sheet/sheet-content.svelte +0 -58
  319. package/dist/components/ui/sheet/sheet-content.svelte.d.ts +0 -35
  320. package/dist/components/ui/sheet/sheet-description.svelte +0 -17
  321. package/dist/components/ui/sheet/sheet-description.svelte.d.ts +0 -4
  322. package/dist/components/ui/sheet/sheet-footer.svelte +0 -20
  323. package/dist/components/ui/sheet/sheet-footer.svelte.d.ts +0 -5
  324. package/dist/components/ui/sheet/sheet-header.svelte +0 -20
  325. package/dist/components/ui/sheet/sheet-header.svelte.d.ts +0 -5
  326. package/dist/components/ui/sheet/sheet-overlay.svelte +0 -20
  327. package/dist/components/ui/sheet/sheet-overlay.svelte.d.ts +0 -4
  328. package/dist/components/ui/sheet/sheet-title.svelte +0 -17
  329. package/dist/components/ui/sheet/sheet-title.svelte.d.ts +0 -4
  330. package/dist/components/ui/sheet/sheet-trigger.svelte +0 -7
  331. package/dist/components/ui/sheet/sheet-trigger.svelte.d.ts +0 -4
  332. package/dist/components/ui/sidebar/constants.d.ts +0 -6
  333. package/dist/components/ui/sidebar/constants.js +0 -6
  334. package/dist/components/ui/sidebar/context.svelte.d.ts +0 -42
  335. package/dist/components/ui/sidebar/context.svelte.js +0 -54
  336. package/dist/components/ui/sidebar/index.d.ts +0 -25
  337. package/dist/components/ui/sidebar/index.js +0 -27
  338. package/dist/components/ui/sidebar/sidebar-content.svelte +0 -24
  339. package/dist/components/ui/sidebar/sidebar-content.svelte.d.ts +0 -5
  340. package/dist/components/ui/sidebar/sidebar-footer.svelte +0 -21
  341. package/dist/components/ui/sidebar/sidebar-footer.svelte.d.ts +0 -5
  342. package/dist/components/ui/sidebar/sidebar-group-action.svelte +0 -36
  343. package/dist/components/ui/sidebar/sidebar-group-action.svelte.d.ts +0 -11
  344. package/dist/components/ui/sidebar/sidebar-group-content.svelte +0 -21
  345. package/dist/components/ui/sidebar/sidebar-group-content.svelte.d.ts +0 -5
  346. package/dist/components/ui/sidebar/sidebar-group-label.svelte +0 -34
  347. package/dist/components/ui/sidebar/sidebar-group-label.svelte.d.ts +0 -11
  348. package/dist/components/ui/sidebar/sidebar-group.svelte +0 -21
  349. package/dist/components/ui/sidebar/sidebar-group.svelte.d.ts +0 -5
  350. package/dist/components/ui/sidebar/sidebar-header.svelte +0 -21
  351. package/dist/components/ui/sidebar/sidebar-header.svelte.d.ts +0 -5
  352. package/dist/components/ui/sidebar/sidebar-input.svelte +0 -21
  353. package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +0 -11
  354. package/dist/components/ui/sidebar/sidebar-inset.svelte +0 -24
  355. package/dist/components/ui/sidebar/sidebar-inset.svelte.d.ts +0 -5
  356. package/dist/components/ui/sidebar/sidebar-menu-action.svelte +0 -43
  357. package/dist/components/ui/sidebar/sidebar-menu-action.svelte.d.ts +0 -12
  358. package/dist/components/ui/sidebar/sidebar-menu-badge.svelte +0 -29
  359. package/dist/components/ui/sidebar/sidebar-menu-badge.svelte.d.ts +0 -5
  360. package/dist/components/ui/sidebar/sidebar-menu-button.svelte +0 -103
  361. package/dist/components/ui/sidebar/sidebar-menu-button.svelte.d.ts +0 -51
  362. package/dist/components/ui/sidebar/sidebar-menu-item.svelte +0 -21
  363. package/dist/components/ui/sidebar/sidebar-menu-item.svelte.d.ts +0 -5
  364. package/dist/components/ui/sidebar/sidebar-menu-skeleton.svelte +0 -36
  365. package/dist/components/ui/sidebar/sidebar-menu-skeleton.svelte.d.ts +0 -8
  366. package/dist/components/ui/sidebar/sidebar-menu-sub-button.svelte +0 -43
  367. package/dist/components/ui/sidebar/sidebar-menu-sub-button.svelte.d.ts +0 -13
  368. package/dist/components/ui/sidebar/sidebar-menu-sub-item.svelte +0 -21
  369. package/dist/components/ui/sidebar/sidebar-menu-sub-item.svelte.d.ts +0 -5
  370. package/dist/components/ui/sidebar/sidebar-menu-sub.svelte +0 -25
  371. package/dist/components/ui/sidebar/sidebar-menu-sub.svelte.d.ts +0 -5
  372. package/dist/components/ui/sidebar/sidebar-menu.svelte +0 -21
  373. package/dist/components/ui/sidebar/sidebar-menu.svelte.d.ts +0 -5
  374. package/dist/components/ui/sidebar/sidebar-provider.svelte +0 -53
  375. package/dist/components/ui/sidebar/sidebar-provider.svelte.d.ts +0 -9
  376. package/dist/components/ui/sidebar/sidebar-rail.svelte +0 -36
  377. package/dist/components/ui/sidebar/sidebar-rail.svelte.d.ts +0 -5
  378. package/dist/components/ui/sidebar/sidebar-separator.svelte +0 -19
  379. package/dist/components/ui/sidebar/sidebar-separator.svelte.d.ts +0 -13
  380. package/dist/components/ui/sidebar/sidebar-trigger.svelte +0 -35
  381. package/dist/components/ui/sidebar/sidebar-trigger.svelte.d.ts +0 -8
  382. package/dist/components/ui/sidebar/sidebar.svelte +0 -104
  383. package/dist/components/ui/sidebar/sidebar.svelte.d.ts +0 -10
  384. package/dist/components/ui/skeleton/index.d.ts +0 -2
  385. package/dist/components/ui/skeleton/index.js +0 -4
  386. package/dist/components/ui/skeleton/skeleton.svelte +0 -17
  387. package/dist/components/ui/skeleton/skeleton.svelte.d.ts +0 -5
  388. package/dist/components/ui/table/index.d.ts +0 -9
  389. package/dist/components/ui/table/index.js +0 -11
  390. package/dist/components/ui/table/table-body.svelte +0 -20
  391. package/dist/components/ui/table/table-body.svelte.d.ts +0 -5
  392. package/dist/components/ui/table/table-caption.svelte +0 -20
  393. package/dist/components/ui/table/table-caption.svelte.d.ts +0 -5
  394. package/dist/components/ui/table/table-cell.svelte +0 -20
  395. package/dist/components/ui/table/table-cell.svelte.d.ts +0 -5
  396. package/dist/components/ui/table/table-footer.svelte +0 -20
  397. package/dist/components/ui/table/table-footer.svelte.d.ts +0 -5
  398. package/dist/components/ui/table/table-head.svelte +0 -23
  399. package/dist/components/ui/table/table-head.svelte.d.ts +0 -5
  400. package/dist/components/ui/table/table-header.svelte +0 -20
  401. package/dist/components/ui/table/table-header.svelte.d.ts +0 -5
  402. package/dist/components/ui/table/table-row.svelte +0 -23
  403. package/dist/components/ui/table/table-row.svelte.d.ts +0 -5
  404. package/dist/components/ui/table/table.svelte +0 -22
  405. package/dist/components/ui/table/table.svelte.d.ts +0 -5
  406. package/dist/components/ui/tabs/index.d.ts +0 -5
  407. package/dist/components/ui/tabs/index.js +0 -7
  408. package/dist/components/ui/tabs/tabs-content.svelte +0 -17
  409. package/dist/components/ui/tabs/tabs-content.svelte.d.ts +0 -4
  410. package/dist/components/ui/tabs/tabs-list.svelte +0 -20
  411. package/dist/components/ui/tabs/tabs-list.svelte.d.ts +0 -4
  412. package/dist/components/ui/tabs/tabs-trigger.svelte +0 -20
  413. package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +0 -4
  414. package/dist/components/ui/tabs/tabs.svelte +0 -19
  415. package/dist/components/ui/tabs/tabs.svelte.d.ts +0 -4
  416. package/dist/components/ui/toggle/index.d.ts +0 -3
  417. package/dist/components/ui/toggle/index.js +0 -5
  418. package/dist/components/ui/toggle/toggle.svelte +0 -52
  419. package/dist/components/ui/toggle/toggle.svelte.d.ts +0 -43
  420. package/dist/components/ui/toggle-group/index.d.ts +0 -3
  421. package/dist/components/ui/toggle-group/index.js +0 -5
  422. package/dist/components/ui/toggle-group/toggle-group-item.svelte +0 -34
  423. package/dist/components/ui/toggle-group/toggle-group-item.svelte.d.ts +0 -6
  424. package/dist/components/ui/toggle-group/toggle-group.svelte +0 -47
  425. package/dist/components/ui/toggle-group/toggle-group.svelte.d.ts +0 -8
  426. package/dist/components/ui/tooltip/index.d.ts +0 -7
  427. package/dist/components/ui/tooltip/index.js +0 -9
  428. package/dist/components/ui/tooltip/tooltip-content.svelte +0 -47
  429. package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +0 -7
  430. package/dist/components/ui/tooltip/tooltip-trigger.svelte +0 -7
  431. package/dist/components/ui/tooltip/tooltip-trigger.svelte.d.ts +0 -4
  432. package/dist/hooks/is-mobile.svelte.d.ts +0 -4
  433. package/dist/hooks/is-mobile.svelte.js +0 -7
  434. package/dist/services/index.d.ts +0 -9
  435. package/dist/services/index.js +0 -10
  436. package/dist/types/docs.d.ts +0 -67
  437. package/dist/utils.d.ts +0 -15
  438. package/dist/utils.js +0 -44
  439. /package/dist/{types/docs.js → services/in-app-messaging.d.ts} +0 -0
@@ -1,944 +1,579 @@
1
- /**
2
- * @fileoverview FirekitAuth - Complete Firebase Authentication Service for Svelte
3
- * @module FirekitAuth
4
- * @version 1.0.0
5
- */
6
- import { EmailAuthProvider, PhoneAuthProvider, RecaptchaVerifier, signInWithEmailAndPassword, signInWithPopup, signInWithPhoneNumber as firebaseSignInWithPhoneNumber, signInWithCredential, signInAnonymously as firebaseSignInAnonymously, createUserWithEmailAndPassword, signOut, sendPasswordResetEmail, confirmPasswordReset, sendEmailVerification, updateProfile, updateEmail, updatePassword, reauthenticateWithCredential, deleteUser, reload, getIdToken, onAuthStateChanged, getAdditionalUserInfo } from 'firebase/auth';
1
+ import { EmailAuthProvider, PhoneAuthProvider, RecaptchaVerifier, SAMLAuthProvider, OAuthProvider, signInWithEmailAndPassword, signInWithPopup, signInWithRedirect, getRedirectResult, signInWithCustomToken as firebaseSignInWithCustomToken, signInWithPhoneNumber as firebaseSignInWithPhoneNumber, signInWithCredential, signInAnonymously as firebaseSignInAnonymously, createUserWithEmailAndPassword, signOut as firebaseSignOut, sendPasswordResetEmail, confirmPasswordReset as firebaseConfirmPasswordReset, sendEmailVerification, updateProfile, updateEmail, updatePassword, reauthenticateWithCredential, deleteUser, reload, getIdToken, getAdditionalUserInfo, multiFactor, PhoneMultiFactorGenerator, getMultiFactorResolver } from 'firebase/auth';
7
2
  import { doc, setDoc, serverTimestamp } from 'firebase/firestore';
8
3
  import { firebaseService } from '../firebase.js';
9
4
  import { AuthErrorCode, FirekitAuthError } from '../types/auth.js';
10
- import { mapFirebaseUserToProfile, updateUserInFirestore, createGoogleProvider, createFacebookProvider, createAppleProvider, handleAuthError } from '../utils/index.js';
11
- import { firekitPresence } from './presence.svelte.js';
5
+ import { mapFirebaseUserToProfile, updateUserInFirestore, createGoogleProvider, createFacebookProvider, createAppleProvider, createGithubProvider, createTwitterProvider, createMicrosoftProvider, handleAuthError } from '../utils/index.js';
12
6
  /**
13
- * Comprehensive Firebase Authentication service for Svelte applications.
14
- * Provides a complete authentication solution with automatic Firestore integration,
15
- * error handling, and support for all major authentication methods.
7
+ * Firebase Authentication service.
8
+ * Handles all auth operations sign in, register, sign out, profile updates.
9
+ * Reactive state (loading, user, isAuthenticated) lives in `firekitUser`.
16
10
  *
17
- * @class FirekitAuth
18
11
  * @example
19
- * ```typescript
20
12
  * import { firekitAuth } from 'svelte-firekit';
21
- *
22
- * // Sign in with Google
23
13
  * await firekitAuth.signInWithGoogle();
24
- *
25
- * // Register new user
26
- * await firekitAuth.registerWithEmail("user@example.com", "password123", "John Doe");
27
- *
28
- * // Listen to auth state changes
29
- * const unsubscribe = firekitAuth.onAuthStateChanged((user) => {
30
- * console.log('User:', user);
31
- * });
32
- * ```
14
+ * await firekitAuth.registerWithEmail('user@example.com', 'password', 'Jane Doe');
15
+ * await firekitAuth.signOut();
33
16
  */
34
17
  class FirekitAuth {
35
18
  static instance;
36
19
  auth = null;
37
20
  firestore = null;
38
- _servicesInitialized = false;
39
- authState = {
40
- user: null,
41
- loading: true,
42
- initialized: false
43
- };
44
- stateListeners = new Set();
45
21
  recaptchaVerifiers = new Map();
46
22
  constructor() {
47
23
  if (typeof window !== 'undefined') {
48
- // Initialize Firebase services immediately like the old working code
49
- this.initializeServices();
24
+ this.bootstrap();
50
25
  }
51
26
  }
52
- /**
53
- * Gets singleton instance of FirekitAuth
54
- * @returns {FirekitAuth} The FirekitAuth instance
55
- */
56
27
  static getInstance() {
57
28
  if (!FirekitAuth.instance) {
58
29
  FirekitAuth.instance = new FirekitAuth();
59
30
  }
60
31
  return FirekitAuth.instance;
61
32
  }
62
- /**
63
- * Initializes Firebase services and auth state listener
64
- * @private
65
- */
66
- initializeServices() {
67
- if (this._servicesInitialized)
68
- return;
33
+ bootstrap() {
69
34
  try {
70
35
  this.auth = firebaseService.getAuthInstance();
71
- // Try to get Firestore instance, but don't fail if it's not available
72
36
  try {
73
37
  this.firestore = firebaseService.getDbInstance();
74
38
  }
75
- catch (firestoreError) {
76
- console.warn('Firestore not available, continuing without Firestore integration:', firestoreError);
39
+ catch {
77
40
  this.firestore = null;
78
41
  }
79
- this._servicesInitialized = true;
80
- this.initializeAuthStateListener();
81
42
  }
82
- catch (error) {
83
- console.error('Failed to initialize Firebase services:', error);
84
- this.authState = {
85
- user: null,
86
- loading: false,
87
- initialized: true
88
- };
89
- this.notifyStateListeners();
43
+ catch {
44
+ // Firebase not yet configured — services will be accessed lazily
90
45
  }
91
46
  }
92
- /**
93
- * Initializes the authentication state listener
94
- * @private
95
- */
96
- initializeAuthStateListener() {
47
+ getAuth() {
97
48
  if (!this.auth) {
98
- console.error('Auth instance not available');
99
- return;
49
+ this.auth = firebaseService.getAuthInstance();
100
50
  }
101
- onAuthStateChanged(this.auth, (user) => {
102
- this.authState = {
103
- user: user ? this.mapFirebaseUserToProfile(user) : null,
104
- loading: false,
105
- initialized: true
106
- };
107
- this.notifyStateListeners();
108
- }, (error) => {
109
- console.error('Auth state change error:', error);
110
- this.authState = {
111
- user: null,
112
- loading: false,
113
- initialized: true
114
- };
115
- this.notifyStateListeners();
116
- });
117
- }
118
- /**
119
- * Notifies all state listeners of auth state changes
120
- * @private
121
- */
122
- notifyStateListeners() {
123
- this.stateListeners.forEach((listener) => listener(this.authState));
124
- }
125
- /**
126
- * Maps Firebase User to UserProfile interface
127
- * @private
128
- */
129
- mapFirebaseUserToProfile(user) {
130
- return mapFirebaseUserToProfile(user);
51
+ if (!this.auth) {
52
+ throw new FirekitAuthError('auth/not-initialized', 'Firebase Auth is not initialized.');
53
+ }
54
+ return this.auth;
131
55
  }
132
- /**
133
- * Updates user data in Firestore with comprehensive profile information
134
- * @private
135
- */
136
- async updateUserInFirestore(user) {
137
- if (!this.firestore) {
138
- console.warn('Firestore not available, skipping user update in Firestore');
56
+ async syncToFirestore(user) {
57
+ if (!this.firestore)
139
58
  return;
140
- }
141
59
  await updateUserInFirestore(this.firestore, user);
142
60
  }
143
- /**
144
- * Handles Firebase authentication errors and throws FirekitAuthError
145
- * @private
146
- */
147
- handleAuthError(error) {
148
- handleAuthError(error);
149
- }
150
- /**
151
- * Gets the current authentication state
152
- * @returns {AuthState} Current authentication state
153
- */
154
- getState() {
155
- return { ...this.authState };
156
- }
157
- /**
158
- * Gets the current authenticated user
159
- * @returns {User | null} Current Firebase user or null
160
- */
161
- getCurrentUser() {
162
- return this.auth?.currentUser ?? null;
163
- }
164
- /**
165
- * Gets the current user profile
166
- * @returns {UserProfile | null} Current user profile or null
167
- */
168
- getCurrentUserProfile() {
169
- return this.authState.user;
170
- }
171
- /**
172
- * Waits for auth initialization to complete
173
- * @returns {Promise<UserProfile | null>} Promise that resolves when auth is initialized
174
- */
175
- async waitForAuth() {
176
- return new Promise((resolve) => {
177
- if (this.authState.initialized) {
178
- resolve(this.authState.user);
179
- return;
180
- }
181
- const unsubscribe = this.onAuthStateChanged((state) => {
182
- if (state.initialized) {
183
- unsubscribe();
184
- resolve(state.user);
185
- }
186
- });
187
- });
188
- }
189
- /**
190
- * Subscribes to authentication state changes
191
- * @param {Function} callback Callback function to handle state changes
192
- * @returns {Function} Unsubscribe function
193
- */
194
- onAuthStateChanged(callback) {
195
- this.stateListeners.add(callback);
196
- // Immediately call with current state
197
- callback(this.authState);
198
- return () => {
199
- this.stateListeners.delete(callback);
200
- };
61
+ profile(user) {
62
+ return mapFirebaseUserToProfile(user);
201
63
  }
202
- // ========================================
203
- // SIGN IN METHODS
204
- // ========================================
205
- /**
206
- * Signs in user with email and password
207
- * @param {string} email User's email address
208
- * @param {string} password User's password
209
- * @returns {Promise<SignInResult>} Promise resolving to sign-in result
210
- * @throws {FirekitAuthError} If sign-in fails
211
- *
212
- * @example
213
- * ```typescript
214
- * try {
215
- * const result = await firekitAuth.signInWithEmail("user@example.com", "password123");
216
- * console.log("Signed in:", result.user.displayName);
217
- * console.log("Is new user:", result.isNewUser);
218
- * } catch (error) {
219
- * console.error("Sign-in failed:", error.message);
220
- * }
221
- * ```
222
- */
64
+ // ─── Sign-in ────────────────────────────────────────────────────────────────
223
65
  async signInWithEmail(email, password) {
224
- if (!this.auth) {
225
- throw new Error('Auth instance not available');
226
- }
227
66
  try {
228
- this.authState.loading = true;
229
- this.notifyStateListeners();
230
- const userCredential = await signInWithEmailAndPassword(this.auth, email, password);
231
- await this.updateUserInFirestore(userCredential.user);
232
- const userProfile = this.mapFirebaseUserToProfile(userCredential.user);
233
- const additionalUserInfo = getAdditionalUserInfo(userCredential);
234
- const isNewUser = additionalUserInfo?.isNewUser ?? false;
67
+ const cred = await signInWithEmailAndPassword(this.getAuth(), email, password);
68
+ await this.syncToFirestore(cred.user);
69
+ const profile = this.profile(cred.user);
70
+ const isNewUser = getAdditionalUserInfo(cred)?.isNewUser ?? false;
235
71
  return {
236
72
  success: true,
237
- user: userProfile,
73
+ user: profile,
238
74
  method: 'email',
239
75
  timestamp: new Date(),
240
76
  isNewUser,
241
- requiresEmailVerification: !userProfile.emailVerified
77
+ requiresEmailVerification: !profile.emailVerified
242
78
  };
243
79
  }
244
80
  catch (error) {
245
- this.handleAuthError(error);
246
- }
247
- finally {
248
- this.authState.loading = false;
249
- this.notifyStateListeners();
81
+ handleAuthError(error);
250
82
  }
251
83
  }
252
- /**
253
- * Signs in user with Google popup
254
- * @returns {Promise<OAuthSignInResult>} Promise resolving to OAuth sign-in result
255
- * @throws {FirekitAuthError} If sign-in fails
256
- *
257
- * @example
258
- * ```typescript
259
- * try {
260
- * const result = await firekitAuth.signInWithGoogle();
261
- * console.log("Signed in with Google:", result.user.email);
262
- * console.log("Is new user:", result.isNewUser);
263
- * console.log("Access token:", result.accessToken);
264
- * } catch (error) {
265
- * if (error.code === 'auth/popup-closed-by-user') {
266
- * console.log("User cancelled sign-in");
267
- * }
268
- * }
269
- * ```
270
- */
271
84
  async signInWithGoogle() {
272
- if (!this.auth) {
273
- throw new Error('Auth instance not available');
274
- }
275
- try {
276
- this.authState.loading = true;
277
- this.notifyStateListeners();
278
- const provider = createGoogleProvider();
279
- const result = await signInWithPopup(this.auth, provider);
280
- await this.updateUserInFirestore(result.user);
281
- const userProfile = this.mapFirebaseUserToProfile(result.user);
282
- const additionalUserInfo = getAdditionalUserInfo(result);
283
- const isNewUser = additionalUserInfo?.isNewUser ?? false;
284
- return {
285
- success: true,
286
- user: userProfile,
287
- method: 'google',
288
- timestamp: new Date(),
289
- isNewUser,
290
- provider: 'google'
291
- };
292
- }
293
- catch (error) {
294
- this.handleAuthError(error);
295
- }
296
- finally {
297
- this.authState.loading = false;
298
- this.notifyStateListeners();
299
- }
85
+ return this.signInWithOAuth('google', createGoogleProvider());
300
86
  }
301
- /**
302
- * Signs in user with Facebook popup
303
- * @returns {Promise<OAuthSignInResult>} Promise resolving to OAuth sign-in result
304
- * @throws {FirekitAuthError} If sign-in fails
305
- */
306
87
  async signInWithFacebook() {
307
- if (!this.auth) {
308
- throw new Error('Auth instance not available');
309
- }
310
- try {
311
- this.authState.loading = true;
312
- this.notifyStateListeners();
313
- const provider = createFacebookProvider();
314
- const result = await signInWithPopup(this.auth, provider);
315
- await this.updateUserInFirestore(result.user);
316
- const userProfile = this.mapFirebaseUserToProfile(result.user);
317
- const additionalUserInfo = getAdditionalUserInfo(result);
318
- const isNewUser = additionalUserInfo?.isNewUser ?? false;
319
- return {
320
- success: true,
321
- user: userProfile,
322
- method: 'facebook',
323
- timestamp: new Date(),
324
- isNewUser,
325
- provider: 'facebook'
326
- };
327
- }
328
- catch (error) {
329
- this.handleAuthError(error);
330
- }
331
- finally {
332
- this.authState.loading = false;
333
- this.notifyStateListeners();
334
- }
88
+ return this.signInWithOAuth('facebook', createFacebookProvider());
335
89
  }
336
- /**
337
- * Signs in user with Apple popup
338
- * @returns {Promise<OAuthSignInResult>} Promise resolving to OAuth sign-in result
339
- * @throws {FirekitAuthError} If sign-in fails
340
- */
341
90
  async signInWithApple() {
342
- if (!this.auth) {
343
- throw new Error('Auth instance not available');
344
- }
91
+ return this.signInWithOAuth('apple', createAppleProvider());
92
+ }
93
+ async signInWithGithub() {
94
+ return this.signInWithOAuth('github', createGithubProvider());
95
+ }
96
+ async signInWithTwitter() {
97
+ return this.signInWithOAuth('twitter', createTwitterProvider());
98
+ }
99
+ async signInWithMicrosoft() {
100
+ return this.signInWithOAuth('microsoft', createMicrosoftProvider());
101
+ }
102
+ async signInWithOAuth(provider, providerInstance) {
345
103
  try {
346
- this.authState.loading = true;
347
- this.notifyStateListeners();
348
- const provider = createAppleProvider();
349
- const result = await signInWithPopup(this.auth, provider);
350
- await this.updateUserInFirestore(result.user);
351
- const userProfile = this.mapFirebaseUserToProfile(result.user);
352
- const additionalUserInfo = getAdditionalUserInfo(result);
353
- const isNewUser = additionalUserInfo?.isNewUser ?? false;
104
+ const result = await signInWithPopup(this.getAuth(), providerInstance);
105
+ await this.syncToFirestore(result.user);
106
+ const profile = this.profile(result.user);
107
+ const isNewUser = getAdditionalUserInfo(result)?.isNewUser ?? false;
354
108
  return {
355
109
  success: true,
356
- user: userProfile,
357
- method: 'apple',
110
+ user: profile,
111
+ method: provider,
358
112
  timestamp: new Date(),
359
113
  isNewUser,
360
- provider: 'apple'
114
+ provider
361
115
  };
362
116
  }
363
117
  catch (error) {
364
- this.handleAuthError(error);
365
- }
366
- finally {
367
- this.authState.loading = false;
368
- this.notifyStateListeners();
118
+ handleAuthError(error);
369
119
  }
370
120
  }
371
- /**
372
- * Signs in user anonymously
373
- * @returns {Promise<SignInResult>} Promise resolving to sign-in result
374
- * @throws {FirekitAuthError} If sign-in fails
375
- *
376
- * @example
377
- * ```typescript
378
- * const result = await firekitAuth.signInAnonymously();
379
- * console.log("Anonymous user:", result.user.uid);
380
- * console.log("Is new user:", result.isNewUser);
381
- * ```
382
- */
383
121
  async signInAnonymously() {
384
- if (!this.auth) {
385
- throw new Error('Auth instance not available');
386
- }
387
122
  try {
388
- this.authState.loading = true;
389
- this.notifyStateListeners();
390
- const result = await firebaseSignInAnonymously(this.auth);
391
- await this.updateUserInFirestore(result.user);
392
- const userProfile = this.mapFirebaseUserToProfile(result.user);
393
- const additionalUserInfo = getAdditionalUserInfo(result);
394
- const isNewUser = additionalUserInfo?.isNewUser ?? false;
123
+ const result = await firebaseSignInAnonymously(this.getAuth());
124
+ await this.syncToFirestore(result.user);
125
+ const profile = this.profile(result.user);
126
+ const isNewUser = getAdditionalUserInfo(result)?.isNewUser ?? false;
395
127
  return {
396
128
  success: true,
397
- user: userProfile,
129
+ user: profile,
398
130
  method: 'anonymous',
399
131
  timestamp: new Date(),
400
132
  isNewUser
401
133
  };
402
134
  }
403
135
  catch (error) {
404
- this.handleAuthError(error);
405
- }
406
- finally {
407
- this.authState.loading = false;
408
- this.notifyStateListeners();
136
+ handleAuthError(error);
409
137
  }
410
138
  }
411
- /**
412
- * Initiates phone number sign-in process
413
- * @param {string} phoneNumber Phone number in international format
414
- * @param {string} recaptchaContainerId ID of the reCAPTCHA container element
415
- * @returns {Promise<PhoneVerificationResult>} Promise resolving to verification result
416
- * @throws {FirekitAuthError} If verification initiation fails
417
- *
418
- * @example
419
- * ```typescript
420
- * const verification = await firekitAuth.signInWithPhoneNumber("+1234567890", "recaptcha-container");
421
- * const user = await verification.confirm("123456");
422
- * ```
423
- */
424
139
  async signInWithPhoneNumber(phoneNumber, recaptchaContainerId) {
425
- if (!this.auth) {
426
- throw new Error('Auth instance not available');
427
- }
140
+ const auth = this.getAuth();
428
141
  try {
429
- this.authState.loading = true;
430
- this.notifyStateListeners();
431
- // Clean up existing verifier if any
432
- const existingVerifier = this.recaptchaVerifiers.get(recaptchaContainerId);
433
- if (existingVerifier) {
434
- existingVerifier.clear();
142
+ // Reuse or create the reCAPTCHA verifier for this container
143
+ const existing = this.recaptchaVerifiers.get(recaptchaContainerId);
144
+ if (existing) {
145
+ existing.clear();
435
146
  this.recaptchaVerifiers.delete(recaptchaContainerId);
436
147
  }
437
- const recaptchaVerifier = new RecaptchaVerifier(this.auth, recaptchaContainerId, {
438
- size: 'normal',
439
- callback: () => {
440
- console.log('reCAPTCHA solved');
441
- },
442
- 'expired-callback': () => {
443
- console.log('reCAPTCHA expired');
444
- }
445
- });
446
- this.recaptchaVerifiers.set(recaptchaContainerId, recaptchaVerifier);
447
- const confirmationResult = await firebaseSignInWithPhoneNumber(this.auth, phoneNumber, recaptchaVerifier);
148
+ const verifier = new RecaptchaVerifier(auth, recaptchaContainerId, { size: 'normal' });
149
+ this.recaptchaVerifiers.set(recaptchaContainerId, verifier);
150
+ const confirmation = await firebaseSignInWithPhoneNumber(auth, phoneNumber, verifier);
448
151
  return {
449
- verificationId: confirmationResult.verificationId,
450
- confirm: async (verificationCode) => {
152
+ verificationId: confirmation.verificationId,
153
+ confirm: async (code) => {
451
154
  try {
452
- const userCredential = await confirmationResult.confirm(verificationCode);
453
- await this.updateUserInFirestore(userCredential.user);
454
- const userProfile = this.mapFirebaseUserToProfile(userCredential.user);
455
- const additionalUserInfo = getAdditionalUserInfo(userCredential);
456
- const isNewUser = additionalUserInfo?.isNewUser ?? false;
155
+ const cred = await confirmation.confirm(code);
156
+ await this.syncToFirestore(cred.user);
157
+ const profile = this.profile(cred.user);
158
+ const isNewUser = getAdditionalUserInfo(cred)?.isNewUser ?? false;
457
159
  return {
458
160
  success: true,
459
- user: userProfile,
161
+ user: profile,
460
162
  method: 'phone',
461
163
  timestamp: new Date(),
462
164
  isNewUser
463
165
  };
464
166
  }
465
167
  catch (error) {
466
- this.handleAuthError(error);
168
+ handleAuthError(error);
467
169
  }
468
170
  finally {
469
- // Clean up verifier after use
470
- recaptchaVerifier.clear();
171
+ verifier.clear();
471
172
  this.recaptchaVerifiers.delete(recaptchaContainerId);
472
173
  }
473
174
  }
474
175
  };
475
176
  }
476
177
  catch (error) {
477
- this.handleAuthError(error);
478
- }
479
- finally {
480
- this.authState.loading = false;
481
- this.notifyStateListeners();
178
+ handleAuthError(error);
482
179
  }
483
180
  }
484
- // ========================================
485
- // REGISTRATION METHODS
486
- // ========================================
487
- /**
488
- * Registers new user with email and password
489
- * @param {string} email User's email address
490
- * @param {string} password User's password
491
- * @param {string} [displayName] User's display name
492
- * @param {boolean} [sendVerification=true] Whether to send email verification
493
- * @returns {Promise<RegistrationResult>} Promise resolving to registration result
494
- * @throws {FirekitAuthError} If registration fails
495
- *
496
- * @example
497
- * ```typescript
498
- * const result = await firekitAuth.registerWithEmail(
499
- * "user@example.com",
500
- * "password123",
501
- * "John Doe"
502
- * );
503
- * console.log("Registered:", result.user.displayName);
504
- * console.log("Email verification sent:", result.emailVerificationSent);
505
- * ```
506
- */
181
+ // ─── Registration ────────────────────────────────────────────────────────────
507
182
  async registerWithEmail(email, password, displayName, sendVerification = true) {
508
- if (!this.auth) {
509
- throw new Error('Auth instance not available');
510
- }
511
183
  try {
512
- this.authState.loading = true;
513
- this.notifyStateListeners();
514
- const userCredential = await createUserWithEmailAndPassword(this.auth, email, password);
515
- const user = userCredential.user;
516
- // Update profile if displayName provided
517
- if (displayName) {
184
+ const cred = await createUserWithEmailAndPassword(this.getAuth(), email, password);
185
+ const { user } = cred;
186
+ if (displayName)
518
187
  await updateProfile(user, { displayName });
519
- }
520
- // Send email verification
521
- if (sendVerification) {
188
+ if (sendVerification)
522
189
  await sendEmailVerification(user);
523
- }
524
- await this.updateUserInFirestore(user);
525
- const userProfile = this.mapFirebaseUserToProfile(user);
190
+ await this.syncToFirestore(user);
191
+ const profile = this.profile(user);
526
192
  return {
527
193
  success: true,
528
- user: userProfile,
194
+ user: profile,
529
195
  method: 'email',
530
196
  timestamp: new Date(),
531
197
  emailVerificationSent: sendVerification,
532
- requiresEmailVerification: !userProfile.emailVerified
198
+ requiresEmailVerification: !profile.emailVerified
533
199
  };
534
200
  }
535
201
  catch (error) {
536
- this.handleAuthError(error);
202
+ handleAuthError(error);
203
+ }
204
+ }
205
+ // ─── Sign-out ────────────────────────────────────────────────────────────────
206
+ async signOut() {
207
+ try {
208
+ this.recaptchaVerifiers.forEach((v) => v.clear());
209
+ this.recaptchaVerifiers.clear();
210
+ await firebaseSignOut(this.getAuth());
537
211
  }
538
- finally {
539
- this.authState.loading = false;
540
- this.notifyStateListeners();
212
+ catch (error) {
213
+ handleAuthError(error);
541
214
  }
542
215
  }
543
- // ========================================
544
- // PASSWORD METHODS
545
- // ========================================
546
- /**
547
- * Sends password reset email
548
- * @param {string} email User's email address
549
- * @returns {Promise<void>} Promise that resolves when email is sent
550
- * @throws {FirekitAuthError} If sending fails
551
- *
552
- * @example
553
- * ```typescript
554
- * await firekitAuth.sendPasswordReset("user@example.com");
555
- * console.log("Password reset email sent");
556
- * ```
557
- */
216
+ // ─── Password ────────────────────────────────────────────────────────────────
558
217
  async sendPasswordReset(email) {
559
- if (!this.auth) {
560
- throw new Error('Auth instance not available');
561
- }
562
218
  try {
563
- await sendPasswordResetEmail(this.auth, email);
219
+ await sendPasswordResetEmail(this.getAuth(), email);
564
220
  }
565
221
  catch (error) {
566
- this.handleAuthError(error);
222
+ handleAuthError(error);
567
223
  }
568
224
  }
569
- /**
570
- * Confirms password reset with code
571
- * @param {string} code Password reset code from email
572
- * @param {string} newPassword New password
573
- * @returns {Promise<void>} Promise that resolves when password is reset
574
- * @throws {FirekitAuthError} If reset fails
575
- */
576
225
  async confirmPasswordReset(code, newPassword) {
577
- if (!this.auth) {
578
- throw new Error('Auth instance not available');
579
- }
580
226
  try {
581
- await confirmPasswordReset(this.auth, code, newPassword);
227
+ await firebaseConfirmPasswordReset(this.getAuth(), code, newPassword);
582
228
  }
583
229
  catch (error) {
584
- this.handleAuthError(error);
230
+ handleAuthError(error);
585
231
  }
586
232
  }
587
- /**
588
- * Updates user password with reauthentication
589
- * @param {string} newPassword New password
590
- * @param {string} currentPassword Current password for reauthentication
591
- * @returns {Promise<PasswordUpdateResult>} Promise resolving to update result
592
- *
593
- * @example
594
- * ```typescript
595
- * const result = await firekitAuth.updatePassword("newPassword123", "oldPassword123");
596
- * if (result.success) {
597
- * console.log("Password updated successfully");
598
- * } else {
599
- * console.error("Update failed:", result.message);
600
- * }
601
- * ```
602
- */
603
233
  async updatePassword(newPassword, currentPassword) {
604
- if (!this.auth?.currentUser) {
605
- return {
606
- success: false,
607
- message: 'No authenticated user found.',
608
- code: 'auth/no-current-user'
609
- };
234
+ const auth = this.getAuth();
235
+ if (!auth.currentUser) {
236
+ return { success: false, message: 'No authenticated user found.', code: 'auth/no-current-user' };
610
237
  }
611
238
  try {
612
- await this.reauthenticateUser(currentPassword);
613
- await updatePassword(this.auth.currentUser, newPassword);
614
- return {
615
- success: true,
616
- message: 'Password successfully updated.'
617
- };
239
+ await this.reauthenticate(currentPassword);
240
+ await updatePassword(auth.currentUser, newPassword);
241
+ return { success: true, message: 'Password successfully updated.' };
618
242
  }
619
243
  catch (error) {
620
- const code = error.code;
621
- if (code === AuthErrorCode.WRONG_PASSWORD) {
622
- return {
623
- success: false,
624
- code,
625
- message: 'Current password is incorrect.'
626
- };
627
- }
244
+ const err = error;
245
+ const code = err.code;
628
246
  return {
629
247
  success: false,
630
- code: code || 'unknown_error',
631
- message: error.message || 'Failed to update password.'
248
+ code: code || 'unknown',
249
+ message: code === AuthErrorCode.WRONG_PASSWORD
250
+ ? 'Current password is incorrect.'
251
+ : (err.message ?? 'Failed to update password.')
632
252
  };
633
253
  }
634
254
  }
635
- // ========================================
636
- // PROFILE METHODS
637
- // ========================================
638
- /**
639
- * Updates user profile
640
- * @param {Object} profile Profile update data
641
- * @param {string} [profile.displayName] New display name
642
- * @param {string} [profile.photoURL] New photo URL
643
- * @returns {Promise<void>} Promise that resolves when profile is updated
644
- * @throws {FirekitAuthError} If update fails
645
- *
646
- * @example
647
- * ```typescript
648
- * await firekitAuth.updateUserProfile({
649
- * displayName: "John Smith",
650
- * photoURL: "https://example.com/photo.jpg"
651
- * });
652
- * ```
653
- */
255
+ // ─── Profile ─────────────────────────────────────────────────────────────────
654
256
  async updateUserProfile(profile) {
655
- if (!this.auth?.currentUser) {
257
+ const auth = this.getAuth();
258
+ if (!auth.currentUser) {
656
259
  throw new FirekitAuthError('auth/no-current-user', 'No authenticated user found.');
657
260
  }
658
261
  try {
659
- await updateProfile(this.auth.currentUser, profile);
660
- await this.updateUserInFirestore(this.auth.currentUser);
262
+ await updateProfile(auth.currentUser, profile);
263
+ await this.syncToFirestore(auth.currentUser);
661
264
  }
662
265
  catch (error) {
663
- this.handleAuthError(error);
266
+ handleAuthError(error);
664
267
  }
665
268
  }
666
- /**
667
- * Updates user email address
668
- * @param {string} newEmail New email address
669
- * @returns {Promise<void>} Promise that resolves when email is updated
670
- * @throws {FirekitAuthError} If update fails
671
- *
672
- * @example
673
- * ```typescript
674
- * await firekitAuth.updateEmail("newemail@example.com");
675
- * ```
676
- */
677
269
  async updateEmail(newEmail) {
678
- if (!this.auth?.currentUser) {
270
+ const auth = this.getAuth();
271
+ if (!auth.currentUser) {
679
272
  throw new FirekitAuthError('auth/no-current-user', 'No authenticated user found.');
680
273
  }
681
274
  try {
682
- await updateEmail(this.auth.currentUser, newEmail);
683
- await this.updateUserInFirestore(this.auth.currentUser);
275
+ await updateEmail(auth.currentUser, newEmail);
276
+ await this.syncToFirestore(auth.currentUser);
684
277
  }
685
278
  catch (error) {
686
- this.handleAuthError(error);
279
+ handleAuthError(error);
687
280
  }
688
281
  }
689
- /**
690
- * Sends email verification to current user
691
- * @returns {Promise<void>} Promise that resolves when verification email is sent
692
- * @throws {FirekitAuthError} If sending fails
693
- *
694
- * @example
695
- * ```typescript
696
- * await firekitAuth.sendEmailVerification();
697
- * ```
698
- */
699
282
  async sendEmailVerification() {
700
- if (!this.auth?.currentUser) {
283
+ const auth = this.getAuth();
284
+ if (!auth.currentUser) {
701
285
  throw new FirekitAuthError('auth/no-current-user', 'No authenticated user found.');
702
286
  }
703
287
  try {
704
- await sendEmailVerification(this.auth.currentUser);
288
+ await sendEmailVerification(auth.currentUser);
705
289
  }
706
290
  catch (error) {
707
- this.handleAuthError(error);
291
+ handleAuthError(error);
708
292
  }
709
293
  }
710
- /**
711
- * Reloads user to get updated data
712
- * @returns {Promise<void>} Promise that resolves when user is reloaded
713
- * @throws {FirekitAuthError} If reload fails
714
- *
715
- * @example
716
- * ```typescript
717
- * await firekitAuth.reloadUser();
718
- * ```
719
- */
720
294
  async reloadUser() {
721
- if (!this.auth?.currentUser) {
295
+ const auth = this.getAuth();
296
+ if (!auth.currentUser) {
722
297
  throw new FirekitAuthError('auth/no-current-user', 'No authenticated user found.');
723
298
  }
724
299
  try {
725
- await reload(this.auth.currentUser);
726
- await this.updateUserInFirestore(this.auth.currentUser);
300
+ await reload(auth.currentUser);
301
+ await this.syncToFirestore(auth.currentUser);
727
302
  }
728
303
  catch (error) {
729
- this.handleAuthError(error);
304
+ handleAuthError(error);
730
305
  }
731
306
  }
732
- /**
733
- * Gets the current user's ID token
734
- * @param {boolean} [forceRefresh=false] Whether to force token refresh
735
- * @returns {Promise<string>} Promise resolving to ID token
736
- * @throws {FirekitAuthError} If getting token fails
737
- *
738
- * @example
739
- * ```typescript
740
- * const token = await firekitAuth.getIdToken();
741
- * ```
742
- */
743
307
  async getIdToken(forceRefresh = false) {
744
- if (!this.auth?.currentUser) {
308
+ const auth = this.getAuth();
309
+ if (!auth.currentUser) {
745
310
  throw new FirekitAuthError('auth/no-current-user', 'No authenticated user found.');
746
311
  }
747
312
  try {
748
- return await getIdToken(this.auth.currentUser, forceRefresh);
313
+ return await getIdToken(auth.currentUser, forceRefresh);
749
314
  }
750
315
  catch (error) {
751
- this.handleAuthError(error);
316
+ handleAuthError(error);
752
317
  }
753
318
  }
754
- /**
755
- * Reauthenticates user with current password
756
- * @private
757
- */
758
- async reauthenticateUser(currentPassword) {
759
- if (!this.auth?.currentUser || !this.auth.currentUser.email) {
760
- throw new FirekitAuthError('auth/no-current-user', 'No authenticated user with email found.');
761
- }
762
- try {
763
- const credential = EmailAuthProvider.credential(this.auth.currentUser.email, currentPassword);
764
- await reauthenticateWithCredential(this.auth.currentUser, credential);
765
- }
766
- catch (error) {
767
- this.handleAuthError(error);
768
- }
769
- }
770
- /**
771
- * Deletes user account
772
- * @param {string} [currentPassword] Current password for reauthentication
773
- * @returns {Promise<AccountDeletionResult>} Promise resolving to deletion result
774
- *
775
- * @example
776
- * ```typescript
777
- * const result = await firekitAuth.deleteAccount("currentPassword123");
778
- * if (result.success) {
779
- * console.log("Account deleted successfully");
780
- * } else {
781
- * console.error("Deletion failed:", result.message);
782
- * }
783
- * ```
784
- */
319
+ // ─── Account deletion ────────────────────────────────────────────────────────
785
320
  async deleteAccount(currentPassword) {
786
- if (!this.auth?.currentUser) {
787
- return {
788
- success: false,
789
- message: 'No authenticated user found.'
790
- };
321
+ const auth = this.getAuth();
322
+ if (!auth.currentUser) {
323
+ return { success: false, message: 'No authenticated user found.' };
791
324
  }
792
325
  try {
793
- const user = this.auth.currentUser;
794
- // Reauthenticate if password provided
795
- if (currentPassword) {
796
- await this.reauthenticateUser(currentPassword);
797
- }
798
- // Delete user data from Firestore first (if available)
326
+ const user = auth.currentUser;
327
+ if (currentPassword)
328
+ await this.reauthenticate(currentPassword);
329
+ // Soft-delete record in Firestore before removing auth
799
330
  if (this.firestore) {
800
331
  try {
801
- const userRef = doc(this.firestore, 'users', user.uid);
802
- await setDoc(userRef, { deleted: true, deletedAt: serverTimestamp() }, { merge: true });
332
+ await setDoc(doc(this.firestore, 'users', user.uid), { deleted: true, deletedAt: serverTimestamp() }, { merge: true });
803
333
  }
804
- catch (firestoreError) {
805
- console.warn('Failed to update Firestore before account deletion:', firestoreError);
334
+ catch {
335
+ // Non-blocking
806
336
  }
807
337
  }
808
- // Delete the user account
809
338
  await deleteUser(user);
810
- return {
811
- success: true,
812
- message: 'Account successfully deleted.'
813
- };
339
+ return { success: true, message: 'Account successfully deleted.' };
814
340
  }
815
341
  catch (error) {
816
- return {
817
- success: false,
818
- message: error.message || 'Failed to delete account.'
819
- };
342
+ const err = error;
343
+ return { success: false, message: err.message ?? 'Failed to delete account.' };
820
344
  }
821
345
  }
822
- /**
823
- * Signs out the current user
824
- * @returns {Promise<void>} Promise that resolves when sign-out completes
825
- * @throws {FirekitAuthError} If sign-out fails
826
- *
827
- * @example
828
- * ```typescript
829
- * await firekitAuth.signOut();
830
- * console.log("User signed out");
831
- * ```
832
- */
833
- async signOut() {
834
- if (!this.auth) {
835
- throw new Error('Auth instance not available');
346
+ // ─── Reauthentication ────────────────────────────────────────────────────────
347
+ async reauthenticate(currentPassword) {
348
+ const auth = this.getAuth();
349
+ if (!auth.currentUser?.email) {
350
+ throw new FirekitAuthError('auth/no-current-user', 'No authenticated user with email found.');
836
351
  }
837
352
  try {
838
- // Set presence offline before signing out
839
- try {
840
- if (firekitPresence.initialized) {
841
- await firekitPresence.setPresence('offline');
842
- }
843
- }
844
- catch (presenceError) {
845
- console.warn('Failed to set presence offline during sign out:', presenceError);
846
- }
847
- // Clear reCAPTCHA verifiers
848
- this.recaptchaVerifiers.forEach((verifier) => verifier.clear());
849
- this.recaptchaVerifiers.clear();
850
- await signOut(this.auth);
353
+ const credential = EmailAuthProvider.credential(auth.currentUser.email, currentPassword);
354
+ await reauthenticateWithCredential(auth.currentUser, credential);
851
355
  }
852
356
  catch (error) {
853
- this.handleAuthError(error);
357
+ handleAuthError(error);
854
358
  }
855
359
  }
856
- // ========================================
857
- // UTILITY METHODS
858
- // ========================================
859
- /**
860
- * Checks if user is authenticated
861
- * @returns {boolean} True if user is authenticated
862
- */
863
- isAuthenticated() {
864
- return this.authState.user !== null && !this.authState.user.isAnonymous;
360
+ // ─── Custom token ────────────────────────────────────────────────────────────
361
+ async signInWithCustomToken(token) {
362
+ try {
363
+ const cred = await firebaseSignInWithCustomToken(this.getAuth(), token);
364
+ await this.syncToFirestore(cred.user);
365
+ const profile = this.profile(cred.user);
366
+ const isNewUser = getAdditionalUserInfo(cred)?.isNewUser ?? false;
367
+ return {
368
+ success: true,
369
+ user: profile,
370
+ method: 'custom',
371
+ timestamp: new Date(),
372
+ isNewUser
373
+ };
374
+ }
375
+ catch (error) {
376
+ handleAuthError(error);
377
+ }
378
+ }
379
+ // ─── SAML / OIDC ─────────────────────────────────────────────────────────────
380
+ /** Signs in with a SAML provider (popup). */
381
+ async signInWithSAML(providerId) {
382
+ return this.signInWithOAuth('saml', new SAMLAuthProvider(providerId));
383
+ }
384
+ /** Signs in with a SAML provider (redirect). Pair with `getRedirectResult()` on load. */
385
+ async signInWithSAMLRedirect(providerId) {
386
+ await signInWithRedirect(this.getAuth(), new SAMLAuthProvider(providerId));
865
387
  }
866
388
  /**
867
- * Checks if user is anonymous
868
- * @returns {boolean} True if user is anonymous
389
+ * Signs in with a generic OIDC/OAuth2 provider (popup).
390
+ * @param providerId Firebase provider ID, e.g. `'oidc.my-provider'`
391
+ * @param scopes Additional OAuth scopes to request.
869
392
  */
870
- isAnonymous() {
871
- return this.authState.user?.isAnonymous ?? false;
393
+ async signInWithOIDC(providerId, scopes = []) {
394
+ const provider = new OAuthProvider(providerId);
395
+ scopes.forEach((s) => provider.addScope(s));
396
+ return this.signInWithOAuth('oidc', provider);
397
+ }
398
+ /** Signs in with a generic OIDC/OAuth2 provider (redirect). Pair with `getRedirectResult()` on load. */
399
+ async signInWithOIDCRedirect(providerId, scopes = []) {
400
+ const provider = new OAuthProvider(providerId);
401
+ scopes.forEach((s) => provider.addScope(s));
402
+ await signInWithRedirect(this.getAuth(), provider);
403
+ }
404
+ // ─── Redirect sign-in ────────────────────────────────────────────────────────
405
+ async signInWithGoogleRedirect() {
406
+ await signInWithRedirect(this.getAuth(), createGoogleProvider());
407
+ }
408
+ async signInWithFacebookRedirect() {
409
+ await signInWithRedirect(this.getAuth(), createFacebookProvider());
410
+ }
411
+ async signInWithAppleRedirect() {
412
+ await signInWithRedirect(this.getAuth(), createAppleProvider());
413
+ }
414
+ async signInWithGithubRedirect() {
415
+ await signInWithRedirect(this.getAuth(), createGithubProvider());
416
+ }
417
+ async signInWithTwitterRedirect() {
418
+ await signInWithRedirect(this.getAuth(), createTwitterProvider());
419
+ }
420
+ async signInWithMicrosoftRedirect() {
421
+ await signInWithRedirect(this.getAuth(), createMicrosoftProvider());
872
422
  }
873
423
  /**
874
- * Checks if user's email is verified
875
- * @returns {boolean} True if email is verified
424
+ * Completes a redirect sign-in flow.
425
+ * Call this once on app load to pick up the result of a `signInWith*Redirect()` call.
426
+ * Returns null if no redirect sign-in is pending.
876
427
  */
877
- isEmailVerified() {
878
- return this.authState.user?.emailVerified ?? false;
428
+ async getRedirectResult() {
429
+ // Firebase returns provider IDs in the form 'google.com', 'github.com', etc.
430
+ // Map them to our OAuthProviderType format.
431
+ const PROVIDER_ID_MAP = {
432
+ 'google.com': 'google',
433
+ 'facebook.com': 'facebook',
434
+ 'apple.com': 'apple',
435
+ 'microsoft.com': 'microsoft',
436
+ 'github.com': 'github',
437
+ 'twitter.com': 'twitter'
438
+ };
439
+ try {
440
+ const result = await getRedirectResult(this.getAuth());
441
+ if (!result)
442
+ return null;
443
+ await this.syncToFirestore(result.user);
444
+ const profile = this.profile(result.user);
445
+ const isNewUser = getAdditionalUserInfo(result)?.isNewUser ?? false;
446
+ const rawId = result.providerId ?? '';
447
+ const provider = PROVIDER_ID_MAP[rawId] ??
448
+ (rawId.startsWith('saml.') ? 'saml' : rawId.startsWith('oidc.') ? 'oidc' : 'google');
449
+ return {
450
+ success: true,
451
+ user: profile,
452
+ method: provider,
453
+ timestamp: new Date(),
454
+ isNewUser,
455
+ provider
456
+ };
457
+ }
458
+ catch (error) {
459
+ handleAuthError(error);
460
+ }
879
461
  }
462
+ // ─── Multi-factor authentication ─────────────────────────────────────────────
880
463
  /**
881
- * Gets user's email address
882
- * @returns {string | null} User's email or null
464
+ * Starts phone MFA enrollment for the currently signed-in user.
465
+ * Returns a `verificationId` to pass to `completeMFAEnrollment()`.
883
466
  */
884
- getUserEmail() {
885
- return this.authState.user?.email ?? null;
467
+ async startPhoneMFAEnrollment(phoneNumber, recaptchaContainerId) {
468
+ const auth = this.getAuth();
469
+ if (!auth.currentUser) {
470
+ throw new FirekitAuthError('auth/no-current-user', 'No authenticated user found.');
471
+ }
472
+ const existing = this.recaptchaVerifiers.get(recaptchaContainerId);
473
+ if (existing) {
474
+ existing.clear();
475
+ this.recaptchaVerifiers.delete(recaptchaContainerId);
476
+ }
477
+ const verifier = new RecaptchaVerifier(auth, recaptchaContainerId, { size: 'invisible' });
478
+ this.recaptchaVerifiers.set(recaptchaContainerId, verifier);
479
+ const mfaUser = multiFactor(auth.currentUser);
480
+ const session = await mfaUser.getSession();
481
+ const phoneProvider = new PhoneAuthProvider(auth);
482
+ return phoneProvider.verifyPhoneNumber({ phoneNumber, session }, verifier);
886
483
  }
887
484
  /**
888
- * Gets user's display name
889
- * @returns {string | null} User's display name or null
485
+ * Completes phone MFA enrollment using the SMS code.
890
486
  */
891
- getUserDisplayName() {
892
- return this.authState.user?.displayName ?? null;
487
+ async completeMFAEnrollment(verificationId, code, displayName) {
488
+ const auth = this.getAuth();
489
+ if (!auth.currentUser) {
490
+ throw new FirekitAuthError('auth/no-current-user', 'No authenticated user found.');
491
+ }
492
+ const credential = PhoneAuthProvider.credential(verificationId, code);
493
+ const assertion = PhoneMultiFactorGenerator.assertion(credential);
494
+ await multiFactor(auth.currentUser).enroll(assertion, displayName);
495
+ }
496
+ /** Returns all enrolled MFA factors for the currently signed-in user. */
497
+ getMFAEnrolledFactors() {
498
+ const auth = this.getAuth();
499
+ if (!auth.currentUser)
500
+ return [];
501
+ return multiFactor(auth.currentUser).enrolledFactors;
502
+ }
503
+ /** Unenrolls a specific MFA factor by its UID or `MultiFactorInfo` object. */
504
+ async unenrollMFA(factorUidOrInfo) {
505
+ const auth = this.getAuth();
506
+ if (!auth.currentUser) {
507
+ throw new FirekitAuthError('auth/no-current-user', 'No authenticated user found.');
508
+ }
509
+ await multiFactor(auth.currentUser).unenroll(factorUidOrInfo);
893
510
  }
894
511
  /**
895
- * Gets user's photo URL
896
- * @returns {string | null} User's photo URL or null
512
+ * Gets the `MultiFactorResolver` from a sign-in error that requires MFA.
513
+ * Catch this error from any `signIn*` method when MFA is required.
897
514
  */
898
- getUserPhotoURL() {
899
- return this.authState.user?.photoURL ?? null;
515
+ getMFAResolver(error) {
516
+ return getMultiFactorResolver(this.getAuth(), error);
900
517
  }
901
518
  /**
902
- * Gets user's unique ID
903
- * @returns {string | null} User's UID or null
519
+ * Sends an SMS code to complete an MFA sign-in challenge.
520
+ * Returns a `verificationId` to pass to `completeMFASignIn()`.
521
+ *
522
+ * @param resolver From `getMFAResolver(error)`.
523
+ * @param factorIndex Index into `resolver.hints` (default 0).
524
+ * @param recaptchaContainerId DOM container ID for reCAPTCHA (required for phone MFA).
904
525
  */
905
- getUserId() {
906
- return this.authState.user?.uid ?? null;
526
+ async startMFASignIn(resolver, factorIndex = 0, recaptchaContainerId) {
527
+ const auth = this.getAuth();
528
+ const existing = this.recaptchaVerifiers.get(recaptchaContainerId);
529
+ if (existing) {
530
+ existing.clear();
531
+ this.recaptchaVerifiers.delete(recaptchaContainerId);
532
+ }
533
+ const verifier = new RecaptchaVerifier(auth, recaptchaContainerId, { size: 'invisible' });
534
+ this.recaptchaVerifiers.set(recaptchaContainerId, verifier);
535
+ const hint = resolver.hints[factorIndex];
536
+ const phoneProvider = new PhoneAuthProvider(auth);
537
+ return phoneProvider.verifyPhoneNumber({ multiFactorHint: hint, session: resolver.session }, verifier);
907
538
  }
908
539
  /**
909
- * Cleans up resources and listeners
910
- * @returns {Promise<void>} Promise that resolves when cleanup completes
540
+ * Completes MFA sign-in using the SMS code.
911
541
  */
542
+ async completeMFASignIn(resolver, verificationId, code) {
543
+ const credential = PhoneAuthProvider.credential(verificationId, code);
544
+ const assertion = PhoneMultiFactorGenerator.assertion(credential);
545
+ try {
546
+ const cred = await resolver.resolveSignIn(assertion);
547
+ await this.syncToFirestore(cred.user);
548
+ const profile = this.profile(cred.user);
549
+ return {
550
+ success: true,
551
+ user: profile,
552
+ method: 'phone',
553
+ timestamp: new Date(),
554
+ isNewUser: false
555
+ };
556
+ }
557
+ catch (error) {
558
+ handleAuthError(error);
559
+ }
560
+ }
561
+ // ─── Utility getters ─────────────────────────────────────────────────────────
562
+ getCurrentUser() {
563
+ return this.auth?.currentUser ?? null;
564
+ }
565
+ isAuthenticated() {
566
+ return this.auth?.currentUser !== null && !this.auth?.currentUser?.isAnonymous;
567
+ }
568
+ isAnonymous() {
569
+ return this.auth?.currentUser?.isAnonymous ?? false;
570
+ }
571
+ isEmailVerified() {
572
+ return this.auth?.currentUser?.emailVerified ?? false;
573
+ }
912
574
  async cleanup() {
913
- // Clear reCAPTCHA verifiers
914
- this.recaptchaVerifiers.forEach((verifier) => verifier.clear());
575
+ this.recaptchaVerifiers.forEach((v) => v.clear());
915
576
  this.recaptchaVerifiers.clear();
916
- // Clear state listeners
917
- this.stateListeners.clear();
918
577
  }
919
578
  }
920
- /**
921
- * Pre-initialized singleton instance of FirekitAuth.
922
- * This is the main export that should be used throughout your application.
923
- *
924
- * @example
925
- * ```typescript
926
- * import { firekitAuth } from 'svelte-firekit';
927
- *
928
- * // Sign in with email
929
- * await firekitAuth.signInWithEmail("user@example.com", "password");
930
- *
931
- * // Listen to auth state
932
- * const unsubscribe = firekitAuth.onAuthStateChanged((state) => {
933
- * if (state.user) {
934
- * console.log("User is signed in:", state.user.email);
935
- * } else {
936
- * console.log("User is signed out");
937
- * }
938
- * });
939
- *
940
- * // Clean up listener
941
- * unsubscribe();
942
- * ```
943
- */
944
579
  export const firekitAuth = FirekitAuth.getInstance();