feat: more docs

This commit is contained in:
Bereket Engida
2024-09-02 13:01:25 +03:00
parent 7234291718
commit 94919e7d48
27 changed files with 1001 additions and 977 deletions

View File

@@ -14,11 +14,6 @@ export const authClient = createAuthClient({
], ],
}); });
export const {
useSession,
useActiveOrganization,
useInvitation,
useListOrganization,
} = authClient;
authClient.signInPasskey(); authClient.signInPasskey();
const res = authClient.useActiveOrganization();

View File

@@ -0,0 +1,29 @@
import { organization } from "better-auth/plugins";
import { createAccessControl, AccessControl } from "better-auth/plugins/access";
const statement = {
project: ["create"],
};
const ac = createAccessControl(statement);
const member = ac.newRole({
project: ["create"],
});
const owner = ac.newRole({
project: ["create", "share", "delete"],
});
const admin = ac.newRole({
project: ["create", "share", "delete"],
});
organization({
ac,
roles: {
member,
owner,
admin,
},
});

View File

@@ -1,3 +1,5 @@
import { createAuthClient } from "better-auth/vue"; import { createAuthClient } from "better-auth/vue";
import { organizationClient } from "better-auth/client";
export const client = createAuthClient(); export const client = createAuthClient({
authPlugins: [organizationClient()],
});

View File

@@ -1,5 +1,6 @@
import { env } from "$env/dynamic/private"; import { env } from "$env/dynamic/private";
import { betterAuth } from "better-auth"; import { betterAuth } from "better-auth";
import { organization } from "better-auth/plugins";
import { github } from "better-auth/social-providers"; import { github } from "better-auth/social-providers";
export const auth = betterAuth({ export const auth = betterAuth({
@@ -13,4 +14,9 @@ export const auth = betterAuth({
clientSecret: env.GITHUB_CLIENT_SECRET, clientSecret: env.GITHUB_CLIENT_SECRET,
}), }),
], ],
plugins: [
organization({
async sendInvitationEmail(invitation, email) {},
}),
],
}); });

View File

@@ -1,7 +1,7 @@
import { createAuthClient } from "better-auth/svelte"; import { createAuthClient } from "better-auth/svelte";
import { organization } from "better-auth/client"; import { organizationClient } from "better-auth/client";
export const client = createAuthClient({ export const client = createAuthClient({
baseURL: "http://localhost:3000/api/auth", baseURL: "http://localhost:3000/api/auth",
authPlugins: [organization], authPlugins: [organizationClient()],
}); });

View File

@@ -4,51 +4,58 @@
@layer base { @layer base {
:root { :root {
--background: 360 74% 95%; --background: 0 0% 100%;
--foreground: 360 5% 0%; --foreground: 240 10% 3.9%;
--card: 360 50% 90%; --card: 0 0% 100%;
--card-foreground: 360 5% 10%; --card-foreground: 240 10% 3.9%;
--popover: 360 74% 95%; --popover: 0 0% 100%;
--popover-foreground: 360 95% 0%; --popover-foreground: 240 10% 3.9%;
--primary: 360 0% 90%; --primary: 240 5.9% 10%;
--primary-foreground: 0 0% 0%; --primary-foreground: 0 0% 98%;
--secondary: 360 30% 70%; --secondary: 240 4.8% 95.9%;
--secondary-foreground: 0 0% 0%; --secondary-foreground: 240 5.9% 10%;
--muted: 322 30% 85%; --muted: 240 4.8% 95.9%;
--muted-foreground: 360 5% 35%; --muted-foreground: 240 3.8% 46.1%;
--accent: 322 30% 80%; --accent: 240 4.8% 95.9%;
--accent-foreground: 360 5% 10%; --accent-foreground: 240 5.9% 10%;
--destructive: 0 74% 30%; --destructive: 0 84.2% 60.2%;
--destructive-foreground: 360 5% 90%; --destructive-foreground: 0 0% 98%;
--border: 360 30% 50%; --border: 240 5.9% 90%;
--input: 360 30% 18%; --input: 240 5.9% 90%;
--ring: 360 0% 90%; --ring: 240 4.9% 83.9%;
--radius: 0.5rem; --radius: 0.5rem;
--chart-1: 12 76% 61%;
--chart-2: 173 58% 39%;
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%
} }
.dark { .dark {
--background: 360 50% 5%; --background: 360 50% 5%;
--foreground: 360 5% 90%; --foreground: 0 0% 98%;
--card: 360 50% 0%; --card: 240 10% 3.9%;
--card-foreground: 360 5% 90%; --card-foreground: 0 0% 98%;
--popover: 360 50% 5%; --popover: 240 10% 3.9%;
--popover-foreground: 360 5% 90%; --popover-foreground: 0 0% 98%;
--primary: 360 0% 90%; --primary: 0 0% 98%;
--primary-foreground: 0 0% 0%; --primary-foreground: 240 5.9% 10%;
--secondary: 360 30% 10%; --secondary: 240 3.7% 15.9%;
--secondary-foreground: 0 0% 100%; --secondary-foreground: 0 0% 98%;
--muted: 322 30% 15%; --muted: 240 3.7% 15.9%;
--muted-foreground: 360 5% 60%; --muted-foreground: 240 5% 64.9%;
--accent: 322 30% 15%; --accent: 240 3.7% 15.9%;
--accent-foreground: 360 5% 90%; --accent-foreground: 0 0% 98%;
--destructive: 0 74% 30%; --destructive: 0 62.8% 30.6%;
--destructive-foreground: 360 5% 90%; --destructive-foreground: 0 0% 98%;
--border: 360 30% 18%; --border: 240 3.7% 15.9%;
--input: 360 30% 18%; --input: 240 3.7% 15.9%;
--ring: 360 0% 90%; --ring: 240 4.9% 83.9%;
--radius: 0.5rem; --chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
} }
} }

22
docs/components/icons.tsx Normal file
View File

@@ -0,0 +1,22 @@
export const Icons = {
nextJS: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10s-4.477 10-10 10m4-14h-1.35v4H16zM9.346 9.71l6.059 7.828l1.054-.809L9.683 8H8v7.997h1.346z"></path></svg>
),
nuxt: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 512 512"><path fill="currentColor" d="M200.662 81.35L0 430.65h130.774l139.945-239.803zm134.256 40.313l-39.023 69.167l138.703 239.82H512zm-51.596 91.052L155.924 430.651h253.485z"></path></svg>
),
svelteKit: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 426 512"><path fill="currentColor" d="M403.508 229.23C491.235 87.7 315.378-58.105 190.392 23.555L71.528 99.337c-57.559 37.487-82.55 109.513-47.45 183.53c-87.761 133.132 83.005 289.03 213.116 205.762l118.864-75.782c64.673-42.583 79.512-116.018 47.45-183.616m-297.592-80.886l118.69-75.739c77.973-46.679 167.756 34.942 135.388 110.992c-19.225-15.274-40.65-24.665-56.923-28.894c6.186-24.57-22.335-42.796-42.174-30.106l-118.95 75.48c-29.411 20.328 1.946 62.138 31.014 44.596l45.33-28.895c101.725-57.403 198 80.425 103.38 147.975l-118.692 75.739C131.455 485.225 34.11 411.96 67.592 328.5c17.786 13.463 36.677 23.363 56.923 28.894c-4.47 28.222 24.006 41.943 42.476 30.365L285.64 312.02c29.28-21.955-2.149-61.692-30.97-44.595l-45.504 28.894c-100.56 58.77-199.076-80.42-103.25-147.975"></path></svg>
),
solidStart: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 128 128"><path fill="currentColor" d="M61.832 4.744c-3.205.058-6.37.395-9.45 1.07l-2.402.803c-4.806 1.603-8.813 4.005-11.216 7.21l-1.602 2.404l-12.017 20.828l.166.031c-4.785 5.823-5.007 14.07-.166 21.6c1.804 2.345 4.073 4.431 6.634 6.234l-15.445 4.982L.311 97.946s42.46 32.044 75.306 24.033l2.403-.801c5.322-1.565 9.292-4.48 11.683-8.068l.334.056l16.022-28.84c3.204-5.608 2.404-12.016-1.602-18.425a36 36 0 0 0-7.059-6.643l15.872-5.375l14.42-24.033S92.817 4.19 61.831 4.744z"></path></svg>
),
react: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 15 15"><path fill="currentColor" fillRule="evenodd" d="M5.315 1.837c-.4-.116-.695-.085-.91.032c-.216.116-.404.347-.526.745c-.122.401-.163.936-.104 1.582q.015.157.037.321a14 14 0 0 1 1.676-.311a13 13 0 0 1 1.275-1.54l-.066-.053c-.508-.402-.98-.66-1.382-.776m2.185.14q-.09-.076-.182-.148C6.746 1.377 6.16 1.04 5.594.876C5.024.711 4.441.711 3.928.99s-.833.767-1.005 1.334c-.172.564-.21 1.238-.144 1.965q.023.255.065.523q-.256.09-.49.192c-.671.287-1.246.642-1.66 1.062C.278 6.487 0 7 0 7.584S.278 8.68.694 9.103c.414.42.989.774 1.66 1.062q.235.1.49.192a9 9 0 0 0-.065.523c-.066.726-.028 1.4.144 1.965c.172.567.492 1.056 1.005 1.333c.513.278 1.097.279 1.666.114c.566-.165 1.152-.5 1.724-.953l.182-.149q.09.076.182.149c.572.452 1.158.788 1.724.953c.569.165 1.153.164 1.666-.114c.513-.277.833-.766 1.005-1.333c.172-.564.21-1.239.144-1.965a9 9 0 0 0-.065-.523q.255-.09.49-.192c.671-.288 1.246-.643 1.66-1.062c.416-.422.694-.936.694-1.52c0-.582-.278-1.096-.694-1.518c-.414-.42-.989-.775-1.66-1.062a9 9 0 0 0-.49-.192q.04-.268.065-.523c.066-.727.028-1.4-.144-1.965c-.172-.567-.492-1.056-1.005-1.334S9.975.711 9.406.876c-.566.164-1.152.5-1.724.953zm0 1.365q-.338.346-.672.755a17 17 0 0 1 1.344 0a11 11 0 0 0-.672-.755m2.012.864c-.41-.574-.84-1.092-1.275-1.54l.065-.053c.51-.402.98-.66 1.383-.776c.399-.116.695-.085.91.032c.216.116.404.347.525.745c.122.401.164.936.105 1.582q-.015.158-.037.32a14 14 0 0 0-1.676-.31m-.563.944a15.6 15.6 0 0 0-2.898 0A15.6 15.6 0 0 0 4.72 7.584a15.7 15.7 0 0 0 1.33 2.433a15.6 15.6 0 0 0 2.9 0a15.6 15.6 0 0 0 1.33-2.433A15.7 15.7 0 0 0 8.95 5.15m1.824 1.138a17 17 0 0 0-.527-.956q.39.075.752.168q-.094.385-.225.788m0 2.591a17 17 0 0 1-.527.957q.39-.075.752-.169a12 12 0 0 0-.225-.788m1.18.487a14 14 0 0 0-.588-1.782c.246-.61.443-1.209.588-1.782q.154.058.3.12c.596.256 1.047.547 1.341.845c.292.296.406.572.406.817s-.114.52-.406.816c-.294.299-.745.59-1.341.846a8 8 0 0 1-.3.12m-.765 1.285a14 14 0 0 1-1.676.311c-.41.574-.84 1.091-1.275 1.54l.066.052c.508.403.98.66 1.382.777c.399.116.695.085.91-.032s.404-.348.525-.746c.123-.4.164-.936.105-1.582a7 7 0 0 0-.037-.32M7.5 11.826q.338-.346.672-.755a17 17 0 0 1-1.344 0q.334.408.672.755m-2.746-1.99a17 17 0 0 1-.527-.957q-.13.404-.225.788q.361.094.752.169m-.942.815a14 14 0 0 0 1.676.311c.41.574.839 1.091 1.275 1.54l-.066.052c-.508.403-.98.66-1.382.777c-.4.116-.695.085-.911-.032s-.403-.348-.525-.746c-.122-.4-.163-.936-.104-1.582a8 8 0 0 1 .037-.32m-.765-1.285c.145-.574.341-1.172.588-1.782a14 14 0 0 1-.588-1.782q-.155.058-.3.12c-.596.256-1.047.547-1.341.845c-.292.296-.406.572-.406.817s.114.52.406.816c.294.299.745.59 1.341.846q.146.061.3.12m.955-3.865q.094.384.225.787a17 17 0 0 1 .527-.956q-.39.075-.752.169M6 7.584a1.5 1.5 0 1 1 3 0a1.5 1.5 0 0 1-3 0m1.5-.5a.5.5 0 1 0 0 1a.5.5 0 0 0 0-1" clipRule="evenodd"></path></svg>
),
hono: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 256 330"><path fill="#9E9494" d="M134.129.029q1.315-.17 2.319.662a1256 1256 0 0 1 69.573 93.427q24.141 36.346 41.082 76.862q27.055 72.162-28.16 125.564q-48.313 40.83-111.318 31.805q-75.312-15.355-102.373-87.133Q-1.796 217.85.614 193.51q4.014-41.896 19.878-80.838q6.61-15.888 17.228-29.154a382 382 0 0 1 16.565 21.203q3.66 3.825 7.62 7.289Q92.138 52.013 134.13.029" opacity=".993"></path><path fill="#3C2020" d="M129.49 53.7q36.47 42.3 65.93 90.114a187.3 187.3 0 0 1 15.24 33.13q12.507 49.206-26.836 81.169q-38.05 26.774-83.488 15.902q-48.999-15.205-56.653-65.929q-1.857-15.993 3.314-31.142a225.4 225.4 0 0 1 17.89-35.78l19.878-29.155a5510 5510 0 0 0 44.726-58.31"></path></svg>
)
}

View File

