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