svelte-firekit 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/README.md +58 -0
  2. package/dist/auth/reset-password.svelte +20 -0
  3. package/dist/auth/reset-password.svelte.d.ts +18 -0
  4. package/dist/auth/sign-in.svelte +30 -0
  5. package/dist/auth/sign-in.svelte.d.ts +4 -0
  6. package/dist/auth/sign-up.svelte +30 -0
  7. package/dist/auth/sign-up.svelte.d.ts +4 -0
  8. package/dist/auth/uid.d.ts +1 -0
  9. package/dist/auth/uid.js +7 -0
  10. package/dist/auth/user-button.svelte +117 -0
  11. package/dist/auth/user-button.svelte.d.ts +5 -0
  12. package/dist/auth/user.svelte.d.ts +10 -0
  13. package/dist/auth/user.svelte.js +21 -0
  14. package/dist/auth.d.ts +39 -0
  15. package/dist/auth.js +100 -0
  16. package/dist/components/auth/google-sign-in.svelte +46 -0
  17. package/dist/components/auth/google-sign-in.svelte.d.ts +4 -0
  18. package/dist/components/auth/reset-password-form.svelte +58 -0
  19. package/dist/components/auth/reset-password-form.svelte.d.ts +18 -0
  20. package/dist/components/auth/sign-in-form.svelte +77 -0
  21. package/dist/components/auth/sign-in-form.svelte.d.ts +18 -0
  22. package/dist/components/auth/sign-up-form.svelte +112 -0
  23. package/dist/components/auth/sign-up-form.svelte.d.ts +18 -0
  24. package/dist/components/ui/alert-dialog/alert-dialog-action.svelte +13 -0
  25. package/dist/components/ui/alert-dialog/alert-dialog-action.svelte.d.ts +3 -0
  26. package/dist/components/ui/alert-dialog/alert-dialog-cancel.svelte +17 -0
  27. package/dist/components/ui/alert-dialog/alert-dialog-cancel.svelte.d.ts +3 -0
  28. package/dist/components/ui/alert-dialog/alert-dialog-content.svelte +23 -0
  29. package/dist/components/ui/alert-dialog/alert-dialog-content.svelte.d.ts +2 -0
  30. package/dist/components/ui/alert-dialog/alert-dialog-description.svelte +16 -0
  31. package/dist/components/ui/alert-dialog/alert-dialog-description.svelte.d.ts +3 -0
  32. package/dist/components/ui/alert-dialog/alert-dialog-footer.svelte +20 -0
  33. package/dist/components/ui/alert-dialog/alert-dialog-footer.svelte.d.ts +4 -0
  34. package/dist/components/ui/alert-dialog/alert-dialog-header.svelte +20 -0
  35. package/dist/components/ui/alert-dialog/alert-dialog-header.svelte.d.ts +4 -0
  36. package/dist/components/ui/alert-dialog/alert-dialog-overlay.svelte +19 -0
  37. package/dist/components/ui/alert-dialog/alert-dialog-overlay.svelte.d.ts +3 -0
  38. package/dist/components/ui/alert-dialog/alert-dialog-title.svelte +18 -0
  39. package/dist/components/ui/alert-dialog/alert-dialog-title.svelte.d.ts +3 -0
  40. package/dist/components/ui/alert-dialog/index.js +15 -0
  41. package/dist/components/ui/avatar/avatar-fallback.svelte +16 -0
  42. package/dist/components/ui/avatar/avatar-fallback.svelte.d.ts +3 -0
  43. package/dist/components/ui/avatar/avatar-image.svelte +20 -0
  44. package/dist/components/ui/avatar/avatar-image.svelte.d.ts +3 -0
  45. package/dist/components/ui/avatar/avatar.svelte +18 -0
  46. package/dist/components/ui/avatar/avatar.svelte.d.ts +3 -0
  47. package/dist/components/ui/avatar/index.d.ts +4 -0
  48. package/dist/components/ui/avatar/index.js +6 -0
  49. package/dist/components/ui/button/button.svelte +75 -0
  50. package/dist/components/ui/button/button.svelte.d.ts +117 -0
  51. package/dist/components/ui/button/index.d.ts +2 -0
  52. package/dist/components/ui/button/index.js +4 -0
  53. package/dist/components/ui/card/card-content.svelte +16 -0
  54. package/dist/components/ui/card/card-content.svelte.d.ts +4 -0
  55. package/dist/components/ui/card/card-description.svelte +16 -0
  56. package/dist/components/ui/card/card-description.svelte.d.ts +4 -0
  57. package/dist/components/ui/card/card-footer.svelte +16 -0
  58. package/dist/components/ui/card/card-footer.svelte.d.ts +4 -0
  59. package/dist/components/ui/card/card-header.svelte +16 -0
  60. package/dist/components/ui/card/card-header.svelte.d.ts +4 -0
  61. package/dist/components/ui/card/card-title.svelte +25 -0
  62. package/dist/components/ui/card/card-title.svelte.d.ts +7 -0
  63. package/dist/components/ui/card/card.svelte +20 -0
  64. package/dist/components/ui/card/card.svelte.d.ts +4 -0
  65. package/dist/components/ui/card/index.d.ts +7 -0
  66. package/dist/components/ui/card/index.js +9 -0
  67. package/dist/components/ui/checkbox/checkbox.svelte +33 -0
  68. package/dist/components/ui/checkbox/checkbox.svelte.d.ts +3 -0
  69. package/dist/components/ui/checkbox/index.d.ts +2 -0
  70. package/dist/components/ui/checkbox/index.js +4 -0
  71. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +37 -0
  72. package/dist/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte.d.ts +5 -0
  73. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte +22 -0
  74. package/dist/components/ui/dropdown-menu/dropdown-menu-content.svelte.d.ts +3 -0
  75. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +19 -0
  76. package/dist/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte.d.ts +11 -0
  77. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte +23 -0
  78. package/dist/components/ui/dropdown-menu/dropdown-menu-item.svelte.d.ts +17 -0
  79. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte +23 -0
  80. package/dist/components/ui/dropdown-menu/dropdown-menu-label.svelte.d.ts +7 -0
  81. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +30 -0
  82. package/dist/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte.d.ts +3 -0
  83. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte +16 -0
  84. package/dist/components/ui/dropdown-menu/dropdown-menu-separator.svelte.d.ts +3 -0
  85. package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +20 -0
  86. package/dist/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte.d.ts +4 -0
  87. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +19 -0
  88. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte.d.ts +3 -0
  89. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +28 -0
  90. package/dist/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte.d.ts +5 -0
  91. package/dist/components/ui/dropdown-menu/index.js +17 -0
  92. package/dist/components/ui/form/form-button.svelte +7 -0
  93. package/dist/components/ui/form/form-button.svelte.d.ts +3 -0
  94. package/dist/components/ui/form/form-description.svelte +17 -0
  95. package/dist/components/ui/form/form-description.svelte.d.ts +3 -0
  96. package/dist/components/ui/form/form-element-field.svelte +30 -0
  97. package/dist/components/ui/form/form-element-field.svelte.d.ts +22 -0
  98. package/dist/components/ui/form/form-field-errors.svelte +30 -0
  99. package/dist/components/ui/form/form-field-errors.svelte.d.ts +5 -0
  100. package/dist/components/ui/form/form-field.svelte +30 -0
  101. package/dist/components/ui/form/form-field.svelte.d.ts +21 -0
  102. package/dist/components/ui/form/form-fieldset.svelte +21 -0
  103. package/dist/components/ui/form/form-fieldset.svelte.d.ts +19 -0
  104. package/dist/components/ui/form/form-label.svelte +21 -0
  105. package/dist/components/ui/form/form-label.svelte.d.ts +3 -0
  106. package/dist/components/ui/form/form-legend.svelte +17 -0
  107. package/dist/components/ui/form/form-legend.svelte.d.ts +3 -0
  108. package/dist/components/ui/form/index.d.ts +11 -0
  109. package/dist/components/ui/form/index.js +13 -0
  110. package/dist/components/ui/input/index.d.ts +2 -0
  111. package/dist/components/ui/input/index.js +4 -0
  112. package/dist/components/ui/input/input.svelte +22 -0
  113. package/dist/components/ui/input/input.svelte.d.ts +4 -0
  114. package/dist/components/ui/label/index.d.ts +2 -0
  115. package/dist/components/ui/label/index.js +4 -0
  116. package/dist/components/ui/label/label.svelte +19 -0
  117. package/dist/components/ui/label/label.svelte.d.ts +3 -0
  118. package/dist/components/ui/sonner/index.d.ts +1 -0
  119. package/dist/components/ui/sonner/index.js +1 -0
  120. package/dist/components/ui/sonner/sonner.svelte +20 -0
  121. package/dist/components/ui/sonner/sonner.svelte.d.ts +3 -0
  122. package/dist/config.d.ts +2 -0
  123. package/dist/config.js +39 -0
  124. package/dist/firebase.d.ts +43 -0
  125. package/dist/firebase.js +110 -0
  126. package/dist/firestore/Collection.svelte +148 -0
  127. package/dist/firestore/Collection.svelte.d.ts +27 -0
  128. package/dist/firestore/collection.svelte.js +207 -0
  129. package/dist/firestore/doc.svelte.d.ts +1 -0
  130. package/dist/firestore/doc.svelte.js +1 -0
  131. package/dist/firestore/firestore.d.ts +31 -0
  132. package/dist/firestore/firestore.js +100 -0
  133. package/dist/firestore/perf.d.ts +3 -0
  134. package/dist/firestore/perf.js +12 -0
  135. package/dist/index.d.ts +2 -0
  136. package/dist/index.js +3 -0
  137. package/dist/schemas/reset-password.d.ts +4 -0
  138. package/dist/schemas/reset-password.js +4 -0
  139. package/dist/schemas/sign-in.d.ts +5 -0
  140. package/dist/schemas/sign-in.js +5 -0
  141. package/dist/schemas/sign-up.d.ts +8 -0
  142. package/dist/schemas/sign-up.js +8 -0
  143. package/dist/types/nav.d.ts +9 -0
  144. package/dist/types/nav.js +1 -0
  145. package/dist/utils.d.ts +3 -0
  146. package/dist/utils.js +16 -0
  147. package/package.json +64 -0