@@ -2,12 +2,13 @@
import { GridPattern } from "./grid-pattern"; import { GridPattern } from "./grid-pattern";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import clsx from "clsx"; import clsx from "clsx";
import { Github } from "lucide-react"; import { Github, Icon } from "lucide-react";
import { useTheme } from "next-themes"; import { useTheme } from "next-themes";
import Link from "next/link"; import Link from "next/link";
import { Highlight, themes } from "prism-react-renderer"; import { Highlight, themes } from "prism-react-renderer";
import { Fragment, useId, useState } from "react"; import { Fragment, useEffect, useId, useState } from "react";
import { LayoutGroup, motion } from "framer-motion" import { LayoutGroup, motion } from "framer-motion"
import { Icons } from "../icons";
function Glow() { function Glow() {
@@ -51,7 +52,7 @@ function Glow() {
const tabs = [ const tabs = [
{ {
name: "server.ts", code: `export const auth = betterAuth({ name: "auth.ts", code: `export const auth = betterAuth({
database: { database: {
provider: "postgresql", provider: "postgresql",
url: process.env.DATABASE_URL, url: process.env.DATABASE_URL,
@@ -85,8 +86,10 @@ function TrafficLightsIcon(props: React.ComponentPropsWithoutRef<"svg">) {
export default function Hero() { export default function Hero() {
const theme = useTheme(); const theme = useTheme();
const [activeTab, setActiveTab] = useState("server.ts"); const [activeTab, setActiveTab] = useState("auth.ts");
const code = tabs.find((tab) => tab.name === activeTab)?.code ?? ""; const code = tabs.find((tab) => tab.name === activeTab)?.code ?? "";
return ( return (
<section className="flex mt-1 min-h-screen items-center justify-center gap-20 p-5"> <section className="flex mt-1 min-h-screen items-center justify-center gap-20 p-5">
<div className="overflow-hidden bg-transparent dark:-mb-32 dark:mt-[-4.75rem] dark:pb-32 dark:pt-[4.75rem] px-10"> <div className="overflow-hidden bg-transparent dark:-mb-32 dark:mt-[-4.75rem] dark:pb-32 dark:pt-[4.75rem] px-10">
@@ -122,16 +125,10 @@ export default function Hero() {
<div className="absolute inset-0 rounded-none bg-gradient-to-tr from-stone-300 via-stone-300/70 to-blue-300 opacity-5" /> */} <div className="absolute inset-0 rounded-none bg-gradient-to-tr from-stone-300 via-stone-300/70 to-blue-300 opacity-5" /> */}
<LayoutGroup > <LayoutGroup >
<motion.div <motion.div
layoutId="hero" layoutId="hero"
animate={{
y: [10, -10, 0], className="relative rounded-sm bg-gradient-to-tr from-stone-100 to-stone-200 dark:from-stone-950/70 dark:to-stone-900/90 ring-1 ring-white/10 backdrop-blur-lg">
transition: {
duration: 2,
stiffness: 10,
type: "just"
},
}}
className="relative rounded-sm bg-gradient-to-tr from-stone-50 to-stone-100 dark:from-stone-950/70 dark:to-stone-900/90 ring-1 ring-white/10 backdrop-blur-lg">
<div className="absolute -top-px left-0 right-0 h-px " /> <div className="absolute -top-px left-0 right-0 h-px " />
<div className="absolute -bottom-px left-11 right-20 h-px" /> <div className="absolute -bottom-px left-11 right-20 h-px" />
<div className="pl-4 pt-4"> <div className="pl-4 pt-4">
@@ -185,6 +182,7 @@ export default function Hero() {
))} ))}
</div> </div>
<Highlight <Highlight
key={theme.resolvedTheme}
code={code} code={code}
language={"javascript"} language={"javascript"}
theme={{ theme={{
@@ -192,7 +190,8 @@ export default function Hero() {
plain: { plain: {
backgroundColor: "transparent", backgroundColor: "transparent",
} }
}} }
}
> >
{({ {({
@@ -212,7 +211,6 @@ export default function Hero() {
<code className="px-4"> <code className="px-4">
{tokens.map((line, lineIndex) => ( {tokens.map((line, lineIndex) => (
<div <div
key={lineIndex} key={lineIndex}
{...getLineProps({ line })} {...getLineProps({ line })}
> >
@@ -231,6 +229,7 @@ export default function Hero() {
</div> </div>
</div> </div>
</motion.div> </motion.div>
</LayoutGroup> </LayoutGroup>
</div> </div>
</div> </div>
@@ -238,7 +237,7 @@ export default function Hero() {
</div> </div>
</div> </div>
<GridPattern <GridPattern
className="absolute inset-x-0 -top-14 -z-10 h-full w-full dark:fill-secondary/20 fill-neutral-100 dark:stroke-secondary/30 stroke-neutral-700/5 [mask-image:linear-gradient(to_bottom_left,white_40%,transparent_50%)]" className="absolute inset-x-0 -top-14 -z-10 h-full w-full dark:fill-secondary/30 fill-neutral-100 dark:stroke-secondary/30 stroke-neutral-700/5 [mask-image:linear-gradient(to_bottom_left,white_40%,transparent_50%)]"
yOffset={-96} yOffset={-96}
interactive interactive
/> />
@@ -248,7 +247,6 @@ export default function Hero() {
export function HeroBackground(props: React.ComponentPropsWithoutRef<"svg">) { export function HeroBackground(props: React.ComponentPropsWithoutRef<"svg">) {
const id = useId(); const id = useId();
return ( return (
<svg <svg
aria-hidden="true" aria-hidden="true"

View File

@@ -7,15 +7,11 @@ import {
} from "@/components/ui/accordion"; } from "@/components/ui/accordion";
import { AsideLink } from "@/components/ui/aside-link"; import { AsideLink } from "@/components/ui/aside-link";
import { FadeIn, FadeInStagger } from "@/components/ui/fade-in"; import { FadeIn, FadeInStagger } from "@/components/ui/fade-in";
import { Key, LucideAArrowDown, LucideIcon, MailCheck, ScanFace, Search, Users2, UserSquare2 } from "lucide-react"; import { Suspense } from "react";
import { ReactNode, Suspense, SVGProps, useState } from "react";
import {
SearchDialog,
type SharedProps
} from 'fumadocs-ui/components/dialog/search'
import { useSearchContext } from "fumadocs-ui/provider"; import { useSearchContext } from "fumadocs-ui/provider";
import { Input } from "./ui/input";
import { usePathname } from "next/navigation"; import { usePathname } from "next/navigation";
import { contents } from "./sidebar-content";
import { Search } from "lucide-react";
export default function ArticleLayout() { export default function ArticleLayout() {
const { setOpenSearch } = useSearchContext() const { setOpenSearch } = useSearchContext()
const pathname = usePathname() const pathname = usePathname()
@@ -25,7 +21,7 @@ export default function ArticleLayout() {
} }
return ( return (
<aside className="border-r border-lines md:block hidden overflow-y-auto min-w-[--fd-sidebar-width] h-full sticky top-[60px] min-h-[92dvh]"> <aside className="border-r border-lines md:block hidden overflow-y-auto min-w-[--fd-sidebar-width] h-full sticky top-[60px] min-h-[92dvh]">
<div className="flex items-center gap-2 p-2 px-4 border-b bg-gradient-to-br from-stone-900 to-stone-950/80" onClick={() => { <div className="flex items-center gap-2 p-2 px-4 border-b bg-gradient-to-br dark:from-stone-900 dark:to-stone-950/80" onClick={() => {
setOpenSearch(true) setOpenSearch(true)
}}> }}>
<Search className="h-4 w-4" /> <Search className="h-4 w-4" />
@@ -83,445 +79,5 @@ export default function ArticleLayout() {
); );
} }
interface Content {
title: string;
href?: string;
Icon: ((props?: SVGProps<any>) => ReactNode) | LucideIcon;
list: {
title: string;
href: string;
icon: ((props?: SVGProps<any>) => ReactNode) | LucideIcon;
group?: boolean;
}[];
}
const contents: Content[] = [
{
title: "Get Started",
Icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.4em"
height="1.4em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2m-1 14H9V8h2zm1 0V8l5 4z"
/>
</svg>
),
list: [
{
title: "Introduction",
href: "/docs/introduction",
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 256 256"
>
<path
fill="currentColor"
d="M232 48h-64a32 32 0 0 0-32 32v87.73a8.17 8.17 0 0 1-7.47 8.25a8 8 0 0 1-8.53-8V80a32 32 0 0 0-32-32H24a8 8 0 0 0-8 8v144a8 8 0 0 0 8 8h72a24 24 0 0 1 24 23.94a7.9 7.9 0 0 0 5.12 7.55A8 8 0 0 0 136 232a24 24 0 0 1 24-24h72a8 8 0 0 0 8-8V56a8 8 0 0 0-8-8m-24 120h-39.73a8.17 8.17 0 0 1-8.25-7.47a8 8 0 0 1 8-8.53h39.73a8.17 8.17 0 0 1 8.25 7.47a8 8 0 0 1-8 8.53m0-32h-39.73a8.17 8.17 0 0 1-8.25-7.47a8 8 0 0 1 8-8.53h39.73a8.17 8.17 0 0 1 8.25 7.47a8 8 0 0 1-8 8.53m0-32h-39.73a8.17 8.17 0 0 1-8.27-7.47a8 8 0 0 1 8-8.53h39.73a8.17 8.17 0 0 1 8.27 7.47a8 8 0 0 1-8 8.53"
/>
</svg>
),
},
{
title: "Installation",
href: "/docs/installation",
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M2 12c0-4.714 0-7.071 1.464-8.536C4.93 2 7.286 2 12 2c4.714 0 7.071 0 8.535 1.464C22 4.93 22 7.286 22 12c0 4.714 0 7.071-1.465 8.535C19.072 22 16.714 22 12 22s-7.071 0-8.536-1.465C2 19.072 2 16.714 2 12m10-5.75a.75.75 0 0 1 .75.75v5.19l1.72-1.72a.75.75 0 1 1 1.06 1.06l-3 3a.75.75 0 0 1-1.06 0l-3-3a.75.75 0 1 1 1.06-1.06l1.72 1.72V7a.75.75 0 0 1 .75-.75m-4 10a.75.75 0 0 0 0 1.5h8a.75.75 0 0 0 0-1.5z"
clipRule="evenodd"
/>
</svg>
),
},
{
title: "Basic Usage",
href: "/docs/basic-usage",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 24 24"><path fill="currentColor" d="M21 2H3c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2M10 19.4l-1.6.6C6.9 18.6 6 16.6 6 14.5s.9-4.1 2.4-5.5l1.6.6c-1.3 1.1-2 3-2 4.9s.7 3.7 2 4.9m5.6.6l-1.6-.6c1.3-1.2 2-3 2-4.9s-.7-3.7-2-4.9l1.6-.6c1.5 1.4 2.4 3.4 2.4 5.5s-.9 4.1-2.4 5.5M21 7H3V4h18z"></path></svg>
),
},
],
},
{
title: "Authentication",
Icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.4em"
height="1.4em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M10 4h4c3.771 0 5.657 0 6.828 1.172C22 6.343 22 8.229 22 12c0 3.771 0 5.657-1.172 6.828C19.657 20 17.771 20 14 20h-4c-3.771 0-5.657 0-6.828-1.172C2 17.657 2 15.771 2 12c0-3.771 0-5.657 1.172-6.828C4.343 4 6.229 4 10 4m3.25 5a.75.75 0 0 1 .75-.75h5a.75.75 0 0 1 0 1.5h-5a.75.75 0 0 1-.75-.75m1 3a.75.75 0 0 1 .75-.75h4a.75.75 0 0 1 0 1.5h-4a.75.75 0 0 1-.75-.75m1 3a.75.75 0 0 1 .75-.75h3a.75.75 0 0 1 0 1.5h-3a.75.75 0 0 1-.75-.75M11 9a2 2 0 1 1-4 0a2 2 0 0 1 4 0m-2 8c4 0 4-.895 4-2s-1.79-2-4-2s-4 .895-4 2s0 2 4 2"
clipRule="evenodd"
/>
</svg>
),
list: [
{
title: "Email & Password",
group: true,
href: "/docs/email-password",
icon: () => (
<svg>
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm4.59-12.42L10 14.17l-2.59-2.58L6 13l4 4 8-8z"></path>
</svg>
)
},
{
title: "Sign-In & Sign-Up",
href: "/docs/email-password/sign-in-and-sign-up",
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M3.172 5.172C2 6.343 2 8.229 2 12c0 3.771 0 5.657 1.172 6.828C4.343 20 6.229 20 10 20h4c3.771 0 5.657 0 6.828-1.172C22 17.657 22 15.771 22 12c0-3.771 0-5.657-1.172-6.828C19.657 4 17.771 4 14 4h-4C6.229 4 4.343 4 3.172 5.172M8 13a1 1 0 1 0 0-2a1 1 0 0 0 0 2m5-1a1 1 0 1 1-2 0a1 1 0 0 1 2 0m3 1a1 1 0 1 0 0-2a1 1 0 0 0 0 2"
clipRule="evenodd"
/>
</svg>
)
},
{
title: "Password Reset",
href: "/docs/email-password/password-reset",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M15.75 2a.75.75 0 0 0-1.5 0v20a.75.75 0 0 0 1.5 0v-2.006c2.636-.027 4.104-.191 5.078-1.166C22 17.657 22 15.771 22 12s0-5.657-1.172-6.828c-.974-.975-2.442-1.139-5.078-1.166z"></path><path fill="currentColor" fillRule="evenodd" d="M3.172 18.828C4.343 20 6.229 20 10 20h3V4h-3C6.229 4 4.343 4 3.172 5.172S2 8.229 2 12s0 5.657 1.172 6.828M13 12a1 1 0 1 0-2 0a1 1 0 0 0 2 0m-4 0a1 1 0 1 1-2 0a1 1 0 0 1 2 0" clipRule="evenodd"></path></svg>
)
},
{
title: "Configuration",
href: "/docs/email-password/configuration",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 48 48"><defs><mask id="ipSConfig0"><g fill="none" stroke-linejoin="round" stroke-width="4"><path fill="#fff" stroke="#fff" d="m24 4l-6 6h-8v8l-6 6l6 6v8h8l6 6l6-6h8v-8l6-6l-6-6v-8h-8z"></path><path fill="#000" stroke="#000" d="M24 30a6 6 0 1 0 0-12a6 6 0 0 0 0 12Z"></path></g></mask></defs><path fill="currentColor" d="M0 0h48v48H0z" mask="url(#ipSConfig0)"></path></svg>
)
},
{
title: "Social Sign-On",
group: true,
href: "/docs/providers/social-providers",
icon: () => (
<svg>
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm4.59-12.42L10 14.17l-2.59-2.58L6 13l4 4 8-8z"></path>
</svg>
)
},
{
title: "Apple",
href: "/docs/providers/apple",
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 20 20"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M14.122 4.682c1.35 0 2.781.743 3.8 2.028c-3.34 1.851-2.797 6.674.578 7.963c-.465 1.04-.687 1.505-1.285 2.426c-.835 1.284-2.01 2.884-3.469 2.898c-1.295.012-1.628-.853-3.386-.843c-1.758.01-2.125.858-3.42.846c-1.458-.014-2.573-1.458-3.408-2.743C1.198 13.665.954 9.45 2.394 7.21C3.417 5.616 5.03 4.683 6.548 4.683c1.545 0 2.516.857 3.794.857c1.24 0 1.994-.858 3.78-.858M13.73 0c.18 1.215-.314 2.405-.963 3.247c-.695.902-1.892 1.601-3.05 1.565c-.21-1.163.332-2.36.99-3.167C11.43.755 12.67.074 13.73 0"
/>
</svg>
),
},
{
title: "Discord",
href: "/docs/providers/discord",
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M18.59 5.89c-1.23-.57-2.54-.99-3.92-1.23c-.17.3-.37.71-.5 1.04c-1.46-.22-2.91-.22-4.34 0c-.14-.33-.34-.74-.51-1.04c-1.38.24-2.69.66-3.92 1.23c-2.48 3.74-3.15 7.39-2.82 10.98c1.65 1.23 3.24 1.97 4.81 2.46c.39-.53.73-1.1 1.03-1.69c-.57-.21-1.11-.48-1.62-.79c.14-.1.27-.21.4-.31c3.13 1.46 6.52 1.46 9.61 0c.13.11.26.21.4.31c-.51.31-1.06.57-1.62.79c.3.59.64 1.16 1.03 1.69c1.57-.49 3.17-1.23 4.81-2.46c.39-4.17-.67-7.78-2.82-10.98Zm-9.75 8.78c-.94 0-1.71-.87-1.71-1.94s.75-1.94 1.71-1.94s1.72.87 1.71 1.94c0 1.06-.75 1.94-1.71 1.94m6.31 0c-.94 0-1.71-.87-1.71-1.94s.75-1.94 1.71-1.94s1.72.87 1.71 1.94c0 1.06-.75 1.94-1.71 1.94"
/>
</svg>
),
},
{
title: "Facebook",
href: "/docs/providers/facebook",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 24 24"><g fill="none"><path d="M24 0v24H0V0zM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.019-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"></path><path fill="currentColor" d="M13.5 21.888C18.311 21.164 22 17.013 22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 5.013 3.689 9.165 8.5 9.888V15H9a1.5 1.5 0 0 1 0-3h1.5v-2A3.5 3.5 0 0 1 14 6.5h.5a1.5 1.5 0 0 1 0 3H14a.5.5 0 0 0-.5.5v2H15a1.5 1.5 0 0 1 0 3h-1.5z"></path></g></svg>
),
},
{
title: "Github",
href: "/docs/providers/github",
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 15 15"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M7.5.25a7.25 7.25 0 0 0-2.292 14.13c.363.066.495-.158.495-.35c0-.172-.006-.628-.01-1.233c-2.016.438-2.442-.972-2.442-.972c-.33-.838-.805-1.06-.805-1.06c-.658-.45.05-.441.05-.441c.728.051 1.11.747 1.11.747c.647 1.108 1.697.788 2.11.602c.066-.468.254-.788.46-.969c-1.61-.183-3.302-.805-3.302-3.583a2.8 2.8 0 0 1 .747-1.945c-.075-.184-.324-.92.07-1.92c0 0 .61-.194 1.994.744A6.963 6.963 0 0 1 7.5 3.756A6.97 6.97 0 0 1 9.315 4c1.384-.938 1.992-.743 1.992-.743c.396.998.147 1.735.072 1.919c.465.507.745 1.153.745 1.945c0 2.785-1.695 3.398-3.31 3.577c.26.224.492.667.492 1.343c0 .97-.009 1.751-.009 1.989c0 .194.131.42.499.349A7.25 7.25 0 0 0 7.499.25"
clipRule="evenodd"
/>
</svg>
),
},
{
title: "Google",
href: "/docs/providers/google",
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 56 56"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M28.458 5c6.167 0 11.346 2.2 15.368 5.804l.323.295l-6.62 6.464c-1.695-1.59-4.666-3.493-9.07-3.493c-6.204 0-11.47 4.093-13.372 9.749c-.47 1.46-.756 3.023-.756 4.64c0 1.615.287 3.18.782 4.639c1.877 5.656 7.142 9.748 13.345 9.748c3.347 0 5.928-.886 7.881-2.176l.251-.17l.307-.222c2.813-2.108 4.144-5.084 4.46-7.169l.03-.22h-12.93v-8.705h22.025c.339 1.46.495 2.867.495 4.795c0 7.142-2.554 13.163-6.985 17.255c-3.884 3.597-9.201 5.682-15.535 5.682c-9.031 0-16.85-5.102-20.772-12.57l-.184-.358l-.222-.457A23.45 23.45 0 0 1 5 28.458c0-3.6.827-7.01 2.28-10.073l.222-.457l.184-.357C11.608 10.1 19.426 5 28.458 5"
/>
</svg>
),
},
{
title: "Twitch",
href: "/docs/providers/twitch",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" fillRule="evenodd" d="M3.9 2.5a.9.9 0 0 0-.9.9v14.194a.9.9 0 0 0 .9.9h4.116v3.03a.7.7 0 0 0 1.194.494l3.525-3.524h4.643a.9.9 0 0 0 .636-.264l2.722-2.722a.9.9 0 0 0 .264-.636V3.4a.9.9 0 0 0-.9-.9zm7.319 5.2a.75.75 0 0 0-1.5 0v4.272a.75.75 0 1 0 1.5 0zm5.016 0a.75.75 0 0 0-1.5 0v4.272a.75.75 0 1 0 1.5 0z" clipRule="evenodd"></path></svg>
)
},
{
title: "X (Twitter)",
href: "/docs/providers/twitter",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="0.88em" height="1em" viewBox="0 0 448 512"><path fill="currentColor" d="M64 32C28.7 32 0 60.7 0 96v320c0 35.3 28.7 64 64 64h320c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64zm297.1 84L257.3 234.6L379.4 396h-95.6L209 298.1L123.3 396H75.8l111-126.9L69.7 116h98l67.7 89.5l78.2-89.5zm-37.8 251.6L153.4 142.9h-28.3l171.8 224.7h26.3z"></path></svg>
)
}
],
},
{
title: "Integrations",
Icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.3em" height="1.3em" viewBox="0 0 48 48"><path fill="currentColor" stroke="currentColor" stroke-linejoin="round" stroke-width="4" d="M18 6H8a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2Zm0 22H8a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V30a2 2 0 0 0-2-2ZM40 6H30a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2Zm0 22H30a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V30a2 2 0 0 0-2-2Z"></path></svg>
),
list: [
{
group: true,
title: "Frameworks",
href: "/docs/integrations",
icon: LucideAArrowDown
},
{
title: "Hono",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 256 330"><path fill="#9E9494" d="M134.129.029q1.315-.17 2.319.662a1256 1256 0 0 1 69.573 93.427q24.141 36.346 41.082 76.862q27.055 72.162-28.16 125.564q-48.313 40.83-111.318 31.805q-75.312-15.355-102.373-87.133Q-1.796 217.85.614 193.51q4.014-41.896 19.878-80.838q6.61-15.888 17.228-29.154a382 382 0 0 1 16.565 21.203q3.66 3.825 7.62 7.289Q92.138 52.013 134.13.029" opacity=".993"></path><path fill="#3C2020" d="M129.49 53.7q36.47 42.3 65.93 90.114a187.3 187.3 0 0 1 15.24 33.13q12.507 49.206-26.836 81.169q-38.05 26.774-83.488 15.902q-48.999-15.205-56.653-65.929q-1.857-15.993 3.314-31.142a225.4 225.4 0 0 1 17.89-35.78l19.878-29.155a5510 5510 0 0 0 44.726-58.31"></path></svg>
),
href: "/docs/integrations/hono",
},
{
title: "Next",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 24 24"><path fill="currentColor" d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2s10 4.477 10 10s-4.477 10-10 10m4-14h-1.35v4H16zM9.346 9.71l6.059 7.828l1.054-.809L9.683 8H8v7.997h1.346z"></path></svg>
),
href: "/docs/integrations/next",
},
{
title: "Nuxt",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 512 512"><path fill="currentColor" d="M200.662 81.35L0 430.65h130.774l139.945-239.803zm134.256 40.313l-39.023 69.167l138.703 239.82H512zm-51.596 91.052L155.924 430.651h253.485z"></path></svg>
),
href: "/docs/integrations/nuxt",
},
{
title: "Svelte Kit",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 426 512"><path fill="currentColor" d="M403.508 229.23C491.235 87.7 315.378-58.105 190.392 23.555L71.528 99.337c-57.559 37.487-82.55 109.513-47.45 183.53c-87.761 133.132 83.005 289.03 213.116 205.762l118.864-75.782c64.673-42.583 79.512-116.018 47.45-183.616m-297.592-80.886l118.69-75.739c77.973-46.679 167.756 34.942 135.388 110.992c-19.225-15.274-40.65-24.665-56.923-28.894c6.186-24.57-22.335-42.796-42.174-30.106l-118.95 75.48c-29.411 20.328 1.946 62.138 31.014 44.596l45.33-28.895c101.725-57.403 198 80.425 103.38 147.975l-118.692 75.739C131.455 485.225 34.11 411.96 67.592 328.5c17.786 13.463 36.677 23.363 56.923 28.894c-4.47 28.222 24.006 41.943 42.476 30.365L285.64 312.02c29.28-21.955-2.149-61.692-30.97-44.595l-45.504 28.894c-100.56 58.77-199.076-80.42-103.25-147.975"></path></svg>
),
href: "/docs/integrations/svelte-kit",
},
{
title: "Solid Start",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 128 128"><path fill="currentColor" d="M61.832 4.744c-3.205.058-6.37.395-9.45 1.07l-2.402.803c-4.806 1.603-8.813 4.005-11.216 7.21l-1.602 2.404l-12.017 20.828l.166.031c-4.785 5.823-5.007 14.07-.166 21.6c1.804 2.345 4.073 4.431 6.634 6.234l-15.445 4.982L.311 97.946s42.46 32.044 75.306 24.033l2.403-.801c5.322-1.565 9.292-4.48 11.683-8.068l.334.056l16.022-28.84c3.204-5.608 2.404-12.016-1.602-18.425a36 36 0 0 0-7.059-6.643l15.872-5.375l14.42-24.033S92.817 4.19 61.831 4.744z"></path></svg>
),
href: "/docs/integrations/solid-start",
},
{
title: "React",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 15 15"><path fill="currentColor" fillRule="evenodd" d="M5.315 1.837c-.4-.116-.695-.085-.91.032c-.216.116-.404.347-.526.745c-.122.401-.163.936-.104 1.582q.015.157.037.321a14 14 0 0 1 1.676-.311a13 13 0 0 1 1.275-1.54l-.066-.053c-.508-.402-.98-.66-1.382-.776m2.185.14q-.09-.076-.182-.148C6.746 1.377 6.16 1.04 5.594.876C5.024.711 4.441.711 3.928.99s-.833.767-1.005 1.334c-.172.564-.21 1.238-.144 1.965q.023.255.065.523q-.256.09-.49.192c-.671.287-1.246.642-1.66 1.062C.278 6.487 0 7 0 7.584S.278 8.68.694 9.103c.414.42.989.774 1.66 1.062q.235.1.49.192a9 9 0 0 0-.065.523c-.066.726-.028 1.4.144 1.965c.172.567.492 1.056 1.005 1.333c.513.278 1.097.279 1.666.114c.566-.165 1.152-.5 1.724-.953l.182-.149q.09.076.182.149c.572.452 1.158.788 1.724.953c.569.165 1.153.164 1.666-.114c.513-.277.833-.766 1.005-1.333c.172-.564.21-1.239.144-1.965a9 9 0 0 0-.065-.523q.255-.09.49-.192c.671-.288 1.246-.643 1.66-1.062c.416-.422.694-.936.694-1.52c0-.582-.278-1.096-.694-1.518c-.414-.42-.989-.775-1.66-1.062a9 9 0 0 0-.49-.192q.04-.268.065-.523c.066-.727.028-1.4-.144-1.965c-.172-.567-.492-1.056-1.005-1.334S9.975.711 9.406.876c-.566.164-1.152.5-1.724.953zm0 1.365q-.338.346-.672.755a17 17 0 0 1 1.344 0a11 11 0 0 0-.672-.755m2.012.864c-.41-.574-.84-1.092-1.275-1.54l.065-.053c.51-.402.98-.66 1.383-.776c.399-.116.695-.085.91.032c.216.116.404.347.525.745c.122.401.164.936.105 1.582q-.015.158-.037.32a14 14 0 0 0-1.676-.31m-.563.944a15.6 15.6 0 0 0-2.898 0A15.6 15.6 0 0 0 4.72 7.584a15.7 15.7 0 0 0 1.33 2.433a15.6 15.6 0 0 0 2.9 0a15.6 15.6 0 0 0 1.33-2.433A15.7 15.7 0 0 0 8.95 5.15m1.824 1.138a17 17 0 0 0-.527-.956q.39.075.752.168q-.094.385-.225.788m0 2.591a17 17 0 0 1-.527.957q.39-.075.752-.169a12 12 0 0 0-.225-.788m1.18.487a14 14 0 0 0-.588-1.782c.246-.61.443-1.209.588-1.782q.154.058.3.12c.596.256 1.047.547 1.341.845c.292.296.406.572.406.817s-.114.52-.406.816c-.294.299-.745.59-1.341.846a8 8 0 0 1-.3.12m-.765 1.285a14 14 0 0 1-1.676.311c-.41.574-.84 1.091-1.275 1.54l.066.052c.508.403.98.66 1.382.777c.399.116.695.085.91-.032s.404-.348.525-.746c.123-.4.164-.936.105-1.582a7 7 0 0 0-.037-.32M7.5 11.826q.338-.346.672-.755a17 17 0 0 1-1.344 0q.334.408.672.755m-2.746-1.99a17 17 0 0 1-.527-.957q-.13.404-.225.788q.361.094.752.169m-.942.815a14 14 0 0 0 1.676.311c.41.574.839 1.091 1.275 1.54l-.066.052c-.508.403-.98.66-1.382.777c-.4.116-.695.085-.911-.032s-.403-.348-.525-.746c-.122-.4-.163-.936-.104-1.582a8 8 0 0 1 .037-.32m-.765-1.285c.145-.574.341-1.172.588-1.782a14 14 0 0 1-.588-1.782q-.155.058-.3.12c-.596.256-1.047.547-1.341.845c-.292.296-.406.572-.406.817s.114.52.406.816c.294.299.745.59 1.341.846q.146.061.3.12m.955-3.865q.094.384.225.787a17 17 0 0 1 .527-.956q-.39.075-.752.169M6 7.584a1.5 1.5 0 1 1 3 0a1.5 1.5 0 0 1-3 0m1.5-.5a.5.5 0 1 0 0 1a.5.5 0 0 0 0-1" clipRule="evenodd"></path></svg>
),
href: "/docs/integrations/react",
},
]
},
{
title: "Plugins",
Icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.4em"
height="1.4em"
viewBox="0 0 24 24"
>
<g fill="none">
<path d="M24 0v24H0V0zM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035c-.01-.004-.019-.001-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427c-.002-.01-.009-.017-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093c.012.004.023 0 .029-.008l.004-.014l-.034-.614c-.003-.012-.01-.02-.02-.022m-.715.002a.023.023 0 0 0-.027.006l-.006.014l-.034.614c0 .012.007.02.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
<path
fill="currentColor"
d="M15 20a1 1 0 1 1 0 2H9a1 1 0 1 1 0-2zm0-18a1 1 0 0 1 .993.883L16 3v3h2a2 2 0 0 1 1.995 1.85L20 8v5a6 6 0 0 1-5.775 5.996L14 19h-4a6 6 0 0 1-5.996-5.775L4 13V8a2 2 0 0 1 1.85-1.995L6 6h2V3a1 1 0 0 1 1.993-.117L10 3v3h4V3a1 1 0 0 1 1-1"
/>
</g>
</svg>
),
list: [
{
title: "Introduction",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.1em" height="1.1em" viewBox="0 0 14 14"><path fill="currentColor" fillRule="evenodd" d="M12.402 8.976H7.259a2.278 2.278 0 0 0-.193-4.547h-1.68A3.095 3.095 0 0 0 4.609 0h7.793a1.35 1.35 0 0 1 1.348 1.35v6.279c0 .744-.604 1.348-1.348 1.348ZM2.898 4.431a1.848 1.848 0 1 0 0-3.695a1.848 1.848 0 0 0 0 3.695m5.195 2.276c0-.568-.46-1.028-1.027-1.028H2.899a2.65 2.65 0 0 0-2.65 2.65v1.205c0 .532.432.963.964.963h.172l.282 2.61A1 1 0 0 0 2.66 14h.502a1 1 0 0 0 .99-.862l.753-5.404h2.16c.567 0 1.027-.46 1.027-1.027Z" clipRule="evenodd"></path></svg>
),
href: "/docs/plugins/introduction",
},
{
title: "Authentication",
group: true,
href: "/docs/plugins/1st-party-plugins",
icon: LucideAArrowDown
},
{
title: "Passkey",
href: "/docs/plugins/passkey",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 24 24"><path fill="currentColor" d="M18 16.663a3.5 3.5 0 0 1-2-3.163a3.5 3.5 0 1 1 4.5 3.355V17l1.146 1.146a.5.5 0 0 1 0 .708L20.5 20l1.161 1.161a.5.5 0 0 1 .015.692l-1.823 1.984a.5.5 0 0 1-.722.015l-.985-.984a.5.5 0 0 1-.146-.354zM20.5 13a1 1 0 1 0-2 0a1 1 0 0 0 2 0M17 17.242v3.69c-1.36.714-3.031 1.07-5 1.07c-3.42 0-5.944-1.073-7.486-3.237a2.75 2.75 0 0 1-.51-1.596v-.92a2.25 2.25 0 0 1 2.249-2.25h8.775A4.5 4.5 0 0 0 17 17.243M12 2.005a5 5 0 1 1 0 10a5 5 0 0 1 0-10"></path></svg>
),
},
{
title: "Two Factor",
icon: ScanFace,
href: "/docs/plugins/2fa",
},
{
title: "Username",
icon: UserSquare2,
href: "/docs/plugins/username",
},
{
title: "Authorization",
group: true,
href: "/docs/plugins/1st-party-plugins",
icon: LucideAArrowDown
},
{
title: "Organization",
icon: Users2,
href: "/docs/plugins/organization",
},
{
title: "Utility",
group: true,
href: "/docs/plugins/1st-party-plugins",
icon: LucideAArrowDown
},
{
title: "Bearer",
icon: Key,
href: "/docs/plugins/email-verifier",
},
{
title: "Email Checker",
icon: MailCheck,
href: "/docs/plugins/email-verifier",
},
],
},
// {
// title: "Database",
// Icon: () => (
// <svg
// xmlns="http://www.w3.org/2000/svg"
// width="1.4em"
// height="1.4em"
// viewBox="0 0 24 24"
// >
// <path
// fill="currentColor"
// d="M20 18c0 2.21-3.582 4-8 4s-8-1.79-8-4v-4.026c.502.617 1.215 1.129 2.008 1.525C7.58 16.285 9.7 16.75 12 16.75s4.42-.465 5.992-1.25c.793-.397 1.506-.91 2.008-1.526z"
// />
// <path
// fill="currentColor"
// d="M12 10.75c2.3 0 4.42-.465 5.992-1.25c.793-.397 1.506-.91 2.008-1.526V12c0 .5-1.786 1.591-2.679 2.158c-1.323.661-3.203 1.092-5.321 1.092s-3.998-.43-5.321-1.092C5.5 13.568 4 12.5 4 12V7.974c.502.617 1.215 1.129 2.008 1.525C7.58 10.285 9.7 10.75 12 10.75"
// />
// <path
// fill="currentColor"
// d="M17.321 8.158C15.998 8.819 14.118 9.25 12 9.25s-3.998-.43-5.321-1.092c-.515-.202-1.673-.843-2.477-1.879a.81.81 0 0 1-.162-.621c.023-.148.055-.301.096-.396C4.828 3.406 8.086 2 12 2c3.914 0 7.172 1.406 7.864 3.262c.041.095.073.248.096.396a.81.81 0 0 1-.162.621c-.804 1.036-1.962 1.677-2.477 1.879"
// />
// </svg>
// ),
// list: [
// {
// title: "Drizzle",
// href: "/docs/adapters/drizzle",
// icon: () => (
// <svg
// xmlns="http://www.w3.org/2000/svg"
// width="1.2em"
// height="1.2em"
// viewBox="0 0 24 24"
// >
// <path
// fill="currentColor"
// d="M5.353 11.823a1.036 1.036 0 0 0-.395-1.422a1.063 1.063 0 0 0-1.437.399L.138 16.702a1.035 1.035 0 0 0 .395 1.422a1.063 1.063 0 0 0 1.437-.398zm11.216 0a1.036 1.036 0 0 0-.394-1.422a1.064 1.064 0 0 0-1.438.399l-3.382 5.902a1.036 1.036 0 0 0 .394 1.422c.506.283 1.15.104 1.438-.398zm7.293-4.525a1.036 1.036 0 0 0-.395-1.422a1.06 1.06 0 0 0-1.437.399l-3.383 5.902a1.036 1.036 0 0 0 .395 1.422a1.063 1.063 0 0 0 1.437-.399zm-11.219 0a1.035 1.035 0 0 0-.394-1.422a1.064 1.064 0 0 0-1.438.398l-3.382 5.903a1.036 1.036 0 0 0 .394 1.422c.506.282 1.15.104 1.438-.399z"
// />
// </svg>
// ),
// },
// {
// title: "Prisma",
// href: "/docs/adapters/prisma",
// icon: () => (
// <svg
// xmlns="http://www.w3.org/2000/svg"
// width="1.2em"
// height="1.2em"
// viewBox="0 0 24 24"
// >
// <path
// fill="currentColor"
// d="M21.807 18.285L13.553.757a1.32 1.32 0 0 0-1.129-.755a1.31 1.31 0 0 0-1.206.626l-8.952 14.5a1.36 1.36 0 0 0 .016 1.455l4.376 6.778a1.41 1.41 0 0 0 1.58.581l12.703-3.757c.389-.115.707-.39.873-.755s.164-.783-.007-1.145m-1.848.752L9.18 22.224a.452.452 0 0 1-.575-.52l3.85-18.438c.072-.345.549-.4.699-.08l7.129 15.138a.515.515 0 0 1-.325.713"
// />
// </svg>
// ),
// },
// ],
// },
];

View File

@@ -0,0 +1,374 @@
import { Key, LucideAArrowDown, LucideIcon, MailCheck, ScanFace, Users2, UserSquare2 } from "lucide-react";
import { ReactNode, SVGProps } from "react";
import { Icons } from "./icons";
interface Content {
title: string;
href?: string;
Icon: ((props?: SVGProps<any>) => ReactNode) | LucideIcon;
list: {
title: string;
href: string;
icon: ((props?: SVGProps<any>) => ReactNode) | LucideIcon;
group?: boolean;
}[];
}
export const contents: Content[] = [
{
title: "Get Started",
Icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.4em"
height="1.4em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10s10-4.48 10-10S17.52 2 12 2m-1 14H9V8h2zm1 0V8l5 4z"
/>
</svg>
),
list: [
{
title: "Introduction",
href: "/docs/introduction",
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 256 256"
>
<path
fill="currentColor"
d="M232 48h-64a32 32 0 0 0-32 32v87.73a8.17 8.17 0 0 1-7.47 8.25a8 8 0 0 1-8.53-8V80a32 32 0 0 0-32-32H24a8 8 0 0 0-8 8v144a8 8 0 0 0 8 8h72a24 24 0 0 1 24 23.94a7.9 7.9 0 0 0 5.12 7.55A8 8 0 0 0 136 232a24 24 0 0 1 24-24h72a8 8 0 0 0 8-8V56a8 8 0 0 0-8-8m-24 120h-39.73a8.17 8.17 0 0 1-8.25-7.47a8 8 0 0 1 8-8.53h39.73a8.17 8.17 0 0 1 8.25 7.47a8 8 0 0 1-8 8.53m0-32h-39.73a8.17 8.17 0 0 1-8.25-7.47a8 8 0 0 1 8-8.53h39.73a8.17 8.17 0 0 1 8.25 7.47a8 8 0 0 1-8 8.53m0-32h-39.73a8.17 8.17 0 0 1-8.27-7.47a8 8 0 0 1 8-8.53h39.73a8.17 8.17 0 0 1 8.27 7.47a8 8 0 0 1-8 8.53"
/>
</svg>
),
},
{
title: "Installation",
href: "/docs/installation",
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M2 12c0-4.714 0-7.071 1.464-8.536C4.93 2 7.286 2 12 2c4.714 0 7.071 0 8.535 1.464C22 4.93 22 7.286 22 12c0 4.714 0 7.071-1.465 8.535C19.072 22 16.714 22 12 22s-7.071 0-8.536-1.465C2 19.072 2 16.714 2 12m10-5.75a.75.75 0 0 1 .75.75v5.19l1.72-1.72a.75.75 0 1 1 1.06 1.06l-3 3a.75.75 0 0 1-1.06 0l-3-3a.75.75 0 1 1 1.06-1.06l1.72 1.72V7a.75.75 0 0 1 .75-.75m-4 10a.75.75 0 0 0 0 1.5h8a.75.75 0 0 0 0-1.5z"
clipRule="evenodd"
/>
</svg>
),
},
{
title: "Basic Usage",
href: "/docs/basic-usage",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 24 24"><path fill="currentColor" d="M21 2H3c-1.1 0-2 .9-2 2v16c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2M10 19.4l-1.6.6C6.9 18.6 6 16.6 6 14.5s.9-4.1 2.4-5.5l1.6.6c-1.3 1.1-2 3-2 4.9s.7 3.7 2 4.9m5.6.6l-1.6-.6c1.3-1.2 2-3 2-4.9s-.7-3.7-2-4.9l1.6-.6c1.5 1.4 2.4 3.4 2.4 5.5s-.9 4.1-2.4 5.5M21 7H3V4h18z"></path></svg>
),
},
],
},
{
title: "Authentication",
Icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.4em"
height="1.4em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M10 4h4c3.771 0 5.657 0 6.828 1.172C22 6.343 22 8.229 22 12c0 3.771 0 5.657-1.172 6.828C19.657 20 17.771 20 14 20h-4c-3.771 0-5.657 0-6.828-1.172C2 17.657 2 15.771 2 12c0-3.771 0-5.657 1.172-6.828C4.343 4 6.229 4 10 4m3.25 5a.75.75 0 0 1 .75-.75h5a.75.75 0 0 1 0 1.5h-5a.75.75 0 0 1-.75-.75m1 3a.75.75 0 0 1 .75-.75h4a.75.75 0 0 1 0 1.5h-4a.75.75 0 0 1-.75-.75m1 3a.75.75 0 0 1 .75-.75h3a.75.75 0 0 1 0 1.5h-3a.75.75 0 0 1-.75-.75M11 9a2 2 0 1 1-4 0a2 2 0 0 1 4 0m-2 8c4 0 4-.895 4-2s-1.79-2-4-2s-4 .895-4 2s0 2 4 2"
clipRule="evenodd"
/>
</svg>
),
list: [
{
title: "Email & Password",
group: true,
href: "/docs/email-password",
icon: () => (
<svg>
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm4.59-12.42L10 14.17l-2.59-2.58L6 13l4 4 8-8z"></path>
</svg>
)
},
{
title: "Sign-In & Sign-Up",
href: "/docs/email-password/sign-in-and-sign-up",
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M3.172 5.172C2 6.343 2 8.229 2 12c0 3.771 0 5.657 1.172 6.828C4.343 20 6.229 20 10 20h4c3.771 0 5.657 0 6.828-1.172C22 17.657 22 15.771 22 12c0-3.771 0-5.657-1.172-6.828C19.657 4 17.771 4 14 4h-4C6.229 4 4.343 4 3.172 5.172M8 13a1 1 0 1 0 0-2a1 1 0 0 0 0 2m5-1a1 1 0 1 1-2 0a1 1 0 0 1 2 0m3 1a1 1 0 1 0 0-2a1 1 0 0 0 0 2"
clipRule="evenodd"
/>
</svg>
)
},
{
title: "Password Reset",
href: "/docs/email-password/password-reset",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" d="M15.75 2a.75.75 0 0 0-1.5 0v20a.75.75 0 0 0 1.5 0v-2.006c2.636-.027 4.104-.191 5.078-1.166C22 17.657 22 15.771 22 12s0-5.657-1.172-6.828c-.974-.975-2.442-1.139-5.078-1.166z"></path><path fill="currentColor" fillRule="evenodd" d="M3.172 18.828C4.343 20 6.229 20 10 20h3V4h-3C6.229 4 4.343 4 3.172 5.172S2 8.229 2 12s0 5.657 1.172 6.828M13 12a1 1 0 1 0-2 0a1 1 0 0 0 2 0m-4 0a1 1 0 1 1-2 0a1 1 0 0 1 2 0" clipRule="evenodd"></path></svg>
)
},
{
title: "Configuration",
href: "/docs/email-password/configuration",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 48 48"><defs><mask id="ipSConfig0"><g fill="none" stroke-linejoin="round" stroke-width="4"><path fill="#fff" stroke="#fff" d="m24 4l-6 6h-8v8l-6 6l6 6v8h8l6 6l6-6h8v-8l6-6l-6-6v-8h-8z"></path><path fill="#000" stroke="#000" d="M24 30a6 6 0 1 0 0-12a6 6 0 0 0 0 12Z"></path></g></mask></defs><path fill="currentColor" d="M0 0h48v48H0z" mask="url(#ipSConfig0)"></path></svg>
)
},
{
title: "Social Sign-On",
group: true,
href: "/docs/providers/social-providers",
icon: () => (
<svg>
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm0 18c-4.41 0-8-3.59-8-8s3.59-8 8-8 8 3.59 8 8-3.59 8-8 8zm4.59-12.42L10 14.17l-2.59-2.58L6 13l4 4 8-8z"></path>
</svg>
)
},
{
title: "Apple",
href: "/docs/providers/apple",
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 20 20"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M14.122 4.682c1.35 0 2.781.743 3.8 2.028c-3.34 1.851-2.797 6.674.578 7.963c-.465 1.04-.687 1.505-1.285 2.426c-.835 1.284-2.01 2.884-3.469 2.898c-1.295.012-1.628-.853-3.386-.843c-1.758.01-2.125.858-3.42.846c-1.458-.014-2.573-1.458-3.408-2.743C1.198 13.665.954 9.45 2.394 7.21C3.417 5.616 5.03 4.683 6.548 4.683c1.545 0 2.516.857 3.794.857c1.24 0 1.994-.858 3.78-.858M13.73 0c.18 1.215-.314 2.405-.963 3.247c-.695.902-1.892 1.601-3.05 1.565c-.21-1.163.332-2.36.99-3.167C11.43.755 12.67.074 13.73 0"
/>
</svg>
),
},
{
title: "Discord",
href: "/docs/providers/discord",
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M18.59 5.89c-1.23-.57-2.54-.99-3.92-1.23c-.17.3-.37.71-.5 1.04c-1.46-.22-2.91-.22-4.34 0c-.14-.33-.34-.74-.51-1.04c-1.38.24-2.69.66-3.92 1.23c-2.48 3.74-3.15 7.39-2.82 10.98c1.65 1.23 3.24 1.97 4.81 2.46c.39-.53.73-1.1 1.03-1.69c-.57-.21-1.11-.48-1.62-.79c.14-.1.27-.21.4-.31c3.13 1.46 6.52 1.46 9.61 0c.13.11.26.21.4.31c-.51.31-1.06.57-1.62.79c.3.59.64 1.16 1.03 1.69c1.57-.49 3.17-1.23 4.81-2.46c.39-4.17-.67-7.78-2.82-10.98Zm-9.75 8.78c-.94 0-1.71-.87-1.71-1.94s.75-1.94 1.71-1.94s1.72.87 1.71 1.94c0 1.06-.75 1.94-1.71 1.94m6.31 0c-.94 0-1.71-.87-1.71-1.94s.75-1.94 1.71-1.94s1.72.87 1.71 1.94c0 1.06-.75 1.94-1.71 1.94"
/>
</svg>
),
},
{
title: "Facebook",
href: "/docs/providers/facebook",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 24 24"><g fill="none"><path d="M24 0v24H0V0zM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.019-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z"></path><path fill="currentColor" d="M13.5 21.888C18.311 21.164 22 17.013 22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 5.013 3.689 9.165 8.5 9.888V15H9a1.5 1.5 0 0 1 0-3h1.5v-2A3.5 3.5 0 0 1 14 6.5h.5a1.5 1.5 0 0 1 0 3H14a.5.5 0 0 0-.5.5v2H15a1.5 1.5 0 0 1 0 3h-1.5z"></path></g></svg>
),
},
{
title: "Github",
href: "/docs/providers/github",
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 15 15"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M7.5.25a7.25 7.25 0 0 0-2.292 14.13c.363.066.495-.158.495-.35c0-.172-.006-.628-.01-1.233c-2.016.438-2.442-.972-2.442-.972c-.33-.838-.805-1.06-.805-1.06c-.658-.45.05-.441.05-.441c.728.051 1.11.747 1.11.747c.647 1.108 1.697.788 2.11.602c.066-.468.254-.788.46-.969c-1.61-.183-3.302-.805-3.302-3.583a2.8 2.8 0 0 1 .747-1.945c-.075-.184-.324-.92.07-1.92c0 0 .61-.194 1.994.744A6.963 6.963 0 0 1 7.5 3.756A6.97 6.97 0 0 1 9.315 4c1.384-.938 1.992-.743 1.992-.743c.396.998.147 1.735.072 1.919c.465.507.745 1.153.745 1.945c0 2.785-1.695 3.398-3.31 3.577c.26.224.492.667.492 1.343c0 .97-.009 1.751-.009 1.989c0 .194.131.42.499.349A7.25 7.25 0 0 0 7.499.25"
clipRule="evenodd"
/>
</svg>
),
},
{
title: "Google",
href: "/docs/providers/google",
icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 56 56"
>
<path
fill="currentColor"
fillRule="evenodd"
d="M28.458 5c6.167 0 11.346 2.2 15.368 5.804l.323.295l-6.62 6.464c-1.695-1.59-4.666-3.493-9.07-3.493c-6.204 0-11.47 4.093-13.372 9.749c-.47 1.46-.756 3.023-.756 4.64c0 1.615.287 3.18.782 4.639c1.877 5.656 7.142 9.748 13.345 9.748c3.347 0 5.928-.886 7.881-2.176l.251-.17l.307-.222c2.813-2.108 4.144-5.084 4.46-7.169l.03-.22h-12.93v-8.705h22.025c.339 1.46.495 2.867.495 4.795c0 7.142-2.554 13.163-6.985 17.255c-3.884 3.597-9.201 5.682-15.535 5.682c-9.031 0-16.85-5.102-20.772-12.57l-.184-.358l-.222-.457A23.45 23.45 0 0 1 5 28.458c0-3.6.827-7.01 2.28-10.073l.222-.457l.184-.357C11.608 10.1 19.426 5 28.458 5"
/>
</svg>
),
},
{
title: "Twitch",
href: "/docs/providers/twitch",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24"><path fill="currentColor" fillRule="evenodd" d="M3.9 2.5a.9.9 0 0 0-.9.9v14.194a.9.9 0 0 0 .9.9h4.116v3.03a.7.7 0 0 0 1.194.494l3.525-3.524h4.643a.9.9 0 0 0 .636-.264l2.722-2.722a.9.9 0 0 0 .264-.636V3.4a.9.9 0 0 0-.9-.9zm7.319 5.2a.75.75 0 0 0-1.5 0v4.272a.75.75 0 1 0 1.5 0zm5.016 0a.75.75 0 0 0-1.5 0v4.272a.75.75 0 1 0 1.5 0z" clipRule="evenodd"></path></svg>
)
},
{
title: "X (Twitter)",
href: "/docs/providers/twitter",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="0.88em" height="1em" viewBox="0 0 448 512"><path fill="currentColor" d="M64 32C28.7 32 0 60.7 0 96v320c0 35.3 28.7 64 64 64h320c35.3 0 64-28.7 64-64V96c0-35.3-28.7-64-64-64zm297.1 84L257.3 234.6L379.4 396h-95.6L209 298.1L123.3 396H75.8l111-126.9L69.7 116h98l67.7 89.5l78.2-89.5zm-37.8 251.6L153.4 142.9h-28.3l171.8 224.7h26.3z"></path></svg>
)
}
],
},
{
title: "Integrations",
Icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.3em" height="1.3em" viewBox="0 0 48 48"><path fill="currentColor" stroke="currentColor" stroke-linejoin="round" stroke-width="4" d="M18 6H8a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2Zm0 22H8a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V30a2 2 0 0 0-2-2ZM40 6H30a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2Zm0 22H30a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V30a2 2 0 0 0-2-2Z"></path></svg>
),
list: [
{
group: true,
title: "Frameworks",
href: "/docs/integrations",
icon: LucideAArrowDown
},
{
title: "Hono",
icon: Icons.hono,
href: "/docs/integrations/hono",
},
{
title: "Next",
icon: Icons.nextJS,
href: "/docs/integrations/next",
},
{
title: "Nuxt",
icon: Icons.nuxt,
href: "/docs/integrations/nuxt",
},
{
title: "Svelte Kit",
icon: Icons.svelteKit,
href: "/docs/integrations/svelte-kit",
},
{
title: "Solid Start",
icon: Icons.solidStart,
href: "/docs/integrations/solid-start",
},
{
title: "React",
icon: Icons.react,
href: "/docs/integrations/react",
},
]
},
{
title: "Plugins",
Icon: () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="1.4em"
height="1.4em"
viewBox="0 0 24 24"
>
<g fill="none">
<path d="M24 0v24H0V0zM12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035c-.01-.004-.019-.001-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427c-.002-.01-.009-.017-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093c.012.004.023 0 .029-.008l.004-.014l-.034-.614c-.003-.012-.01-.02-.02-.022m-.715.002a.023.023 0 0 0-.027.006l-.006.014l-.034.614c0 .012.007.02.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
<path
fill="currentColor"
d="M15 20a1 1 0 1 1 0 2H9a1 1 0 1 1 0-2zm0-18a1 1 0 0 1 .993.883L16 3v3h2a2 2 0 0 1 1.995 1.85L20 8v5a6 6 0 0 1-5.775 5.996L14 19h-4a6 6 0 0 1-5.996-5.775L4 13V8a2 2 0 0 1 1.85-1.995L6 6h2V3a1 1 0 0 1 1.993-.117L10 3v3h4V3a1 1 0 0 1 1-1"
/>
</g>
</svg>
),
list: [
{
title: "Introduction",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.1em" height="1.1em" viewBox="0 0 14 14"><path fill="currentColor" fillRule="evenodd" d="M12.402 8.976H7.259a2.278 2.278 0 0 0-.193-4.547h-1.68A3.095 3.095 0 0 0 4.609 0h7.793a1.35 1.35 0 0 1 1.348 1.35v6.279c0 .744-.604 1.348-1.348 1.348ZM2.898 4.431a1.848 1.848 0 1 0 0-3.695a1.848 1.848 0 0 0 0 3.695m5.195 2.276c0-.568-.46-1.028-1.027-1.028H2.899a2.65 2.65 0 0 0-2.65 2.65v1.205c0 .532.432.963.964.963h.172l.282 2.61A1 1 0 0 0 2.66 14h.502a1 1 0 0 0 .99-.862l.753-5.404h2.16c.567 0 1.027-.46 1.027-1.027Z" clipRule="evenodd"></path></svg>
),
href: "/docs/plugins/introduction",
},
{
title: "Authentication",
group: true,
href: "/docs/plugins/1st-party-plugins",
icon: LucideAArrowDown
},
{
title: "Passkey",
href: "/docs/plugins/passkey",
icon: () => (
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 24 24"><path fill="currentColor" d="M18 16.663a3.5 3.5 0 0 1-2-3.163a3.5 3.5 0 1 1 4.5 3.355V17l1.146 1.146a.5.5 0 0 1 0 .708L20.5 20l1.161 1.161a.5.5 0 0 1 .015.692l-1.823 1.984a.5.5 0 0 1-.722.015l-.985-.984a.5.5 0 0 1-.146-.354zM20.5 13a1 1 0 1 0-2 0a1 1 0 0 0 2 0M17 17.242v3.69c-1.36.714-3.031 1.07-5 1.07c-3.42 0-5.944-1.073-7.486-3.237a2.75 2.75 0 0 1-.51-1.596v-.92a2.25 2.25 0 0 1 2.249-2.25h8.775A4.5 4.5 0 0 0 17 17.243M12 2.005a5 5 0 1 1 0 10a5 5 0 0 1 0-10"></path></svg>
),
},
{
title: "Two Factor",
icon: ScanFace,
href: "/docs/plugins/2fa",
},
{
title: "Username",
icon: UserSquare2,
href: "/docs/plugins/username",
},
{
title: "Authorization",
group: true,
href: "/docs/plugins/1st-party-plugins",
icon: LucideAArrowDown
},
{
title: "Organization",
icon: Users2,
href: "/docs/plugins/organization",
},
{
title: "Utility",
group: true,
href: "/docs/plugins/1st-party-plugins",
icon: LucideAArrowDown
},
{
title: "Bearer",
icon: Key,
href: "/docs/plugins/email-verifier",
},
{
title: "Email Checker",
icon: MailCheck,
href: "/docs/plugins/email-verifier",
},
],
},
];

