Skip to content

Commit d36c1f5

Browse files
edgedb-auth-next15 (#10)
* edgedb-auth-next15 feat: next15 * fix: server actions must be async functions * fix: dynamic access * fix trpc
1 parent c40837e commit d36c1f5

File tree

36 files changed

+2480
-3012
lines changed

36 files changed

+2480
-3012
lines changed

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ import { Params } from "@/types";
6161
*/
6262
import { useTranslation } from "@/i18n";
6363

64-
export default async function Page({ params: { lng } }: Params) {
64+
export default async function Page({ params }: Params) {
65+
const { lng } = await params;
6566
// Specify the feature name as your namespace.
6667
// Use the "global" namespace for reusable components like Button.
6768
const { t } = await useTranslation("feature", lng);

package-lock.json

+2,265-2,833
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+29-25
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"scripts": {
1515
"postinstall": "npm run db:edgeql-js",
1616
"build": "next build",
17-
"dev": "next dev",
17+
"dev": "next dev --turbopack",
1818
"lint": "next lint",
1919
"start": "next start",
2020
"db:edgeql-js": "npx @edgedb/generate edgeql-js --out ./src/edgeql-js",
@@ -34,25 +34,25 @@
3434
"next:tel:dis": "next telemetry disable"
3535
},
3636
"dependencies": {
37-
"@edgedb/auth-nextjs": "0.3.2",
37+
"@edgedb/auth-nextjs": "^0.4.0-canary.20241202T173112",
3838
"@t3-oss/env-nextjs": "^0.9.2",
39-
"@tanstack/react-query": "^5.56.2",
40-
"@tanstack/react-query-devtools": "^5.24.0",
41-
"@trpc/client": "^11.0.0-rc.502",
42-
"@trpc/next": "^11.0.0-rc.502",
43-
"@trpc/react-query": "^11.0.0-rc.502",
44-
"@trpc/server": "^11.0.0-rc.502",
39+
"@tanstack/react-query": "^5.62.2",
40+
"@tanstack/react-query-devtools": "^5.62.2",
41+
"@trpc/client": "^11.0.0-rc.648",
42+
"@trpc/next": "^11.0.0-rc.648",
43+
"@trpc/react-query": "^11.0.0-rc.648",
44+
"@trpc/server": "^11.0.0-rc.648",
4545
"accept-language": "^3.0.20",
4646
"edgedb": "^1.5.12",
4747
"flowbite-react": "^0.10.1",
4848
"i18next": "^23.15.1",
4949
"i18next-browser-languagedetector": "^8.0.0",
5050
"i18next-resources-to-backend": "^1.2.1",
51-
"next": "^14.1.0",
52-
"react": "18.2.0",
51+
"next": "15.0.3",
52+
"react": "19.0.0-rc-66855b96-20241106",
5353
"react-cookie": "^7.2.0",
54-
"react-dom": "18.2.0",
55-
"react-form-action": "^0.4.2",
54+
"react-dom": "19.0.0-rc-66855b96-20241106",
55+
"react-form-action": "^1.1.1",
5656
"react-i18next": "^15.0.2",
5757
"superjson": "^2.2.1",
5858
"zod": "^3.23.8",
@@ -61,34 +61,38 @@
6161
},
6262
"devDependencies": {
6363
"@edgedb/generate": "^0.5.6",
64-
"@storybook/addon-essentials": "^8.3.0",
65-
"@storybook/addon-interactions": "^8.3.0",
66-
"@storybook/addon-links": "^8.3.0",
64+
"@storybook/addon-essentials": "^8.4.6",
65+
"@storybook/addon-interactions": "^8.4.6",
66+
"@storybook/addon-links": "^8.4.6",
6767
"@storybook/addon-styling": "^1.3.7",
68-
"@storybook/blocks": "^8.3.0",
69-
"@storybook/nextjs": "^8.3.0",
70-
"@storybook/react": "^8.3.0",
71-
"@storybook/test": "^8.3.0",
68+
"@storybook/blocks": "^8.4.6",
69+
"@storybook/nextjs": "^8.4.6",
70+
"@storybook/react": "^8.4.6",
71+
"@storybook/test": "^8.4.6",
7272
"@types/eslint": "^8.56.2",
7373
"@types/node": "^20.11.19",
74-
"@types/react": "^18.2.57",
75-
"@types/react-dom": "^18.2.19",
74+
"@types/react": "npm:[email protected]",
75+
"@types/react-dom": "npm:[email protected]",
7676
"@typescript-eslint/eslint-plugin": "^7.0.2",
7777
"@typescript-eslint/parser": "^7.0.2",
7878
"autoprefixer": "^10.4.20",
7979
"eslint": "^8.56.0",
80-
"eslint-config-next": "^14.1.0",
81-
"eslint-plugin-storybook": "^0.8.0",
80+
"eslint-config-next": "15.0.3",
81+
"eslint-plugin-storybook": "^0.11.1",
8282
"i18next-parser": "^9.0.2",
8383
"jwt-decode": "^4.0.0",
8484
"npm-check-updates": "^17.1.1",
8585
"postcss": "^8.4.47",
8686
"prettier": "^3.3.3",
8787
"prettier-plugin-tailwindcss": "^0.6.6",
8888
"react-render-prop-type": "^0.1.0",
89-
"storybook": "^8.3.0",
89+
"storybook": "^8.4.6",
9090
"tailwindcss": "^3.4.11",
9191
"typescript": "^5.3.3"
9292
},
93-
"packageManager": "[email protected]"
93+
"packageManager": "[email protected]",
94+
"overrides": {
95+
"@types/react": "npm:[email protected]",
96+
"@types/react-dom": "npm:[email protected]"
97+
}
9498
}

src/app/[lng]/(auth-ui)/layout.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { auth } from "@/edgedb";
33
import { redirect } from "next/navigation";
44

55
export default async function AuthLayout({ children }: PropsWithChildren) {
6-
const session = auth.getSession();
6+
const session = await auth.getSession();
77
const isSignedIn = await session.isSignedIn();
88

99
if (isSignedIn) redirect("/dashboard");

src/app/[lng]/(auth-ui)/reset-password-email/_components/form.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export function ResetPasswordEmailForm() {
3939
<Label
4040
htmlFor="email"
4141
color={
42-
isInvalid && validationError.fieldErrors.email
42+
isInvalid && validationError.email
4343
? "failure"
4444
: isSuccess
4545
? "success"
@@ -54,15 +54,15 @@ export function ResetPasswordEmailForm() {
5454
name="email"
5555
disabled={isPending}
5656
color={
57-
isInvalid && validationError.fieldErrors.email
57+
isInvalid && validationError.email
5858
? "failure"
5959
: isSuccess
6060
? "success"
6161
: undefined
6262
}
6363
type="text"
6464
placeholder="[email protected]"
65-
helperText={validationError?.fieldErrors.email?.[0]}
65+
helperText={validationError?.email?._errors[0]}
6666
/>
6767
</FormItem>
6868
<SubmitButton />

src/app/[lng]/(auth-ui)/reset-password-email/page.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22

33
import { PageHeader } from "@/app/_components/page-header";
44
import { ResetPasswordEmailForm } from "./_components/form";
5-
import { useTranslation } from "@/i18n";
5+
import { translate } from "@/i18n";
66
import { type Params } from "@/types";
77

8-
export default async function ResetPasswordEmail({ params: { lng } }: Params) {
9-
const { t } = await useTranslation("auth", lng);
8+
export default async function ResetPasswordEmail({ params }: Params) {
9+
const { lng } = await params;
10+
const { t } = await translate("auth", lng);
1011

1112
return (
1213
<>

src/app/[lng]/(auth-ui)/reset-password/_components/form.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export function ResetPasswordForm({ reset_token }: ResetTokenParam) {
4040
<Label
4141
htmlFor="password"
4242
color={
43-
isInvalid && validationError.fieldErrors.password
43+
isInvalid && validationError.password
4444
? "failure"
4545
: isSuccess
4646
? "success"
@@ -56,13 +56,13 @@ export function ResetPasswordForm({ reset_token }: ResetTokenParam) {
5656
type="password"
5757
disabled={isPending}
5858
color={
59-
isInvalid && validationError.fieldErrors.password
59+
isInvalid && validationError.password
6060
? "failure"
6161
: isSuccess
6262
? "success"
6363
: undefined
6464
}
65-
helperText={validationError?.fieldErrors.password?.[0]}
65+
helperText={validationError?.password?._errors[0]}
6666
/>
6767
</FormItem>
6868
<input name={resetTokenFieldName} defaultValue={reset_token} hidden />

src/app/[lng]/(auth-ui)/reset-password/page.tsx

+7-5
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@
22
import { PageHeader } from "@/app/_components/page-header";
33
import { ResetPasswordForm } from "./_components/form";
44
import { type Params } from "@/types";
5-
import { useTranslation } from "@/i18n";
5+
import { translate } from "@/i18n";
66
import { type ResetTokenParam } from "@/edgedb/shared";
77

88
export default async function ResetPassword({
9-
params: { lng },
10-
searchParams: { reset_token },
11-
}: Params & { searchParams: ResetTokenParam }) {
12-
const { t } = await useTranslation("auth", lng);
9+
params,
10+
searchParams,
11+
}: Params & { searchParams: Promise<ResetTokenParam> }) {
12+
const { lng } = await params;
13+
const { reset_token } = await searchParams;
14+
const { t } = await translate("auth", lng);
1315

1416
return (
1517
<>

src/app/[lng]/(auth-ui)/signin/_components/form.tsx

+68-66
Original file line numberDiff line numberDiff line change
@@ -22,76 +22,78 @@ export function SignInForm() {
2222
isFailure,
2323
isSuccess,
2424
isPending,
25-
}) => (
26-
<Stack>
27-
{isFailure && (
28-
<div>
29-
<Alert color="failure">{error.message}</Alert>
30-
</div>
31-
)}
32-
<FormItem>
33-
<FormLabel>
34-
<Label htmlFor="email">{t("signIn.email")}</Label>
35-
</FormLabel>
36-
<TextInput
37-
id="email"
38-
name="email"
39-
disabled={isPending}
40-
color={
41-
isInvalid && validationError.fieldErrors.email
42-
? "failure"
43-
: isSuccess
44-
? "success"
45-
: undefined
46-
}
47-
type="text"
48-
placeholder="[email protected]"
49-
helperText={validationError?.fieldErrors.email?.[0]}
50-
/>
51-
</FormItem>
52-
<FormItem>
53-
<FormLabel>
54-
<Label htmlFor="password" className="flex justify-between">
55-
<span>{t("signIn.password")}</span>
25+
}) => {
26+
return (
27+
<Stack>
28+
{isFailure && (
29+
<div>
30+
<Alert color="failure">{error.message}</Alert>
31+
</div>
32+
)}
33+
<FormItem>
34+
<FormLabel>
35+
<Label htmlFor="email">{t("signIn.email")}</Label>
36+
</FormLabel>
37+
<TextInput
38+
id="email"
39+
name="email"
40+
disabled={isPending}
41+
color={
42+
isInvalid && validationError.email
43+
? "failure"
44+
: isSuccess
45+
? "success"
46+
: undefined
47+
}
48+
type="text"
49+
placeholder="[email protected]"
50+
helperText={validationError?.email?._errors[0]}
51+
/>
52+
</FormItem>
53+
<FormItem>
54+
<FormLabel>
55+
<Label htmlFor="password" className="flex justify-between">
56+
<span>{t("signIn.password")}</span>
57+
<Link
58+
tabIndex={-1}
59+
href="/reset-password-email"
60+
className="text-cyan-600 hover:underline dark:text-cyan-500"
61+
>
62+
{t("signIn.forgotPassword")}
63+
</Link>
64+
</Label>
65+
</FormLabel>
66+
<TextInput
67+
id="password"
68+
name="password"
69+
disabled={isPending}
70+
color={
71+
isInvalid && validationError.password
72+
? "failure"
73+
: isSuccess
74+
? "success"
75+
: undefined
76+
}
77+
type="password"
78+
placeholder="Your password"
79+
helperText={validationError?.password?._errors?.[0]}
80+
/>
81+
</FormItem>
82+
<SubmitButton />
83+
<Label>
84+
<Trans i18nKey="signIn.linkToSignUp" t={t}>
85+
Don&apos;t have an account?&nbsp;
5686
<Link
57-
tabIndex={-1}
58-
href="/reset-password-email"
87+
href="/signup"
5988
className="text-cyan-600 hover:underline dark:text-cyan-500"
6089
>
61-
{t("signIn.forgotPassword")}
90+
Sign up
6291
</Link>
63-
</Label>
64-
</FormLabel>
65-
<TextInput
66-
id="password"
67-
name="password"
68-
disabled={isPending}
69-
color={
70-
isInvalid && validationError.fieldErrors.password
71-
? "failure"
72-
: isSuccess
73-
? "success"
74-
: undefined
75-
}
76-
type="password"
77-
placeholder="Your password"
78-
helperText={validationError?.fieldErrors.password?.[0]}
79-
/>
80-
</FormItem>
81-
<SubmitButton />
82-
<Label>
83-
<Trans i18nKey="signIn.linkToSignUp" t={t}>
84-
Don&apos;t have an account?&nbsp;
85-
<Link
86-
href="/signup"
87-
className="text-cyan-600 hover:underline dark:text-cyan-500"
88-
>
89-
Sign up
90-
</Link>
91-
</Trans>
92-
</Label>
93-
</Stack>
94-
)}
92+
</Trans>
93+
</Label>
94+
</Stack>
95+
);
96+
}}
9597
</Form>
9698
);
9799
}

src/app/[lng]/(auth-ui)/signin/page.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
"use server";
22
import { PageHeader } from "@/app/_components/page-header";
33
import { SignInForm } from "./_components/form";
4-
import { useTranslation } from "@/i18n";
4+
import { translate } from "@/i18n";
55
import { type Params } from "@/types";
66

7-
export default async function SignIn({ params: { lng } }: Params) {
8-
const { t } = await useTranslation("auth", lng);
7+
export default async function SignIn({ params }: Params) {
8+
const { lng } = await params;
9+
const { t } = await translate("auth", lng);
910

1011
return (
1112
<>

0 commit comments

Comments
 (0)