create-better-t-stack 2.45.4 → 2.46.0-canary.85c43fef
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.
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.js +1 -1
- package/dist/{src-Cun9EO6e.js → src-lN80CwOs.js} +396 -162
- package/package.json +1 -1
- package/templates/auth/better-auth/convex/backend/convex/auth.config.ts.hbs +8 -0
- package/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs +48 -0
- package/templates/auth/better-auth/convex/backend/convex/convex.config.ts.hbs +7 -0
- package/templates/auth/better-auth/convex/backend/convex/http.ts.hbs +12 -0
- package/templates/auth/better-auth/convex/backend/convex/privateData.ts.hbs +16 -0
- package/templates/auth/better-auth/convex/web/react/next/src/app/api/auth/[...all]/route.ts.hbs +3 -0
- package/templates/auth/better-auth/convex/web/react/next/src/app/dashboard/page.tsx.hbs +40 -0
- package/templates/auth/better-auth/convex/web/react/next/src/components/sign-in-form.tsx.hbs +129 -0
- package/templates/auth/better-auth/convex/web/react/next/src/components/sign-up-form.tsx.hbs +154 -0
- package/templates/auth/better-auth/convex/web/react/next/src/components/user-menu.tsx.hbs +48 -0
- package/templates/auth/better-auth/convex/web/react/next/src/lib/auth-client.ts.hbs +6 -0
- package/templates/auth/better-auth/convex/web/react/next/src/lib/auth-server.ts.hbs +6 -0
- package/templates/auth/better-auth/convex/web/react/tanstack-router/src/lib/auth-client.ts.hbs +10 -0
- package/templates/auth/better-auth/convex/web/react/tanstack-router/src/routes/dashboard.tsx.hbs +43 -0
- package/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-in-form.tsx.hbs +133 -0
- package/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/sign-up-form.tsx.hbs +158 -0
- package/templates/auth/better-auth/convex/web/react/tanstack-start/src/components/user-menu.tsx.hbs +50 -0
- package/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-client.ts.hbs +6 -0
- package/templates/auth/better-auth/convex/web/react/tanstack-start/src/lib/auth-server.ts.hbs +5 -0
- package/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/api/auth/$.ts.hbs +11 -0
- package/templates/auth/better-auth/convex/web/react/tanstack-start/src/routes/dashboard.tsx.hbs +43 -0
- package/templates/auth/better-auth/server/base/src/lib/auth.ts.hbs +163 -16
- package/templates/auth/better-auth/web/nuxt/app/pages/dashboard.vue.hbs +36 -2
- package/templates/auth/better-auth/web/nuxt/app/plugins/auth-client.ts.hbs +22 -0
- package/templates/auth/better-auth/web/react/base/src/lib/auth-client.ts.hbs +6 -0
- package/templates/auth/better-auth/web/react/next/src/app/dashboard/dashboard.tsx.hbs +58 -0
- package/templates/auth/better-auth/web/react/next/src/app/dashboard/page.tsx.hbs +31 -41
- package/templates/auth/better-auth/web/react/react-router/src/routes/dashboard.tsx.hbs +37 -3
- package/templates/auth/better-auth/web/react/tanstack-router/src/routes/dashboard.tsx.hbs +50 -32
- package/templates/auth/better-auth/web/react/tanstack-start/src/routes/dashboard.tsx.hbs +51 -36
- package/templates/auth/better-auth/web/solid/src/lib/auth-client.ts.hbs +11 -0
- package/templates/auth/better-auth/web/solid/src/routes/dashboard.tsx.hbs +52 -29
- package/templates/auth/better-auth/web/svelte/src/lib/{auth-client.ts → auth-client.ts.hbs} +6 -0
- package/templates/auth/better-auth/web/svelte/src/routes/dashboard/+page.svelte.hbs +24 -3
- package/templates/backend/server/server-base/package.json.hbs +1 -1
- package/templates/extras/bunfig.toml.hbs +4 -0
- package/templates/frontend/react/next/src/components/providers.tsx.hbs +8 -0
- package/templates/frontend/react/tanstack-router/src/main.tsx.hbs +8 -1
- package/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs +51 -0
- package/templates/frontend/react/tanstack-start/src/routes/index.tsx.hbs +2 -2
- package/templates/frontend/react/web-base/src/components/header.tsx.hbs +2 -2
- package/templates/frontend/solid/package.json.hbs +10 -10
- package/templates/payments/polar/server/base/src/lib/payments.ts.hbs +6 -0
- package/templates/payments/polar/web/nuxt/app/pages/success.vue.hbs +11 -0
- package/templates/payments/polar/web/react/next/src/app/success/page.tsx.hbs +15 -0
- package/templates/payments/polar/web/react/react-router/src/routes/success.tsx.hbs +13 -0
- package/templates/payments/polar/web/react/tanstack-router/src/routes/success.tsx.hbs +19 -0
- package/templates/payments/polar/web/react/tanstack-start/src/routes/success.tsx.hbs +19 -0
- package/templates/payments/polar/web/solid/src/routes/success.tsx.hbs +23 -0
- package/templates/payments/polar/web/svelte/src/routes/success/+page.svelte.hbs +12 -0
- package/templates/auth/better-auth/web/nuxt/app/plugins/auth-client.ts +0 -16
- package/templates/auth/better-auth/web/react/next/src/components/theme-provider.tsx +0 -11
- package/templates/auth/better-auth/web/solid/src/lib/auth-client.ts +0 -5
- /package/templates/auth/better-auth/web/nuxt/app/components/{SignInForm.vue → SignInForm.vue.hbs} +0 -0
- /package/templates/auth/better-auth/web/nuxt/app/components/{SignUpForm.vue → SignUpForm.vue.hbs} +0 -0
- /package/templates/auth/better-auth/web/nuxt/app/components/{UserMenu.vue → UserMenu.vue.hbs} +0 -0
- /package/templates/auth/better-auth/web/nuxt/app/pages/{login.vue → login.vue.hbs} +0 -0
- /package/templates/auth/better-auth/web/react/next/src/app/login/{page.tsx → page.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/react/next/src/components/{sign-in-form.tsx → sign-in-form.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/react/next/src/components/{sign-up-form.tsx → sign-up-form.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/react/next/src/components/{user-menu.tsx → user-menu.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/react/react-router/src/components/{sign-in-form.tsx → sign-in-form.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/react/react-router/src/components/{sign-up-form.tsx → sign-up-form.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/react/react-router/src/components/{user-menu.tsx → user-menu.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/react/react-router/src/routes/{login.tsx → login.tsx.hbs} +0 -0
- /package/templates/auth/better-auth/web/svelte/src/components/{SignInForm.svelte → SignInForm.svelte.hbs} +0 -0
- /package/templates/auth/better-auth/web/svelte/src/components/{SignUpForm.svelte → SignUpForm.svelte.hbs} +0 -0
- /package/templates/auth/better-auth/web/svelte/src/components/{UserMenu.svelte → UserMenu.svelte.hbs} +0 -0
- /package/templates/auth/better-auth/web/svelte/src/routes/login/{+page.svelte → +page.svelte.hbs} +0 -0
- /package/templates/frontend/react/web-base/src/components/{loader.tsx → loader.tsx.hbs} +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Button } from "@/components/ui/button";
|
|
3
|
+
import { authClient } from "@/lib/auth-client";
|
|
4
|
+
{{#if (eq api "orpc")}}
|
|
5
|
+
import { useQuery } from "@tanstack/react-query";
|
|
6
|
+
import { orpc } from "@/utils/orpc";
|
|
7
|
+
{{/if}}
|
|
8
|
+
{{#if (eq api "trpc")}}
|
|
9
|
+
import { useQuery } from "@tanstack/react-query";
|
|
10
|
+
import { trpc } from "@/utils/trpc";
|
|
11
|
+
{{/if}}
|
|
12
|
+
|
|
13
|
+
export default function Dashboard({
|
|
14
|
+
{{#if (eq payments "polar")}}
|
|
15
|
+
customerState,
|
|
16
|
+
{{/if}}
|
|
17
|
+
session
|
|
18
|
+
}: {
|
|
19
|
+
{{#if (eq payments "polar")}}
|
|
20
|
+
customerState: ReturnType<typeof authClient.customer.state>;
|
|
21
|
+
{{/if}}
|
|
22
|
+
session: typeof authClient.$Infer.Session;
|
|
23
|
+
}) {
|
|
24
|
+
{{#if (eq api "orpc")}}
|
|
25
|
+
const privateData = useQuery(orpc.privateData.queryOptions());
|
|
26
|
+
{{/if}}
|
|
27
|
+
{{#if (eq api "trpc")}}
|
|
28
|
+
const privateData = useQuery(trpc.privateData.queryOptions());
|
|
29
|
+
{{/if}}
|
|
30
|
+
|
|
31
|
+
{{#if (eq payments "polar")}}
|
|
32
|
+
const hasProSubscription = customerState?.activeSubscriptions?.length! > 0;
|
|
33
|
+
console.log("Active subscriptions:", customerState?.activeSubscriptions);
|
|
34
|
+
{{/if}}
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<>
|
|
38
|
+
{{#if (eq api "orpc")}}
|
|
39
|
+
<p>API: {privateData.data?.message}</p>
|
|
40
|
+
{{/if}}
|
|
41
|
+
{{#if (eq api "trpc")}}
|
|
42
|
+
<p>API: {privateData.data?.message}</p>
|
|
43
|
+
{{/if}}
|
|
44
|
+
{{#if (eq payments "polar")}}
|
|
45
|
+
<p>Plan: {hasProSubscription ? "Pro" : "Free"}</p>
|
|
46
|
+
{hasProSubscription ? (
|
|
47
|
+
<Button onClick={async () => await authClient.customer.portal()}>
|
|
48
|
+
Manage Subscription
|
|
49
|
+
</Button>
|
|
50
|
+
) : (
|
|
51
|
+
<Button onClick={async () => await authClient.checkout({ slug: "pro" })}>
|
|
52
|
+
Upgrade to Pro
|
|
53
|
+
</Button>
|
|
54
|
+
)}
|
|
55
|
+
{{/if}}
|
|
56
|
+
</>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
@@ -1,47 +1,37 @@
|
|
|
1
|
-
"use client"
|
|
2
1
|
import { authClient } from "@/lib/auth-client";
|
|
3
|
-
{
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
{{/if}}
|
|
7
|
-
{{#if (eq api "trpc")}}
|
|
8
|
-
import { useQuery } from "@tanstack/react-query";
|
|
9
|
-
import { trpc } from "@/utils/trpc";
|
|
10
|
-
{{/if}}
|
|
11
|
-
import { useRouter } from "next/navigation";
|
|
12
|
-
import { useEffect } from "react";
|
|
2
|
+
import { redirect } from "next/navigation";
|
|
3
|
+
import Dashboard from "./dashboard";
|
|
4
|
+
import { headers } from "next/headers";
|
|
13
5
|
|
|
14
|
-
export default function
|
|
15
|
-
|
|
16
|
-
|
|
6
|
+
export default async function DashboardPage() {
|
|
7
|
+
const session = await authClient.getSession({
|
|
8
|
+
fetchOptions: {
|
|
9
|
+
headers: await headers()
|
|
10
|
+
}
|
|
11
|
+
});
|
|
17
12
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
{{#if (eq api "trpc")}}
|
|
22
|
-
const privateData = useQuery(trpc.privateData.queryOptions());
|
|
23
|
-
{{/if}}
|
|
13
|
+
if (!session.data) {
|
|
14
|
+
redirect("/login");
|
|
15
|
+
}
|
|
24
16
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
17
|
+
{{#if (eq payments "polar")}}
|
|
18
|
+
const { data: customerState, error } = await authClient.customer.state({
|
|
19
|
+
fetchOptions: {
|
|
20
|
+
headers: await headers()
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
{{/if}}
|
|
30
24
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
<p>privateData: {privateData.data?.message}</p>
|
|
44
|
-
{{/if}}
|
|
45
|
-
</div>
|
|
46
|
-
);
|
|
25
|
+
return (
|
|
26
|
+
<div>
|
|
27
|
+
<h1>Dashboard</h1>
|
|
28
|
+
<p>Welcome {session.data.user.name}</p>
|
|
29
|
+
<Dashboard
|
|
30
|
+
session={session.data}
|
|
31
|
+
{{#if (eq payments "polar")}}
|
|
32
|
+
customerState={customerState}
|
|
33
|
+
{{/if}}
|
|
34
|
+
/>
|
|
35
|
+
</div>
|
|
36
|
+
);
|
|
47
37
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Button } from "@/components/ui/button";
|
|
1
2
|
import { authClient } from "@/lib/auth-client";
|
|
2
3
|
{{#if (eq api "orpc")}}
|
|
3
4
|
import { orpc } from "@/utils/orpc";
|
|
@@ -8,12 +9,15 @@ import { trpc } from "@/utils/trpc";
|
|
|
8
9
|
{{#if ( or (eq api "orpc") (eq api "trpc"))}}
|
|
9
10
|
import { useQuery } from "@tanstack/react-query";
|
|
10
11
|
{{/if}}
|
|
11
|
-
import { useEffect } from "react";
|
|
12
|
+
import { useEffect, useState } from "react";
|
|
12
13
|
import { useNavigate } from "react-router";
|
|
13
14
|
|
|
14
15
|
export default function Dashboard() {
|
|
15
16
|
const { data: session, isPending } = authClient.useSession();
|
|
16
17
|
const navigate = useNavigate();
|
|
18
|
+
{{#if (eq payments "polar")}}
|
|
19
|
+
const [customerState, setCustomerState] = useState<any>(null);
|
|
20
|
+
{{/if}}
|
|
17
21
|
|
|
18
22
|
{{#if (eq api "orpc")}}
|
|
19
23
|
const privateData = useQuery(orpc.privateData.queryOptions());
|
|
@@ -26,18 +30,48 @@ export default function Dashboard() {
|
|
|
26
30
|
if (!session && !isPending) {
|
|
27
31
|
navigate("/login");
|
|
28
32
|
}
|
|
29
|
-
}, [session, isPending]);
|
|
33
|
+
}, [session, isPending, navigate]);
|
|
34
|
+
|
|
35
|
+
{{#if (eq payments "polar")}}
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
async function fetchCustomerState() {
|
|
38
|
+
if (session) {
|
|
39
|
+
const { data } = await authClient.customer.state();
|
|
40
|
+
setCustomerState(data);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
fetchCustomerState();
|
|
45
|
+
}, [session]);
|
|
46
|
+
{{/if}}
|
|
30
47
|
|
|
31
48
|
if (isPending) {
|
|
32
49
|
return <div>Loading...</div>;
|
|
33
50
|
}
|
|
34
51
|
|
|
52
|
+
{{#if (eq payments "polar")}}
|
|
53
|
+
const hasProSubscription = customerState?.activeSubscriptions?.length! > 0;
|
|
54
|
+
console.log("Active subscriptions:", customerState?.activeSubscriptions);
|
|
55
|
+
{{/if}}
|
|
56
|
+
|
|
35
57
|
return (
|
|
36
58
|
<div>
|
|
37
59
|
<h1>Dashboard</h1>
|
|
38
60
|
<p>Welcome {session?.user.name}</p>
|
|
39
61
|
{{#if ( or (eq api "orpc") (eq api "trpc"))}}
|
|
40
|
-
<p>
|
|
62
|
+
<p>API: {privateData.data?.message}</p>
|
|
63
|
+
{{/if}}
|
|
64
|
+
{{#if (eq payments "polar")}}
|
|
65
|
+
<p>Plan: {hasProSubscription ? "Pro" : "Free"}</p>
|
|
66
|
+
{hasProSubscription ? (
|
|
67
|
+
<Button onClick={async () => await authClient.customer.portal()}>
|
|
68
|
+
Manage Subscription
|
|
69
|
+
</Button>
|
|
70
|
+
) : (
|
|
71
|
+
<Button onClick={async () => await authClient.checkout({ slug: "pro" })}>
|
|
72
|
+
Upgrade to Pro
|
|
73
|
+
</Button>
|
|
74
|
+
)}
|
|
41
75
|
{{/if}}
|
|
42
76
|
</div>
|
|
43
77
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Button } from "@/components/ui/button";
|
|
1
2
|
import { authClient } from "@/lib/auth-client";
|
|
2
3
|
{{#if (eq api "orpc")}}
|
|
3
4
|
import { orpc } from "@/utils/orpc";
|
|
@@ -8,44 +9,61 @@ import { trpc } from "@/utils/trpc";
|
|
|
8
9
|
{{#if ( or (eq api "orpc") (eq api "trpc"))}}
|
|
9
10
|
import { useQuery } from "@tanstack/react-query";
|
|
10
11
|
{{/if}}
|
|
11
|
-
import { createFileRoute } from "@tanstack/react-router";
|
|
12
|
-
import { useEffect } from "react";
|
|
12
|
+
import { createFileRoute, redirect } from "@tanstack/react-router";
|
|
13
13
|
|
|
14
14
|
export const Route = createFileRoute("/dashboard")({
|
|
15
|
-
|
|
15
|
+
component: RouteComponent,
|
|
16
|
+
beforeLoad: async () => {
|
|
17
|
+
const session = await authClient.getSession();
|
|
18
|
+
if (!session.data) {
|
|
19
|
+
redirect({
|
|
20
|
+
to: "/login",
|
|
21
|
+
throw: true
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
{{#if (eq payments "polar")}}
|
|
25
|
+
const {data: customerState} = await authClient.customer.state()
|
|
26
|
+
return { session, customerState };
|
|
27
|
+
{{else}}
|
|
28
|
+
return { session };
|
|
29
|
+
{{/if}}
|
|
30
|
+
}
|
|
16
31
|
});
|
|
17
32
|
|
|
18
33
|
function RouteComponent() {
|
|
19
|
-
|
|
34
|
+
const { session{{#if (eq payments "polar")}}, customerState{{/if}} } = Route.useRouteContext();
|
|
20
35
|
|
|
21
|
-
|
|
36
|
+
{{#if (eq api "orpc")}}
|
|
37
|
+
const privateData = useQuery(orpc.privateData.queryOptions());
|
|
38
|
+
{{/if}}
|
|
39
|
+
{{#if (eq api "trpc")}}
|
|
40
|
+
const privateData = useQuery(trpc.privateData.queryOptions());
|
|
41
|
+
{{/if}}
|
|
22
42
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const privateData = useQuery(trpc.privateData.queryOptions());
|
|
28
|
-
{{/if}}
|
|
43
|
+
{{#if (eq payments "polar")}}
|
|
44
|
+
const hasProSubscription = customerState?.activeSubscriptions?.length! > 0
|
|
45
|
+
console.log("Active subscriptions:", customerState?.activeSubscriptions)
|
|
46
|
+
{{/if}}
|
|
29
47
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
return (
|
|
49
|
+
<div>
|
|
50
|
+
<h1>Dashboard</h1>
|
|
51
|
+
<p>Welcome {session.data?.user.name}</p>
|
|
52
|
+
{{#if ( or (eq api "orpc") (eq api "trpc"))}}
|
|
53
|
+
<p>API: {privateData.data?.message}</p>
|
|
54
|
+
{{/if}}
|
|
55
|
+
{{#if (eq payments "polar")}}
|
|
56
|
+
<p>Plan: {hasProSubscription ? "Pro" : "Free"}</p>
|
|
57
|
+
{hasProSubscription ? (
|
|
58
|
+
<Button onClick={async () => await authClient.customer.portal()}>
|
|
59
|
+
Manage Subscription
|
|
60
|
+
</Button>
|
|
61
|
+
) : (
|
|
62
|
+
<Button onClick={async () => await authClient.checkout({ slug: "pro" })}>
|
|
63
|
+
Upgrade to Pro
|
|
64
|
+
</Button>
|
|
65
|
+
)}
|
|
66
|
+
{{/if}}
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
51
69
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Button } from "@/components/ui/button";
|
|
1
2
|
import { authClient } from "@/lib/auth-client";
|
|
2
3
|
{{#if (eq api "trpc")}}
|
|
3
4
|
import { useTRPC } from "@/utils/trpc";
|
|
@@ -7,48 +8,62 @@ import { useQuery } from "@tanstack/react-query";
|
|
|
7
8
|
import { orpc } from "@/utils/orpc";
|
|
8
9
|
import { useQuery } from "@tanstack/react-query";
|
|
9
10
|
{{/if}}
|
|
10
|
-
import { createFileRoute } from "@tanstack/react-router";
|
|
11
|
-
import { useEffect } from "react";
|
|
11
|
+
import { createFileRoute, redirect } from "@tanstack/react-router";
|
|
12
12
|
|
|
13
13
|
export const Route = createFileRoute("/dashboard")({
|
|
14
|
-
|
|
14
|
+
component: RouteComponent,
|
|
15
|
+
beforeLoad: async () => {
|
|
16
|
+
const session = await authClient.getSession();
|
|
17
|
+
if (!session.data) {
|
|
18
|
+
redirect({
|
|
19
|
+
to: "/login",
|
|
20
|
+
throw: true
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
{{#if (eq payments "polar")}}
|
|
24
|
+
const {data: customerState} = await authClient.customer.state()
|
|
25
|
+
return { session, customerState };
|
|
26
|
+
{{else}}
|
|
27
|
+
return { session };
|
|
28
|
+
{{/if}}
|
|
29
|
+
}
|
|
15
30
|
});
|
|
16
31
|
|
|
17
32
|
function RouteComponent() {
|
|
18
|
-
|
|
19
|
-
{{#if (eq api "trpc")}}
|
|
20
|
-
const trpc = useTRPC();
|
|
21
|
-
{{/if}}
|
|
22
|
-
{{#if (eq api "orpc")}}
|
|
23
|
-
{{/if}}
|
|
24
|
-
const { data: session, isPending } = authClient.useSession();
|
|
33
|
+
const { session{{#if (eq payments "polar")}}, customerState{{/if}} } = Route.useRouteContext();
|
|
25
34
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
{{#if (eq api "trpc")}}
|
|
36
|
+
const trpc = useTRPC();
|
|
37
|
+
const privateData = useQuery(trpc.privateData.queryOptions());
|
|
38
|
+
{{/if}}
|
|
39
|
+
{{#if (eq api "orpc")}}
|
|
40
|
+
const privateData = useQuery(orpc.privateData.queryOptions());
|
|
41
|
+
{{/if}}
|
|
32
42
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
}, [session, isPending]);
|
|
43
|
+
{{#if (eq payments "polar")}}
|
|
44
|
+
const hasProSubscription = customerState?.activeSubscriptions?.length! > 0
|
|
45
|
+
console.log("Active subscriptions:", customerState?.activeSubscriptions)
|
|
46
|
+
{{/if}}
|
|
40
47
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
return (
|
|
49
|
+
<div>
|
|
50
|
+
<h1>Dashboard</h1>
|
|
51
|
+
<p>Welcome {session.data?.user.name}</p>
|
|
52
|
+
{{#if ( or (eq api "orpc") (eq api "trpc"))}}
|
|
53
|
+
<p>API: {privateData.data?.message}</p>
|
|
54
|
+
{{/if}}
|
|
55
|
+
{{#if (eq payments "polar")}}
|
|
56
|
+
<p>Plan: {hasProSubscription ? "Pro" : "Free"}</p>
|
|
57
|
+
{hasProSubscription ? (
|
|
58
|
+
<Button onClick={async () => await authClient.customer.portal()}>
|
|
59
|
+
Manage Subscription
|
|
60
|
+
</Button>
|
|
61
|
+
) : (
|
|
62
|
+
<Button onClick={async () => await authClient.checkout({ slug: "pro" })}>
|
|
63
|
+
Upgrade to Pro
|
|
64
|
+
</Button>
|
|
65
|
+
)}
|
|
66
|
+
{{/if}}
|
|
67
|
+
</div>
|
|
68
|
+
);
|
|
54
69
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createAuthClient } from "better-auth/solid";
|
|
2
|
+
{{#if (eq payments "polar")}}
|
|
3
|
+
import { polarClient } from "@polar-sh/better-auth";
|
|
4
|
+
{{/if}}
|
|
5
|
+
|
|
6
|
+
export const authClient = createAuthClient({
|
|
7
|
+
baseURL: import.meta.env.VITE_SERVER_URL,
|
|
8
|
+
{{#if (eq payments "polar")}}
|
|
9
|
+
plugins: [polarClient()]
|
|
10
|
+
{{/if}}
|
|
11
|
+
});
|
|
@@ -3,42 +3,65 @@ import { authClient } from "@/lib/auth-client";
|
|
|
3
3
|
import { orpc } from "@/utils/orpc";
|
|
4
4
|
import { useQuery } from "@tanstack/solid-query";
|
|
5
5
|
{{/if}}
|
|
6
|
-
import { createFileRoute } from "@tanstack/solid-router";
|
|
7
|
-
import { createEffect, Show } from "solid-js";
|
|
6
|
+
import { createFileRoute, redirect } from "@tanstack/solid-router";
|
|
8
7
|
|
|
9
8
|
export const Route = createFileRoute("/dashboard")({
|
|
10
|
-
|
|
9
|
+
component: RouteComponent,
|
|
10
|
+
beforeLoad: async () => {
|
|
11
|
+
const session = await authClient.getSession();
|
|
12
|
+
if (!session.data) {
|
|
13
|
+
redirect({
|
|
14
|
+
to: "/login",
|
|
15
|
+
throw: true,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
{{#if (eq payments "polar")}}
|
|
19
|
+
const { data: customerState } = await authClient.customer.state();
|
|
20
|
+
return { session, customerState };
|
|
21
|
+
{{else}}
|
|
22
|
+
return { session };
|
|
23
|
+
{{/if}}
|
|
24
|
+
},
|
|
11
25
|
});
|
|
12
26
|
|
|
13
27
|
function RouteComponent() {
|
|
14
|
-
|
|
15
|
-
const navigate = Route.useNavigate();
|
|
28
|
+
const context = Route.useRouteContext();
|
|
16
29
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
30
|
+
const session = context().session;
|
|
31
|
+
{{#if (eq payments "polar")}}
|
|
32
|
+
const customerState = context().customerState;
|
|
33
|
+
{{/if}}
|
|
20
34
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
to: "/login",
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
});
|
|
35
|
+
{{#if (eq api "orpc")}}
|
|
36
|
+
const privateData = useQuery(() => orpc.privateData.queryOptions());
|
|
37
|
+
{{/if}}
|
|
28
38
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
</Show>
|
|
39
|
+
{{#if (eq payments "polar")}}
|
|
40
|
+
const hasProSubscription = () =>
|
|
41
|
+
customerState?.activeSubscriptions?.length! > 0;
|
|
42
|
+
{{/if}}
|
|
34
43
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
+
return (
|
|
45
|
+
<div>
|
|
46
|
+
<h1>Dashboard</h1>
|
|
47
|
+
<p>Welcome {session.data?.user.name}</p>
|
|
48
|
+
{{#if (eq api "orpc")}}
|
|
49
|
+
<p>API: {privateData.data?.message}</p>
|
|
50
|
+
{{/if}}
|
|
51
|
+
{{#if (eq payments "polar")}}
|
|
52
|
+
<p>Plan: {hasProSubscription() ? "Pro" : "Free"}</p>
|
|
53
|
+
{hasProSubscription() ? (
|
|
54
|
+
<button onClick={async () => await authClient.customer.portal()}>
|
|
55
|
+
Manage Subscription
|
|
56
|
+
</button>
|
|
57
|
+
) : (
|
|
58
|
+
<button
|
|
59
|
+
onClick={async () => await authClient.checkout({ slug: "pro" })}
|
|
60
|
+
>
|
|
61
|
+
Upgrade to Pro
|
|
62
|
+
</button>
|
|
63
|
+
)}
|
|
64
|
+
{{/if}}
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
44
67
|
}
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { PUBLIC_SERVER_URL } from "$env/static/public";
|
|
2
2
|
import { createAuthClient } from "better-auth/svelte";
|
|
3
|
+
{{#if (eq payments "polar")}}
|
|
4
|
+
import { polarClient } from "@polar-sh/better-auth";
|
|
5
|
+
{{/if}}
|
|
3
6
|
|
|
4
7
|
export const authClient = createAuthClient({
|
|
5
8
|
baseURL: PUBLIC_SERVER_URL,
|
|
9
|
+
{{#if (eq payments "polar")}}
|
|
10
|
+
plugins: [polarClient()]
|
|
11
|
+
{{/if}}
|
|
6
12
|
});
|
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
import { orpc } from '$lib/orpc';
|
|
7
7
|
import { createQuery } from '@tanstack/svelte-query';
|
|
8
8
|
{{/if}}
|
|
9
|
-
|
|
9
|
+
{{#if (eq payments "polar")}}
|
|
10
|
+
let customerState: any = null;
|
|
11
|
+
{{/if}}
|
|
10
12
|
|
|
11
13
|
const sessionQuery = authClient.useSession();
|
|
12
14
|
|
|
@@ -15,10 +17,17 @@
|
|
|
15
17
|
{{/if}}
|
|
16
18
|
|
|
17
19
|
onMount(() => {
|
|
18
|
-
const { data: session, isPending } =
|
|
20
|
+
const { data: session, isPending } = $sessionQuery;
|
|
19
21
|
if (!session && !isPending) {
|
|
20
22
|
goto('/login');
|
|
21
23
|
}
|
|
24
|
+
{{#if (eq payments "polar")}}
|
|
25
|
+
if (session) {
|
|
26
|
+
authClient.customer.state().then(({ data }) => {
|
|
27
|
+
customerState = data;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
{{/if}}
|
|
22
31
|
});
|
|
23
32
|
</script>
|
|
24
33
|
|
|
@@ -30,7 +39,19 @@
|
|
|
30
39
|
<h1>Dashboard</h1>
|
|
31
40
|
<p>Welcome {$sessionQuery.data.user.name}</p>
|
|
32
41
|
{{#if (eq api "orpc")}}
|
|
33
|
-
<p>
|
|
42
|
+
<p>API: {$privateDataQuery.data?.message}</p>
|
|
43
|
+
{{/if}}
|
|
44
|
+
{{#if (eq payments "polar")}}
|
|
45
|
+
<p>Plan: {customerState?.activeSubscriptions?.length > 0 ? "Pro" : "Free"}</p>
|
|
46
|
+
{#if customerState?.activeSubscriptions?.length > 0}
|
|
47
|
+
<button onclick={async () => await authClient.customer.portal()}>
|
|
48
|
+
Manage Subscription
|
|
49
|
+
</button>
|
|
50
|
+
{:else}
|
|
51
|
+
<button onclick={async () => await authClient.checkout({ slug: "pro" })}>
|
|
52
|
+
Upgrade to Pro
|
|
53
|
+
</button>
|
|
54
|
+
{/if}
|
|
34
55
|
{{/if}}
|
|
35
56
|
</div>
|
|
36
57
|
{/if}
|
|
@@ -5,6 +5,10 @@
|
|
|
5
5
|
import { useAuth } from "@clerk/nextjs";
|
|
6
6
|
import { ConvexReactClient } from "convex/react";
|
|
7
7
|
import { ConvexProviderWithClerk } from "convex/react-clerk";
|
|
8
|
+
{{else if (eq auth "better-auth")}}
|
|
9
|
+
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
|
10
|
+
import { ConvexBetterAuthProvider } from "@convex-dev/better-auth/react";
|
|
11
|
+
import { authClient } from "@/lib/auth-client";
|
|
8
12
|
{{else}}
|
|
9
13
|
import { ConvexProvider, ConvexReactClient } from "convex/react";
|
|
10
14
|
{{/if}}
|
|
@@ -44,6 +48,10 @@ export default function Providers({
|
|
|
44
48
|
<ConvexProviderWithClerk client={convex} useAuth={useAuth}>
|
|
45
49
|
{children}
|
|
46
50
|
</ConvexProviderWithClerk>
|
|
51
|
+
{{else if (eq auth "better-auth")}}
|
|
52
|
+
<ConvexBetterAuthProvider client={convex} authClient={authClient}>
|
|
53
|
+
{children}
|
|
54
|
+
</ConvexBetterAuthProvider>
|
|
47
55
|
{{else}}
|
|
48
56
|
<ConvexProvider client={convex}>{children}</ConvexProvider>
|
|
49
57
|
{{/if}}
|
|
@@ -16,10 +16,15 @@ import { routeTree } from "./routeTree.gen";
|
|
|
16
16
|
{{#if (eq auth "clerk")}}
|
|
17
17
|
import { ClerkProvider, useAuth } from "@clerk/clerk-react";
|
|
18
18
|
import { ConvexProviderWithClerk } from "convex/react-clerk";
|
|
19
|
+
{{else if (eq auth "better-auth")}}
|
|
20
|
+
import { ConvexBetterAuthProvider } from "@convex-dev/better-auth/react";
|
|
21
|
+
import { authClient } from "@/lib/auth-client";
|
|
19
22
|
{{else}}
|
|
20
23
|
import { ConvexProvider } from "convex/react";
|
|
21
24
|
{{/if}}
|
|
22
|
-
const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string)
|
|
25
|
+
const convex = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL as string{{#if (eq auth "better-auth")}}, {
|
|
26
|
+
expectAuth: true,
|
|
27
|
+
}{{/if}});
|
|
23
28
|
{{/if}}
|
|
24
29
|
|
|
25
30
|
const router = createRouter({
|
|
@@ -57,6 +62,8 @@ const router = createRouter({
|
|
|
57
62
|
</ConvexProviderWithClerk>
|
|
58
63
|
</ClerkProvider>
|
|
59
64
|
);
|
|
65
|
+
{{else if (eq auth "better-auth")}}
|
|
66
|
+
return <ConvexBetterAuthProvider client={convex} authClient={authClient}>{children}</ConvexBetterAuthProvider>;
|
|
60
67
|
{{else}}
|
|
61
68
|
return <ConvexProvider client={convex}>{children}</ConvexProvider>;
|
|
62
69
|
{{/if}}
|