View File

@@ -20,8 +20,7 @@ export function ThemeToggle() {
<Button <Button
variant="ghost" variant="ghost"
size="icon" size="icon"
className="border-l rounded-none h-14 w-14 hidden md:flex shrink-0" className="border-l ring-0 rounded-none h-14 w-14 hidden md:flex shrink-0"
data-umami-event="theme-toggle"
> >
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" /> <Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" /> <Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />

View File

@@ -0,0 +1,10 @@
---
title: Introduction
description: Introduction to better auth plugins
---
Better Auth comes with a plugin system. It provides a set of built-in plugins that you can use to authenticate users using different methods. You can also create your own custom plugins to extend the functionality of Better Auth.
## What are plugins?
Plugins can be used to extend the functionality of Better Auth. They allow you to add new features or modify existing features of Better Auth. Plugins can be used to authenticate users using different methods, store user data in a databases, hook into existing authentication methods, and more.

View File

@@ -25,7 +25,18 @@ Organizations Plugin offer a versatile and scalable approach to controlling user
] // [!code highlight] ] // [!code highlight]
}) })
``` ```
Now you have all the endpoints that are required to manage organizations and members. You can call them on the serer using the `api` object. Let's see how to use them on the client.
</Step>
<Step>
### Migarate database
Once you've added the plugin, you need to migrate your database to add the necessary tables and fields. You can do this by running the following command:
```bash
npx better-auth migrate
```
</Step>
<Step>
### Add the client plugin ### Add the client plugin
```ts title="client.ts" twoslash ```ts title="client.ts" twoslash
@@ -39,4 +50,381 @@ Organizations Plugin offer a versatile and scalable approach to controlling user
}) })
``` ```
</Step> </Step>
</Steps> <Step>
### Create an Organization
this will create an organization with the name `My Organization` and slug `my-org`. The user who creates the organization will be the `owner` of the organization by default.
```ts title="client.ts" twoslash
import { createAuthClient } from "better-auth/client"
import { organizationClient } from "better-auth/client/plugins"
const client = createAuthClient({
authPlugins: [ // [!code highlight]
organizationClient() // [!code highlight]
] // [!code highlight]
})
// ---cut---
const data = await client.organization.create({
name: "My Organization",
slug: "my-org"
})
```
</Step>
<Step>
### List Organizations
To list all user's organization on the client you can use `useListOrganizations` hook or for svelte you can use `client.$listOrganizations`.
```tsx title="client.tsx"
import { createAuthClient } from "better-auth/react"
import { organizationClient } from "better-auth/client/plugins"
const client = createAuthClient({
authPlugins: [
organizationClient()
]
})
function App(){
const organizations = client.useListOrganizations()
return (
<div>
{
organizations.map(org => <p>{org.name}</p>)
}
</div>
)
}
```
</Step>
<Step>
### Active Organization
#### Set Active Organization
Active organization is the organization that the user is currently working on. You can set the active organization by calling the `setActiveOrganization` function. It'll set the active organization for the user both on the client state and the session on the server.
```ts title="client.ts" twoslash
import { createAuthClient } from "better-auth/client"
import { organizationClient } from "better-auth/client/plugins"
const client = createAuthClient({
authPlugins: [ // [!code highlight]
organizationClient() // [!code highlight]
] // [!code highlight]
})
// ---cut---
client.setActiveOrganization("organization-id")
```
<Callout type="info">
`setActiveOrganization` updates the active organization reactively. Ensure it's used according to your framework's rules for reactive calls. For React, call it within a component and follow the rules of hooks.
</Callout>
#### Get Active Organization
To retrieve the active organization for the user, you can call the `useActiveOrganization` hook. It returns the active organization for the user.
```tsx title="client.tsx"
import { createAuthClient } from "better-auth/react"
import { organizationClient } from "better-auth/client/plugins"
const client = createAuthClient({
authPlugins: [
organizationClient()
]
})
function App(){
const activeOrganization = client.useActiveOrganization()
return (
<div>
{
activeOrganization ? <p>{activeOrganization.name}</p> : null
}
</div>
)
}
```
The above example should be roughly similar for all frameworks except for the svelte. For svelte, you can need to use `client.$activeOrganization`. instead. And make sure to call it with `$` to make it reactive.
```svelte title="page.svelte"
<script lang="ts">
import { createAuthClient } from "better-auth/svelte"
import { organizationClient } from "better-auth/client/plugins"
const client = createAuthClient({
authPlugins: [
organizationClient()
]
})
const activeOrganization = client.$activeOrganization
</script>
<div>
{#if $activeOrganization}
<p>{$activeOrganization.name}</p>
{/if}
</div>
```
</Step>
<Step>
### Invite Users to Organization
#### Send Invitation
For member invitation to work we first need to provider `sendInvitationEmail` to the `better-auth` instance. This function is responsible for sending the invitation email to the user. The function takes an object with the following properties:
- `email`: The email address of the user.
- `invitation`: The invitation object that contains the organization id and the role of the user in the organization and the invitation id which serve as a token for the user to accept the invitation.
```ts title="auth.ts" twoslash
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
export const { api, handler } = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
plugins: [
organization({
sendInvitationEmail: async (invitation, email) => {
const url = `http://example.com/accept-invitation?token={invitation.id}`
// send email
}
})
]
})
````
To invite users to an organization, you can use the `invite` function provided by the client. The `invite` function takes an object with the following properties:
- `email`: The email address of the user.
- `role`: The role of the user in the organization. It can be `admin`, `member`, or `guest`.
- `organizationId`: The id of the organization. this is optional by default it will use the active organization.
```ts title="client.ts" twoslash
import { createAuthClient } from "better-auth/client"
import { organizationClient } from "better-auth/client/plugins"
const client = createAuthClient({
authPlugins: [ // [!code highlight]
organizationClient() // [!code highlight]
] // [!code highlight]
})
// ---cut---
const data = await client.organization.inviteMember({
email: "test@email.com",
role: "admin",
})
```
#### Get Invitation
When a user clicks the invitation link, use setInvitationId with the invitation ID. Then, use the useInvitation hook to fetch the invitation object. If the token is valid, the hook returns the invitation object; if not, it returns null.
```tsx title="client.tsx"
import { createAuthClient } from "better-auth/react"
const client = createAuthClient({
authPlugins: [
organizationClient()
]
})
function App(){
useEffect(() => {
client.setInvitationId(
urlParams.get("token")
)
}, [])
const invitation = client.useInvitation()
return (
<div>
{
invitation ? <p>{invitation.email}</p> : null
}
</div>
)
}
```
#### Update Invitation Status
To update the status of invitation you can use the `acceptInvitation`, `cancelInvitation`, `rejectInvitation` functions provided by the client. The functions take the invitation id as an argument.
```ts title="client.ts" twoslash
import { createAuthClient } from "better-auth/client"
import { organizationClient } from "better-auth/client/plugins"
const client = createAuthClient({
authPlugins: [ // [!code highlight]
organizationClient() // [!code highlight]
] // [!code highlight]
})
// ---cut---
const data = await client.organization.acceptInvitation({
invitationId: "invitation-id"
})
```
<Callout>
To accept or cancel an invitation, the invited user must sign in using the email address specified in the invitation. Upon accepting the invitation, the user will be added to the organization with the role outlined in the invitation.
</Callout>
</Step>
<Step>
### Remove and Update Memeber
To remove or update memebrs you can use `organization.removeMember` or `organization.updateMember`.
</Step>
<Step>
🎉 Congrats you have setup organization sucessfully.
</Step>
</Steps>
## Access Control
The plugin providers a very flexible access control system. You can control the access of the user based on the role they have in the organization. You can define your own set of permissions based on the role of the user.
### Roles
`owner`: The user who created the organization by default. The owner has full control over the organization and can perform any action.
`admin`: Users with the admin role have full control over the organization except for deleting the organization or changing the owner.
`member`: Users with the member role have limited control over the organization. They can create projects, invite users, and manage projects they have created.
### Permissons
By defualt there are 3 resources and they have 2 to 3 actions.
**organization**:
`update` `delete`
**member**:
`create` `update` `delete`
**invitation**:
`create` `cancel`
The owner have full control over all the resources and actions. The admin have full control over all the resources except for deleting the organization or changing the owner. The member have no control over any of those action other than reading the data.
### Custom Permissions
the plugin providers easy way to define your own set of permission for each role.
**Terminologies**
`resource`: The resource for which you want to define the permission. For example, `project`, `task`, `comment`, etc.
`action`: The action that the user can perform on the resource. For example, `create`, `read`, `update`, `delete`.
`statement`: The statement that defines the permission for the role. The statement is an object with the resource as the key and an array of actions as the value.
`role`: The role for which you want to define the permission. For example, `admin`, `member`, `owner`.
<Callout type="warn">
Currently the plugin only supports those 3 pre-defined roles. You can't add your own role.
</Callout>
```ts title="permissions.ts" twoslash
import { createAccessControl } from "better-auth/plugins/access";
const statement = {
project: ["create", "share", "update", "delete"],
};
const ac = createAccessControl(statement);
const member = ac.newRole({
project: ["create"],
});
const admin = ac.newRole({
project: ["create", "update"],
});
const owner = ac.newRole({
project: ["create", "update", "delete"],
});
```
<Callout type="info">
We need to share the permission with both the client and the server. You can define the permission in a separate file and import it in both the client and the server.
</Callout>
**Add permissions to the serever**
```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
import { ac, member, owner, admin } from "./permissions" // [!code highlight]
export const { api, handler } = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
plugins: [
organization({
ac, // [!code highlight]
roles: { // [!code highlight]
member, // [!code highlight]
admin, // [!code highlight]
owner, // [!code highlight]
} // [!code highlight]
})
]
})
```
## Options
### Server
**allowUserToCreateOrganization**: `boolean` | `((user: User) => Promise<boolean> | boolean)` - Allow users to create organizations. By default, it's `true`. You can set it to `false` to disable users from creating organizations. You can also provide a function that returns a boolean value to determine if the user can create an organization. For emxaple you can allow them based on their subscription plan.
```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
const { api, handler } = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
plugins: [
organization({
allowUserToCreateOrganization: (user) => {
const subscription = await getSubscription(user.id)
return subscription.plan === "pro"
}
})
]
})
```
**creatorRole**: `admin | owner` - The role of the user who creates the organization. By default, it's `owner`. You can set it to `admin`.
**membershipLimit**: `number` - The maximum number of members allowed in an organization. By default, it's `100`. You can set it to any number you want.
**sendInvitationEmail**: `async (invitation: Invitation, email: string) => Promise<void>` - A function that sends an invitation email to the user. The function takes an invitation object and the email address of the user as arguments. You can use this function to send an email with an invitation link to the user. The invitation object contains the organization id, the role of the user in the organization, and the invitation id which serves as a token for the user to accept the invitation.
```ts title="auth.ts"
import { betterAuth } from "better-auth"
import { organization } from "better-auth/plugins"
export const { api, handler } = await betterAuth({
database: {
provider: "sqlite",
url: "./db.sqlite",
},
plugins: [
organization({
sendInvitationEmail: async (invitation, email) => {
const url = `http://example.com/accept-invitation?token={invitation.id}`
// send email
}
})
]
})
```

View File

@@ -2,7 +2,7 @@ import createMDX from 'fumadocs-mdx/config';
import { rehypeCodeDefaultOptions } from "fumadocs-core/mdx-plugins"; import { rehypeCodeDefaultOptions } from "fumadocs-core/mdx-plugins";
import { remarkInstall } from "fumadocs-docgen"; import { remarkInstall } from "fumadocs-docgen";
import { transformerTwoslash } from "fumadocs-twoslash" import { transformerTwoslash } from "fumadocs-twoslash"
import { ModuleResolutionKind } from 'typescript'; import { JsxEmit, ModuleResolutionKind } from 'typescript';
const withMDX = createMDX({ const withMDX = createMDX({
mdxOptions: { mdxOptions: {
rehypeCodeOptions: { rehypeCodeOptions: {
@@ -11,7 +11,8 @@ const withMDX = createMDX({
transformerTwoslash({ transformerTwoslash({
twoslashOptions: { twoslashOptions: {
compilerOptions: { compilerOptions: {
moduleResolution: ModuleResolutionKind.Bundler moduleResolution: ModuleResolutionKind.Bundler,
jsx: JsxEmit.React
} }
} }
}), }),

View File

@@ -29,6 +29,7 @@
"./solid": "./dist/solid.js", "./solid": "./dist/solid.js",
"./vue": "./dist/vue.js", "./vue": "./dist/vue.js",
"./plugins": "./dist/plugins.js", "./plugins": "./dist/plugins.js",
"./plugins/access": "./dist/access.js",
"./svelte-kit": "./dist/svelte-kit.js", "./svelte-kit": "./dist/svelte-kit.js",
"./solid-start": "./dist/solid-start.js", "./solid-start": "./dist/solid-start.js",
"./svelte": "./dist/svelte.js", "./svelte": "./dist/svelte.js",
@@ -50,7 +51,7 @@
"swr": "^2.2.5", "swr": "^2.2.5",
"tsup": "^8.2.4", "tsup": "^8.2.4",
"type-fest": "^4.24.0", "type-fest": "^4.24.0",
"typescript": "^5.5.0-dev.20240508", "typescript": "5.6.0-beta",
"vitest": "^1.6.0" "vitest": "^1.6.0"
}, },
"dependencies": { "dependencies": {

View File

@@ -1,140 +0,0 @@
import { atom, computed, task } from "nanostores";
import type {
Invitation,
Member,
Organization,
} from "../../plugins/organization/schema";
import type { Prettify } from "../../types/helper";
import type { organization as org } from "../../plugins";
import { createClientPlugin } from "../create-client-plugin";
export const organization = createClientPlugin<ReturnType<typeof org>>()(
($fetch) => {
const activeOrgId = atom<string | null>(null);
const $listOrg = atom<boolean>(false);
const $activeOrgSignal = atom<boolean>(false);
const $activeOrganization = computed([activeOrgId, $activeOrgSignal], () =>
task(async () => {
if (!activeOrgId.get()) {
return null;
}
const organization = await $fetch<
Prettify<
Organization & {
members: Member[];
invitations: Invitation[];
}
>
>("/organization/set-active", {
method: "POST",
credentials: "include",
body: {
orgId: activeOrgId.get(),
},
});
return organization.data;
}),
);
const $listOrganizations = computed($listOrg, () =>
task(async () => {
const organizations = await $fetch<Organization[]>(
"/organization/list",
{
method: "GET",
},
);
return organizations.data;
}),
);
const $activeInvitationId = atom<string | null>(null);
const $invitation = computed($activeInvitationId, () =>
task(async () => {
if (!$activeInvitationId.get()) {
return {
error: {
message: "No invitation found",
status: 400,
data: null,
},
data: null,
};
}
const res = await $fetch<
Prettify<
Invitation & {
organizationName: string;
organizationSlug: string;
inviterEmail: string;
inviterName: string;
}
>
>("/organization/get-active-invitation", {
method: "GET",
query: {
id: $activeInvitationId.get(),
},
credentials: "include",
});
return res;
}),
);
return {
id: "organization",
actions: {
setActiveOrganization(orgId: string | null) {
activeOrgId.set(orgId);
},
setInvitationId: (id: string | null) => {
$activeInvitationId.set(id);
},
},
integrations: {
react(useStore) {
return {
useActiveOrganization() {
return useStore($activeOrganization);
},
useListOrganization() {
return useStore($listOrganizations);
},
useInvitation() {
return useStore($invitation);
},
};
},
vue(useStore) {
return {
useActiveOrganization() {
return useStore($activeOrganization);
},
useListOrganization() {
return useStore($listOrganizations);
},
useInvitation() {
return useStore($invitation);
},
};
},
preact(useStore) {
return {
useActiveOrganization() {
return useStore($activeOrganization);
},
useListOrganization() {
return useStore($listOrganizations);
},
useInvitation() {
return useStore($invitation);
},
};
},
},
signals: {
$listOrg,
$activeOrgSignal,
},
};
},
);

View File

@@ -1,107 +0,0 @@
import type { BetterFetch } from "@better-fetch/fetch";
import {
WebAuthnError,
startAuthentication,
startRegistration,
} from "@simplewebauthn/browser";
import type {
PublicKeyCredentialCreationOptionsJSON,
PublicKeyCredentialRequestOptionsJSON,
} from "@simplewebauthn/types";
import type { Session } from "inspector";
import type { User } from "../../adapters/schema";
import type { passkey as passkeyPl, Passkey } from "../../plugins";
import { createClientPlugin } from "../create-client-plugin";
export const getPasskeyActions = ($fetch: BetterFetch) => {
const signInPasskey = async (opts?: {
autoFill?: boolean;
email?: string;
callbackURL?: string;
}) => {
const response = await $fetch<PublicKeyCredentialRequestOptionsJSON>(
"/passkey/generate-authenticate-options",
{
method: "POST",
body: {
email: opts?.email,
},
},
);
if (!response.data) {
return response;
}
try {
const res = await startAuthentication(
response.data,
opts?.autoFill || false,
);
const verified = await $fetch<{
session: Session;
user: User;
}>("/passkey/verify-authentication", {
body: {
response: res,
type: "authenticate",
},
});
if (!verified.data) {
return verified;
}
} catch (e) {
console.log(e);
}
};
const register = async () => {
const options = await $fetch<PublicKeyCredentialCreationOptionsJSON>(
"/passkey/generate-register-options",
{
method: "GET",
},
);
if (!options.data) {
return options;
}
try {
const res = await startRegistration(options.data);
const verified = await $fetch<{
passkey: Passkey;
}>("/passkey/verify-registration", {
body: {
response: res,
type: "register",
},
});
if (!verified.data) {
return verified;
}
} catch (e) {
if (e instanceof WebAuthnError) {
if (e.code === "ERROR_AUTHENTICATOR_PREVIOUSLY_REGISTERED") {
return {
data: null,
error: {
message: "previously registered",
status: 400,
statusText: "BAD_REQUEST",
},
};
}
}
}
};
return {
signInPasskey,
register,
};
};
export const passkey = createClientPlugin<ReturnType<typeof passkeyPl>>()(
($fetch) => {
return {
id: "passkey",
actions: getPasskeyActions($fetch),
};
},
);

View File

@@ -1,23 +0,0 @@
import { createClientPlugin } from "../create-client-plugin";
import type { twoFactor as twoFa } from "../../plugins/two-factor";
export const twoFactor = createClientPlugin<ReturnType<typeof twoFa>>()(
($fetch) => {
return {
id: "two-factor",
authProxySignal: [
{
matcher: (path) =>
path === "/two-factor/enable" || path === "/two-factor/send-otp",
atom: "$sessionSignal",
},
],
pathMethods: {
"enable/totp": "POST",
"/two-factor/disable": "POST",
"/two-factor/enable": "POST",
"/two-factor/send-otp": "POST",
},
};
},
);

View File

@@ -1,5 +1,4 @@
import { useStore } from "@nanostores/react"; import { useStore } from "@nanostores/react";
import type { InferSession, InferUser } from "../types";
import { createAuthClient as createVanillaClient } from "./base"; import { createAuthClient as createVanillaClient } from "./base";
import type { AuthPlugin, ClientOptions } from "./type"; import type { AuthPlugin, ClientOptions } from "./type";
import type { UnionToIntersection } from "../types/helper"; import type { UnionToIntersection } from "../types/helper";
@@ -25,9 +24,7 @@ export const createAuthClient = <Option extends ClientOptions>(
} }
| undefined | undefined
? R ? R
: { : {}
test1: ReturnType<Pl>["integrations"];
}
> >
: {} : {}
: {}; : {};

View File

@@ -1,14 +1,37 @@
import type { BetterFetchOption } from "@better-fetch/fetch";
import { useStore } from "@nanostores/vue"; import { useStore } from "@nanostores/vue";
import { createAuthClient as createClient } from "./base"; import { createAuthClient as createClient } from "./base";
import type { AuthPlugin, ClientOptions } from "./type";
import type { UnionToIntersection } from "type-fest";
export const createAuthClient = <O extends BetterFetchOption>(options?: O) => { export const createAuthClient = <O extends ClientOptions>(options?: O) => {
const client = createClient(options); const client = createClient(options);
function useSession() { function useSession() {
return useStore(client.$atoms.$session); return useStore(client.$atoms.$session);
} }
const hooks = options?.authPlugins?.reduce(
(acc, plugin) => {
return {
...acc,
...(plugin(client.$fetch).integrations?.vue?.(useStore) || {}),
};
},
{} as Record<string, any>,
) as O["authPlugins"] extends Array<infer Pl>
? Pl extends AuthPlugin
? UnionToIntersection<
ReturnType<Pl>["integrations"] extends
| {
vue?: (useStore: any) => infer R;
}
| undefined
? R
: {}
>
: {}
: {};
const obj = Object.assign(client, { const obj = Object.assign(client, {
useSession, useSession,
...hooks,
}); });
return obj; return obj;
}; };

View File

@@ -142,5 +142,19 @@ export const organizationClient = () =>
$listOrg, $listOrg,
$activeOrgSignal, $activeOrgSignal,
}, },
authProxySignal: [
{
matcher(path) {
return path.startsWith("/organization");
},
atom: "$listOrg",
},
{
matcher(path) {
return path.startsWith("/organization");
},
atom: "$activeOrgSignal",
},
],
}; };
}); });

View File

@@ -1 +1,2 @@
export * from "./organization"; export * from "./organization";
export * as ac from "./access";

View File

@@ -19,7 +19,7 @@ import {
type defaultStatements, type defaultStatements,
} from "./access"; } from "./access";
import { getOrgAdapter } from "./adapter"; import { getOrgAdapter } from "./adapter";
import { orgMiddleware, orgSessionMiddleware } from "./call"; import { orgSessionMiddleware } from "./call";
import { import {
acceptInvitation, acceptInvitation,
cancelInvitation, cancelInvitation,
@@ -27,7 +27,7 @@ import {
getActiveInvitation, getActiveInvitation,
rejectInvitation, rejectInvitation,
} from "./routes/crud-invites"; } from "./routes/crud-invites";
import { deleteMember, updateMember } from "./routes/crud-members"; import { removeMember, updateMember } from "./routes/crud-members";
import { import {
createOrganization, createOrganization,
getFullOrganization, getFullOrganization,
@@ -117,7 +117,7 @@ export const organization = <O extends OrganizationOptions>(options?: O) => {
acceptInvitation, acceptInvitation,
getActiveInvitation, getActiveInvitation,
rejectInvitation, rejectInvitation,
deleteMember, removeMember,
updateMember, updateMember,
}; };

View File

@@ -3,8 +3,8 @@ import { createAuthEndpoint } from "../../../api/call";
import { getOrgAdapter } from "../adapter"; import { getOrgAdapter } from "../adapter";
import { orgMiddleware, orgSessionMiddleware } from "../call"; import { orgMiddleware, orgSessionMiddleware } from "../call";
export const deleteMember = createAuthEndpoint( export const removeMember = createAuthEndpoint(
"/org/delete-member", "/organization/remove-member",
{ {
method: "POST", method: "POST",
body: z.object({ body: z.object({
@@ -88,7 +88,7 @@ export const deleteMember = createAuthEndpoint(
); );
export const updateMember = createAuthEndpoint( export const updateMember = createAuthEndpoint(
"/org/update-member", "/organization/update-member",
{ {
method: "POST", method: "POST",
body: z.object({ body: z.object({

View File

@@ -14,6 +14,7 @@ export default defineConfig({
"client/plugins": "./src/client/plugins.ts", "client/plugins": "./src/client/plugins.ts",
"svelte-kit": "./src/integrations/svelte-kit.ts", "svelte-kit": "./src/integrations/svelte-kit.ts",
svelte: "./src/client/svelte.ts", svelte: "./src/client/svelte.ts",
access: "./src/plugins/organization/access/index.ts",
solid: "./src/client/solid.ts", solid: "./src/client/solid.ts",
"solid-start": "./src/integrations/solid-start.ts", "solid-start": "./src/integrations/solid-start.ts",
"next-js": "./src/integrations/next-js.ts", "next-js": "./src/integrations/next-js.ts",

212
pnpm-lock.yaml generated
View File

@@ -520,7 +520,7 @@ importers:
version: 0.4.2(nanostores@0.11.2)(solid-js@1.8.21) version: 0.4.2(nanostores@0.11.2)(solid-js@1.8.21)
'@nanostores/vue': '@nanostores/vue':
specifier: ^0.10.0 specifier: ^0.10.0
version: 0.10.0(@vue/devtools-api@6.6.3)(nanostores@0.11.2)(vue@3.4.38(typescript@5.5.4)) version: 0.10.0(@vue/devtools-api@6.6.3)(nanostores@0.11.2)(vue@3.4.38(typescript@5.6.0-beta))
'@noble/ciphers': '@noble/ciphers':
specifier: ^0.6.0 specifier: ^0.6.0
version: 0.6.0 version: 0.6.0
@@ -541,7 +541,7 @@ importers:
version: 2.0.0-next.5 version: 2.0.0-next.5
better-call: better-call:
specifier: ^0.1.38 specifier: ^0.1.38
version: 0.1.38(typescript@5.5.4) version: 0.1.38(typescript@5.6.0-beta)
chalk: chalk:
specifier: ^5.3.0 specifier: ^5.3.0
version: 5.3.0 version: 5.3.0
@@ -629,13 +629,13 @@ importers:
version: 2.2.5(react@18.3.1) version: 2.2.5(react@18.3.1)
tsup: tsup:
specifier: ^8.2.4 specifier: ^8.2.4
version: 8.2.4(jiti@1.21.6)(postcss@8.4.41)(tsx@4.19.0)(typescript@5.5.4)(yaml@2.5.0) version: 8.2.4(jiti@1.21.6)(postcss@8.4.41)(tsx@4.19.0)(typescript@5.6.0-beta)(yaml@2.5.0)
type-fest: type-fest:
specifier: ^4.24.0 specifier: ^4.24.0
version: 4.24.0 version: 4.24.0
typescript: typescript:
specifier: ^5.5.0-dev.20240508 specifier: 5.6.0-beta
version: 5.5.4 version: 5.6.0-beta
vitest: vitest:
specifier: ^1.6.0 specifier: ^1.6.0
version: 1.6.0(@types/node@22.3.0)(terser@5.31.6) version: 1.6.0(@types/node@22.3.0)(terser@5.31.6)
@@ -2915,161 +2915,81 @@ packages:
rollup: rollup:
optional: true optional: true
'@rollup/rollup-android-arm-eabi@4.19.1':
resolution: {integrity: sha512-XzqSg714++M+FXhHfXpS1tDnNZNpgxxuGZWlRG/jSj+VEPmZ0yg6jV4E0AL3uyBKxO8mO3xtOsP5mQ+XLfrlww==}
cpu: [arm]
os: [android]
'@rollup/rollup-android-arm-eabi@4.21.2': '@rollup/rollup-android-arm-eabi@4.21.2':
resolution: {integrity: sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==} resolution: {integrity: sha512-fSuPrt0ZO8uXeS+xP3b+yYTCBUd05MoSp2N/MFOgjhhUhMmchXlpTQrTpI8T+YAwAQuK7MafsCOxW7VrPMrJcg==}
cpu: [arm] cpu: [arm]
os: [android] os: [android]
'@rollup/rollup-android-arm64@4.19.1':
resolution: {integrity: sha512-thFUbkHteM20BGShD6P08aungq4irbIZKUNbG70LN8RkO7YztcGPiKTTGZS7Kw+x5h8hOXs0i4OaHwFxlpQN6A==}
cpu: [arm64]
os: [android]
'@rollup/rollup-android-arm64@4.21.2': '@rollup/rollup-android-arm64@4.21.2':
resolution: {integrity: sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==} resolution: {integrity: sha512-xGU5ZQmPlsjQS6tzTTGwMsnKUtu0WVbl0hYpTPauvbRAnmIvpInhJtgjj3mcuJpEiuUw4v1s4BimkdfDWlh7gA==}
cpu: [arm64] cpu: [arm64]
os: [android] os: [android]
'@rollup/rollup-darwin-arm64@4.19.1':
resolution: {integrity: sha512-8o6eqeFZzVLia2hKPUZk4jdE3zW7LCcZr+MD18tXkgBBid3lssGVAYuox8x6YHoEPDdDa9ixTaStcmx88lio5Q==}
cpu: [arm64]
os: [darwin]
'@rollup/rollup-darwin-arm64@4.21.2': '@rollup/rollup-darwin-arm64@4.21.2':
resolution: {integrity: sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==} resolution: {integrity: sha512-99AhQ3/ZMxU7jw34Sq8brzXqWH/bMnf7ZVhvLk9QU2cOepbQSVTns6qoErJmSiAvU3InRqC2RRZ5ovh1KN0d0Q==}
cpu: [arm64] cpu: [arm64]
os: [darwin] os: [darwin]
'@rollup/rollup-darwin-x64@4.19.1':
resolution: {integrity: sha512-4T42heKsnbjkn7ovYiAdDVRRWZLU9Kmhdt6HafZxFcUdpjlBlxj4wDrt1yFWLk7G4+E+8p2C9tcmSu0KA6auGA==}
cpu: [x64]
os: [darwin]
'@rollup/rollup-darwin-x64@4.21.2': '@rollup/rollup-darwin-x64@4.21.2':
resolution: {integrity: sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==} resolution: {integrity: sha512-ZbRaUvw2iN/y37x6dY50D8m2BnDbBjlnMPotDi/qITMJ4sIxNY33HArjikDyakhSv0+ybdUxhWxE6kTI4oX26w==}
cpu: [x64] cpu: [x64]
os: [darwin] os: [darwin]
'@rollup/rollup-linux-arm-gnueabihf@4.19.1':
resolution: {integrity: sha512-MXg1xp+e5GhZ3Vit1gGEyoC+dyQUBy2JgVQ+3hUrD9wZMkUw/ywgkpK7oZgnB6kPpGrxJ41clkPPnsknuD6M2Q==}
cpu: [arm]
os: [linux]
'@rollup/rollup-linux-arm-gnueabihf@4.21.2': '@rollup/rollup-linux-arm-gnueabihf@4.21.2':
resolution: {integrity: sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==} resolution: {integrity: sha512-ztRJJMiE8nnU1YFcdbd9BcH6bGWG1z+jP+IPW2oDUAPxPjo9dverIOyXz76m6IPA6udEL12reYeLojzW2cYL7w==}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@rollup/rollup-linux-arm-musleabihf@4.19.1':
resolution: {integrity: sha512-DZNLwIY4ftPSRVkJEaxYkq7u2zel7aah57HESuNkUnz+3bZHxwkCUkrfS2IWC1sxK6F2QNIR0Qr/YXw7nkF3Pw==}
cpu: [arm]
os: [linux]
'@rollup/rollup-linux-arm-musleabihf@4.21.2': '@rollup/rollup-linux-arm-musleabihf@4.21.2':
resolution: {integrity: sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==} resolution: {integrity: sha512-flOcGHDZajGKYpLV0JNc0VFH361M7rnV1ee+NTeC/BQQ1/0pllYcFmxpagltANYt8FYf9+kL6RSk80Ziwyhr7w==}
cpu: [arm] cpu: [arm]
os: [linux] os: [linux]
'@rollup/rollup-linux-arm64-gnu@4.19.1':
resolution: {integrity: sha512-C7evongnjyxdngSDRRSQv5GvyfISizgtk9RM+z2biV5kY6S/NF/wta7K+DanmktC5DkuaJQgoKGf7KUDmA7RUw==}
cpu: [arm64]
os: [linux]
'@rollup/rollup-linux-arm64-gnu@4.21.2': '@rollup/rollup-linux-arm64-gnu@4.21.2':
resolution: {integrity: sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==} resolution: {integrity: sha512-69CF19Kp3TdMopyteO/LJbWufOzqqXzkrv4L2sP8kfMaAQ6iwky7NoXTp7bD6/irKgknDKM0P9E/1l5XxVQAhw==}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@rollup/rollup-linux-arm64-musl@4.19.1':
resolution: {integrity: sha512-89tFWqxfxLLHkAthAcrTs9etAoBFRduNfWdl2xUs/yLV+7XDrJ5yuXMHptNqf1Zw0UCA3cAutkAiAokYCkaPtw==}
cpu: [arm64]
os: [linux]
'@rollup/rollup-linux-arm64-musl@4.21.2': '@rollup/rollup-linux-arm64-musl@4.21.2':
resolution: {integrity: sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==} resolution: {integrity: sha512-48pD/fJkTiHAZTnZwR0VzHrao70/4MlzJrq0ZsILjLW/Ab/1XlVUStYyGt7tdyIiVSlGZbnliqmult/QGA2O2w==}
cpu: [arm64] cpu: [arm64]
os: [linux] os: [linux]
'@rollup/rollup-linux-powerpc64le-gnu@4.19.1':
resolution: {integrity: sha512-PromGeV50sq+YfaisG8W3fd+Cl6mnOOiNv2qKKqKCpiiEke2KiKVyDqG/Mb9GWKbYMHj5a01fq/qlUR28PFhCQ==}
cpu: [ppc64]
os: [linux]
'@rollup/rollup-linux-powerpc64le-gnu@4.21.2': '@rollup/rollup-linux-powerpc64le-gnu@4.21.2':
resolution: {integrity: sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==} resolution: {integrity: sha512-cZdyuInj0ofc7mAQpKcPR2a2iu4YM4FQfuUzCVA2u4HI95lCwzjoPtdWjdpDKyHxI0UO82bLDoOaLfpZ/wviyQ==}
cpu: [ppc64] cpu: [ppc64]
os: [linux] os: [linux]
'@rollup/rollup-linux-riscv64-gnu@4.19.1':
resolution: {integrity: sha512-/1BmHYh+iz0cNCP0oHCuF8CSiNj0JOGf0jRlSo3L/FAyZyG2rGBuKpkZVH9YF+x58r1jgWxvm1aRg3DHrLDt6A==}
cpu: [riscv64]
os: [linux]
'@rollup/rollup-linux-riscv64-gnu@4.21.2': '@rollup/rollup-linux-riscv64-gnu@4.21.2':
resolution: {integrity: sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==} resolution: {integrity: sha512-RL56JMT6NwQ0lXIQmMIWr1SW28z4E4pOhRRNqwWZeXpRlykRIlEpSWdsgNWJbYBEWD84eocjSGDu/XxbYeCmwg==}
cpu: [riscv64] cpu: [riscv64]
os: [linux] os: [linux]
'@rollup/rollup-linux-s390x-gnu@4.19.1':
resolution: {integrity: sha512-0cYP5rGkQWRZKy9/HtsWVStLXzCF3cCBTRI+qRL8Z+wkYlqN7zrSYm6FuY5Kd5ysS5aH0q5lVgb/WbG4jqXN1Q==}
cpu: [s390x]
os: [linux]
'@rollup/rollup-linux-s390x-gnu@4.21.2': '@rollup/rollup-linux-s390x-gnu@4.21.2':
resolution: {integrity: sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==} resolution: {integrity: sha512-PMxkrWS9z38bCr3rWvDFVGD6sFeZJw4iQlhrup7ReGmfn7Oukrr/zweLhYX6v2/8J6Cep9IEA/SmjXjCmSbrMQ==}
cpu: [s390x] cpu: [s390x]
os: [linux] os: [linux]
'@rollup/rollup-linux-x64-gnu@4.19.1':
resolution: {integrity: sha512-XUXeI9eM8rMP8aGvii/aOOiMvTs7xlCosq9xCjcqI9+5hBxtjDpD+7Abm1ZhVIFE1J2h2VIg0t2DX/gjespC2Q==}
cpu: [x64]
os: [linux]
'@rollup/rollup-linux-x64-gnu@4.21.2': '@rollup/rollup-linux-x64-gnu@4.21.2':
resolution: {integrity: sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==} resolution: {integrity: sha512-B90tYAUoLhU22olrafY3JQCFLnT3NglazdwkHyxNDYF/zAxJt5fJUB/yBoWFoIQ7SQj+KLe3iL4BhOMa9fzgpw==}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@rollup/rollup-linux-x64-musl@4.19.1':
resolution: {integrity: sha512-V7cBw/cKXMfEVhpSvVZhC+iGifD6U1zJ4tbibjjN+Xi3blSXaj/rJynAkCFFQfoG6VZrAiP7uGVzL440Q6Me2Q==}
cpu: [x64]
os: [linux]
'@rollup/rollup-linux-x64-musl@4.21.2': '@rollup/rollup-linux-x64-musl@4.21.2':
resolution: {integrity: sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==} resolution: {integrity: sha512-7twFizNXudESmC9oneLGIUmoHiiLppz/Xs5uJQ4ShvE6234K0VB1/aJYU3f/4g7PhssLGKBVCC37uRkkOi8wjg==}
cpu: [x64] cpu: [x64]
os: [linux] os: [linux]
'@rollup/rollup-win32-arm64-msvc@4.19.1':
resolution: {integrity: sha512-88brja2vldW/76jWATlBqHEoGjJLRnP0WOEKAUbMcXaAZnemNhlAHSyj4jIwMoP2T750LE9lblvD4e2jXleZsA==}
cpu: [arm64]
os: [win32]
'@rollup/rollup-win32-arm64-msvc@4.21.2': '@rollup/rollup-win32-arm64-msvc@4.21.2':
resolution: {integrity: sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==} resolution: {integrity: sha512-9rRero0E7qTeYf6+rFh3AErTNU1VCQg2mn7CQcI44vNUWM9Ze7MSRS/9RFuSsox+vstRt97+x3sOhEey024FRQ==}
cpu: [arm64] cpu: [arm64]
os: [win32] os: [win32]
'@rollup/rollup-win32-ia32-msvc@4.19.1':
resolution: {integrity: sha512-LdxxcqRVSXi6k6JUrTah1rHuaupoeuiv38du8Mt4r4IPer3kwlTo+RuvfE8KzZ/tL6BhaPlzJ3835i6CxrFIRQ==}
cpu: [ia32]
os: [win32]
'@rollup/rollup-win32-ia32-msvc@4.21.2': '@rollup/rollup-win32-ia32-msvc@4.21.2':
resolution: {integrity: sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==} resolution: {integrity: sha512-5rA4vjlqgrpbFVVHX3qkrCo/fZTj1q0Xxpg+Z7yIo3J2AilW7t2+n6Q8Jrx+4MrYpAnjttTYF8rr7bP46BPzRw==}
cpu: [ia32] cpu: [ia32]
os: [win32] os: [win32]
'@rollup/rollup-win32-x64-msvc@4.19.1':
resolution: {integrity: sha512-2bIrL28PcK3YCqD9anGxDxamxdiJAxA+l7fWIwM5o8UqNy1t3d1NdAweO2XhA0KTDJ5aH1FsuiT5+7VhtHliXg==}
cpu: [x64]
os: [win32]
'@rollup/rollup-win32-x64-msvc@4.21.2': '@rollup/rollup-win32-x64-msvc@4.21.2':
resolution: {integrity: sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==} resolution: {integrity: sha512-6UUxd0+SKomjdzuAcp+HAmxw1FlGBnl1v2yEPSabtx4lBfdXHDVsW7+lQkgz9cNFJGY3AWR7+V8P5BqkD9L9nA==}
cpu: [x64] cpu: [x64]
@@ -6870,11 +6790,6 @@ packages:
rollup: rollup:
optional: true optional: true
rollup@4.19.1:
resolution: {integrity: sha512-K5vziVlg7hTpYfFBI+91zHBEMo6jafYXpkMlqZjg7/zhIG9iHqazBf4xz9AVdjS9BruRn280ROqLI7G3OFRIlw==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
hasBin: true
rollup@4.21.2: rollup@4.21.2:
resolution: {integrity: sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==} resolution: {integrity: sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'} engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@@ -7564,6 +7479,11 @@ packages:
engines: {node: '>=14.17'} engines: {node: '>=14.17'}
hasBin: true hasBin: true
typescript@5.6.0-beta:
resolution: {integrity: sha512-wqVumY25SwHmCJvZPHqbWfjSyWdAqTTUM+LqaPpFccOnln54EZoPr8Ra7qJV8HMEdFYcDc+S5xro0RyvaHvIvw==}
engines: {node: '>=14.17'}
hasBin: true
ufo@1.5.4: ufo@1.5.4:
resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==} resolution: {integrity: sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==}
@@ -8883,10 +8803,10 @@ snapshots:
nanostores: 0.11.2 nanostores: 0.11.2
solid-js: 1.8.21 solid-js: 1.8.21
'@nanostores/vue@0.10.0(@vue/devtools-api@6.6.3)(nanostores@0.11.2)(vue@3.4.38(typescript@5.5.4))': '@nanostores/vue@0.10.0(@vue/devtools-api@6.6.3)(nanostores@0.11.2)(vue@3.4.38(typescript@5.6.0-beta))':
dependencies: dependencies:
nanostores: 0.11.2 nanostores: 0.11.2
vue: 3.4.38(typescript@5.5.4) vue: 3.4.38(typescript@5.6.0-beta)
optionalDependencies: optionalDependencies:
'@vue/devtools-api': 6.6.3 '@vue/devtools-api': 6.6.3
@@ -10283,99 +10203,51 @@ snapshots:
optionalDependencies: optionalDependencies:
rollup: 4.21.2 rollup: 4.21.2
'@rollup/rollup-android-arm-eabi@4.19.1':
optional: true
'@rollup/rollup-android-arm-eabi@4.21.2': '@rollup/rollup-android-arm-eabi@4.21.2':
optional: true optional: true
'@rollup/rollup-android-arm64@4.19.1':
optional: true
'@rollup/rollup-android-arm64@4.21.2': '@rollup/rollup-android-arm64@4.21.2':
optional: true optional: true
'@rollup/rollup-darwin-arm64@4.19.1':
optional: true
'@rollup/rollup-darwin-arm64@4.21.2': '@rollup/rollup-darwin-arm64@4.21.2':
optional: true optional: true
'@rollup/rollup-darwin-x64@4.19.1':
optional: true
'@rollup/rollup-darwin-x64@4.21.2': '@rollup/rollup-darwin-x64@4.21.2':
optional: true optional: true
'@rollup/rollup-linux-arm-gnueabihf@4.19.1':
optional: true
'@rollup/rollup-linux-arm-gnueabihf@4.21.2': '@rollup/rollup-linux-arm-gnueabihf@4.21.2':
optional: true optional: true
'@rollup/rollup-linux-arm-musleabihf@4.19.1':
optional: true
'@rollup/rollup-linux-arm-musleabihf@4.21.2': '@rollup/rollup-linux-arm-musleabihf@4.21.2':
optional: true optional: true
'@rollup/rollup-linux-arm64-gnu@4.19.1':
optional: true
'@rollup/rollup-linux-arm64-gnu@4.21.2': '@rollup/rollup-linux-arm64-gnu@4.21.2':
optional: true optional: true
'@rollup/rollup-linux-arm64-musl@4.19.1':
optional: true
'@rollup/rollup-linux-arm64-musl@4.21.2': '@rollup/rollup-linux-arm64-musl@4.21.2':
optional: true optional: true
'@rollup/rollup-linux-powerpc64le-gnu@4.19.1':
optional: true
'@rollup/rollup-linux-powerpc64le-gnu@4.21.2': '@rollup/rollup-linux-powerpc64le-gnu@4.21.2':
optional: true optional: true
'@rollup/rollup-linux-riscv64-gnu@4.19.1':
optional: true
'@rollup/rollup-linux-riscv64-gnu@4.21.2': '@rollup/rollup-linux-riscv64-gnu@4.21.2':
optional: true optional: true
'@rollup/rollup-linux-s390x-gnu@4.19.1':
optional: true
'@rollup/rollup-linux-s390x-gnu@4.21.2': '@rollup/rollup-linux-s390x-gnu@4.21.2':
optional: true optional: true
'@rollup/rollup-linux-x64-gnu@4.19.1':
optional: true
'@rollup/rollup-linux-x64-gnu@4.21.2': '@rollup/rollup-linux-x64-gnu@4.21.2':
optional: true optional: true
'@rollup/rollup-linux-x64-musl@4.19.1':
optional: true
'@rollup/rollup-linux-x64-musl@4.21.2': '@rollup/rollup-linux-x64-musl@4.21.2':
optional: true optional: true
'@rollup/rollup-win32-arm64-msvc@4.19.1':
optional: true
'@rollup/rollup-win32-arm64-msvc@4.21.2': '@rollup/rollup-win32-arm64-msvc@4.21.2':
optional: true optional: true
'@rollup/rollup-win32-ia32-msvc@4.19.1':
optional: true
'@rollup/rollup-win32-ia32-msvc@4.21.2': '@rollup/rollup-win32-ia32-msvc@4.21.2':
optional: true optional: true
'@rollup/rollup-win32-x64-msvc@4.19.1':
optional: true
'@rollup/rollup-win32-x64-msvc@4.21.2': '@rollup/rollup-win32-x64-msvc@4.21.2':
optional: true optional: true
@@ -11056,6 +10928,12 @@ snapshots:
'@vue/shared': 3.4.38 '@vue/shared': 3.4.38
vue: 3.4.38(typescript@5.5.4) vue: 3.4.38(typescript@5.5.4)
'@vue/server-renderer@3.4.38(vue@3.4.38(typescript@5.6.0-beta))':
dependencies:
'@vue/compiler-ssr': 3.4.38
'@vue/shared': 3.4.38
vue: 3.4.38(typescript@5.6.0-beta)
'@vue/shared@3.4.38': {} '@vue/shared@3.4.38': {}
abbrev@1.1.1: {} abbrev@1.1.1: {}
@@ -11256,13 +11134,13 @@ snapshots:
rou3: 0.5.1 rou3: 0.5.1
typescript: 5.5.4 typescript: 5.5.4
better-call@0.1.38(typescript@5.5.4): better-call@0.1.38(typescript@5.6.0-beta):
dependencies: dependencies:
'@better-fetch/fetch': 1.1.4 '@better-fetch/fetch': 1.1.4
'@types/set-cookie-parser': 2.4.10 '@types/set-cookie-parser': 2.4.10
rou3: 0.5.1 rou3: 0.5.1
set-cookie-parser: 2.7.0 set-cookie-parser: 2.7.0
typescript: 5.5.4 typescript: 5.6.0-beta
better-sqlite3@11.1.2: better-sqlite3@11.1.2:
dependencies: dependencies:
@@ -11365,9 +11243,9 @@ snapshots:
dependencies: dependencies:
run-applescript: 7.0.0 run-applescript: 7.0.0
bundle-require@5.0.0(esbuild@0.23.0): bundle-require@5.0.0(esbuild@0.23.1):
dependencies: dependencies:
esbuild: 0.23.0 esbuild: 0.23.1
load-tsconfig: 0.2.5 load-tsconfig: 0.2.5
busboy@1.6.0: busboy@1.6.0:
@@ -12703,7 +12581,7 @@ snapshots:
array-union: 2.1.0 array-union: 2.1.0
dir-glob: 3.0.1 dir-glob: 3.0.1
fast-glob: 3.3.2 fast-glob: 3.3.2
ignore: 5.3.1 ignore: 5.3.2
merge2: 1.4.1 merge2: 1.4.1
slash: 3.0.0 slash: 3.0.0
@@ -15214,28 +15092,6 @@ snapshots:
optionalDependencies: optionalDependencies:
rollup: 4.21.2 rollup: 4.21.2
rollup@4.19.1:
dependencies:
'@types/estree': 1.0.5
optionalDependencies:
'@rollup/rollup-android-arm-eabi': 4.19.1
'@rollup/rollup-android-arm64': 4.19.1
'@rollup/rollup-darwin-arm64': 4.19.1
'@rollup/rollup-darwin-x64': 4.19.1
'@rollup/rollup-linux-arm-gnueabihf': 4.19.1
'@rollup/rollup-linux-arm-musleabihf': 4.19.1
'@rollup/rollup-linux-arm64-gnu': 4.19.1
'@rollup/rollup-linux-arm64-musl': 4.19.1
'@rollup/rollup-linux-powerpc64le-gnu': 4.19.1
'@rollup/rollup-linux-riscv64-gnu': 4.19.1
'@rollup/rollup-linux-s390x-gnu': 4.19.1
'@rollup/rollup-linux-x64-gnu': 4.19.1
'@rollup/rollup-linux-x64-musl': 4.19.1
'@rollup/rollup-win32-arm64-msvc': 4.19.1
'@rollup/rollup-win32-ia32-msvc': 4.19.1
'@rollup/rollup-win32-x64-msvc': 4.19.1
fsevents: 2.3.3
rollup@4.21.2: rollup@4.21.2:
dependencies: dependencies:
'@types/estree': 1.0.5 '@types/estree': 1.0.5
@@ -15858,27 +15714,27 @@ snapshots:
tslib@2.6.3: {} tslib@2.6.3: {}
tsup@8.2.4(jiti@1.21.6)(postcss@8.4.41)(tsx@4.19.0)(typescript@5.5.4)(yaml@2.5.0): tsup@8.2.4(jiti@1.21.6)(postcss@8.4.41)(tsx@4.19.0)(typescript@5.6.0-beta)(yaml@2.5.0):
dependencies: dependencies:
bundle-require: 5.0.0(esbuild@0.23.0) bundle-require: 5.0.0(esbuild@0.23.1)
cac: 6.7.14 cac: 6.7.14
chokidar: 3.6.0 chokidar: 3.6.0
consola: 3.2.3 consola: 3.2.3
debug: 4.3.6 debug: 4.3.6
esbuild: 0.23.0 esbuild: 0.23.1
execa: 5.1.1 execa: 5.1.1
globby: 11.1.0 globby: 11.1.0
joycon: 3.1.1 joycon: 3.1.1
picocolors: 1.0.1 picocolors: 1.0.1
postcss-load-config: 6.0.1(jiti@1.21.6)(postcss@8.4.41)(tsx@4.19.0)(yaml@2.5.0) postcss-load-config: 6.0.1(jiti@1.21.6)(postcss@8.4.41)(tsx@4.19.0)(yaml@2.5.0)
resolve-from: 5.0.0 resolve-from: 5.0.0
rollup: 4.19.1 rollup: 4.21.2
source-map: 0.8.0-beta.0 source-map: 0.8.0-beta.0
sucrase: 3.35.0 sucrase: 3.35.0
tree-kill: 1.2.2 tree-kill: 1.2.2
optionalDependencies: optionalDependencies:
postcss: 8.4.41 postcss: 8.4.41
typescript: 5.5.4 typescript: 5.6.0-beta
transitivePeerDependencies: transitivePeerDependencies:
- jiti - jiti
- supports-color - supports-color
@@ -15962,6 +15818,8 @@ snapshots:
typescript@5.5.4: {} typescript@5.5.4: {}
typescript@5.6.0-beta: {}
ufo@1.5.4: {} ufo@1.5.4: {}
ultrahtml@1.5.3: {} ultrahtml@1.5.3: {}
@@ -16517,6 +16375,16 @@ snapshots:
optionalDependencies: optionalDependencies:
typescript: 5.5.4 typescript: 5.5.4
vue@3.4.38(typescript@5.6.0-beta):
dependencies:
'@vue/compiler-dom': 3.4.38
'@vue/compiler-sfc': 3.4.38
'@vue/runtime-dom': 3.4.38
'@vue/server-renderer': 3.4.38(vue@3.4.38(typescript@5.6.0-beta))
'@vue/shared': 3.4.38
optionalDependencies:
typescript: 5.6.0-beta
web-namespaces@2.0.1: {} web-namespaces@2.0.1: {}
web-worker@1.3.0: {} web-worker@1.3.0: {}

View File

@@ -5,4 +5,6 @@
[x] add all oauth providers [x] add all oauth providers
[x] providers should only be oauth [x] providers should only be oauth
[ ] add tests [ ] add tests
[ ] add callback url on otp and backup code verification [ ] add callback url on otp and backup code verification
[ ] implement the ac check on the client to for organization
[ ] add delete organization endpoint