authverse 1.0.7-canary.1 → 1.0.7

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.
@@ -0,0 +1,189 @@
1
+ import { useForm } from "@tanstack/react-form";
2
+ import { toast } from "sonner";
3
+ import * as z from "zod";
4
+ import { Button } from "@/components/ui/button";
5
+ import {
6
+ Card,
7
+ CardContent,
8
+ CardDescription,
9
+ CardFooter,
10
+ CardHeader,
11
+ CardTitle,
12
+ } from "@/components/ui/card";
13
+ import {
14
+ Field,
15
+ FieldError,
16
+ FieldGroup,
17
+ FieldLabel,
18
+ } from "@/components/ui/field";
19
+ import { Input } from "@/components/ui/input";
20
+ import { useState } from "react";
21
+ import { Link } from "@tanstack/react-router";
22
+ import { authClient } from "@/lib/auth-client";
23
+
24
+ const formSchema = z.object({
25
+ name: z.string().min(3, {
26
+ message: "Name must be at least 3 characters",
27
+ }),
28
+ email: z.string().email(),
29
+ password: z.string().min(8, {
30
+ message: "Password must be at least 8 characters",
31
+ }),
32
+ });
33
+
34
+ const SingUpComponent = () => {
35
+ const [isLoading, setIsLoading] = useState(false);
36
+
37
+ const form = useForm({
38
+ defaultValues: {
39
+ name: "",
40
+ email: "",
41
+ password: "",
42
+ },
43
+ validators: {
44
+ onSubmit: formSchema,
45
+ },
46
+ onSubmit: async ({ value }) => {
47
+ setIsLoading(true);
48
+ await authClient.signUp.email(
49
+ {
50
+ name: value.name,
51
+ email: value.email,
52
+ password: value.password,
53
+ callbackURL: "/",
54
+ },
55
+ {
56
+ onSuccess: () => {
57
+ toast.success("Sign up successful!");
58
+ },
59
+ onError: (error: any) => {
60
+ setIsLoading(false);
61
+ toast.error(error.error.message);
62
+ },
63
+ }
64
+ );
65
+ },
66
+ });
67
+
68
+ return (
69
+ <Card className="w-full sm:max-w-md shadow-md">
70
+ <CardHeader>
71
+ <CardTitle className="text-2xl leading-4">Sign Up</CardTitle>
72
+ <CardDescription>Create an account</CardDescription>
73
+ </CardHeader>
74
+ <CardContent>
75
+ <form
76
+ id="form-login"
77
+ onSubmit={(e) => {
78
+ e.preventDefault();
79
+ form.handleSubmit();
80
+ }}
81
+ >
82
+ <FieldGroup>
83
+ <form.Field
84
+ name="name"
85
+ children={(field) => {
86
+ const isInvalid =
87
+ field.state.meta.isTouched && !field.state.meta.isValid;
88
+ return (
89
+ <Field data-invalid={isInvalid}>
90
+ <FieldLabel htmlFor={field.name}>Name</FieldLabel>
91
+ <Input
92
+ id={field.name}
93
+ name={field.name}
94
+ value={field.state.value}
95
+ onBlur={field.handleBlur}
96
+ onChange={(e) => field.handleChange(e.target.value)}
97
+ aria-invalid={isInvalid}
98
+ placeholder="John Doe"
99
+ autoComplete="off"
100
+ disabled={isLoading}
101
+ />
102
+ {isInvalid && (
103
+ <FieldError errors={field.state.meta.errors} />
104
+ )}
105
+ </Field>
106
+ );
107
+ }}
108
+ />
109
+ <form.Field
110
+ name="email"
111
+ children={(field) => {
112
+ const isInvalid =
113
+ field.state.meta.isTouched && !field.state.meta.isValid;
114
+ return (
115
+ <Field data-invalid={isInvalid}>
116
+ <FieldLabel htmlFor={field.name}>Email</FieldLabel>
117
+ <Input
118
+ id={field.name}
119
+ name={field.name}
120
+ value={field.state.value}
121
+ onBlur={field.handleBlur}
122
+ onChange={(e) => field.handleChange(e.target.value)}
123
+ aria-invalid={isInvalid}
124
+ placeholder="example@example.com"
125
+ autoComplete="off"
126
+ disabled={isLoading}
127
+ />
128
+ {isInvalid && (
129
+ <FieldError errors={field.state.meta.errors} />
130
+ )}
131
+ </Field>
132
+ );
133
+ }}
134
+ />
135
+ <form.Field
136
+ name="password"
137
+ children={(field) => {
138
+ const isInvalid =
139
+ field.state.meta.isTouched && !field.state.meta.isValid;
140
+ return (
141
+ <Field data-invalid={isInvalid}>
142
+ <FieldLabel htmlFor={field.name}>Password</FieldLabel>
143
+ <Input
144
+ id={field.name}
145
+ name={field.name}
146
+ value={field.state.value}
147
+ onBlur={field.handleBlur}
148
+ onChange={(e) => field.handleChange(e.target.value)}
149
+ aria-invalid={isInvalid}
150
+ placeholder="********"
151
+ type="password"
152
+ autoComplete="off"
153
+ disabled={isLoading}
154
+ />
155
+ {isInvalid && (
156
+ <FieldError errors={field.state.meta.errors} />
157
+ )}
158
+ </Field>
159
+ );
160
+ }}
161
+ />
162
+ </FieldGroup>
163
+ </form>
164
+ </CardContent>
165
+ <CardFooter>
166
+ <div className="w-full">
167
+ <Field orientation="horizontal">
168
+ <Button
169
+ type="submit"
170
+ form="form-login"
171
+ className="w-full"
172
+ disabled={isLoading}
173
+ >
174
+ {isLoading ? "Signing up..." : "Sign up"}
175
+ </Button>
176
+ </Field>
177
+ <div className="w-full text-center pt-4 space-x-2">
178
+ <span>Already have an account?</span>
179
+ <Link to="/auth/login" className="underline">
180
+ Login
181
+ </Link>
182
+ </div>
183
+ </div>
184
+ </CardFooter>
185
+ </Card>
186
+ );
187
+ };
188
+
189
+ export default SingUpComponent;
@@ -0,0 +1,25 @@
1
+ import { betterAuth } from "better-auth";
2
+ import { prismaAdapter } from "better-auth/adapters/prisma";
3
+ import { PrismaClient } from "../../generated/prisma/client";
4
+ import { tanstackStartCookies } from "better-auth/tanstack-start";
5
+
6
+ declare global {
7
+ var __prisma: PrismaClient | undefined;
8
+ }
9
+
10
+ const prisma = globalThis.__prisma || new PrismaClient();
11
+
12
+ export const auth = betterAuth({
13
+ database: prismaAdapter(prisma, {
14
+ provider: "mongodb",
15
+ }),
16
+ advanced: {
17
+ database: {
18
+ generateId: false,
19
+ },
20
+ },
21
+ emailAndPassword: {
22
+ enabled: true,
23
+ },
24
+ plugins: [tanstackStartCookies()],
25
+ });
@@ -0,0 +1,30 @@
1
+ import { betterAuth } from "better-auth";
2
+ import { prismaAdapter } from "better-auth/adapters/prisma";
3
+ import { PrismaMariaDb } from "@prisma/adapter-mariadb";
4
+ import { PrismaClient } from "../../generated/prisma/client";
5
+ import { tanstackStartCookies } from "better-auth/tanstack-start";
6
+
7
+ const url = new URL(process.env.DATABASE_URL!);
8
+
9
+ const adapter = new PrismaMariaDb({
10
+ host: url.hostname,
11
+ user: url.username,
12
+ password: url.password,
13
+ database: url.pathname.replace("/", ""),
14
+ port: Number(url.port),
15
+ });
16
+
17
+ declare global {
18
+ var __prisma: PrismaClient | undefined;
19
+ }
20
+
21
+ const prisma = globalThis.__prisma || new PrismaClient({ adapter });
22
+ export const auth = betterAuth({
23
+ database: prismaAdapter(prisma, {
24
+ provider: "sqlite",
25
+ }),
26
+ emailAndPassword: {
27
+ enabled: true,
28
+ },
29
+ plugins: [tanstackStartCookies()],
30
+ });
@@ -0,0 +1,23 @@
1
+ import { betterAuth } from "better-auth";
2
+ import { prismaAdapter } from "better-auth/adapters/prisma";
3
+ import { PrismaPg } from "@prisma/adapter-pg";
4
+ import { PrismaClient } from "../../generated/prisma/client";
5
+ import { tanstackStartCookies } from "better-auth/tanstack-start";
6
+
7
+ const connectionString = `${process.env.DATABASE_URL}`;
8
+ const adapter = new PrismaPg({ connectionString });
9
+
10
+ declare global {
11
+ var __prisma: PrismaClient | undefined;
12
+ }
13
+
14
+ const prisma = globalThis.__prisma || new PrismaClient({ adapter });
15
+ export const auth = betterAuth({
16
+ database: prismaAdapter(prisma, {
17
+ provider: "sqlite",
18
+ }),
19
+ emailAndPassword: {
20
+ enabled: true,
21
+ },
22
+ plugins: [tanstackStartCookies()],
23
+ });
@@ -0,0 +1,16 @@
1
+ import { betterAuth } from "better-auth";
2
+ import { drizzleAdapter } from "better-auth/adapters/drizzle";
3
+ import { db } from "../../db/drizzle";
4
+ import { schema } from "../../db/schema";
5
+ import { tanstackStartCookies } from "better-auth/tanstack-start";
6
+
7
+ export const auth = betterAuth({
8
+ database: drizzleAdapter(db, {
9
+ provider: "pg",
10
+ schema,
11
+ }),
12
+ emailAndPassword: {
13
+ enabled: true,
14
+ },
15
+ plugins: [tanstackStartCookies()],
16
+ });
@@ -0,0 +1,15 @@
1
+ import { redirect } from "@tanstack/react-router";
2
+ import { createMiddleware } from "@tanstack/react-start";
3
+ import { getRequestHeaders } from "@tanstack/react-start/server";
4
+ import { auth } from "@/lib/auth";
5
+
6
+ export const authMiddleware = createMiddleware().server(async ({ next }) => {
7
+ const headers = getRequestHeaders();
8
+ const session = await auth.api.getSession({ headers });
9
+
10
+ if (!session) {
11
+ throw redirect({ to: "/auth/login" });
12
+ }
13
+
14
+ return await next();
15
+ });
@@ -0,0 +1,15 @@
1
+ import { createFileRoute } from "@tanstack/react-router";
2
+ import { auth } from "@/lib/auth";
3
+
4
+ export const Route = createFileRoute("/api/auth/$")({
5
+ server: {
6
+ handlers: {
7
+ GET: async ({ request }: { request: Request }) => {
8
+ return await auth.handler(request);
9
+ },
10
+ POST: async ({ request }: { request: Request }) => {
11
+ return await auth.handler(request);
12
+ },
13
+ },
14
+ },
15
+ });
@@ -0,0 +1,14 @@
1
+ import ForgetComponent from "@/components/authverse/ForgetComponent";
2
+ import { createFileRoute } from "@tanstack/react-router";
3
+
4
+ export const Route = createFileRoute("/auth/forget")({
5
+ component: RouteComponent,
6
+ });
7
+
8
+ function RouteComponent() {
9
+ return (
10
+ <div className="flex items-center justify-center min-h-screen bg-slate-100 dark:bg-slate-800">
11
+ <ForgetComponent />
12
+ </div>
13
+ );
14
+ }
@@ -0,0 +1,14 @@
1
+ import LoginComponent from "@/components/authverse/LoginComponent";
2
+ import { createFileRoute } from "@tanstack/react-router";
3
+
4
+ export const Route = createFileRoute("/auth/login")({
5
+ component: RouteComponent,
6
+ });
7
+
8
+ function RouteComponent() {
9
+ return (
10
+ <div className="w-full h-screen flex items-center justify-center bg-slate-100 dark:bg-slate-800">
11
+ <LoginComponent />
12
+ </div>
13
+ );
14
+ }
@@ -0,0 +1,18 @@
1
+ import ResetComponent from "@/components/authverse/ResetComponent";
2
+ import { createFileRoute } from "@tanstack/react-router";
3
+ import { z } from "zod";
4
+
5
+ export const Route = createFileRoute("/auth/reset-password")({
6
+ validateSearch: z.object({
7
+ token: z.string(),
8
+ }),
9
+ component: RouteComponent,
10
+ });
11
+
12
+ function RouteComponent() {
13
+ return (
14
+ <div className="flex items-center justify-center min-h-screen bg-slate-100 dark:bg-slate-800">
15
+ <ResetComponent />
16
+ </div>
17
+ );
18
+ }
@@ -0,0 +1,14 @@
1
+ import SingUpComponent from "@/components/authverse/SingUpComponent";
2
+ import { createFileRoute } from "@tanstack/react-router";
3
+
4
+ export const Route = createFileRoute("/auth/signup")({
5
+ component: RouteComponent,
6
+ });
7
+
8
+ function RouteComponent() {
9
+ return (
10
+ <div className="w-full h-screen flex items-center justify-center bg-slate-100 dark:bg-slate-800">
11
+ <SingUpComponent />
12
+ </div>
13
+ );
14
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "authverse",
3
- "version": "1.0.7-canary.1",
3
+ "version": "1.0.7",
4
4
  "description": "Authverse Fast modern CLI to generate full auth systems with OAuth Prisma Drizzle better auth and ready-to-use ShadCN UI screens",
5
5
  "repository": {
6
6
  "url": "git+https://github.com/abdirahmanmahamoud/authverse.git"
@@ -39,6 +39,7 @@
39
39
  "auth-ui-templates",
40
40
  "better-auth",
41
41
  "nextjs",
42
+ "tanstack state",
42
43
  "shadcn"
43
44
  ],
44
45
  "dependencies": {