Skip to content

Commit 078cb68

Browse files
authored
feat(react): add react integration package (@aura-stack/react) (#137)
* feat(react): add react integration package (@aura-stack/react) * chore: improve code and apply coderabbit * chore: apply coderabbit
1 parent e70355d commit 078cb68

49 files changed

Lines changed: 910 additions & 373 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.vscode/settings.json

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,23 @@
11
{
22
"editor.formatOnSave": true,
3-
"oxc.fmt.configPath": ".oxfmtrc.json",
4-
"editor.defaultFormatter": "oxc.oxc-vscode"
3+
"oxc.fmt.configPath": "./.oxfmtrc.json",
4+
"editor.defaultFormatter": "oxc.oxc-vscode",
5+
"[javascript]": {
6+
"editor.defaultFormatter": "oxc.oxc-vscode"
7+
},
8+
"[typescript]": {
9+
"editor.defaultFormatter": "oxc.oxc-vscode"
10+
},
11+
"[javascriptreact]": {
12+
"editor.defaultFormatter": "oxc.oxc-vscode"
13+
},
14+
"[typescriptreact]": {
15+
"editor.defaultFormatter": "oxc.oxc-vscode"
16+
},
17+
"[json]": {
18+
"editor.defaultFormatter": "oxc.oxc-vscode"
19+
},
20+
"[markdown]": {
21+
"editor.defaultFormatter": "oxc.oxc-vscode"
22+
}
523
}

apps/astro/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"@astrojs/node": "^10.0.2",
1818
"@astrojs/react": "^5.0.0",
1919
"@aura-stack/auth": "workspace:*",
20+
"@aura-stack/react": "workspace:*",
2021
"@radix-ui/react-slot": "^1.2.4",
2122
"astro": "^6.0.5",
2223
"lucide-react": "catalog:lucide-react",

apps/astro/src/components/auth-client.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { LayoutDashboard } from "lucide-react"
2-
import { useAuth, AuthProvider } from "@/contexts/auth"
32
import { Button } from "@/components/ui/button"
3+
import { useAuth } from "@aura-stack/react"
4+
import { AuthProvider } from "@/contexts/auth"
45
import type { Session } from "@aura-stack/auth"
56

67
const AuthClientContent = () => {
7-
const { session, isAuthenticated, isLoading, signIn, signOut } = useAuth()
8+
const { session, status, isPending, signIn, signOut } = useAuth()
9+
const isAuthenticated = status === "authenticated"
810

911
return (
1012
<div className="w-full p-6 pr-3 bg-black md:py-10">
@@ -34,7 +36,7 @@ const AuthClientContent = () => {
3436
<span className="text-white/60 truncate max-w-37.5">{session?.user?.sub}</span>
3537
</div>
3638
</div>
37-
<Button type="button" variant="outline" size="sm" disabled={isLoading} onClick={() => signOut()}>
39+
<Button type="button" variant="outline" size="sm" disabled={isPending} onClick={() => signOut()}>
3840
Sign Out
3941
</Button>
4042
</div>
@@ -54,7 +56,7 @@ const AuthClientContent = () => {
5456
className="w-full rounded-none"
5557
variant="outline"
5658
size="sm"
57-
disabled={isLoading}
59+
disabled={isPending}
5860
onClick={() => signIn(provider.toLowerCase())}
5961
>
6062
Sign In with {provider}
@@ -72,7 +74,7 @@ const AuthClientContent = () => {
7274

7375
export const AuthClient = (props: { session?: Session | null }) => {
7476
return (
75-
<AuthProvider session={props.session}>
77+
<AuthProvider initialSession={props.session}>
7678
<AuthClientContent />
7779
</AuthProvider>
7880
)

apps/astro/src/components/header.tsx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { useState } from "react"
22
import { Menu, X } from "lucide-react"
33
import { Button } from "@/components/ui/button"
4-
import { useAuth, AuthProvider } from "@/contexts/auth"
4+
import { useAuth } from "@aura-stack/react"
5+
import { AuthProvider } from "@/contexts/auth"
56
import type { Session } from "@aura-stack/auth"
67

78
const HeaderContent = () => {
89
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
9-
const { isAuthenticated, isLoading, signOut, signIn } = useAuth()
10+
const { status, isPending, signOut, signIn } = useAuth()
11+
const isAuthenticated = status === "authenticated"
1012

1113
const handleSignOut = async () => {
1214
await signOut()
@@ -103,7 +105,7 @@ const HeaderContent = () => {
103105
Discord
104106
</a>
105107
<div className="flex flex-col gap-2 pt-4 border-t border-gray-800/50">
106-
{!isLoading && !isAuthenticated && (
108+
{!isPending && !isAuthenticated && (
107109
<Button type="button" onClick={() => signIn("github")}>
108110
Sign in with GitHub
109111
</Button>
@@ -125,7 +127,7 @@ const HeaderContent = () => {
125127

126128
export const Header = (props: { session?: Session }) => {
127129
return (
128-
<AuthProvider session={props.session}>
130+
<AuthProvider initialSession={props.session}>
129131
<HeaderContent />
130132
</AuthProvider>
131133
)

apps/astro/src/contexts/auth.tsx

Lines changed: 7 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,10 @@
1-
import { createContext, use, useState, useEffect } from "react"
1+
import { AuthProvider as AuraAuthProvider, type AuthProviderProps } from "@aura-stack/react"
22
import { authClient } from "@/lib/client"
3-
import type { Session, LiteralUnion, BuiltInOAuthProvider, SignInOptions, SignOutOptions } from "@aura-stack/auth"
4-
import type { AuthProviderProps } from "@/@types/props"
5-
import type { AuthContextValue } from "@/@types/types"
63

7-
export const AuthContext = createContext<AuthContextValue | undefined>(undefined)
8-
9-
export const AuthProvider = ({ children, session: defaultSession }: AuthProviderProps) => {
10-
const [isLoading, setIsLoading] = useState(defaultSession === undefined)
11-
const [session, setSession] = useState<Session | null>(defaultSession ?? null)
12-
const isAuthenticated = Boolean(session?.user)
13-
14-
const signIn = async (provider: LiteralUnion<BuiltInOAuthProvider>, options?: SignInOptions) => {
15-
setIsLoading(true)
16-
try {
17-
return await authClient.signIn(provider, options)
18-
} finally {
19-
setIsLoading(false)
20-
}
21-
}
22-
23-
const signOut = async (options?: SignOutOptions) => {
24-
setIsLoading(true)
25-
try {
26-
const value = await authClient.signOut(options)
27-
setSession(null)
28-
return value
29-
} finally {
30-
setIsLoading(false)
31-
}
32-
}
33-
34-
useEffect(() => {
35-
if (defaultSession !== undefined) {
36-
setSession(defaultSession)
37-
setIsLoading(false)
38-
return
39-
}
40-
const fetchSession = async () => {
41-
try {
42-
const session = await authClient.getSession()
43-
setSession(session)
44-
} catch {
45-
setSession(null)
46-
} finally {
47-
setIsLoading(false)
48-
}
49-
}
50-
fetchSession()
51-
}, [defaultSession])
52-
53-
return <AuthContext value={{ session, isAuthenticated, isLoading, signIn, signOut }}>{children}</AuthContext>
54-
}
55-
56-
export const useAuth = () => {
57-
const ctx = use(AuthContext)
58-
if (!ctx) {
59-
throw new Error("useAuth must be used within an AuthProvider")
60-
}
61-
return ctx
4+
export const AuthProvider = ({ children, initialSession }: Omit<AuthProviderProps, "client">) => {
5+
return (
6+
<AuraAuthProvider client={authClient} initialSession={initialSession}>
7+
{children}
8+
</AuraAuthProvider>
9+
)
6210
}

apps/astro/tsconfig.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
"jsxImportSource": "react",
88
"paths": {
99
"@/*": ["./src/*"]
10-
},
11-
"baseUrl": "./"
10+
}
1211
}
1312
}

apps/nextjs/app-router/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
},
1414
"dependencies": {
1515
"@aura-stack/auth": "workspace:*",
16+
"@aura-stack/react": "workspace:*",
1617
"@radix-ui/react-slot": "^1.2.4",
1718
"lucide-react": "catalog:lucide-react",
1819
"next": "catalog:next",

apps/nextjs/app-router/src/app/layout.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { Geist, Geist_Mono } from "next/font/google"
22
import { Header } from "@/components/header"
3-
import { AuthProvider } from "@/contexts/auth"
43
import { Footer } from "@/components/footer"
54
import { metadataInfo } from "@/lib/metadata"
6-
import "./globals.css"
5+
import { AuthProvider } from "@/contexts/auth"
6+
import "@/app/globals.css"
77

88
const geistSans = Geist({
99
variable: "--font-geist-sans",

apps/nextjs/app-router/src/components/auth-client.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
"use client"
22

3-
import { useAuth } from "@/contexts/auth"
43
import { LayoutDashboard } from "lucide-react"
54
import { Button } from "./ui/button"
5+
import { useAuth } from "@aura-stack/react/hooks"
66

77
export const AuthClient = () => {
8-
const { session, isAuthenticated, isLoading, signIn, signOut } = useAuth()
8+
const { session, status, isPending, signIn, signOut } = useAuth()
9+
const isAuthenticated = status === "authenticated"
910

1011
return (
1112
<div className="w-full p-6 pr-3 bg-black md:py-10">
@@ -35,7 +36,7 @@ export const AuthClient = () => {
3536
<span className="text-white/60 truncate max-w-37.5">{session?.user?.sub}</span>
3637
</div>
3738
</div>
38-
<Button type="button" variant="outline" size="sm" disabled={isLoading} onClick={() => signOut()}>
39+
<Button type="button" variant="outline" size="sm" disabled={isPending} onClick={() => signOut()}>
3940
Sign Out
4041
</Button>
4142
</div>
@@ -55,7 +56,7 @@ export const AuthClient = () => {
5556
className="w-full rounded-none"
5657
variant="outline"
5758
size="sm"
58-
disabled={isLoading}
59+
disabled={isPending}
5960
onClick={() => signIn(provider.toLowerCase())}
6061
>
6162
Sign In with {provider}

apps/nextjs/app-router/src/components/header.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
import Link from "next/link"
44
import { useState } from "react"
55
import { Menu, X } from "lucide-react"
6-
import { useAuth } from "@/contexts/auth"
76
import { Button } from "@/components/ui/button"
7+
import { useAuth } from "@aura-stack/react"
88

99
export const Header = () => {
1010
const [mobileMenuOpen, setMobileMenuOpen] = useState(false)
11-
const { isAuthenticated, isLoading, signOut, signIn } = useAuth()
11+
const { status, isPending, signOut, signIn } = useAuth()
12+
const isAuthenticated = status === "authenticated"
1213

1314
const handleSignOut = async () => {
1415
await signOut()
@@ -102,7 +103,7 @@ export const Header = () => {
102103
Discord
103104
</a>
104105
<div className="flex flex-col gap-2 pt-4 border-t border-gray-800/50">
105-
{!isLoading && !isAuthenticated && (
106+
{!isPending && !isAuthenticated && (
106107
<Button type="button" onClick={handleSignIn}>
107108
Sign in with GitHub
108109
</Button>

0 commit comments

Comments
 (0)