package/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # create-svelte
2
+
3
+ Everything you need to build a Svelte library, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
4
+
5
+ Read more about creating a library [in the docs](https://svelte.dev/docs/kit/packaging).
6
+
7
+ ## Creating a project
8
+
9
+ If you're seeing this, you've probably already done this step. Congrats!
10
+
11
+ ```bash
12
+ # create a new project in the current directory
13
+ npx sv create
14
+
15
+ # create a new project in my-app
16
+ npx sv create my-app
17
+ ```
18
+
19
+ ## Developing
20
+
21
+ Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
22
+
23
+ ```bash
24
+ npm run dev
25
+
26
+ # or start the server and open the app in a new browser tab
27
+ npm run dev -- --open
28
+ ```
29
+
30
+ Everything inside `src/lib` is part of your library, everything inside `src/routes` can be used as a showcase or preview app.
31
+
32
+ ## Building
33
+
34
+ To build your library:
35
+
36
+ ```bash
37
+ npm run package
38
+ ```
39
+
40
+ To create a production version of your showcase app:
41
+
42
+ ```bash
43
+ npm run build
44
+ ```
45
+
46
+ You can preview the production build with `npm run preview`.
47
+
48
+ > To deploy your app, you may need to install an [adapter](https://svelte.dev/docs/kit/adapters) for your target environment.
49
+
50
+ ## Publishing
51
+
52
+ Go into the `package.json` and give your package the desired name through the `"name"` option. Also consider adding a `"license"` field and point it to a `LICENSE` file which you can create from a template (one popular option is the [MIT license](https://opensource.org/license/mit/)).
53
+
54
+ To publish your library to [npm](https://www.npmjs.com):
55
+
56
+ ```bash
57
+ npm publish
58
+ ```
@@ -0,0 +1,20 @@
1
+ <script lang="ts">
2
+ import ResetPasswordForm from "../components/auth/reset-password-form.svelte";
3
+ import Button from "../components/ui/button/button.svelte";
4
+ import * as Card from "../components/ui/card";
5
+ </script>
6
+
7
+ <Card.Root class="sm:w-[448px]">
8
+ <Card.Header>
9
+ <Card.Title class="text-center text-2xl">Forgot password?</Card.Title>
10
+ <Card.Description class="text-center">
11
+ Remember your password?
12
+ <Button variant="link" href="/sign-in" class="p-0"
13
+ >Sign in here</Button
14
+ >
15
+ </Card.Description>
16
+ </Card.Header>
17
+ <Card.Content>
18
+ <ResetPasswordForm />
19
+ </Card.Content>
20
+ </Card.Root>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const ResetPassword: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type ResetPassword = InstanceType<typeof ResetPassword>;
18
+ export default ResetPassword;
@@ -0,0 +1,30 @@
1
+ <script lang="ts">
2
+ import SignInWithGoogle from "../components/auth/google-sign-in.svelte";
3
+ import SignInForm from "../components/auth/sign-in-form.svelte";
4
+ import Button from "../components/ui/button/button.svelte";
5
+ import * as Card from "../components/ui/card";
6
+ let { title = "Sign in" }: { title: string } = $props();
7
+ </script>
8
+
9
+ <Card.Root class="sm:w-[448px]">
10
+ <Card.Header>
11
+ <Card.Title class="text-center text-2xl">{title}</Card.Title>
12
+ <Card.Description class="text-center">
13
+ Don't have an account yet?
14
+ <Button variant="link" href="/sign-up" class="p-0"
15
+ >Sign up here</Button
16
+ >
17
+ </Card.Description>
18
+ </Card.Header>
19
+ <Card.Content class="space-y-5">
20
+ <SignInWithGoogle label="Sign in" />
21
+
22
+ <div
23
+ class="before:muted-foreground after:muted-foreground flex items-center text-xs uppercase text-muted-foreground before:me-6 before:flex-1 before:border-t after:ms-6 after:flex-1 after:border-t dark:before:border-muted-foreground dark:after:border-muted-foreground"
24
+ >
25
+ Or
26
+ </div>
27
+
28
+ <SignInForm />
29
+ </Card.Content>
30
+ </Card.Root>
@@ -0,0 +1,4 @@
1
+ declare const SignIn: import("svelte").Component<{
2
+ title: string;
3
+ }, {}, "">;
4
+ export default SignIn;
@@ -0,0 +1,30 @@
1
+ <script lang="ts">
2
+ import SignInWithGoogle from "../components/auth/google-sign-in.svelte";
3
+ import SignUpForm from "../components/auth/sign-up-form.svelte";
4
+ import Button from "../components/ui/button/button.svelte";
5
+ import * as Card from "../components/ui/card";
6
+ let { title = "Sign up" }: { title: string } = $props();
7
+ </script>
8
+
9
+ <Card.Root class="sm:w-[448px]">
10
+ <Card.Header>
11
+ <Card.Title class="text-center text-2xl">{title}</Card.Title>
12
+ <Card.Description class="text-center">
13
+ Already have an account?
14
+ <Button variant="link" href="/sign-in" class="p-0"
15
+ >Sign in here</Button
16
+ >
17
+ </Card.Description>
18
+ </Card.Header>
19
+ <Card.Content class="space-y-5">
20
+ <SignInWithGoogle label="Sign up" />
21
+
22
+ <div
23
+ class="before:muted-foreground after:muted-foreground flex items-center text-xs uppercase text-muted-foreground before:me-6 before:flex-1 before:border-t after:ms-6 after:flex-1 after:border-t dark:before:border-muted-foreground dark:after:border-muted-foreground"
24
+ >
25
+ Or
26
+ </div>
27
+
28
+ <SignUpForm />
29
+ </Card.Content>
30
+ </Card.Root>
@@ -0,0 +1,4 @@
1
+ declare const SignUp: import("svelte").Component<{
2
+ title: string;
3
+ }, {}, "">;
4
+ export default SignUp;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ // import { get } from "svelte/store";
3
+ // import { authState } from "./user";
4
+ // export const getUid = () => {
5
+ // const u = get(authState);
6
+ // return (u && u.uid) || "anonymous"; // 'anonymous' allows support messages to be saved by non-logged-in users
7
+ // };
@@ -0,0 +1,117 @@
1
+ <script lang="ts">
2
+ import * as DropdownMenu from "../components/ui/dropdown-menu/index.js";
3
+ import * as Avatar from "../components/ui/avatar/index.js";
4
+ import { authUser } from "./user.svelte.js";
5
+ import { getInitials } from "../utils.js";
6
+ import { LogOut } from "lucide-svelte";
7
+ import { logOut } from "../auth.js";
8
+ import type { NavItem } from "../types/nav.js";
9
+ let { nav }: { nav: NavItem[] } = $props();
10
+ import * as AlertDialog from "../components/ui/alert-dialog/index.js";
11
+ import Button from "../components/ui/button/button.svelte";
12
+ let isOpen = $state(false);
13
+ </script>
14
+
15
+ {#if authUser.currentUser}
16
+ <DropdownMenu.Root>
17
+ <DropdownMenu.Trigger>
18
+ <Avatar.Root>
19
+ <Avatar.Image
20
+ src={authUser.currentUser?.photoURL}
21
+ alt="Avatar"
22
+ />
23
+ <Avatar.Fallback>
24
+ {getInitials(authUser.currentUser?.displayName)}
25
+ </Avatar.Fallback>
26
+ </Avatar.Root>
27
+ </DropdownMenu.Trigger>
28
+ <DropdownMenu.Content>
29
+ <DropdownMenu.Group>
30
+ <DropdownMenu.GroupHeading>
31
+ <div class="flex items-center gap-3">
32
+ <Avatar.Root>
33
+ <Avatar.Image
34
+ src={authUser.currentUser?.photoURL}
35
+ alt="Avatar"
36
+ />
37
+ <Avatar.Fallback>
38
+ {getInitials(authUser.currentUser?.displayName)}
39
+ </Avatar.Fallback>
40
+ </Avatar.Root>
41
+ <div class="grow">
42
+ <span
43
+ class="block font-medium text-sm text-gray-800 dark:text-neutral-200"
44
+ >
45
+ {authUser.currentUser?.displayName}
46
+ </span>
47
+ <p class="text-xs text-foreground-500">
48
+ {authUser.currentUser?.email}
49
+ </p>
50
+ </div>
51
+ </div>
52
+ </DropdownMenu.GroupHeading>
53
+ <DropdownMenu.Separator />
54
+ <DropdownMenu.Item onclick={() => (isOpen = true)}>
55
+ Profile
56
+ </DropdownMenu.Item>
57
+ {#each nav as { href, label }}
58
+ <DropdownMenu.Item>
59
+ <a {href}>
60
+ {label}
61
+ </a>
62
+ </DropdownMenu.Item>
63
+ {/each}
64
+
65
+ <DropdownMenu.Separator />
66
+ <DropdownMenu.Item onclick={logOut}>
67
+ <LogOut /> Logout
68
+ </DropdownMenu.Item>
69
+ </DropdownMenu.Group>
70
+ </DropdownMenu.Content>
71
+ </DropdownMenu.Root>
72
+ <AlertDialog.Root bind:open={isOpen}>
73
+ <AlertDialog.Content>
74
+ <AlertDialog.Header>
75
+ <AlertDialog.Title>
76
+ <div class="flex justify-between items-center">
77
+ <div class="flex items-center gap-3">
78
+ <Avatar.Root>
79
+ <Avatar.Image
80
+ src={authUser.currentUser?.photoURL}
81
+ alt="Avatar"
82
+ />
83
+ <Avatar.Fallback>
84
+ {getInitials(
85
+ authUser.currentUser?.displayName,
86
+ )}
87
+ </Avatar.Fallback>
88
+ </Avatar.Root>
89
+ <div class="grow">
90
+ <span
91
+ class="block font-medium text-sm text-gray-800 dark:text-neutral-200"
92
+ >
93
+ {authUser.currentUser?.displayName}
94
+ </span>
95
+ <p class="text-xs text-foreground-500">
96
+ {authUser.currentUser?.email}
97
+ </p>
98
+ </div>
99
+ </div>
100
+ <Button onclick={logOut} variant="link">
101
+ <LogOut />Logout
102
+ </Button>
103
+ </div>
104
+ </AlertDialog.Title>
105
+ <AlertDialog.Description>
106
+ Manage your name, password and account settings.
107
+ </AlertDialog.Description>
108
+ </AlertDialog.Header>
109
+ <AlertDialog.Footer>
110
+ <AlertDialog.Cancel>Cancel</AlertDialog.Cancel>
111
+ <AlertDialog.Action>Continue</AlertDialog.Action>
112
+ </AlertDialog.Footer>
113
+ </AlertDialog.Content>
114
+ </AlertDialog.Root>
115
+ {:else}
116
+ <Button href="/login">Login</Button>
117
+ {/if}
@@ -0,0 +1,5 @@
1
+ import type { NavItem } from "../types/nav.js";
2
+ declare const UserButton: import("svelte").Component<{
3
+ nav: NavItem[];
4
+ }, {}, "">;
5
+ export default UserButton;
@@ -0,0 +1,10 @@
1
+ import { type User } from "firebase/auth";
2
+ export declare class FirebaseAuthUser {
3
+ #private;
4
+ constructor();
5
+ get isAuthenticated(): boolean;
6
+ get isAnonymousUser(): boolean | undefined;
7
+ get userId(): string | undefined;
8
+ get currentUser(): User | null | undefined;
9
+ }
10
+ export declare const authUser: FirebaseAuthUser;
@@ -0,0 +1,21 @@
1
+ import { getAuthInstance } from "../firebase.js";
2
+ import { onAuthStateChanged } from "firebase/auth";
3
+ export class FirebaseAuthUser {
4
+ #currentUser = $state();
5
+ constructor() {
6
+ onAuthStateChanged(getAuthInstance(), (user) => (this.#currentUser = user));
7
+ }
8
+ get isAuthenticated() {
9
+ return this.currentUser !== null;
10
+ }
11
+ get isAnonymousUser() {
12
+ return this.currentUser?.isAnonymous;
13
+ }
14
+ get userId() {
15
+ return this.currentUser?.uid;
16
+ }
17
+ get currentUser() {
18
+ return this.#currentUser;
19
+ }
20
+ }
21
+ export const authUser = new FirebaseAuthUser();
package/dist/auth.d.ts ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Handles Google Sign-In.
3
+ */
4
+ export declare function signInWithGoogle(): Promise<void>;
5
+ /**
6
+ * Signs in with email and password.
7
+ */
8
+ export declare function signInWithEmail(email: string, password: string): Promise<void>;
9
+ /**
10
+ * Registers a new user and updates Firestore.
11
+ */
12
+ export declare function registerWithEmail(email: string, password: string, displayName: string): Promise<void>;
13
+ /**
14
+ * Signs out the user and redirects.
15
+ */
16
+ export declare function logOut(): Promise<void>;
17
+ /**
18
+ * Sends a password reset email.
19
+ */
20
+ export declare function sendPasswordReset(email: string): Promise<void>;
21
+ /**
22
+ * Verifies email for current user.
23
+ */
24
+ export declare function sendEmailVerificationToUser(): Promise<void>;
25
+ /**
26
+ * Updates user profile with display name and photo URL.
27
+ */
28
+ export declare function updateUserProfile(profile: {
29
+ displayName?: string;
30
+ photoURL?: string;
31
+ }): Promise<void>;
32
+ /**
33
+ * Updates password for current user.
34
+ */
35
+ export declare function updateUserPassword(newPassword: string): Promise<void>;
36
+ /**
37
+ * Checks onboarding completion by verifying profile data.
38
+ */
39
+ export declare function checkOnboardingCompletion(uid: string): Promise<void>;
package/dist/auth.js ADDED
@@ -0,0 +1,100 @@
1
+ // firebaseAuthService.ts
2
+ import { GoogleAuthProvider, sendPasswordResetEmail, signInWithEmailAndPassword, signInWithPopup, signOut, createUserWithEmailAndPassword, sendEmailVerification, updateProfile, updatePassword } from 'firebase/auth';
3
+ import { doc, getDoc, setDoc } from 'firebase/firestore';
4
+ import { getAuthInstance, getDb } from './firebase.js';
5
+ import { goto } from '$app/navigation';
6
+ const auth = getAuthInstance();
7
+ const firestore = getDb();
8
+ /**
9
+ * Handles Google Sign-In.
10
+ */
11
+ export async function signInWithGoogle() {
12
+ const provider = new GoogleAuthProvider();
13
+ const result = await signInWithPopup(auth, provider);
14
+ await updateUserInFirestore(result.user);
15
+ }
16
+ /**
17
+ * Signs in with email and password.
18
+ */
19
+ export async function signInWithEmail(email, password) {
20
+ const result = await signInWithEmailAndPassword(auth, email, password);
21
+ await updateUserInFirestore(result.user);
22
+ }
23
+ /**
24
+ * Registers a new user and updates Firestore.
25
+ */
26
+ export async function registerWithEmail(email, password, displayName) {
27
+ const result = await createUserWithEmailAndPassword(auth, email, password);
28
+ const user = result.user;
29
+ if (user) {
30
+ await updateProfile(user, { displayName });
31
+ await updateUserInFirestore(user);
32
+ await sendEmailVerification(user);
33
+ }
34
+ }
35
+ /**
36
+ * Updates Firestore with user data.
37
+ */
38
+ async function updateUserInFirestore(user) {
39
+ const ref = doc(firestore, 'users', user.uid);
40
+ const userData = {
41
+ uid: user.uid,
42
+ email: user.email,
43
+ emailVerified: user.emailVerified,
44
+ displayName: user.displayName,
45
+ photoURL: user.photoURL,
46
+ isAnonymous: user.isAnonymous,
47
+ providerId: user.providerId,
48
+ phoneNumber: user.phoneNumber,
49
+ providerData: user.providerData
50
+ };
51
+ await setDoc(ref, userData, { merge: true });
52
+ }
53
+ /**
54
+ * Signs out the user and redirects.
55
+ */
56
+ export async function logOut() {
57
+ await signOut(auth);
58
+ goto('/sign-in');
59
+ }
60
+ /**
61
+ * Sends a password reset email.
62
+ */
63
+ export async function sendPasswordReset(email) {
64
+ await sendPasswordResetEmail(auth, email);
65
+ }
66
+ /**
67
+ * Verifies email for current user.
68
+ */
69
+ export async function sendEmailVerificationToUser() {
70
+ if (auth.currentUser) {
71
+ await sendEmailVerification(auth.currentUser);
72
+ }
73
+ }
74
+ /**
75
+ * Updates user profile with display name and photo URL.
76
+ */
77
+ export async function updateUserProfile(profile) {
78
+ if (auth.currentUser) {
79
+ await updateProfile(auth.currentUser, profile);
80
+ await updateUserInFirestore(auth.currentUser);
81
+ }
82
+ }
83
+ /**
84
+ * Updates password for current user.
85
+ */
86
+ export async function updateUserPassword(newPassword) {
87
+ if (auth.currentUser) {
88
+ await updatePassword(auth.currentUser, newPassword);
89
+ }
90
+ }
91
+ /**
92
+ * Checks onboarding completion by verifying profile data.
93
+ */
94
+ export async function checkOnboardingCompletion(uid) {
95
+ const profileDoc = await getDoc(doc(firestore, 'profiles', uid));
96
+ if (!profileDoc.exists() || !profileDoc.data()?.username) {
97
+ alert("Please complete onboarding");
98
+ goto('/onboarding');
99
+ }
100
+ }
@@ -0,0 +1,46 @@
1
+ <script lang="ts">
2
+ import { signInWithGoogle } from "../../auth.js";
3
+ import Button from "../ui/button/button.svelte";
4
+ let { label = "Sign in" }: { label: string } = $props();
5
+ </script>
6
+
7
+ <Button onclick={signInWithGoogle} class="w-full gap-2" variant="outline">
8
+ <svg
9
+ class="h-4 w-4 flex-shrink-0"
10
+ width="33"
11
+ height="32"
12
+ viewBox="0 0 33 32"
13
+ fill="none"
14
+ xmlns="http://www.w3.org/2000/svg"
15
+ >
16
+ <g clip-path="url(#clip0_4132_5805)">
17
+ <path
18
+ d="M32.2566 16.36C32.2566 15.04 32.1567 14.08 31.9171 13.08H16.9166V19.02H25.7251C25.5454 20.5 24.5866 22.72 22.4494 24.22L22.4294 24.42L27.1633 28.1L27.4828 28.14C30.5189 25.34 32.2566 21.22 32.2566 16.36Z"
19
+ fill="#4285F4"
20
+ />
21
+ <path
22
+ d="M16.9166 32C21.231 32 24.8463 30.58 27.5028 28.12L22.4694 24.2C21.1111 25.14 19.3135 25.8 16.9366 25.8C12.7021 25.8 9.12677 23 7.84844 19.16L7.66867 19.18L2.71513 23L2.65521 23.18C5.2718 28.4 10.6648 32 16.9166 32Z"
23
+ fill="#34A853"
24
+ />
25
+ <path
26
+ d="M7.82845 19.16C7.48889 18.16 7.28915 17.1 7.28915 16C7.28915 14.9 7.48889 13.84 7.80848 12.84V12.62L2.81499 8.73999L2.6552 8.81999C1.55663 10.98 0.937439 13.42 0.937439 16C0.937439 18.58 1.55663 21.02 2.63522 23.18L7.82845 19.16Z"
27
+ fill="#FBBC05"
28
+ />
29
+ <path
30
+ d="M16.9166 6.18C19.9127 6.18 21.9501 7.48 23.0886 8.56L27.6027 4.16C24.8263 1.58 21.231 0 16.9166 0C10.6648 0 5.27181 3.6 2.63525 8.82L7.80851 12.84C9.10681 8.98 12.6821 6.18 16.9166 6.18Z"
31
+ fill="#EB4335"
32
+ />
33
+ </g>
34
+ <defs>
35
+ <clipPath id="clip0_4132_5805">
36
+ <rect
37
+ width="32"
38
+ height="32"
39
+ fill="white"
40
+ transform="translate(0.937439)"
41
+ />
42
+ </clipPath>
43
+ </defs>
44
+ </svg>
45
+ {label} with Google
46
+ </Button>
@@ -0,0 +1,4 @@
1
+ declare const GoogleSignIn: import("svelte").Component<{
2
+ label: string;
3
+ }, {}, "">;
4
+ export default GoogleSignIn;
@@ -0,0 +1,58 @@
1
+ <script lang="ts">
2
+ import { goto } from "$app/navigation";
3
+ import { sendPasswordReset } from "../../auth.js";
4
+ import * as Form from "../ui/form/index.js";
5
+ import { Input } from "../ui/input/index.js";
6
+ import {
7
+ resetPasswordSchema,
8
+ } from "../../schemas/reset-password.js";
9
+ import { toast } from "svelte-sonner";
10
+ import {
11
+ superForm,defaults
12
+ } from "sveltekit-superforms";
13
+ import { zodClient } from "sveltekit-superforms/adapters";
14
+ import { valibot } from 'sveltekit-superforms/adapters';
15
+
16
+ const data = defaults(valibot(resetPasswordSchema));
17
+
18
+ const form = superForm(data, {
19
+ validators: valibot(resetPasswordSchema),
20
+ dataType: "json",
21
+ SPA: true,
22
+ resetForm: false,
23
+ clearOnSubmit: "errors-and-message",
24
+ async onUpdate({ form }) {
25
+ if (!form.valid) return;
26
+ try {
27
+ const { data } = form;
28
+ const { email } = data;
29
+ await sendPasswordReset(email);
30
+ toast.success("Password reset email sent");
31
+ goto("/sign-in");
32
+ } catch (error) {
33
+ if (error instanceof Error) {
34
+ toast.error(error.message);
35
+ } else {
36
+ toast.error("An error occurred");
37
+ }
38
+ }
39
+ },
40
+ });
41
+
42
+ const { form: formData, enhance } = form;
43
+ </script>
44
+
45
+ <form method="POST" use:enhance class="space-y-4">
46
+ <Form.Field {form} name="email">
47
+ <Form.Control >
48
+ {#snippet children({ props })}
49
+ <Form.Label>Email address</Form.Label>
50
+ <Input {...props} bind:value={$formData.email} placeholder="you@email.com"/>
51
+ {/snippet}
52
+
53
+ </Form.Control>
54
+ <Form.FieldErrors />
55
+ </Form.Field>
56
+
57
+ <Form.Button class="w-full">Send Email</Form.Button>
58
+ </form>
@@ -0,0 +1,18 @@
1
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
2
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
3
+ $$bindings?: Bindings;
4
+ } & Exports;
5
+ (internal: unknown, props: {
6
+ $$events?: Events;
7
+ $$slots?: Slots;
8
+ }): Exports & {
9
+ $set?: any;
10
+ $on?: any;
11
+ };
12
+ z_$$bindings?: Bindings;
13
+ }
14
+ declare const ResetPasswordForm: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
15
+ [evt: string]: CustomEvent<any>;
16
+ }, {}, {}, string>;
17
+ type ResetPasswordForm = InstanceType<typeof ResetPasswordForm>;
18
+ export default ResetPasswordForm;