create-better-t-stack 2.46.3-canary.f7f132c8 → 2.46.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/index.js +1 -1
  3. package/dist/{src-FqipJoqR.js → src-El86OdG5.js} +38 -142
  4. package/package.json +1 -1
  5. package/templates/auth/better-auth/web/react/next/src/components/theme-provider.tsx.hbs +11 -0
  6. package/templates/deploy/alchemy/alchemy.run.ts.hbs +14 -0
  7. package/templates/frontend/react/next/src/components/providers.tsx.hbs +0 -8
  8. package/templates/frontend/react/tanstack-router/src/main.tsx.hbs +1 -8
  9. package/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs +0 -47
  10. package/templates/frontend/react/tanstack-start/src/routes/index.tsx.hbs +2 -2
  11. package/templates/frontend/react/web-base/src/components/header.tsx.hbs +2 -2
  12. package/templates/auth/better-auth/convex/backend/convex/auth.config.ts.hbs +0 -8
  13. package/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs +0 -48
  14. package/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs +0 -7
  15. package/templates/auth/better-auth/convex/backend/convex/http.ts.hbs +0 -12
  16. package/templates/auth/better-auth/convex/backend/convex/privateData.ts.hbs +0 -16
  17. package/templates/auth/better-auth/convex/web/react/next/src/app/api/auth/[...all]/route.ts.hbs +0 -3
  18. package/templates/auth/better-auth/convex/web/react/next/src/app/dashboard/page.tsx.hbs +0 -40
  19. package/templates/auth/better-auth/convex/web/react/next/src/components/sign-in-form.tsx.hbs +0 -129
  20. package/templates/auth/better-auth/convex/web/react/next/src/components/sign-up-form.tsx.hbs +0 -154
  21. package/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbs +0 -48
  22. package/templates/auth/better-auth/convex/web/react/next/src/lib/auth-client.ts.hbs +0 -6
  23. package/templates/auth/better-auth/convex/web/react/next/src/lib/auth-server.ts.hbs +0 -6
  24. package/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-in-form.tsx.hbs +0 -133
  25. package/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/sign-up-form.tsx.hbs +0 -158
  26. package/templates/auth/better-auth/convex/web/react/tanstack-router/src/components/user-menu.tsx.hbs +0 -50
  27. package/templates/auth/better-auth/convex/web/react/tanstack-router/src/lib/auth-client.ts.hbs +0 -10
  28. package/templates/auth/better-auth/convex/web/react/tanstack-router/src/routes/dashboard.tsx.hbs +0 -43
  29. package/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbs +0 -133
  30. package/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs +0 -158
  31. package/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/user-menu.tsx.hbs +0 -50
  32. package/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-client.ts.hbs +0 -6
  33. package/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbs +0 -5
  34. package/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/api/auth/$.ts.hbs +0 -11
  35. package/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/dashboard.tsx.hbs +0 -43
  36. /package/templates/frontend/react/web-base/src/components/{loader.tsx.hbs → loader.tsx} +0 -0
