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.
- package/README.md +550 -354
- package/dist/components/AuthGuard.svelte +64 -0
- package/dist/components/AuthGuard.svelte.d.ts +15 -0
- package/dist/components/Collection.svelte +62 -0
- package/dist/components/Collection.svelte.d.ts +39 -0
- package/dist/components/CustomGuard.svelte +87 -0
- package/dist/components/CustomGuard.svelte.d.ts +13 -0
- package/dist/components/Doc.svelte +56 -0
- package/dist/components/Doc.svelte.d.ts +36 -0
- package/dist/components/DownloadURL.svelte +48 -0
- package/dist/components/DownloadURL.svelte.d.ts +14 -0
- package/dist/components/FirebaseApp.svelte +81 -0
- package/dist/components/FirebaseApp.svelte.d.ts +12 -0
- package/dist/components/Node.svelte +54 -0
- package/dist/components/Node.svelte.d.ts +36 -0
- package/dist/components/SignedIn.svelte +22 -0
- package/dist/components/{firekit/signed-in.svelte.d.ts → SignedIn.svelte.d.ts} +1 -4
- package/dist/components/SignedOut.svelte +32 -0
- package/dist/components/{firekit/signed-out.svelte.d.ts → SignedOut.svelte.d.ts} +3 -5
- package/dist/components/UploadTask.svelte +75 -0
- package/dist/components/UploadTask.svelte.d.ts +33 -0
- package/dist/config.d.ts +29 -6
- package/dist/config.js +37 -74
- package/dist/context.d.ts +46 -0
- package/dist/context.js +56 -0
- package/dist/firebase.d.ts +25 -84
- package/dist/firebase.js +75 -125
- package/dist/index.d.ts +31 -20
- package/dist/index.js +47 -30
- package/dist/services/ai.svelte.d.ts +152 -0
- package/dist/services/ai.svelte.js +302 -0
- package/dist/services/analytics.d.ts +39 -231
- package/dist/services/analytics.js +89 -421
- package/dist/services/app-check.svelte.d.ts +82 -0
- package/dist/services/app-check.svelte.js +159 -0
- package/dist/services/auth.d.ts +63 -352
- package/dist/services/auth.js +353 -718
- package/dist/services/bundles.d.ts +42 -0
- package/dist/services/bundles.js +57 -0
- package/dist/services/callable.d.ts +57 -0
- package/dist/services/callable.js +115 -0
- package/dist/services/collection.svelte.d.ts +154 -221
- package/dist/services/collection.svelte.js +357 -663
- package/dist/services/document.svelte.d.ts +73 -254
- package/dist/services/document.svelte.js +196 -497
- package/dist/services/in-app-messaging.js +4 -0
- package/dist/services/messaging.svelte.d.ts +75 -0
- package/dist/services/messaging.svelte.js +190 -0
- package/dist/services/mutations.d.ts +59 -282
- package/dist/services/mutations.js +202 -951
- package/dist/services/performance.d.ts +60 -0
- package/dist/services/performance.js +118 -0
- package/dist/services/presence.svelte.d.ts +21 -89
- package/dist/services/presence.svelte.js +232 -469
- package/dist/services/realtime.svelte.d.ts +54 -125
- package/dist/services/realtime.svelte.js +111 -175
- package/dist/services/remote-config.svelte.d.ts +73 -0
- package/dist/services/remote-config.svelte.js +204 -0
- package/dist/services/storage.svelte.d.ts +81 -208
- package/dist/services/storage.svelte.js +190 -305
- package/dist/services/user.svelte.d.ts +23 -244
- package/dist/services/user.svelte.js +129 -439
- package/dist/types/analytics.d.ts +2 -36
- package/dist/types/analytics.js +0 -5
- package/dist/types/auth.d.ts +15 -85
- package/dist/types/auth.js +0 -17
- package/dist/types/collection.d.ts +31 -225
- package/dist/types/collection.js +5 -51
- package/dist/types/document.d.ts +11 -236
- package/dist/types/document.js +2 -47
- package/dist/types/firebase.d.ts +10 -13
- package/dist/types/firebase.js +3 -9
- package/dist/types/index.d.ts +5 -5
- package/dist/types/index.js +5 -4
- package/dist/types/mutations.d.ts +11 -225
- package/dist/types/mutations.js +6 -51
- package/dist/types/presence.d.ts +5 -158
- package/dist/types/presence.js +0 -20
- package/dist/utils/errors.d.ts +10 -14
- package/dist/utils/errors.js +11 -16
- package/dist/utils/firestore.d.ts +3 -4
- package/dist/utils/firestore.js +7 -10
- package/dist/utils/index.d.ts +4 -4
- package/dist/utils/index.js +4 -8
- package/dist/utils/providers.d.ts +4 -13
- package/dist/utils/providers.js +14 -13
- package/dist/utils/user.d.ts +1 -3
- package/dist/utils/user.js +1 -3
- package/package.json +41 -55
- package/dist/components/docs/doc-content.svelte +0 -19
- package/dist/components/docs/doc-content.svelte.d.ts +0 -6
- package/dist/components/docs/doc-header.svelte +0 -24
- package/dist/components/docs/doc-header.svelte.d.ts +0 -13
- package/dist/components/docs/doc-renderer.svelte +0 -27
- package/dist/components/docs/doc-renderer.svelte.d.ts +0 -8
- package/dist/components/docs/mobile-table-of-contents.svelte +0 -42
- package/dist/components/docs/mobile-table-of-contents.svelte.d.ts +0 -3
- package/dist/components/docs/table-of-contents.svelte +0 -33
- package/dist/components/docs/table-of-contents.svelte.d.ts +0 -4
- package/dist/components/docs/toc.svelte.d.ts +0 -16
- package/dist/components/docs/toc.svelte.js +0 -59
- package/dist/components/firekit/Collection.svelte +0 -122
- package/dist/components/firekit/Collection.svelte.d.ts +0 -27
- package/dist/components/firekit/Doc.svelte +0 -140
- package/dist/components/firekit/Doc.svelte.d.ts +0 -28
- package/dist/components/firekit/Node.svelte +0 -97
- package/dist/components/firekit/Node.svelte.d.ts +0 -23
- package/dist/components/firekit/auth-guard.svelte +0 -120
- package/dist/components/firekit/auth-guard.svelte.d.ts +0 -26
- package/dist/components/firekit/custom-guard.svelte +0 -163
- package/dist/components/firekit/custom-guard.svelte.d.ts +0 -31
- package/dist/components/firekit/download-url.svelte +0 -92
- package/dist/components/firekit/download-url.svelte.d.ts +0 -19
- package/dist/components/firekit/firebase-app.svelte +0 -33
- package/dist/components/firekit/firebase-app.svelte.d.ts +0 -7
- package/dist/components/firekit/node-list.svelte +0 -102
- package/dist/components/firekit/node-list.svelte.d.ts +0 -27
- package/dist/components/firekit/signed-in.svelte +0 -42
- package/dist/components/firekit/signed-out.svelte +0 -42
- package/dist/components/firekit/storage-list.svelte +0 -97
- package/dist/components/firekit/storage-list.svelte.d.ts +0 -26
- package/dist/components/firekit/upload-task.svelte +0 -108
- package/dist/components/firekit/upload-task.svelte.d.ts +0 -24
- package/dist/components/nav/app-sidebar.svelte +0 -175
- package/dist/components/nav/app-sidebar.svelte.d.ts +0 -9
- package/dist/components/nav/auto-breadcrumb.svelte +0 -41
- package/dist/components/nav/auto-breadcrumb.svelte.d.ts +0 -3
- package/dist/components/nav/dark-mode-toggle.svelte +0 -17
- package/dist/components/nav/dark-mode-toggle.svelte.d.ts +0 -18
- package/dist/components/nav/nav-components.svelte +0 -24
- package/dist/components/nav/nav-components.svelte.d.ts +0 -11
- package/dist/components/nav/nav-main.svelte +0 -45
- package/dist/components/nav/nav-main.svelte.d.ts +0 -11
- package/dist/components/nav/nav-secondary.svelte +0 -32
- package/dist/components/nav/nav-secondary.svelte.d.ts +0 -14
- package/dist/components/nav/site-header.svelte +0 -32
- package/dist/components/nav/site-header.svelte.d.ts +0 -18
- package/dist/components/ui/avatar/avatar-fallback.svelte +0 -17
- package/dist/components/ui/avatar/avatar-fallback.svelte.d.ts +0 -4
- package/dist/components/ui/avatar/avatar-image.svelte +0 -17
- package/dist/components/ui/avatar/avatar-image.svelte.d.ts +0 -4
- package/dist/components/ui/avatar/avatar.svelte +0 -19
- package/dist/components/ui/avatar/avatar.svelte.d.ts +0 -4
- package/dist/components/ui/avatar/index.d.ts +0 -4
- package/dist/components/ui/avatar/index.js +0 -6
- package/dist/components/ui/badge/badge.svelte +0 -50
- package/dist/components/ui/badge/badge.svelte.d.ts +0 -32
- package/dist/components/ui/badge/index.d.ts +0 -2
- package/dist/components/ui/badge/index.js +0 -2
- package/dist/components/ui/breadcrumb/breadcrumb-ellipsis.svelte +0 -23
- package/dist/components/ui/breadcrumb/breadcrumb-ellipsis.svelte.d.ts +0 -5
- package/dist/components/ui/breadcrumb/breadcrumb-item.svelte +0 -20
- package/dist/components/ui/breadcrumb/breadcrumb-item.svelte.d.ts +0 -5
- package/dist/components/ui/breadcrumb/breadcrumb-link.svelte +0 -31
- package/dist/components/ui/breadcrumb/breadcrumb-link.svelte.d.ts +0 -11
- package/dist/components/ui/breadcrumb/breadcrumb-list.svelte +0 -23
- package/dist/components/ui/breadcrumb/breadcrumb-list.svelte.d.ts +0 -5
- package/dist/components/ui/breadcrumb/breadcrumb-page.svelte +0 -23
- package/dist/components/ui/breadcrumb/breadcrumb-page.svelte.d.ts +0 -5
- package/dist/components/ui/breadcrumb/breadcrumb-separator.svelte +0 -27
- package/dist/components/ui/breadcrumb/breadcrumb-separator.svelte.d.ts +0 -5
- package/dist/components/ui/breadcrumb/breadcrumb.svelte +0 -21
- package/dist/components/ui/breadcrumb/breadcrumb.svelte.d.ts +0 -5
- package/dist/components/ui/breadcrumb/index.d.ts +0 -8
- package/dist/components/ui/breadcrumb/index.js +0 -10
- package/dist/components/ui/button/button.svelte +0 -80
- package/dist/components/ui/button/button.svelte.d.ts +0 -58
- package/dist/components/ui/button/index.d.ts +0 -2
- package/dist/components/ui/button/index.js +0 -4
- package/dist/components/ui/card/card-action.svelte +0 -20
- package/dist/components/ui/card/card-action.svelte.d.ts +0 -5
- package/dist/components/ui/card/card-content.svelte +0 -15
- package/dist/components/ui/card/card-content.svelte.d.ts +0 -5
- package/dist/components/ui/card/card-description.svelte +0 -20
- package/dist/components/ui/card/card-description.svelte.d.ts +0 -5
- package/dist/components/ui/card/card-footer.svelte +0 -20
- package/dist/components/ui/card/card-footer.svelte.d.ts +0 -5
- package/dist/components/ui/card/card-header.svelte +0 -23
- package/dist/components/ui/card/card-header.svelte.d.ts +0 -5
- package/dist/components/ui/card/card-title.svelte +0 -20
- package/dist/components/ui/card/card-title.svelte.d.ts +0 -5
- package/dist/components/ui/card/card.svelte +0 -23
- package/dist/components/ui/card/card.svelte.d.ts +0 -5
- package/dist/components/ui/card/index.d.ts +0 -8
- package/dist/components/ui/card/index.js +0 -10
- package/dist/components/ui/chart/chart-container.svelte +0 -80
- package/dist/components/ui/chart/chart-container.svelte.d.ts +0 -9
- package/dist/components/ui/chart/chart-style.svelte +0 -36
- package/dist/components/ui/chart/chart-style.svelte.d.ts +0 -8
- package/dist/components/ui/chart/chart-tooltip.svelte +0 -159
- package/dist/components/ui/chart/chart-tooltip.svelte.d.ts +0 -27
- package/dist/components/ui/chart/chart-utils.d.ts +0 -36
- package/dist/components/ui/chart/chart-utils.js +0 -33
- package/dist/components/ui/chart/index.d.ts +0 -4
- package/dist/components/ui/chart/index.js +0 -4
- package/dist/components/ui/checkbox/checkbox.svelte +0 -36
- package/dist/components/ui/checkbox/checkbox.svelte.d.ts +0 -4
- package/dist/components/ui/checkbox/index.d.ts +0 -2
- package/dist/components/ui/checkbox/index.js +0 -4
- package/dist/components/ui/data-table/data-table.svelte.d.ts +0 -40
- package/dist/components/ui/data-table/data-table.svelte.js +0 -110
- package/dist/components/ui/data-table/flex-render.svelte +0 -36
- package/dist/components/ui/data-table/flex-render.svelte.d.ts +0 -30
- package/dist/components/ui/data-table/index.d.ts +0 -3
- package/dist/components/ui/data-table/index.js +0 -3
- package/dist/components/ui/data-table/render-helpers.d.ts +0 -90
- package/dist/components/ui/data-table/render-helpers.js +0 -99
- package/dist/components/ui/dialog/dialog-close.svelte +0 -7
- package/dist/components/ui/dialog/dialog-close.svelte.d.ts +0 -4
- package/dist/components/ui/dialog/dialog-content.svelte +0 -43
- package/dist/components/ui/dialog/dialog-content.svelte.d.ts +0 -11
- package/dist/components/ui/dialog/dialog-description.svelte +0 -17
- package/dist/components/ui/dialog/dialog-description.svelte.d.ts +0 -4
- package/dist/components/ui/dialog/dialog-footer.svelte +0 -20
- package/dist/components/ui/dialog/dialog-footer.svelte.d.ts +0 -5
- package/dist/components/ui/dialog/dialog-header.svelte +0 -20
- package/dist/components/ui/dialog/dialog-header.svelte.d.ts +0 -5
- package/dist/components/ui/dialog/dialog-overlay.svelte +0 -20
- package/dist/components/ui/dialog/dialog-overlay.svelte.d.ts +0 -4
- package/dist/components/ui/dialog/dialog-title.svelte +0 -17
- package/dist/components/ui/dialog/dialog-title.svelte.d.ts +0 -4
- package/dist/components/ui/dialog/dialog-trigger.svelte +0 -7
- package/dist/components/ui/dialog/dialog-trigger.svelte.d.ts +0 -4
- package/dist/components/ui/dialog/index.d.ts +0 -11
- package/dist/components/ui/dialog/index.js +0 -14
- package/dist/components/ui/drawer/drawer-close.svelte +0 -7
- package/dist/components/ui/drawer/drawer-close.svelte.d.ts +0 -4
- package/dist/components/ui/drawer/drawer-content.svelte +0 -37
- package/dist/components/ui/drawer/drawer-content.svelte.d.ts +0 -7
- package/dist/components/ui/drawer/drawer-description.svelte +0 -17
- package/dist/components/ui/drawer/drawer-description.svelte.d.ts +0 -4
- package/dist/components/ui/drawer/drawer-footer.svelte +0 -20
- package/dist/components/ui/drawer/drawer-footer.svelte.d.ts +0 -5
- package/dist/components/ui/drawer/drawer-header.svelte +0 -20
- package/dist/components/ui/drawer/drawer-header.svelte.d.ts +0 -5
- package/dist/components/ui/drawer/drawer-nested.svelte +0 -12
- package/dist/components/ui/drawer/drawer-nested.svelte.d.ts +0 -3
- package/dist/components/ui/drawer/drawer-overlay.svelte +0 -20
- package/dist/components/ui/drawer/drawer-overlay.svelte.d.ts +0 -4
- package/dist/components/ui/drawer/drawer-title.svelte +0 -17
- package/dist/components/ui/drawer/drawer-title.svelte.d.ts +0 -4
- package/dist/components/ui/drawer/drawer-trigger.svelte +0 -7
- package/dist/components/ui/drawer/drawer-trigger.svelte.d.ts +0 -4
- package/dist/components/ui/drawer/drawer.svelte +0 -12
- package/dist/components/ui/drawer/drawer.svelte.d.ts +0 -3
- package/dist/components/ui/drawer/index.d.ts +0 -13
- package/dist/components/ui/drawer/index.js +0 -15
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +0 -41
- package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +0 -9
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +0 -27
- package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte.d.ts +0 -7
- package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +0 -22
- package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +0 -8
- package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte +0 -7
- package/dist/components/ui/dropdown-menu/dropdown-menu-group.svelte.d.ts +0 -4
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +0 -27
- package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +0 -8
- package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +0 -24
- package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte.d.ts +0 -8
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +0 -16
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte.d.ts +0 -4
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +0 -31
- package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +0 -4
- package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +0 -17
- package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte.d.ts +0 -4
- package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +0 -20
- package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +0 -5
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +0 -20
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +0 -4
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +0 -29
- package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +0 -7
- package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +0 -7
- package/dist/components/ui/dropdown-menu/dropdown-menu-trigger.svelte.d.ts +0 -4
- package/dist/components/ui/dropdown-menu/index.d.ts +0 -25
- package/dist/components/ui/dropdown-menu/index.js +0 -17
- package/dist/components/ui/input/index.d.ts +0 -2
- package/dist/components/ui/input/index.js +0 -4
- package/dist/components/ui/input/input.svelte +0 -51
- package/dist/components/ui/input/input.svelte.d.ts +0 -13
- package/dist/components/ui/label/index.d.ts +0 -2
- package/dist/components/ui/label/index.js +0 -4
- package/dist/components/ui/label/label.svelte +0 -20
- package/dist/components/ui/label/label.svelte.d.ts +0 -4
- package/dist/components/ui/scroll-area/index.d.ts +0 -3
- package/dist/components/ui/scroll-area/index.js +0 -5
- package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte +0 -31
- package/dist/components/ui/scroll-area/scroll-area-scrollbar.svelte.d.ts +0 -4
- package/dist/components/ui/scroll-area/scroll-area.svelte +0 -40
- package/dist/components/ui/scroll-area/scroll-area.svelte.d.ts +0 -10
- package/dist/components/ui/select/index.d.ts +0 -11
- package/dist/components/ui/select/index.js +0 -14
- package/dist/components/ui/select/select-content.svelte +0 -40
- package/dist/components/ui/select/select-content.svelte.d.ts +0 -8
- package/dist/components/ui/select/select-group-heading.svelte +0 -21
- package/dist/components/ui/select/select-group-heading.svelte.d.ts +0 -10
- package/dist/components/ui/select/select-group.svelte +0 -7
- package/dist/components/ui/select/select-group.svelte.d.ts +0 -4
- package/dist/components/ui/select/select-item.svelte +0 -38
- package/dist/components/ui/select/select-item.svelte.d.ts +0 -4
- package/dist/components/ui/select/select-label.svelte +0 -20
- package/dist/components/ui/select/select-label.svelte.d.ts +0 -6
- package/dist/components/ui/select/select-scroll-down-button.svelte +0 -20
- package/dist/components/ui/select/select-scroll-down-button.svelte.d.ts +0 -4
- package/dist/components/ui/select/select-scroll-up-button.svelte +0 -20
- package/dist/components/ui/select/select-scroll-up-button.svelte.d.ts +0 -4
- package/dist/components/ui/select/select-separator.svelte +0 -18
- package/dist/components/ui/select/select-separator.svelte.d.ts +0 -4
- package/dist/components/ui/select/select-trigger.svelte +0 -29
- package/dist/components/ui/select/select-trigger.svelte.d.ts +0 -8
- package/dist/components/ui/separator/index.d.ts +0 -2
- package/dist/components/ui/separator/index.js +0 -4
- package/dist/components/ui/separator/separator.svelte +0 -20
- package/dist/components/ui/separator/separator.svelte.d.ts +0 -4
- package/dist/components/ui/sheet/index.d.ts +0 -11
- package/dist/components/ui/sheet/index.js +0 -14
- package/dist/components/ui/sheet/sheet-close.svelte +0 -7
- package/dist/components/ui/sheet/sheet-close.svelte.d.ts +0 -4
- package/dist/components/ui/sheet/sheet-content.svelte +0 -58
- package/dist/components/ui/sheet/sheet-content.svelte.d.ts +0 -35
- package/dist/components/ui/sheet/sheet-description.svelte +0 -17
- package/dist/components/ui/sheet/sheet-description.svelte.d.ts +0 -4
- package/dist/components/ui/sheet/sheet-footer.svelte +0 -20
- package/dist/components/ui/sheet/sheet-footer.svelte.d.ts +0 -5
- package/dist/components/ui/sheet/sheet-header.svelte +0 -20
- package/dist/components/ui/sheet/sheet-header.svelte.d.ts +0 -5
- package/dist/components/ui/sheet/sheet-overlay.svelte +0 -20
- package/dist/components/ui/sheet/sheet-overlay.svelte.d.ts +0 -4
- package/dist/components/ui/sheet/sheet-title.svelte +0 -17
- package/dist/components/ui/sheet/sheet-title.svelte.d.ts +0 -4
- package/dist/components/ui/sheet/sheet-trigger.svelte +0 -7
- package/dist/components/ui/sheet/sheet-trigger.svelte.d.ts +0 -4
- package/dist/components/ui/sidebar/constants.d.ts +0 -6
- package/dist/components/ui/sidebar/constants.js +0 -6
- package/dist/components/ui/sidebar/context.svelte.d.ts +0 -42
- package/dist/components/ui/sidebar/context.svelte.js +0 -54
- package/dist/components/ui/sidebar/index.d.ts +0 -25
- package/dist/components/ui/sidebar/index.js +0 -27
- package/dist/components/ui/sidebar/sidebar-content.svelte +0 -24
- package/dist/components/ui/sidebar/sidebar-content.svelte.d.ts +0 -5
- package/dist/components/ui/sidebar/sidebar-footer.svelte +0 -21
- package/dist/components/ui/sidebar/sidebar-footer.svelte.d.ts +0 -5
- package/dist/components/ui/sidebar/sidebar-group-action.svelte +0 -36
- package/dist/components/ui/sidebar/sidebar-group-action.svelte.d.ts +0 -11
- package/dist/components/ui/sidebar/sidebar-group-content.svelte +0 -21
- package/dist/components/ui/sidebar/sidebar-group-content.svelte.d.ts +0 -5
- package/dist/components/ui/sidebar/sidebar-group-label.svelte +0 -34
- package/dist/components/ui/sidebar/sidebar-group-label.svelte.d.ts +0 -11
- package/dist/components/ui/sidebar/sidebar-group.svelte +0 -21
- package/dist/components/ui/sidebar/sidebar-group.svelte.d.ts +0 -5
- package/dist/components/ui/sidebar/sidebar-header.svelte +0 -21
- package/dist/components/ui/sidebar/sidebar-header.svelte.d.ts +0 -5
- package/dist/components/ui/sidebar/sidebar-input.svelte +0 -21
- package/dist/components/ui/sidebar/sidebar-input.svelte.d.ts +0 -11
- package/dist/components/ui/sidebar/sidebar-inset.svelte +0 -24
- package/dist/components/ui/sidebar/sidebar-inset.svelte.d.ts +0 -5
- package/dist/components/ui/sidebar/sidebar-menu-action.svelte +0 -43
- package/dist/components/ui/sidebar/sidebar-menu-action.svelte.d.ts +0 -12
- package/dist/components/ui/sidebar/sidebar-menu-badge.svelte +0 -29
- package/dist/components/ui/sidebar/sidebar-menu-badge.svelte.d.ts +0 -5
- package/dist/components/ui/sidebar/sidebar-menu-button.svelte +0 -103
- package/dist/components/ui/sidebar/sidebar-menu-button.svelte.d.ts +0 -51
- package/dist/components/ui/sidebar/sidebar-menu-item.svelte +0 -21
- package/dist/components/ui/sidebar/sidebar-menu-item.svelte.d.ts +0 -5
- package/dist/components/ui/sidebar/sidebar-menu-skeleton.svelte +0 -36
- package/dist/components/ui/sidebar/sidebar-menu-skeleton.svelte.d.ts +0 -8
- package/dist/components/ui/sidebar/sidebar-menu-sub-button.svelte +0 -43
- package/dist/components/ui/sidebar/sidebar-menu-sub-button.svelte.d.ts +0 -13
- package/dist/components/ui/sidebar/sidebar-menu-sub-item.svelte +0 -21
- package/dist/components/ui/sidebar/sidebar-menu-sub-item.svelte.d.ts +0 -5
- package/dist/components/ui/sidebar/sidebar-menu-sub.svelte +0 -25
- package/dist/components/ui/sidebar/sidebar-menu-sub.svelte.d.ts +0 -5
- package/dist/components/ui/sidebar/sidebar-menu.svelte +0 -21
- package/dist/components/ui/sidebar/sidebar-menu.svelte.d.ts +0 -5
- package/dist/components/ui/sidebar/sidebar-provider.svelte +0 -53
- package/dist/components/ui/sidebar/sidebar-provider.svelte.d.ts +0 -9
- package/dist/components/ui/sidebar/sidebar-rail.svelte +0 -36
- package/dist/components/ui/sidebar/sidebar-rail.svelte.d.ts +0 -5
- package/dist/components/ui/sidebar/sidebar-separator.svelte +0 -19
- package/dist/components/ui/sidebar/sidebar-separator.svelte.d.ts +0 -13
- package/dist/components/ui/sidebar/sidebar-trigger.svelte +0 -35
- package/dist/components/ui/sidebar/sidebar-trigger.svelte.d.ts +0 -8
- package/dist/components/ui/sidebar/sidebar.svelte +0 -104
- package/dist/components/ui/sidebar/sidebar.svelte.d.ts +0 -10
- package/dist/components/ui/skeleton/index.d.ts +0 -2
- package/dist/components/ui/skeleton/index.js +0 -4
- package/dist/components/ui/skeleton/skeleton.svelte +0 -17
- package/dist/components/ui/skeleton/skeleton.svelte.d.ts +0 -5
- package/dist/components/ui/table/index.d.ts +0 -9
- package/dist/components/ui/table/index.js +0 -11
- package/dist/components/ui/table/table-body.svelte +0 -20
- package/dist/components/ui/table/table-body.svelte.d.ts +0 -5
- package/dist/components/ui/table/table-caption.svelte +0 -20
- package/dist/components/ui/table/table-caption.svelte.d.ts +0 -5
- package/dist/components/ui/table/table-cell.svelte +0 -20
- package/dist/components/ui/table/table-cell.svelte.d.ts +0 -5
- package/dist/components/ui/table/table-footer.svelte +0 -20
- package/dist/components/ui/table/table-footer.svelte.d.ts +0 -5
- package/dist/components/ui/table/table-head.svelte +0 -23
- package/dist/components/ui/table/table-head.svelte.d.ts +0 -5
- package/dist/components/ui/table/table-header.svelte +0 -20
- package/dist/components/ui/table/table-header.svelte.d.ts +0 -5
- package/dist/components/ui/table/table-row.svelte +0 -23
- package/dist/components/ui/table/table-row.svelte.d.ts +0 -5
- package/dist/components/ui/table/table.svelte +0 -22
- package/dist/components/ui/table/table.svelte.d.ts +0 -5
- package/dist/components/ui/tabs/index.d.ts +0 -5
- package/dist/components/ui/tabs/index.js +0 -7
- package/dist/components/ui/tabs/tabs-content.svelte +0 -17
- package/dist/components/ui/tabs/tabs-content.svelte.d.ts +0 -4
- package/dist/components/ui/tabs/tabs-list.svelte +0 -20
- package/dist/components/ui/tabs/tabs-list.svelte.d.ts +0 -4
- package/dist/components/ui/tabs/tabs-trigger.svelte +0 -20
- package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +0 -4
- package/dist/components/ui/tabs/tabs.svelte +0 -19
- package/dist/components/ui/tabs/tabs.svelte.d.ts +0 -4
- package/dist/components/ui/toggle/index.d.ts +0 -3
- package/dist/components/ui/toggle/index.js +0 -5
- package/dist/components/ui/toggle/toggle.svelte +0 -52
- package/dist/components/ui/toggle/toggle.svelte.d.ts +0 -43
- package/dist/components/ui/toggle-group/index.d.ts +0 -3
- package/dist/components/ui/toggle-group/index.js +0 -5
- package/dist/components/ui/toggle-group/toggle-group-item.svelte +0 -34
- package/dist/components/ui/toggle-group/toggle-group-item.svelte.d.ts +0 -6
- package/dist/components/ui/toggle-group/toggle-group.svelte +0 -47
- package/dist/components/ui/toggle-group/toggle-group.svelte.d.ts +0 -8
- package/dist/components/ui/tooltip/index.d.ts +0 -7
- package/dist/components/ui/tooltip/index.js +0 -9
- package/dist/components/ui/tooltip/tooltip-content.svelte +0 -47
- package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +0 -7
- package/dist/components/ui/tooltip/tooltip-trigger.svelte +0 -7
- package/dist/components/ui/tooltip/tooltip-trigger.svelte.d.ts +0 -4
- package/dist/hooks/is-mobile.svelte.d.ts +0 -4
- package/dist/hooks/is-mobile.svelte.js +0 -7
- package/dist/services/index.d.ts +0 -9
- package/dist/services/index.js +0 -10
- package/dist/types/docs.d.ts +0 -67
- package/dist/utils.d.ts +0 -15
- package/dist/utils.js +0 -44
- /package/dist/{types/docs.js → services/in-app-messaging.d.ts} +0 -0
package/dist/services/auth.js
CHANGED
|
@@ -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
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
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
|
-
*
|
|
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
|
-
|
|
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
|
|
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
|
|
83
|
-
|
|
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
|
-
|
|
99
|
-
return;
|
|
49
|
+
this.auth = firebaseService.getAuthInstance();
|
|
100
50
|
}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
229
|
-
this.
|
|
230
|
-
const
|
|
231
|
-
|
|
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:
|
|
73
|
+
user: profile,
|
|
238
74
|
method: 'email',
|
|
239
75
|
timestamp: new Date(),
|
|
240
76
|
isNewUser,
|
|
241
|
-
requiresEmailVerification: !
|
|
77
|
+
requiresEmailVerification: !profile.emailVerified
|
|
242
78
|
};
|
|
243
79
|
}
|
|
244
80
|
catch (error) {
|
|
245
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
343
|
-
|
|
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.
|
|
347
|
-
this.
|
|
348
|
-
const
|
|
349
|
-
const
|
|
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:
|
|
357
|
-
method:
|
|
110
|
+
user: profile,
|
|
111
|
+
method: provider,
|
|
358
112
|
timestamp: new Date(),
|
|
359
113
|
isNewUser,
|
|
360
|
-
provider
|
|
114
|
+
provider
|
|
361
115
|
};
|
|
362
116
|
}
|
|
363
117
|
catch (error) {
|
|
364
|
-
|
|
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
|
-
|
|
389
|
-
this.
|
|
390
|
-
const
|
|
391
|
-
|
|
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:
|
|
129
|
+
user: profile,
|
|
398
130
|
method: 'anonymous',
|
|
399
131
|
timestamp: new Date(),
|
|
400
132
|
isNewUser
|
|
401
133
|
};
|
|
402
134
|
}
|
|
403
135
|
catch (error) {
|
|
404
|
-
|
|
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
|
-
|
|
426
|
-
throw new Error('Auth instance not available');
|
|
427
|
-
}
|
|
140
|
+
const auth = this.getAuth();
|
|
428
141
|
try {
|
|
429
|
-
this
|
|
430
|
-
this.
|
|
431
|
-
|
|
432
|
-
|
|
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
|
|
438
|
-
|
|
439
|
-
|
|
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:
|
|
450
|
-
confirm: async (
|
|
152
|
+
verificationId: confirmation.verificationId,
|
|
153
|
+
confirm: async (code) => {
|
|
451
154
|
try {
|
|
452
|
-
const
|
|
453
|
-
await this.
|
|
454
|
-
const
|
|
455
|
-
const
|
|
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:
|
|
161
|
+
user: profile,
|
|
460
162
|
method: 'phone',
|
|
461
163
|
timestamp: new Date(),
|
|
462
164
|
isNewUser
|
|
463
165
|
};
|
|
464
166
|
}
|
|
465
167
|
catch (error) {
|
|
466
|
-
|
|
168
|
+
handleAuthError(error);
|
|
467
169
|
}
|
|
468
170
|
finally {
|
|
469
|
-
|
|
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
|
-
|
|
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.
|
|
513
|
-
|
|
514
|
-
|
|
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
|
-
|
|
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:
|
|
194
|
+
user: profile,
|
|
529
195
|
method: 'email',
|
|
530
196
|
timestamp: new Date(),
|
|
531
197
|
emailVerificationSent: sendVerification,
|
|
532
|
-
requiresEmailVerification: !
|
|
198
|
+
requiresEmailVerification: !profile.emailVerified
|
|
533
199
|
};
|
|
534
200
|
}
|
|
535
201
|
catch (error) {
|
|
536
|
-
|
|
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
|
-
|
|
539
|
-
|
|
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.
|
|
219
|
+
await sendPasswordResetEmail(this.getAuth(), email);
|
|
564
220
|
}
|
|
565
221
|
catch (error) {
|
|
566
|
-
|
|
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
|
|
227
|
+
await firebaseConfirmPasswordReset(this.getAuth(), code, newPassword);
|
|
582
228
|
}
|
|
583
229
|
catch (error) {
|
|
584
|
-
|
|
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
|
-
|
|
605
|
-
|
|
606
|
-
|
|
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.
|
|
613
|
-
await updatePassword(
|
|
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
|
|
621
|
-
|
|
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 || '
|
|
631
|
-
message:
|
|
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
|
-
|
|
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(
|
|
660
|
-
await this.
|
|
262
|
+
await updateProfile(auth.currentUser, profile);
|
|
263
|
+
await this.syncToFirestore(auth.currentUser);
|
|
661
264
|
}
|
|
662
265
|
catch (error) {
|
|
663
|
-
|
|
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
|
-
|
|
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(
|
|
683
|
-
await this.
|
|
275
|
+
await updateEmail(auth.currentUser, newEmail);
|
|
276
|
+
await this.syncToFirestore(auth.currentUser);
|
|
684
277
|
}
|
|
685
278
|
catch (error) {
|
|
686
|
-
|
|
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
|
-
|
|
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(
|
|
288
|
+
await sendEmailVerification(auth.currentUser);
|
|
705
289
|
}
|
|
706
290
|
catch (error) {
|
|
707
|
-
|
|
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
|
-
|
|
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(
|
|
726
|
-
await this.
|
|
300
|
+
await reload(auth.currentUser);
|
|
301
|
+
await this.syncToFirestore(auth.currentUser);
|
|
727
302
|
}
|
|
728
303
|
catch (error) {
|
|
729
|
-
|
|
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
|
-
|
|
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(
|
|
313
|
+
return await getIdToken(auth.currentUser, forceRefresh);
|
|
749
314
|
}
|
|
750
315
|
catch (error) {
|
|
751
|
-
|
|
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
|
-
|
|
787
|
-
|
|
788
|
-
|
|
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 =
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
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
|
-
|
|
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
|
|
805
|
-
|
|
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
|
-
|
|
817
|
-
|
|
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
|
-
|
|
824
|
-
|
|
825
|
-
|
|
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
|
-
|
|
839
|
-
|
|
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
|
-
|
|
357
|
+
handleAuthError(error);
|
|
854
358
|
}
|
|
855
359
|
}
|
|
856
|
-
//
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
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
|
-
*
|
|
868
|
-
* @
|
|
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
|
-
|
|
871
|
-
|
|
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
|
-
*
|
|
875
|
-
*
|
|
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
|
-
|
|
878
|
-
|
|
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
|
-
*
|
|
882
|
-
*
|
|
464
|
+
* Starts phone MFA enrollment for the currently signed-in user.
|
|
465
|
+
* Returns a `verificationId` to pass to `completeMFAEnrollment()`.
|
|
883
466
|
*/
|
|
884
|
-
|
|
885
|
-
|
|
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
|
-
*
|
|
889
|
-
* @returns {string | null} User's display name or null
|
|
485
|
+
* Completes phone MFA enrollment using the SMS code.
|
|
890
486
|
*/
|
|
891
|
-
|
|
892
|
-
|
|
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
|
|
896
|
-
*
|
|
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
|
-
|
|
899
|
-
return this.
|
|
515
|
+
getMFAResolver(error) {
|
|
516
|
+
return getMultiFactorResolver(this.getAuth(), error);
|
|
900
517
|
}
|
|
901
518
|
/**
|
|
902
|
-
*
|
|
903
|
-
*
|
|
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
|
-
|
|
906
|
-
|
|
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
|
-
*
|
|
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
|
-
|
|
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();
|