svelte-firekit 0.0.10 → 0.0.12
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/dist/auth/reset-password.svelte +27 -15
- package/dist/auth/reset-password.svelte.d.ts +7 -17
- package/dist/auth/sign-in.svelte +51 -23
- package/dist/auth/sign-in.svelte.d.ts +11 -1
- package/dist/auth/sign-up.svelte +62 -23
- package/dist/auth/sign-up.svelte.d.ts +13 -0
- package/dist/components/app/nav/app-sidebar.svelte +35 -0
- package/dist/components/app/nav/app-sidebar.svelte.d.ts +8 -0
- package/dist/components/app/nav/breadcrumb.svelte +42 -0
- package/dist/components/app/nav/breadcrumb.svelte.d.ts +19 -0
- package/dist/components/auth/google-sign-in.svelte +55 -53
- package/dist/components/auth/reset-password-form.svelte +49 -47
- package/dist/components/auth/reset-password-form.svelte.d.ts +3 -17
- package/dist/components/auth/sign-in-form.svelte +21 -5
- package/dist/components/auth/sign-in-form.svelte.d.ts +7 -17
- package/dist/components/auth/sign-up-form.svelte +127 -110
- package/dist/components/auth/sign-up-form.svelte.d.ts +10 -17
- package/dist/components/auth/user-button/profile-section/avatar-user.svelte +107 -0
- package/dist/components/auth/user-button/profile-section/avatar-user.svelte.d.ts +2 -0
- package/dist/components/auth/user-button/profile-section/connect-user.svelte +45 -0
- package/dist/components/auth/user-button/profile-section/connect-user.svelte.d.ts +18 -0
- package/dist/components/auth/user-button/profile-section/email-user.svelte +81 -0
- package/dist/components/auth/user-button/profile-section/email-user.svelte.d.ts +2 -0
- package/dist/components/auth/user-button/profile-section/phone-user.svelte +122 -0
- package/dist/components/auth/user-button/profile-section/phone-user.svelte.d.ts +2 -0
- package/dist/components/auth/user-button/profile-section/profile-section.svelte +17 -0
- package/dist/components/auth/user-button/profile-section/profile-section.svelte.d.ts +18 -0
- package/dist/components/auth/user-button/settings-dialog.svelte +80 -87
- package/dist/components/auth/user-button/type-account.svelte +35 -0
- package/dist/components/auth/user-button/type-account.svelte.d.ts +4 -0
- package/dist/components/auth/user-button/user-button.svelte +122 -112
- package/dist/components/nav/nav-main.svelte +70 -0
- package/dist/components/nav/nav-main.svelte.d.ts +18 -0
- package/dist/components/ui/badge/badge.svelte +49 -0
- package/dist/components/ui/badge/badge.svelte.d.ts +59 -0
- package/dist/components/ui/badge/index.d.ts +2 -0
- package/dist/components/ui/badge/index.js +2 -0
- package/dist/components/ui/collapsible/index.d.ts +5 -0
- package/dist/components/ui/collapsible/index.js +7 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.js +28 -0
- package/dist/firebase/auth/auth-guard.svelte.d.ts +0 -30
- package/dist/firebase/auth/auth-guard.svelte.js +119 -103
- package/dist/firebase/auth/auth-manager.svelte.d.ts +73 -0
- package/dist/firebase/auth/auth-manager.svelte.js +257 -0
- package/dist/firebase/auth/auth.js +2 -2
- package/dist/firebase/auth/user.svelte.d.ts +0 -53
- package/dist/firebase/auth/user.svelte.js +177 -134
- package/dist/firebase/firestore/document-mutations.svelte.d.ts +1 -1
- package/dist/firebase/firestore/document-mutations.svelte.js +18 -13
- package/dist/firebase/storage/upload-task.svelte.d.ts +1 -0
- package/dist/firebase/storage/upload-task.svelte.js +4 -2
- package/dist/index.d.ts +1 -3
- package/dist/index.js +3 -3
- package/dist/types/nav.d.ts +4 -0
- package/package.json +4 -2
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import * as Collapsible from "../ui/collapsible/index.js";
|
|
3
|
+
import * as Sidebar from "../ui/sidebar/index.js";
|
|
4
|
+
import { navMain } from "../../config.js";
|
|
5
|
+
import ChevronRight from "lucide-svelte/icons/chevron-right";
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
{#if navMain}
|
|
9
|
+
{#each navMain as nav}
|
|
10
|
+
<Sidebar.Group>
|
|
11
|
+
<Sidebar.GroupLabel class="capitalize">{nav.title}</Sidebar.GroupLabel>
|
|
12
|
+
<Sidebar.Menu>
|
|
13
|
+
{#each nav.items as mainItem (mainItem.title)}
|
|
14
|
+
{#if mainItem.items && mainItem.items.length > 0}
|
|
15
|
+
<Collapsible.Root class="group/collapsible">
|
|
16
|
+
{#snippet child({ props })}
|
|
17
|
+
<Sidebar.MenuItem {...props}>
|
|
18
|
+
<Collapsible.Trigger>
|
|
19
|
+
{#snippet child({ props })}
|
|
20
|
+
<Sidebar.MenuButton {...props}>
|
|
21
|
+
{#snippet tooltipContent()}
|
|
22
|
+
{mainItem.title}
|
|
23
|
+
{/snippet}
|
|
24
|
+
{#if mainItem.icon}
|
|
25
|
+
<mainItem.icon />
|
|
26
|
+
{/if}
|
|
27
|
+
<span>{mainItem.title}</span>
|
|
28
|
+
<ChevronRight
|
|
29
|
+
class="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90"
|
|
30
|
+
/>
|
|
31
|
+
</Sidebar.MenuButton>
|
|
32
|
+
{/snippet}
|
|
33
|
+
</Collapsible.Trigger>
|
|
34
|
+
<Collapsible.Content>
|
|
35
|
+
{#if mainItem.items}
|
|
36
|
+
<Sidebar.MenuSub>
|
|
37
|
+
{#each mainItem.items as subItem (subItem.title)}
|
|
38
|
+
<Sidebar.MenuSubItem>
|
|
39
|
+
<Sidebar.MenuSubButton>
|
|
40
|
+
{#snippet child({ props })}
|
|
41
|
+
<a href={subItem.href} {...props}>
|
|
42
|
+
<span>{subItem.title}</span>
|
|
43
|
+
</a>
|
|
44
|
+
{/snippet}
|
|
45
|
+
</Sidebar.MenuSubButton>
|
|
46
|
+
</Sidebar.MenuSubItem>
|
|
47
|
+
{/each}
|
|
48
|
+
</Sidebar.MenuSub>
|
|
49
|
+
{/if}
|
|
50
|
+
</Collapsible.Content>
|
|
51
|
+
</Sidebar.MenuItem>
|
|
52
|
+
{/snippet}
|
|
53
|
+
</Collapsible.Root>
|
|
54
|
+
{:else}
|
|
55
|
+
<Sidebar.MenuItem>
|
|
56
|
+
<Sidebar.MenuButton>
|
|
57
|
+
{#snippet child({ props })}
|
|
58
|
+
<a href={mainItem.href} {...props}>
|
|
59
|
+
<mainItem.icon />
|
|
60
|
+
<span>{mainItem.title}</span>
|
|
61
|
+
</a>
|
|
62
|
+
{/snippet}
|
|
63
|
+
</Sidebar.MenuButton>
|
|
64
|
+
</Sidebar.MenuItem>
|
|
65
|
+
{/if}
|
|
66
|
+
{/each}
|
|
67
|
+
</Sidebar.Menu>
|
|
68
|
+
</Sidebar.Group>
|
|
69
|
+
{/each}
|
|
70
|
+
{/if}
|
|
@@ -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 NavMain: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
|
|
15
|
+
[evt: string]: CustomEvent<any>;
|
|
16
|
+
}, {}, {}, string>;
|
|
17
|
+
type NavMain = InstanceType<typeof NavMain>;
|
|
18
|
+
export default NavMain;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import { type VariantProps, tv } from "tailwind-variants";
|
|
3
|
+
export const badgeVariants = tv({
|
|
4
|
+
base: "focus:ring-ring inline-flex select-none items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2",
|
|
5
|
+
variants: {
|
|
6
|
+
variant: {
|
|
7
|
+
default:
|
|
8
|
+
"bg-primary text-primary-foreground hover:bg-primary/80 border-transparent shadow",
|
|
9
|
+
secondary:
|
|
10
|
+
"bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent",
|
|
11
|
+
destructive:
|
|
12
|
+
"bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent shadow",
|
|
13
|
+
outline: "text-foreground",
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
variant: "default",
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export type BadgeVariant = VariantProps<typeof badgeVariants>["variant"];
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<script lang="ts">
|
|
25
|
+
import type { WithElementRef } from "bits-ui";
|
|
26
|
+
import type { HTMLAnchorAttributes } from "svelte/elements";
|
|
27
|
+
import { cn } from "../../../utils.js";
|
|
28
|
+
|
|
29
|
+
let {
|
|
30
|
+
ref = $bindable(null),
|
|
31
|
+
href,
|
|
32
|
+
class: className,
|
|
33
|
+
variant = "default",
|
|
34
|
+
children,
|
|
35
|
+
...restProps
|
|
36
|
+
}: WithElementRef<HTMLAnchorAttributes> & {
|
|
37
|
+
variant?: BadgeVariant;
|
|
38
|
+
} = $props();
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<svelte:element
|
|
42
|
+
this={href ? "a" : "span"}
|
|
43
|
+
bind:this={ref}
|
|
44
|
+
{href}
|
|
45
|
+
class={cn(badgeVariants({ variant, className }))}
|
|
46
|
+
{...restProps}
|
|
47
|
+
>
|
|
48
|
+
{@render children?.()}
|
|
49
|
+
</svelte:element>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type VariantProps } from "tailwind-variants";
|
|
2
|
+
export declare const badgeVariants: import("tailwind-variants").TVReturnType<{
|
|
3
|
+
variant: {
|
|
4
|
+
default: string;
|
|
5
|
+
secondary: string;
|
|
6
|
+
destructive: string;
|
|
7
|
+
outline: string;
|
|
8
|
+
};
|
|
9
|
+
}, undefined, "focus:ring-ring inline-flex select-none items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2", import("tailwind-variants/dist/config").TVConfig<{
|
|
10
|
+
variant: {
|
|
11
|
+
default: string;
|
|
12
|
+
secondary: string;
|
|
13
|
+
destructive: string;
|
|
14
|
+
outline: string;
|
|
15
|
+
};
|
|
16
|
+
}, {
|
|
17
|
+
variant: {
|
|
18
|
+
default: string;
|
|
19
|
+
secondary: string;
|
|
20
|
+
destructive: string;
|
|
21
|
+
outline: string;
|
|
22
|
+
};
|
|
23
|
+
}>, {
|
|
24
|
+
variant: {
|
|
25
|
+
default: string;
|
|
26
|
+
secondary: string;
|
|
27
|
+
destructive: string;
|
|
28
|
+
outline: string;
|
|
29
|
+
};
|
|
30
|
+
}, undefined, import("tailwind-variants").TVReturnType<{
|
|
31
|
+
variant: {
|
|
32
|
+
default: string;
|
|
33
|
+
secondary: string;
|
|
34
|
+
destructive: string;
|
|
35
|
+
outline: string;
|
|
36
|
+
};
|
|
37
|
+
}, undefined, "focus:ring-ring inline-flex select-none items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2", import("tailwind-variants/dist/config").TVConfig<{
|
|
38
|
+
variant: {
|
|
39
|
+
default: string;
|
|
40
|
+
secondary: string;
|
|
41
|
+
destructive: string;
|
|
42
|
+
outline: string;
|
|
43
|
+
};
|
|
44
|
+
}, {
|
|
45
|
+
variant: {
|
|
46
|
+
default: string;
|
|
47
|
+
secondary: string;
|
|
48
|
+
destructive: string;
|
|
49
|
+
outline: string;
|
|
50
|
+
};
|
|
51
|
+
}>, unknown, unknown, undefined>>;
|
|
52
|
+
export type BadgeVariant = VariantProps<typeof badgeVariants>["variant"];
|
|
53
|
+
import type { HTMLAnchorAttributes } from "svelte/elements";
|
|
54
|
+
declare const Badge: import("svelte").Component<HTMLAnchorAttributes & {
|
|
55
|
+
ref?: HTMLElement | null | undefined;
|
|
56
|
+
} & {
|
|
57
|
+
variant?: BadgeVariant;
|
|
58
|
+
}, {}, "ref">;
|
|
59
|
+
export default Badge;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Collapsible as CollapsiblePrimitive } from "bits-ui";
|
|
2
|
+
declare const Root: typeof CollapsiblePrimitive.Root;
|
|
3
|
+
declare const Trigger: typeof CollapsiblePrimitive.Trigger;
|
|
4
|
+
declare const Content: typeof CollapsiblePrimitive.Content;
|
|
5
|
+
export { Root, Content, Trigger, Root as Collapsible, Content as CollapsibleContent, Trigger as CollapsibleTrigger, };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Collapsible as CollapsiblePrimitive } from "bits-ui";
|
|
2
|
+
const Root = CollapsiblePrimitive.Root;
|
|
3
|
+
const Trigger = CollapsiblePrimitive.Trigger;
|
|
4
|
+
const Content = CollapsiblePrimitive.Content;
|
|
5
|
+
export { Root, Content, Trigger,
|
|
6
|
+
//
|
|
7
|
+
Root as Collapsible, Content as CollapsibleContent, Trigger as CollapsibleTrigger, };
|
package/dist/config.d.ts
ADDED
package/dist/config.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { CircleUserRound, BookOpen, Bot, Settings2, SquareTerminal, ChartPie, Frame, Map, User, LayoutDashboard, StickyNote, } from "lucide-svelte";
|
|
2
|
+
export const navMain = [
|
|
3
|
+
{
|
|
4
|
+
title: "Platform",
|
|
5
|
+
items: [
|
|
6
|
+
{
|
|
7
|
+
title: "Dashboard",
|
|
8
|
+
href: "/dashboard",
|
|
9
|
+
icon: LayoutDashboard,
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
title: "Posts",
|
|
13
|
+
href: "/posts",
|
|
14
|
+
icon: StickyNote,
|
|
15
|
+
},
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
// {
|
|
19
|
+
// title: "Account",
|
|
20
|
+
// items: [
|
|
21
|
+
// {
|
|
22
|
+
// title: "Profile",
|
|
23
|
+
// href: "/account/profile",
|
|
24
|
+
// icon: User,
|
|
25
|
+
// },
|
|
26
|
+
// ],
|
|
27
|
+
// },
|
|
28
|
+
];
|
|
@@ -1,31 +1 @@
|
|
|
1
|
-
import type { DocumentData } from "firebase/firestore";
|
|
2
|
-
import { firekitUser } from "./user.svelte.js";
|
|
3
|
-
interface GuardConfig {
|
|
4
|
-
authRequired?: boolean;
|
|
5
|
-
redirectTo?: string;
|
|
6
|
-
requiredClaims?: string[];
|
|
7
|
-
requiredData?: (data: DocumentData | null) => boolean;
|
|
8
|
-
allowIf?: (user: typeof firekitUser) => boolean;
|
|
9
|
-
redirectParams?: Record<string, string>;
|
|
10
|
-
}
|
|
11
|
-
export declare class FirekitAuthGuard {
|
|
12
|
-
private static instance;
|
|
13
|
-
private _loading;
|
|
14
|
-
private _error;
|
|
15
|
-
private _lastValidationTime;
|
|
16
|
-
private readonly VALIDATION_THROTTLE;
|
|
17
|
-
private constructor();
|
|
18
|
-
static getInstance(): FirekitAuthGuard;
|
|
19
|
-
private shouldThrottleValidation;
|
|
20
|
-
private handleRedirect;
|
|
21
|
-
private validateClaims;
|
|
22
|
-
validateAuth({ authRequired, redirectTo, requiredClaims, requiredData, allowIf, redirectParams }?: GuardConfig): Promise<boolean>;
|
|
23
|
-
requireAuth(redirectTo?: string, redirectParams?: Record<string, string>): Promise<boolean>;
|
|
24
|
-
requireNoAuth(redirectTo?: string, redirectParams?: Record<string, string>): Promise<boolean>;
|
|
25
|
-
requireClaims(claims: string[], redirectTo?: string, redirectParams?: Record<string, string>): Promise<boolean>;
|
|
26
|
-
requireData(validator: (data: DocumentData | null) => boolean, redirectTo?: string, redirectParams?: Record<string, string>): Promise<boolean>;
|
|
27
|
-
get loading(): boolean;
|
|
28
|
-
get error(): Error | null;
|
|
29
|
-
}
|
|
30
|
-
export declare const firekitAuthGuard: FirekitAuthGuard;
|
|
31
1
|
export {};
|
|
@@ -1,103 +1,119 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
// import { browser } from "$app/environment";
|
|
3
|
+
// import { goto } from "$app/navigation";
|
|
4
|
+
// import type { DocumentData } from "firebase/firestore";
|
|
5
|
+
// import { firekitUser } from "./user.svelte.js";
|
|
6
|
+
// type UserClaims = Record<string, any>;
|
|
7
|
+
// interface GuardConfig {
|
|
8
|
+
// authRequired?: boolean;
|
|
9
|
+
// redirectTo?: string;
|
|
10
|
+
// requiredClaims?: string[];
|
|
11
|
+
// requiredData?: (data: DocumentData | null) => boolean;
|
|
12
|
+
// allowIf?: (user: typeof firekitUser) => boolean;
|
|
13
|
+
// redirectParams?: Record<string, string>;
|
|
14
|
+
// }
|
|
15
|
+
// export class FirekitAuthGuard {
|
|
16
|
+
// private static instance: FirekitAuthGuard;
|
|
17
|
+
// private _loading = $state(true);
|
|
18
|
+
// private _error = $state<Error | null>(null);
|
|
19
|
+
// private _lastValidationTime = 0;
|
|
20
|
+
// private readonly VALIDATION_THROTTLE = 1000; // 1 second
|
|
21
|
+
// private constructor() { }
|
|
22
|
+
// static getInstance(): FirekitAuthGuard {
|
|
23
|
+
// if (!FirekitAuthGuard.instance) {
|
|
24
|
+
// FirekitAuthGuard.instance = new FirekitAuthGuard();
|
|
25
|
+
// }
|
|
26
|
+
// return FirekitAuthGuard.instance;
|
|
27
|
+
// }
|
|
28
|
+
// private shouldThrottleValidation(): boolean {
|
|
29
|
+
// const now = Date.now();
|
|
30
|
+
// if (now - this._lastValidationTime < this.VALIDATION_THROTTLE) {
|
|
31
|
+
// return true;
|
|
32
|
+
// }
|
|
33
|
+
// this._lastValidationTime = now;
|
|
34
|
+
// return false;
|
|
35
|
+
// }
|
|
36
|
+
// private async handleRedirect(redirectTo: string, params?: Record<string, string>): Promise<void> {
|
|
37
|
+
// const url = new URL(redirectTo, window.location.origin);
|
|
38
|
+
// if (params) {
|
|
39
|
+
// Object.entries(params).forEach(([key, value]) => {
|
|
40
|
+
// url.searchParams.append(key, value);
|
|
41
|
+
// });
|
|
42
|
+
// }
|
|
43
|
+
// await goto(url.toString());
|
|
44
|
+
// }
|
|
45
|
+
// private async validateClaims(requiredClaims: string[], userClaims?: UserClaims): Promise<boolean> {
|
|
46
|
+
// if (!requiredClaims.length) return true;
|
|
47
|
+
// if (!userClaims) return false;
|
|
48
|
+
// return requiredClaims.every(claim => userClaims[claim]);
|
|
49
|
+
// }
|
|
50
|
+
// async validateAuth({
|
|
51
|
+
// authRequired = true,
|
|
52
|
+
// redirectTo = '/login',
|
|
53
|
+
// requiredClaims = [],
|
|
54
|
+
// requiredData,
|
|
55
|
+
// allowIf,
|
|
56
|
+
// redirectParams
|
|
57
|
+
// }: GuardConfig = {}): Promise<boolean> {
|
|
58
|
+
// if (!browser) return true;
|
|
59
|
+
// if (this.shouldThrottleValidation()) return true;
|
|
60
|
+
// try {
|
|
61
|
+
// this._loading = true;
|
|
62
|
+
// this._error = null;
|
|
63
|
+
// await firekitUser.waitForInit();
|
|
64
|
+
// const isAuthenticated = firekitUser.isLoggedIn;
|
|
65
|
+
// if (authRequired && !isAuthenticated) {
|
|
66
|
+
// await this.handleRedirect(redirectTo, {
|
|
67
|
+
// ...redirectParams,
|
|
68
|
+
// returnTo: window.location.pathname
|
|
69
|
+
// });
|
|
70
|
+
// return false;
|
|
71
|
+
// }
|
|
72
|
+
// if (allowIf && !allowIf(firekitUser)) {
|
|
73
|
+
// await this.handleRedirect(redirectTo, redirectParams);
|
|
74
|
+
// return false;
|
|
75
|
+
// }
|
|
76
|
+
// if (requiredClaims.length > 0) {
|
|
77
|
+
// const userClaims = await firekitUser.user?.getIdTokenResult();
|
|
78
|
+
// const hasClaims = await this.validateClaims(requiredClaims, userClaims?.claims);
|
|
79
|
+
// if (!hasClaims) {
|
|
80
|
+
// await this.handleRedirect(redirectTo, redirectParams);
|
|
81
|
+
// return false;
|
|
82
|
+
// }
|
|
83
|
+
// }
|
|
84
|
+
// if (requiredData && !requiredData(firekitUser.data)) {
|
|
85
|
+
// await this.handleRedirect(redirectTo, redirectParams);
|
|
86
|
+
// return false;
|
|
87
|
+
// }
|
|
88
|
+
// return true;
|
|
89
|
+
// } catch (error) {
|
|
90
|
+
// this._error = error instanceof Error ? error : new Error(String(error));
|
|
91
|
+
// return false;
|
|
92
|
+
// } finally {
|
|
93
|
+
// this._loading = false;
|
|
94
|
+
// }
|
|
95
|
+
// }
|
|
96
|
+
// async requireAuth(redirectTo = '/login', redirectParams?: Record<string, string>) {
|
|
97
|
+
// return this.validateAuth({ authRequired: true, redirectTo, redirectParams });
|
|
98
|
+
// }
|
|
99
|
+
// async requireNoAuth(redirectTo = '/dashboard', redirectParams?: Record<string, string>) {
|
|
100
|
+
// return this.validateAuth({ authRequired: false, redirectTo, redirectParams });
|
|
101
|
+
// }
|
|
102
|
+
// async requireClaims(claims: string[], redirectTo = '/login', redirectParams?: Record<string, string>) {
|
|
103
|
+
// return this.validateAuth({ requiredClaims: claims, redirectTo, redirectParams });
|
|
104
|
+
// }
|
|
105
|
+
// async requireData(
|
|
106
|
+
// validator: (data: DocumentData | null) => boolean,
|
|
107
|
+
// redirectTo = '/login',
|
|
108
|
+
// redirectParams?: Record<string, string>
|
|
109
|
+
// ) {
|
|
110
|
+
// return this.validateAuth({ requiredData: validator, redirectTo, redirectParams });
|
|
111
|
+
// }
|
|
112
|
+
// get loading() {
|
|
113
|
+
// return this._loading;
|
|
114
|
+
// }
|
|
115
|
+
// get error() {
|
|
116
|
+
// return this._error;
|
|
117
|
+
// }
|
|
118
|
+
// }
|
|
119
|
+
// export const firekitAuthGuard = FirekitAuthGuard.getInstance();
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { type User } from "firebase/auth";
|
|
2
|
+
import { type DocumentData } from "firebase/firestore";
|
|
3
|
+
type UserClaims = Record<string, any>;
|
|
4
|
+
interface UserData extends DocumentData {
|
|
5
|
+
displayName?: string;
|
|
6
|
+
email?: string;
|
|
7
|
+
photoURL?: string;
|
|
8
|
+
createdAt?: Date;
|
|
9
|
+
updatedAt?: Date;
|
|
10
|
+
isProfileComplete?: boolean;
|
|
11
|
+
role?: string;
|
|
12
|
+
settings?: Record<string, any>;
|
|
13
|
+
[key: string]: any;
|
|
14
|
+
}
|
|
15
|
+
interface GuardConfig {
|
|
16
|
+
authRequired?: boolean;
|
|
17
|
+
redirectTo?: string;
|
|
18
|
+
requiredClaims?: string[];
|
|
19
|
+
requiredData?: (data: DocumentData | null) => boolean;
|
|
20
|
+
allowIf?: (manager: FirekitAuthManager) => boolean;
|
|
21
|
+
redirectParams?: Record<string, string>;
|
|
22
|
+
}
|
|
23
|
+
export declare class FirekitAuthManager {
|
|
24
|
+
private static instance;
|
|
25
|
+
private _user;
|
|
26
|
+
private _userData;
|
|
27
|
+
private _claims;
|
|
28
|
+
private _initialized;
|
|
29
|
+
private _initPromise;
|
|
30
|
+
private _loading;
|
|
31
|
+
private _error;
|
|
32
|
+
private _lastValidationTime;
|
|
33
|
+
private readonly VALIDATION_THROTTLE;
|
|
34
|
+
readonly isLoggedIn: boolean;
|
|
35
|
+
readonly uid: string | undefined;
|
|
36
|
+
readonly email: string | null | undefined;
|
|
37
|
+
readonly displayName: string | null | undefined;
|
|
38
|
+
readonly photoURL: string | null | undefined;
|
|
39
|
+
readonly emailVerified: boolean | undefined;
|
|
40
|
+
readonly claims: UserClaims;
|
|
41
|
+
readonly data: UserData | null;
|
|
42
|
+
readonly initialized: boolean;
|
|
43
|
+
private constructor();
|
|
44
|
+
static getInstance(): FirekitAuthManager;
|
|
45
|
+
private initialize;
|
|
46
|
+
waitForInit(): Promise<void>;
|
|
47
|
+
private loadUserData;
|
|
48
|
+
private loadUserClaims;
|
|
49
|
+
get user(): User | null | undefined;
|
|
50
|
+
updateEmailUser(email: string): Promise<void>;
|
|
51
|
+
updatePassword(password: string): Promise<void>;
|
|
52
|
+
updateProfileInfo({ displayName, photoURL, }: {
|
|
53
|
+
displayName?: string;
|
|
54
|
+
photoURL?: string;
|
|
55
|
+
}): Promise<void>;
|
|
56
|
+
updateUserData(data: Partial<UserData>): Promise<void>;
|
|
57
|
+
saveUserData(data: UserData): Promise<void>;
|
|
58
|
+
hasRequiredClaims(requiredClaims: string[]): boolean;
|
|
59
|
+
isAdmin(): boolean;
|
|
60
|
+
isPremium(): boolean;
|
|
61
|
+
private shouldThrottleValidation;
|
|
62
|
+
private handleRedirect;
|
|
63
|
+
private validateClaims;
|
|
64
|
+
validateAuth({ authRequired, redirectTo, requiredClaims, requiredData, allowIf, redirectParams, }?: GuardConfig): Promise<boolean>;
|
|
65
|
+
requireAuth(redirectTo?: string, redirectParams?: Record<string, string>): Promise<boolean>;
|
|
66
|
+
requireNoAuth(redirectTo?: string, redirectParams?: Record<string, string>): Promise<boolean>;
|
|
67
|
+
requireClaims(claims: string[], redirectTo?: string, redirectParams?: Record<string, string>): Promise<boolean>;
|
|
68
|
+
requireData(validator: (data: DocumentData | null) => boolean, redirectTo?: string, redirectParams?: Record<string, string>): Promise<boolean>;
|
|
69
|
+
get loading(): boolean;
|
|
70
|
+
get error(): Error | null;
|
|
71
|
+
}
|
|
72
|
+
export declare const firekitAuthManager: FirekitAuthManager;
|
|
73
|
+
export {};
|