@@ -1,40 +0,0 @@
1
- "use client"
2
-
3
- import SignInForm from "@/components/sign-in-form";
4
- import SignUpForm from "@/components/sign-up-form";
5
- import UserMenu from "@/components/user-menu";
6
- import { api } from "@{{projectName}}/backend/convex/_generated/api";
7
- import {
8
- Authenticated,
9
- AuthLoading,
10
- Unauthenticated,
11
- useQuery,
12
- } from "convex/react";
13
- import { useState } from "react";
14
-
15
- export default function DashboardPage() {
16
- const [showSignIn, setShowSignIn] = useState(false);
17
- const privateData = useQuery(api.privateData.get);
18
-
19
- return (
20
- <>
21
- <Authenticated>
22
- <div>
23
- <h1>Dashboard</h1>
24
- <p>privateData: {privateData?.message}</p>
25
- <UserMenu />
26
- </div>
27
- </Authenticated>
28
- <Unauthenticated>
29
- {showSignIn ? (
30
- <SignInForm onSwitchToSignUp={() => setShowSignIn(false)} />
31
- ) : (
32
- <SignUpForm onSwitchToSignIn={() => setShowSignIn(true)} />
33
- )}
34
- </Unauthenticated>
35
- <AuthLoading>
36
- <div>Loading...</div>
37
- </AuthLoading>
38
- </>
39
- );
40
- }
@@ -1,129 +0,0 @@
1
- import { authClient } from "@/lib/auth-client";
2
- import { useForm } from "@tanstack/react-form";
3
- import { toast } from "sonner";
4
- import z from "zod";
5
- import { Button } from "./ui/button";
6
- import { Input } from "./ui/input";
7
- import { Label } from "./ui/label";
8
- import { useRouter } from "next/navigation";
9
-
10
- export default function SignInForm({
11
- onSwitchToSignUp,
12
- }: {
13
- onSwitchToSignUp: () => void;
14
- }) {
15
- const router = useRouter();
16
-
17
- const form = useForm({
18
- defaultValues: {
19
- email: "",
20
- password: "",
21
- },
22
- onSubmit: async ({ value }) => {
23
- await authClient.signIn.email(
24
- {
25
- email: value.email,
26
- password: value.password,
27
- },
28
- {
29
- onSuccess: () => {
30
- router.push("/dashboard");
31
- toast.success("Sign in successful");
32
- },
33
- onError: (error) => {
34
- toast.error(error.error.message || error.error.statusText);
35
- },
36
- },
37
- );
38
- },
39
- validators: {
40
- onSubmit: z.object({
41
- email: z.email("Invalid email address"),
42
- password: z.string().min(8, "Password must be at least 8 characters"),
43
- }),
44
- },
45
- });
46
-
47
- return (
48
- <div className="mx-auto w-full mt-10 max-w-md p-6">
49
- <h1 className="mb-6 text-center text-3xl font-bold">Welcome Back</h1>
50
-
51
- <form
52
- onSubmit={(e) => {
53
- e.preventDefault();
54
- e.stopPropagation();
55
- form.handleSubmit();
56
- }}
57
- className="space-y-4"
58
- >
59
- <div>
60
- <form.Field name="email">
61
- {(field) => (
62
- <div className="space-y-2">
63
- <Label htmlFor={field.name}>Email</Label>
64
- <Input
65
- id={field.name}
66
- name={field.name}
67
- type="email"
68
- value={field.state.value}
69
- onBlur={field.handleBlur}
70
- onChange={(e) => field.handleChange(e.target.value)}
71
- />
72
- {field.state.meta.errors.map((error) => (
73
- <p key={error?.message} className="text-red-500">
74
- {error?.message}
75
- </p>
76
- ))}
77
- </div>
78
- )}
79
- </form.Field>
80
- </div>
81
-
82
- <div>
83
- <form.Field name="password">
84
- {(field) => (
85
- <div className="space-y-2">
86
- <Label htmlFor={field.name}>Password</Label>
87
- <Input
88
- id={field.name}
89
- name={field.name}
90
- type="password"
91
- value={field.state.value}
92
- onBlur={field.handleBlur}
93
- onChange={(e) => field.handleChange(e.target.value)}
94
- />
95
- {field.state.meta.errors.map((error) => (
96
- <p key={error?.message} className="text-red-500">
97
- {error?.message}
98
- </p>
99
- ))}
100
- </div>
101
- )}
102
- </form.Field>
103
- </div>
104
-
105
- <form.Subscribe>
106
- {(state) => (
107
- <Button
108
- type="submit"
109
- className="w-full"
110
- disabled={!state.canSubmit || state.isSubmitting}
111
- >
112
- {state.isSubmitting ? "Submitting..." : "Sign In"}
113
- </Button>
114
- )}
115
- </form.Subscribe>
116
- </form>
117
-
118
- <div className="mt-4 text-center">
119
- <Button
120
- variant="link"
121
- onClick={onSwitchToSignUp}
122
- className="text-indigo-600 hover:text-indigo-800"
123
- >
124
- Need an account? Sign Up
125
- </Button>
126
- </div>
127
- </div>
128
- );
129
- }
@@ -1,154 +0,0 @@
1
- import { authClient } from "@/lib/auth-client";
2
- import { useForm } from "@tanstack/react-form";
3
- import { toast } from "sonner";
4
- import z from "zod";
5
- import { Button } from "./ui/button";
6
- import { Input } from "./ui/input";
7
- import { Label } from "./ui/label";
8
- import { useRouter } from "next/navigation";
9
-
10
- export default function SignUpForm({
11
- onSwitchToSignIn,
12
- }: {
13
- onSwitchToSignIn: () => void;
14
- }) {
15
- const router = useRouter();
16
-
17
- const form = useForm({
18
- defaultValues: {
19
- email: "",
20
- password: "",
21
- name: "",
22
- },
23
- onSubmit: async ({ value }) => {
24
- await authClient.signUp.email(
25
- {
26
- email: value.email,
27
- password: value.password,
28
- name: value.name,
29
- },
30
- {
31
- onSuccess: () => {
32
- router.push("/dashboard");
33
- toast.success("Sign up successful");
34
- },
35
- onError: (error) => {
36
- toast.error(error.error.message || error.error.statusText);
37
- },
38
- },
39
- );
40
- },
41
- validators: {
42
- onSubmit: z.object({
43
- name: z.string().min(2, "Name must be at least 2 characters"),
44
- email: z.email("Invalid email address"),
45
- password: z.string().min(8, "Password must be at least 8 characters"),
46
- }),
47
- },
48
- });
49
-
50
- return (
51
- <div className="mx-auto w-full mt-10 max-w-md p-6">
52
- <h1 className="mb-6 text-center text-3xl font-bold">Create Account</h1>
53
-
54
- <form
55
- onSubmit={(e) => {
56
- e.preventDefault();
57
- e.stopPropagation();
58
- form.handleSubmit();
59
- }}
60
- className="space-y-4"
61
- >
62
- <div>
63
- <form.Field name="name">
64
- {(field) => (
65
- <div className="space-y-2">
66
- <Label htmlFor={field.name}>Name</Label>
67
- <Input
68
- id={field.name}
69
- name={field.name}
70
- value={field.state.value}
71
- onBlur={field.handleBlur}
72
- onChange={(e) => field.handleChange(e.target.value)}
73
- />
74
- {field.state.meta.errors.map((error) => (
75
- <p key={error?.message} className="text-red-500">
76
- {error?.message}
77
- </p>
78
- ))}
79
- </div>
80
- )}
81
- </form.Field>
82
- </div>
83
-
84
- <div>
85
- <form.Field name="email">
86
- {(field) => (
87
- <div className="space-y-2">
88
- <Label htmlFor={field.name}>Email</Label>
89
- <Input
90
- id={field.name}
91
- name={field.name}
92
- type="email"
93
- value={field.state.value}
94
- onBlur={field.handleBlur}
95
- onChange={(e) => field.handleChange(e.target.value)}
96
- />
97
- {field.state.meta.errors.map((error) => (
98
- <p key={error?.message} className="text-red-500">
99
- {error?.message}
100
- </p>
101
- ))}
102
- </div>
103
- )}
104
- </form.Field>
105
- </div>
106
-
107
- <div>
108
- <form.Field name="password">
109
- {(field) => (
110
- <div className="space-y-2">
111
- <Label htmlFor={field.name}>Password</Label>
112
- <Input
113
- id={field.name}
114
- name={field.name}
115
- type="password"
116
- value={field.state.value}
117
- onBlur={field.handleBlur}
118
- onChange={(e) => field.handleChange(e.target.value)}
119
- />
120
- {field.state.meta.errors.map((error) => (
121
- <p key={error?.message} className="text-red-500">
122
- {error?.message}
123
- </p>
124
- ))}
125
- </div>
126
- )}
127
- </form.Field>
128
- </div>
129
-
130
- <form.Subscribe>
131
- {(state) => (
132
- <Button
133
- type="submit"
134
- className="w-full"
135
- disabled={!state.canSubmit || state.isSubmitting}
136
- >
137
- {state.isSubmitting ? "Submitting..." : "Sign Up"}
138
- </Button>
139
- )}
140
- </form.Subscribe>
141
- </form>
142
-
143
- <div className="mt-4 text-center">
144
- <Button
145
- variant="link"
146
- onClick={onSwitchToSignIn}
147
- className="text-indigo-600 hover:text-indigo-800"
148
- >
149
- Already have an account? Sign In
150
- </Button>
151
- </div>
152
- </div>
153
- );
154
- }
@@ -1,48 +0,0 @@
1
- import {
2
- DropdownMenu,
3
- DropdownMenuContent,
4
- DropdownMenuItem,
5
- DropdownMenuLabel,
6
- DropdownMenuSeparator,
7
- DropdownMenuTrigger,
8
- } from "@/components/ui/dropdown-menu";
9
- import { authClient } from "@/lib/auth-client";
10
- import { Button } from "./ui/button";
11
- import { useRouter } from "next/navigation";
12
- import { useQuery } from "convex/react";
13
- import { api } from "@{{projectName}}/backend/convex/_generated/api";
14
-
15
- export default function UserMenu() {
16
- const router = useRouter();
17
- const user = useQuery(api.auth.getCurrentUser)
18
-
19
- return (
20
- <DropdownMenu>
21
- <DropdownMenuTrigger asChild>
22
- <Button variant="outline">{user?.name}</Button>
23
- </DropdownMenuTrigger>
24
- <DropdownMenuContent className="bg-card">
25
- <DropdownMenuLabel>My Account</DropdownMenuLabel>
26
- <DropdownMenuSeparator />
27
- <DropdownMenuItem>{user?.email}</DropdownMenuItem>
28
- <DropdownMenuItem asChild>
29
- <Button
30
- variant="destructive"
31
- className="w-full"
32
- onClick={() => {
33
- authClient.signOut({
34
- fetchOptions: {
35
- onSuccess: () => {
36
- router.push("/dashboard");
37
- },
38
- },
39
- });
40
- }}
41
- >
42
- Sign Out
43
- </Button>
44
- </DropdownMenuItem>
45
- </DropdownMenuContent>
46
- </DropdownMenu>
47
- );
48
- }
@@ -1,6 +0,0 @@
1
- import { createAuthClient } from "better-auth/react";
2
- import { convexClient } from "@convex-dev/better-auth/client/plugins";
3
-
4
- export const authClient = createAuthClient({
5
- plugins: [convexClient()],
6
- });
@@ -1,6 +0,0 @@
1
- import { createAuth } from "@{{projectName}}/backend/convex/auth";
2
- import { getToken as getTokenNextjs } from "@convex-dev/better-auth/nextjs";
3
-
4
- export const getToken = () => {
5
- return getTokenNextjs(createAuth);
6
- };
@@ -1,133 +0,0 @@
1
- import { authClient } from "@/lib/auth-client";
2
- import { useForm } from "@tanstack/react-form";
3
- import { useNavigate } from "@tanstack/react-router";
4
- import { toast } from "sonner";
5
- import z from "zod";
6
- import { Button } from "./ui/button";
7
- import { Input } from "./ui/input";
8
- import { Label } from "./ui/label";
9
-
10
- export default function SignInForm({
11
- onSwitchToSignUp,
12
- }: {
13
- onSwitchToSignUp: () => void;
14
- }) {
15
- const navigate = useNavigate({
16
- from: "/",
17
- });
18
-
19
- const form = useForm({
20
- defaultValues: {
21
- email: "",
22
- password: "",
23
- },
24
- onSubmit: async ({ value }) => {
25
- await authClient.signIn.email(
26
- {
27
- email: value.email,
28
- password: value.password,
29
- },
30
- {
31
- onSuccess: () => {
32
- navigate({
33
- to: "/dashboard",
34
- });
35
- toast.success("Sign in successful");
36
- },
37
- onError: (error) => {
38
- toast.error(error.error.message || error.error.statusText);
39
- },
40
- },
41
- );
42
- },
43
- validators: {
44
- onSubmit: z.object({
45
- email: z.email("Invalid email address"),
46
- password: z.string().min(8, "Password must be at least 8 characters"),
47
- }),
48
- },
49
- });
50
-
51
- return (
52
- <div className="mx-auto w-full mt-10 max-w-md p-6">
53
- <h1 className="mb-6 text-center text-3xl font-bold">Welcome Back</h1>
54
-
55
- <form
56
- onSubmit={(e) => {
57
- e.preventDefault();
58
- e.stopPropagation();
59
- form.handleSubmit();
60
- }}
61
- className="space-y-4"
62
- >
63
- <div>
64
- <form.Field name="email">
65
- {(field) => (
66
- <div className="space-y-2">
67
- <Label htmlFor={field.name}>Email</Label>
68
- <Input
69
- id={field.name}
70
- name={field.name}
71
- type="email"
72
- value={field.state.value}
73
- onBlur={field.handleBlur}
74
- onChange={(e) => field.handleChange(e.target.value)}
75
- />
76
- {field.state.meta.errors.map((error) => (
77
- <p key={error?.message} className="text-red-500">
78
- {error?.message}
79
- </p>
80
- ))}
81
- </div>
82
- )}
83
- </form.Field>
84
- </div>
85
-
86
- <div>
87
- <form.Field name="password">
88
- {(field) => (
89
- <div className="space-y-2">
90
- <Label htmlFor={field.name}>Password</Label>
91
- <Input
92
- id={field.name}
93
- name={field.name}
94
- type="password"
95
- value={field.state.value}
96
- onBlur={field.handleBlur}
97
- onChange={(e) => field.handleChange(e.target.value)}
98
- />
99
- {field.state.meta.errors.map((error) => (
100
- <p key={error?.message} className="text-red-500">
101
- {error?.message}
102
- </p>
103
- ))}
104
- </div>
105
- )}
106
- </form.Field>
107
- </div>
108
-
109
- <form.Subscribe>
110
- {(state) => (
111
- <Button
112
- type="submit"
113
- className="w-full"
114
- disabled={!state.canSubmit || state.isSubmitting}
115
- >
116
- {state.isSubmitting ? "Submitting..." : "Sign In"}
117
- </Button>
118
- )}
119
- </form.Subscribe>
120
- </form>
121
-
122
- <div className="mt-4 text-center">
123
- <Button
124
- variant="link"
125
- onClick={onSwitchToSignUp}
126
- className="text-indigo-600 hover:text-indigo-800"
127
- >
128
- Need an account? Sign Up
129
- </Button>
130
- </div>
131
- </div>
132
- );
133
- }
@@ -1,158 +0,0 @@
1
- import { authClient } from "@/lib/auth-client";
2
- import { useForm } from "@tanstack/react-form";
3
- import { useNavigate } from "@tanstack/react-router";
4
- import { toast } from "sonner";
5
- import z from "zod";
6
- import { Button } from "./ui/button";
7
- import { Input } from "./ui/input";
8
- import { Label } from "./ui/label";
9
-
10
- export default function SignUpForm({
11
- onSwitchToSignIn,
12
- }: {
13
- onSwitchToSignIn: () => void;
14
- }) {
15
- const navigate = useNavigate({
16
- from: "/",
17
- });
18
-
19
- const form = useForm({
20
- defaultValues: {
21
- email: "",
22
- password: "",
23
- name: "",
24
- },
25
- onSubmit: async ({ value }) => {
26
- await authClient.signUp.email(
27
- {
28
- email: value.email,
29
- password: value.password,
30
- name: value.name,
31
- },
32
- {
33
- onSuccess: () => {
34
- navigate({
35
- to: "/dashboard",
36
- });
37
- toast.success("Sign up successful");
38
- },
39
- onError: (error) => {
40
- toast.error(error.error.message || error.error.statusText);
41
- },
42
- },
43
- );
44
- },
45
- validators: {
46
- onSubmit: z.object({
47
- name: z.string().min(2, "Name must be at least 2 characters"),
48
- email: z.email("Invalid email address"),
49
- password: z.string().min(8, "Password must be at least 8 characters"),
50
- }),
51
- },
52
- });
53
-
54
- return (
55
- <div className="mx-auto w-full mt-10 max-w-md p-6">
56
- <h1 className="mb-6 text-center text-3xl font-bold">Create Account</h1>
57
-
58
- <form
59
- onSubmit={(e) => {
60
- e.preventDefault();
61
- e.stopPropagation();
62
- form.handleSubmit();
63
- }}
64
- className="space-y-4"
65
- >
66
- <div>
67
- <form.Field name="name">
68
- {(field) => (
69
- <div className="space-y-2">
70
- <Label htmlFor={field.name}>Name</Label>
71
- <Input
72
- id={field.name}
73
- name={field.name}
74
- value={field.state.value}
75
- onBlur={field.handleBlur}
76
- onChange={(e) => field.handleChange(e.target.value)}
77
- />
78
- {field.state.meta.errors.map((error) => (
79
- <p key={error?.message} className="text-red-500">
80
- {error?.message}
81
- </p>
82
- ))}
83
- </div>
84
- )}
85
- </form.Field>
86
- </div>
87
-
88
- <div>
89
- <form.Field name="email">
90
- {(field) => (
91
- <div className="space-y-2">
92
- <Label htmlFor={field.name}>Email</Label>
93
- <Input
94
- id={field.name}
95
- name={field.name}
96
- type="email"
97
- value={field.state.value}
98
- onBlur={field.handleBlur}
99
- onChange={(e) => field.handleChange(e.target.value)}
100
- />
101
- {field.state.meta.errors.map((error) => (
102
- <p key={error?.message} className="text-red-500">
103
- {error?.message}
104
- </p>
105
- ))}
106
- </div>
107
- )}
108
- </form.Field>
109
- </div>
110
-
111
- <div>
112
- <form.Field name="password">
113
- {(field) => (
114
- <div className="space-y-2">
115
- <Label htmlFor={field.name}>Password</Label>
116
- <Input
117
- id={field.name}
118
- name={field.name}
119
- type="password"
120
- value={field.state.value}
121
- onBlur={field.handleBlur}
122
- onChange={(e) => field.handleChange(e.target.value)}
123
- />
124
- {field.state.meta.errors.map((error) => (
125
- <p key={error?.message} className="text-red-500">
126
- {error?.message}
127
- </p>
128
- ))}
129
- </div>
130
- )}
131
- </form.Field>
132
- </div>
133
-
134
- <form.Subscribe>
135
- {(state) => (
136
- <Button
137
- type="submit"
138
- className="w-full"
139
- disabled={!state.canSubmit || state.isSubmitting}
140
- >
141
- {state.isSubmitting ? "Submitting..." : "Sign Up"}
142
- </Button>
143
- )}
144
- </form.Subscribe>
145
- </form>
146
-
147
- <div className="mt-4 text-center">
148
- <Button
149
- variant="link"
150
- onClick={onSwitchToSignIn}
151
- className="text-indigo-600 hover:text-indigo-800"
152
- >
153
- Already have an account? Sign In
154
- </Button>
155
- </div>
156
- </div>
157
- );
158
- }