create-better-t-stack 2.45.5 → 2.46.0
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-NOw0j6Z9.js} +272 -132
- package/package.json +1 -1
- package/templates/auth/better-auth/server/base/src/lib/auth.ts.hbs +153 -6
- 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/tanstack-start/src/routes/__root.tsx.hbs +4 -0
- 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/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/{theme-provider.tsx → theme-provider.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
|
@@ -4,6 +4,10 @@ import { prismaAdapter } from "better-auth/adapters/prisma";
|
|
|
4
4
|
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
5
5
|
import { expo } from "@better-auth/expo";
|
|
6
6
|
{{/if}}
|
|
7
|
+
{{#if (eq payments "polar")}}
|
|
8
|
+
import { polar, checkout, portal } from "@polar-sh/better-auth";
|
|
9
|
+
import { polarClient } from "./payments";
|
|
10
|
+
{{/if}}
|
|
7
11
|
import prisma from "../db";
|
|
8
12
|
|
|
9
13
|
export const auth = betterAuth<BetterAuthOptions>({
|
|
@@ -28,9 +32,35 @@ export const auth = betterAuth<BetterAuthOptions>({
|
|
|
28
32
|
secure: true,
|
|
29
33
|
httpOnly: true,
|
|
30
34
|
},
|
|
31
|
-
}
|
|
35
|
+
},
|
|
36
|
+
{{#if (eq payments "polar")}}
|
|
37
|
+
plugins: [
|
|
38
|
+
polar({
|
|
39
|
+
client: polarClient,
|
|
40
|
+
createCustomerOnSignUp: true,
|
|
41
|
+
enableCustomerPortal: true,
|
|
42
|
+
use: [
|
|
43
|
+
checkout({
|
|
44
|
+
products: [
|
|
45
|
+
{
|
|
46
|
+
productId: "your-product-id",
|
|
47
|
+
slug: "pro",
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
successUrl: process.env.POLAR_SUCCESS_URL,
|
|
51
|
+
authenticatedUsersOnly: true,
|
|
52
|
+
}),
|
|
53
|
+
portal(),
|
|
54
|
+
],
|
|
55
|
+
}),
|
|
56
|
+
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
57
|
+
expo(),
|
|
58
|
+
{{/if}}
|
|
59
|
+
],
|
|
60
|
+
{{else}}
|
|
32
61
|
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
33
|
-
|
|
62
|
+
plugins: [expo()],
|
|
63
|
+
{{/if}}
|
|
34
64
|
{{/if}}
|
|
35
65
|
});
|
|
36
66
|
{{/if}}
|
|
@@ -42,6 +72,10 @@ import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
|
42
72
|
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
43
73
|
import { expo } from "@better-auth/expo";
|
|
44
74
|
{{/if}}
|
|
75
|
+
{{#if (eq payments "polar")}}
|
|
76
|
+
import { polar, checkout, portal } from "@polar-sh/better-auth";
|
|
77
|
+
import { polarClient } from "./payments";
|
|
78
|
+
{{/if}}
|
|
45
79
|
import { db } from "../db";
|
|
46
80
|
import * as schema from "../db/schema/auth";
|
|
47
81
|
|
|
@@ -68,9 +102,35 @@ export const auth = betterAuth<BetterAuthOptions>({
|
|
|
68
102
|
httpOnly: true,
|
|
69
103
|
},
|
|
70
104
|
},
|
|
105
|
+
{{#if (eq payments "polar")}}
|
|
106
|
+
plugins: [
|
|
107
|
+
polar({
|
|
108
|
+
client: polarClient,
|
|
109
|
+
createCustomerOnSignUp: true,
|
|
110
|
+
enableCustomerPortal: true,
|
|
111
|
+
use: [
|
|
112
|
+
checkout({
|
|
113
|
+
products: [
|
|
114
|
+
{
|
|
115
|
+
productId: "your-product-id",
|
|
116
|
+
slug: "pro",
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
successUrl: process.env.POLAR_SUCCESS_URL,
|
|
120
|
+
authenticatedUsersOnly: true,
|
|
121
|
+
}),
|
|
122
|
+
portal(),
|
|
123
|
+
],
|
|
124
|
+
}),
|
|
125
|
+
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
126
|
+
expo(),
|
|
127
|
+
{{/if}}
|
|
128
|
+
],
|
|
129
|
+
{{else}}
|
|
71
130
|
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
72
131
|
plugins: [expo()],
|
|
73
132
|
{{/if}}
|
|
133
|
+
{{/if}}
|
|
74
134
|
});
|
|
75
135
|
{{/if}}
|
|
76
136
|
|
|
@@ -80,6 +140,10 @@ import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
|
80
140
|
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
81
141
|
import { expo } from "@better-auth/expo";
|
|
82
142
|
{{/if}}
|
|
143
|
+
{{#if (eq payments "polar")}}
|
|
144
|
+
import { polar, checkout, portal } from "@polar-sh/better-auth";
|
|
145
|
+
import { polarClient } from "./payments";
|
|
146
|
+
{{/if}}
|
|
83
147
|
import { db } from "../db";
|
|
84
148
|
import * as schema from "../db/schema/auth";
|
|
85
149
|
import { env } from "cloudflare:workers";
|
|
@@ -109,9 +173,32 @@ export const auth = betterAuth<BetterAuthOptions>({
|
|
|
109
173
|
httpOnly: true,
|
|
110
174
|
},
|
|
111
175
|
},
|
|
176
|
+
{{#if (eq payments "polar")}}
|
|
177
|
+
plugins: [
|
|
178
|
+
polar({
|
|
179
|
+
client: polarClient,
|
|
180
|
+
createCustomerOnSignUp: true,
|
|
181
|
+
enableCustomerPortal: true,
|
|
182
|
+
use: [
|
|
183
|
+
checkout({
|
|
184
|
+
products: [
|
|
185
|
+
{
|
|
186
|
+
productId: "your-product-id",
|
|
187
|
+
slug: "pro",
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
successUrl: env.POLAR_SUCCESS_URL,
|
|
191
|
+
authenticatedUsersOnly: true,
|
|
192
|
+
}),
|
|
193
|
+
portal(),
|
|
194
|
+
],
|
|
195
|
+
}),
|
|
196
|
+
],
|
|
197
|
+
{{else}}
|
|
112
198
|
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
113
199
|
plugins: [expo()],
|
|
114
200
|
{{/if}}
|
|
201
|
+
{{/if}}
|
|
115
202
|
});
|
|
116
203
|
{{/if}}
|
|
117
204
|
{{/if}}
|
|
@@ -122,6 +209,10 @@ import { mongodbAdapter } from "better-auth/adapters/mongodb";
|
|
|
122
209
|
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
123
210
|
import { expo } from "@better-auth/expo";
|
|
124
211
|
{{/if}}
|
|
212
|
+
{{#if (eq payments "polar")}}
|
|
213
|
+
import { polar, checkout, portal } from "@polar-sh/better-auth";
|
|
214
|
+
import { polarClient } from "./payments";
|
|
215
|
+
{{/if}}
|
|
125
216
|
import { client } from "../db";
|
|
126
217
|
|
|
127
218
|
export const auth = betterAuth<BetterAuthOptions>({
|
|
@@ -141,9 +232,35 @@ export const auth = betterAuth<BetterAuthOptions>({
|
|
|
141
232
|
secure: true,
|
|
142
233
|
httpOnly: true,
|
|
143
234
|
},
|
|
144
|
-
}
|
|
235
|
+
},
|
|
236
|
+
{{#if (eq payments "polar")}}
|
|
237
|
+
plugins: [
|
|
238
|
+
polar({
|
|
239
|
+
client: polarClient,
|
|
240
|
+
createCustomerOnSignUp: true,
|
|
241
|
+
enableCustomerPortal: true,
|
|
242
|
+
use: [
|
|
243
|
+
checkout({
|
|
244
|
+
products: [
|
|
245
|
+
{
|
|
246
|
+
productId: "your-product-id",
|
|
247
|
+
slug: "pro",
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
successUrl: process.env.POLAR_SUCCESS_URL,
|
|
251
|
+
authenticatedUsersOnly: true,
|
|
252
|
+
}),
|
|
253
|
+
portal(),
|
|
254
|
+
],
|
|
255
|
+
}),
|
|
256
|
+
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
257
|
+
expo(),
|
|
258
|
+
{{/if}}
|
|
259
|
+
],
|
|
260
|
+
{{else}}
|
|
145
261
|
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
146
|
-
|
|
262
|
+
plugins: [expo()],
|
|
263
|
+
{{/if}}
|
|
147
264
|
{{/if}}
|
|
148
265
|
});
|
|
149
266
|
{{/if}}
|
|
@@ -153,6 +270,10 @@ import { betterAuth, type BetterAuthOptions } from "better-auth";
|
|
|
153
270
|
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
154
271
|
import { expo } from "@better-auth/expo";
|
|
155
272
|
{{/if}}
|
|
273
|
+
{{#if (eq payments "polar")}}
|
|
274
|
+
import { polar, checkout, portal } from "@polar-sh/better-auth";
|
|
275
|
+
import { polarClient } from "./payments";
|
|
276
|
+
{{/if}}
|
|
156
277
|
|
|
157
278
|
export const auth = betterAuth<BetterAuthOptions>({
|
|
158
279
|
database: "", // Invalid configuration
|
|
@@ -171,9 +292,35 @@ export const auth = betterAuth<BetterAuthOptions>({
|
|
|
171
292
|
secure: true,
|
|
172
293
|
httpOnly: true,
|
|
173
294
|
},
|
|
174
|
-
}
|
|
295
|
+
},
|
|
296
|
+
{{#if (eq payments "polar")}}
|
|
297
|
+
plugins: [
|
|
298
|
+
polar({
|
|
299
|
+
client: polarClient,
|
|
300
|
+
createCustomerOnSignUp: true,
|
|
301
|
+
enableCustomerPortal: true,
|
|
302
|
+
use: [
|
|
303
|
+
checkout({
|
|
304
|
+
products: [
|
|
305
|
+
{
|
|
306
|
+
productId: "your-product-id",
|
|
307
|
+
slug: "pro",
|
|
308
|
+
},
|
|
309
|
+
],
|
|
310
|
+
successUrl: process.env.POLAR_SUCCESS_URL,
|
|
311
|
+
authenticatedUsersOnly: true,
|
|
312
|
+
}),
|
|
313
|
+
portal(),
|
|
314
|
+
],
|
|
315
|
+
}),
|
|
316
|
+
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
317
|
+
expo(),
|
|
318
|
+
{{/if}}
|
|
319
|
+
],
|
|
320
|
+
{{else}}
|
|
175
321
|
{{#if (or (includes frontend "native-nativewind") (includes frontend "native-unistyles"))}}
|
|
176
|
-
|
|
322
|
+
plugins: [expo()],
|
|
323
|
+
{{/if}}
|
|
177
324
|
{{/if}}
|
|
178
325
|
});
|
|
179
326
|
{{/if}}
|
|
@@ -11,9 +11,28 @@ definePageMeta({
|
|
|
11
11
|
const { $orpc } = useNuxtApp()
|
|
12
12
|
|
|
13
13
|
const session = $authClient.useSession()
|
|
14
|
+
{{#if (eq payments "polar")}}
|
|
15
|
+
const customerState = ref<any>(null)
|
|
16
|
+
{{/if}}
|
|
14
17
|
|
|
15
18
|
{{#if (eq api "orpc")}}
|
|
16
|
-
const privateData = useQuery(
|
|
19
|
+
const privateData = useQuery({
|
|
20
|
+
...$orpc.privateData.queryOptions(),
|
|
21
|
+
enabled: computed(() => !!session.value?.data?.user)
|
|
22
|
+
})
|
|
23
|
+
{{/if}}
|
|
24
|
+
|
|
25
|
+
{{#if (eq payments "polar")}}
|
|
26
|
+
onMounted(async () => {
|
|
27
|
+
if (session.value?.data) {
|
|
28
|
+
const { data } = await $authClient.customer.state()
|
|
29
|
+
customerState.value = data
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const hasProSubscription = computed(() =>
|
|
34
|
+
customerState.value?.activeSubscriptions?.length! > 0
|
|
35
|
+
)
|
|
17
36
|
{{/if}}
|
|
18
37
|
|
|
19
38
|
</script>
|
|
@@ -27,7 +46,22 @@ const privateData = useQuery($orpc.privateData.queryOptions())
|
|
|
27
46
|
{{#if (eq api "orpc")}}
|
|
28
47
|
<div v-if="privateData.status.value === 'pending'">Loading private data...</div>
|
|
29
48
|
<div v-else-if="privateData.status.value === 'error'">Error loading private data: \{{ privateData.error.value?.message }}</div>
|
|
30
|
-
<p v-else-if="privateData.data.value">
|
|
49
|
+
<p v-else-if="privateData.data.value">API: \{{ privateData.data.value.message }}</p>
|
|
50
|
+
{{/if}}
|
|
51
|
+
{{#if (eq payments "polar")}}
|
|
52
|
+
<p class="mb-2">Plan: \{{ hasProSubscription ? "Pro" : "Free" }}</p>
|
|
53
|
+
<UButton
|
|
54
|
+
v-if="hasProSubscription"
|
|
55
|
+
@click="() => { $authClient.customer.portal() }"
|
|
56
|
+
>
|
|
57
|
+
Manage Subscription
|
|
58
|
+
</UButton>
|
|
59
|
+
<UButton
|
|
60
|
+
v-else
|
|
61
|
+
@click="() => { $authClient.checkout({ slug: 'pro' }) }"
|
|
62
|
+
>
|
|
63
|
+
Upgrade to Pro
|
|
64
|
+
</UButton>
|
|
31
65
|
{{/if}}
|
|
32
66
|
</div>
|
|
33
67
|
</template>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createAuthClient } from "better-auth/vue";
|
|
2
|
+
{{#if (eq payments "polar")}}
|
|
3
|
+
import { polarClient } from "@polar-sh/better-auth";
|
|
4
|
+
{{/if}}
|
|
5
|
+
|
|
6
|
+
export default defineNuxtPlugin((nuxtApp) => {
|
|
7
|
+
const config = useRuntimeConfig();
|
|
8
|
+
const serverUrl = config.public.serverURL;
|
|
9
|
+
|
|
10
|
+
const authClient = createAuthClient({
|
|
11
|
+
baseURL: serverUrl,
|
|
12
|
+
{{#if (eq payments "polar")}}
|
|
13
|
+
plugins: [polarClient()],
|
|
14
|
+
{{/if}}
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return {
|
|
18
|
+
provide: {
|
|
19
|
+
authClient: authClient,
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
});
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { createAuthClient } from "better-auth/react";
|
|
2
|
+
{{#if (eq payments "polar")}}
|
|
3
|
+
import { polarClient } from "@polar-sh/better-auth";
|
|
4
|
+
{{/if}}
|
|
2
5
|
|
|
3
6
|
export const authClient = createAuthClient({
|
|
4
7
|
baseURL:
|
|
@@ -7,4 +10,7 @@ export const authClient = createAuthClient({
|
|
|
7
10
|
{{else}}
|
|
8
11
|
import.meta.env.VITE_SERVER_URL,
|
|
9
12
|
{{/if}}
|
|
13
|
+
{{#if (eq payments "polar")}}
|
|
14
|
+
plugins: [polarClient()]
|
|
15
|
+
{{/if}}
|
|
10
16
|
});
|
|
@@ -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
|
}
|