create-better-t-stack 3.1.8-canary.65dbf382 → 3.1.8

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 (26) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/index.js +1 -1
  3. package/dist/{src-EpWSiOd8.js → src-DeOVz-ZI.js} +13 -51
  4. package/package.json +1 -1
  5. package/templates/auth/better-auth/convex/backend/convex/auth.ts.hbs +33 -45
  6. package/templates/auth/better-auth/convex/backend/convex/http.ts.hbs +1 -1
  7. package/templates/auth/better-auth/native/{base → native-base}/lib/auth-client.ts.hbs +2 -3
  8. package/templates/frontend/native/nativewind/app/(drawer)/index.tsx.hbs +100 -151
  9. package/templates/frontend/native/nativewind/app/_layout.tsx.hbs +0 -21
  10. package/templates/frontend/native/unistyles/app/(drawer)/index.tsx.hbs +91 -201
  11. package/templates/frontend/native/unistyles/app/_layout.tsx.hbs +0 -28
  12. package/templates/auth/better-auth/convex/native/base/lib/auth-client.ts.hbs +0 -19
  13. package/templates/auth/better-auth/convex/native/nativewind/components/sign-in.tsx.hbs +0 -86
  14. package/templates/auth/better-auth/convex/native/nativewind/components/sign-up.tsx.hbs +0 -97
  15. package/templates/auth/better-auth/convex/native/unistyles/components/sign-in.tsx.hbs +0 -127
  16. package/templates/auth/better-auth/convex/native/unistyles/components/sign-up.tsx.hbs +0 -145
  17. /package/templates/frontend/native/{base → native-base}/assets/images/android-icon-background.png +0 -0
  18. /package/templates/frontend/native/{base → native-base}/assets/images/android-icon-foreground.png +0 -0
  19. /package/templates/frontend/native/{base → native-base}/assets/images/android-icon-monochrome.png +0 -0
  20. /package/templates/frontend/native/{base → native-base}/assets/images/favicon.png +0 -0
  21. /package/templates/frontend/native/{base → native-base}/assets/images/icon.png +0 -0
  22. /package/templates/frontend/native/{base → native-base}/assets/images/partial-react-logo.png +0 -0
  23. /package/templates/frontend/native/{base → native-base}/assets/images/react-logo.png +0 -0
  24. /package/templates/frontend/native/{base → native-base}/assets/images/react-logo@2x.png +0 -0
  25. /package/templates/frontend/native/{base → native-base}/assets/images/react-logo@3x.png +0 -0
  26. /package/templates/frontend/native/{base → native-base}/assets/images/splash-icon.png +0 -0
@@ -1,4 +1,4 @@
1
- import { ScrollView, Text, View, TouchableOpacity } from "react-native";
1
+ import { ScrollView, Text, View } from "react-native";
2
2
  import { StyleSheet } from "react-native-unistyles";
3
3
  import { Container } from "@/components/container";
4
4
 
@@ -11,47 +11,33 @@ import { useQuery } from "@tanstack/react-query";
11
11
  import { trpc } from "@/utils/trpc";
12
12
  {{/if}}
13
13
  {{#if (eq backend "convex")}}
14
- {{#if (eq auth "clerk")}}
15
- import { Link } from "expo-router";
16
- import { Authenticated, AuthLoading, Unauthenticated, useQuery } from "convex/react";
17
- import { api } from "@{{ projectName }}/backend/convex/_generated/api";
18
- import { useUser } from "@clerk/clerk-expo";
19
- import { SignOutButton } from "@/components/sign-out-button";
20
- {{else}}
21
- {{#if (eq auth "better-auth")}}
22
- import { useConvexAuth, useQuery } from "convex/react";
23
- import { api } from "@{{ projectName }}/backend/convex/_generated/api";
24
- import { authClient } from "@/lib/auth-client";
25
- import { SignIn } from "@/components/sign-in";
26
- import { SignUp } from "@/components/sign-up";
27
- {{else}}
28
- import { useQuery } from "convex/react";
29
- import { api } from "@{{ projectName }}/backend/convex/_generated/api";
30
- {{/if}}
31
- {{/if}}
14
+ {{#if (eq auth "clerk")}}
15
+ import { Link } from "expo-router";
16
+ import { Authenticated, AuthLoading, Unauthenticated, useQuery } from "convex/react";
17
+ import { api } from "@{{ projectName }}/backend/convex/_generated/api";
18
+ import { useUser } from "@clerk/clerk-expo";
19
+ import { SignOutButton } from "@/components/sign-out-button";
20
+ {{else}}
21
+ import { useQuery } from "convex/react";
22
+ import { api } from "@{{ projectName }}/backend/convex/_generated/api";
23
+ {{/if}}
32
24
  {{/if}}
33
25
 
34
26
  export default function Home() {
35
27
  {{#if (eq api "orpc")}}
36
- const healthCheck = useQuery(orpc.healthCheck.queryOptions());
28
+ const healthCheck = useQuery(orpc.healthCheck.queryOptions());
37
29
  {{/if}}
38
30
  {{#if (eq api "trpc")}}
39
- const healthCheck = useQuery(trpc.healthCheck.queryOptions());
31
+ const healthCheck = useQuery(trpc.healthCheck.queryOptions());
40
32
  {{/if}}
41
33
  {{#if (eq backend "convex")}}
42
- {{#if (eq auth "clerk")}}
43
- const { user } = useUser();
44
- const healthCheck = useQuery(api.healthCheck.get);
45
- const privateData = useQuery(api.privateData.get);
46
- {{else}}
47
- {{#if (eq auth "better-auth")}}
48
- const healthCheck = useQuery(api.healthCheck.get);
49
- const { isAuthenticated } = useConvexAuth();
50
- const user = useQuery(api.auth.getCurrentUser, isAuthenticated ? {} : "skip");
51
- {{else}}
52
- const healthCheck = useQuery(api.healthCheck.get);
53
- {{/if}}
54
- {{/if}}
34
+ {{#if (eq auth "clerk")}}
35
+ const { user } = useUser();
36
+ const healthCheck = useQuery(api.healthCheck.get);
37
+ const privateData = useQuery(api.privateData.get);
38
+ {{else}}
39
+ const healthCheck = useQuery(api.healthCheck.get);
40
+ {{/if}}
55
41
  {{/if}}
56
42
 
57
43
  return (
@@ -68,125 +54,86 @@ export default function Home() {
68
54
  <Text style={styles.statusBadgeText}>LIVE</Text>
69
55
  </View>
70
56
  </View>
57
+
71
58
  {{#if (eq backend "convex")}}
72
- {{#unless (eq auth "better-auth")}}
73
- <View style={styles.statusRow}>
74
- <View
75
- style={[
76
- styles.statusDot,
77
- healthCheck === "OK"
78
- ? styles.statusDotSuccess
79
- : styles.statusDotWarning,
80
- ]}
81
- />
82
- <View style={styles.statusContent}>
83
- <Text style={styles.statusLabel}>Convex</Text>
84
- <Text style={styles.statusDescription}>
85
- {healthCheck === undefined
86
- ? "Checking connection..."
87
- : healthCheck === "OK"
88
- ? "All systems operational"
89
- : "Service unavailable"}
90
- </Text>
91
- </View>
92
- </View>
93
- {{/unless}}
59
+ <View style={styles.statusRow}>
60
+ <View
61
+ style={[
62
+ styles.statusDot,
63
+ healthCheck === "OK"
64
+ ? styles.statusDotSuccess
65
+ : styles.statusDotWarning,
66
+ ]}
67
+ />
68
+ <View style={styles.statusContent}>
69
+ <Text style={styles.statusLabel}>Convex</Text>
70
+ <Text style={styles.statusDescription}>
71
+ {healthCheck === undefined
72
+ ? "Checking connection..."
73
+ : healthCheck === "OK"
74
+ ? "All systems operational"
75
+ : "Service unavailable"}
76
+ </Text>
77
+ </View>
78
+ </View>
94
79
  {{else}}
95
80
  {{#unless (eq api "none")}}
96
- <View style={styles.statusRow}>
97
- <View
98
- style={[
99
- styles.statusDot,
100
- healthCheck.data
101
- ? styles.statusDotSuccess
102
- : styles.statusDotWarning,
103
- ]}
104
- />
105
- <View style={styles.statusContent}>
106
- <Text style={styles.statusLabel}>
107
- {{#if (eq api "orpc")}}ORPC{{/if}}
108
- {{#if (eq api "trpc")}}TRPC{{/if}}
109
- </Text>
110
- <Text style={styles.statusDescription}>
111
- {(healthCheck.isLoading)
112
- ? "Checking connection..."
113
- : healthCheck.data
114
- ? "All systems operational"
115
- : "Service unavailable"}
116
- </Text>
117
- </View>
118
- </View>
119
- {{/unless}}
120
- {{/if}}
121
- </View>
122
- {{#if (and (eq backend "convex") (eq auth "clerk"))}}
123
- <Authenticated>
124
- <Text>
125
- Hello {user?.emailAddresses[0].emailAddress}
126
- </Text>
127
- <Text>
128
- Private Data: {privateData?.message}
129
- </Text>
130
- <SignOutButton />
131
- </Authenticated>
132
- <Unauthenticated>
133
- <Link href="/(auth)/sign-in">
134
- <Text>Sign in</Text>
135
- </Link>
136
- <Link href="/(auth)/sign-up">
137
- <Text>Sign up</Text>
138
- </Link>
139
- </Unauthenticated>
140
- <AuthLoading>
141
- <Text>Loading...</Text>
142
- </AuthLoading>
143
- {{/if}}
144
- {{#if (and (eq backend "convex") (eq auth "better-auth"))}}
145
- {user ? (
146
- <View style={styles.userCard}>
147
- <View style={styles.userHeader}>
148
- <Text style={styles.userWelcome}>
149
- Welcome,{" "}
150
- <Text style={styles.userName}>{user.name}</Text>
151
- </Text>
152
- </View>
153
- <Text style={styles.userEmail}>{user.email}</Text>
154
- <TouchableOpacity
155
- style={styles.signOutButton}
156
- onPress={() => {
157
- authClient.signOut();
158
- }}
159
- >
160
- <Text style={styles.signOutText}>Sign Out</Text>
161
- </TouchableOpacity>
162
- </View>
163
- ) : null}
164
- <View style={styles.apiStatusCard}>
165
- <Text style={styles.apiStatusTitle}>API Status</Text>
166
- <View style={styles.apiStatusRow}>
81
+ <View style={styles.statusRow}>
167
82
  <View
168
83
  style={[
169
84
  styles.statusDot,
170
- healthCheck === "OK"
85
+ healthCheck.data
171
86
  ? styles.statusDotSuccess
172
87
  : styles.statusDotWarning,
173
88
  ]}
174
89
  />
175
- <Text style={styles.apiStatusText}>
176
- {healthCheck === undefined
177
- ? "Checking..."
178
- : healthCheck === "OK"
179
- ? "Connected to API"
180
- : "API Disconnected"}
181
- </Text>
90
+ <View style={styles.statusContent}>
91
+ <Text style={styles.statusLabel}>
92
+ {{#if (eq api "orpc")}}
93
+ ORPC
94
+ {{/if}}
95
+ {{#if (eq api "trpc")}}
96
+ TRPC
97
+ {{/if}}
98
+ </Text>
99
+ <Text style={styles.statusDescription}>
100
+ {{#if (eq api "orpc")}}
101
+ {healthCheck.isLoading
102
+ ? "Checking connection..."
103
+ : healthCheck.data
104
+ ? "All systems operational"
105
+ : "Service unavailable"}
106
+ {{/if}}
107
+ {{#if (eq api "trpc")}}
108
+ {healthCheck.isLoading
109
+ ? "Checking connection..."
110
+ : healthCheck.data
111
+ ? "All systems operational"
112
+ : "Service unavailable"}
113
+ {{/if}}
114
+ </Text>
115
+ </View>
182
116
  </View>
183
- </View>
184
- {!user && (
185
- <>
186
- <SignIn />
187
- <SignUp />
188
- </>
189
- )}
117
+ {{/unless}}
118
+ {{/if}}
119
+ </View>
120
+ {{#if (and (eq backend "convex") (eq auth "clerk"))}}
121
+ <Authenticated>
122
+ <Text>Hello {user?.emailAddresses[0].emailAddress}</Text>
123
+ <Text>Private Data: {privateData?.message}</Text>
124
+ <SignOutButton />
125
+ </Authenticated>
126
+ <Unauthenticated>
127
+ <Link href="/(auth)/sign-in">
128
+ <Text>Sign in</Text>
129
+ </Link>
130
+ <Link href="/(auth)/sign-up">
131
+ <Text>Sign up</Text>
132
+ </Link>
133
+ </Unauthenticated>
134
+ <AuthLoading>
135
+ <Text>Loading...</Text>
136
+ </AuthLoading>
190
137
  {{/if}}
191
138
  </ScrollView>
192
139
  </Container>
@@ -273,62 +220,5 @@ const styles = StyleSheet.create((theme) => ({
273
220
  statusDescription: {
274
221
  fontSize: theme.fontSize.xs,
275
222
  color: theme.colors.mutedForeground,
276
- },
277
- userCard: {
278
- backgroundColor: theme.colors.card,
279
- borderWidth: 1,
280
- borderColor: theme.colors.border,
281
- borderRadius: theme.borderRadius.lg,
282
- padding: theme.spacing.md,
283
- marginBottom: theme.spacing.md,
284
- },
285
- userHeader: {
286
- flexDirection: "row",
287
- justifyContent: "space-between",
288
- alignItems: "center",
289
- marginBottom: theme.spacing.xs,
290
- },
291
- userWelcome: {
292
- fontSize: theme.fontSize.base,
293
- color: theme.colors.foreground,
294
- },
295
- userName: {
296
- fontWeight: "500",
297
- },
298
- userEmail: {
299
- fontSize: theme.fontSize.sm,
300
- color: theme.colors.mutedForeground,
301
- marginBottom: theme.spacing.md,
302
- },
303
- signOutButton: {
304
- backgroundColor: theme.colors.destructive,
305
- paddingVertical: theme.spacing.sm,
306
- paddingHorizontal: theme.spacing.md,
307
- borderRadius: theme.borderRadius.md,
308
- alignSelf: "flex-start",
309
- },
310
- signOutText: {
311
- color: theme.colors.destructiveForeground,
312
- fontWeight: "500",
313
- },
314
- apiStatusCard: {
315
- marginBottom: theme.spacing.md,
316
- borderRadius: theme.borderRadius.lg,
317
- borderWidth: 1,
318
- borderColor: theme.colors.border,
319
- padding: theme.spacing.md,
320
- },
321
- apiStatusTitle: {
322
- marginBottom: theme.spacing.sm,
323
- fontWeight: "500",
324
- color: theme.colors.foreground,
325
- },
326
- apiStatusRow: {
327
- flexDirection: "row",
328
- alignItems: "center",
329
- gap: theme.spacing.xs,
330
- },
331
- apiStatusText: {
332
- color: theme.colors.mutedForeground,
333
- },
334
- }));
223
+ }
224
+ }));
@@ -8,13 +8,7 @@ import { queryClient } from "@/utils/trpc";
8
8
  import { queryClient } from "@/utils/orpc";
9
9
  {{/if}}
10
10
  {{#if (eq backend "convex")}}
11
- {{#if (eq auth "better-auth")}}
12
- import { ConvexReactClient } from "convex/react";
13
- import { ConvexBetterAuthProvider } from "@convex-dev/better-auth/react";
14
- import { authClient } from "@/lib/auth-client";
15
- {{else}}
16
11
  import { ConvexProvider, ConvexReactClient } from "convex/react";
17
- {{/if}}
18
12
  {{#if (eq auth "clerk")}}
19
13
  import { ClerkProvider, useAuth } from "@clerk/clerk-expo";
20
14
  import { ConvexProviderWithClerk } from "convex/react-clerk";
@@ -73,28 +67,6 @@ export default function RootLayout() {
73
67
  </GestureHandlerRootView>
74
68
  </ConvexProviderWithClerk>
75
69
  </ClerkProvider>
76
- {{else if (eq auth "better-auth")}}
77
- <ConvexBetterAuthProvider client={convex} authClient={authClient}>
78
- <GestureHandlerRootView style=\{{ flex: 1 }}>
79
- <Stack
80
- screenOptions=\{{
81
- headerStyle: {
82
- backgroundColor: theme.colors.background,
83
- },
84
- headerTitleStyle: {
85
- color: theme.colors.foreground,
86
- },
87
- headerTintColor: theme.colors.foreground,
88
- }}}
89
- >
90
- <Stack.Screen name="(drawer)" options=\{{ headerShown: false }} />
91
- <Stack.Screen
92
- name="modal"
93
- options=\{{ title: "Modal", presentation: "modal" }}
94
- />
95
- </Stack>
96
- </GestureHandlerRootView>
97
- </ConvexBetterAuthProvider>
98
70
  {{else}}
99
71
  <ConvexProvider client={convex}>
100
72
  <GestureHandlerRootView style=\{{ flex: 1 }}>
@@ -1,19 +0,0 @@
1
- import { createAuthClient } from "better-auth/react";
2
- import { anonymousClient } from "better-auth/client/plugins";
3
- import { convexClient } from "@convex-dev/better-auth/client/plugins";
4
- import { expoClient } from "@better-auth/expo/client";
5
- import Constants from "expo-constants";
6
- import * as SecureStore from "expo-secure-store";
7
-
8
- export const authClient = createAuthClient({
9
- baseURL: process.env.EXPO_PUBLIC_CONVEX_SITE_URL,
10
- plugins: [
11
- anonymousClient(),
12
- expoClient({
13
- scheme: Constants.expoConfig?.scheme as string,
14
- storagePrefix: Constants.expoConfig?.scheme as string,
15
- storage: SecureStore,
16
- }),
17
- convexClient(),
18
- ],
19
- });
@@ -1,86 +0,0 @@
1
- import { authClient } from "@/lib/auth-client";
2
- import { useState } from "react";
3
- import {
4
- ActivityIndicator,
5
- Text,
6
- TextInput,
7
- TouchableOpacity,
8
- View,
9
- } from "react-native";
10
-
11
- export function SignIn() {
12
- const [email, setEmail] = useState("");
13
- const [password, setPassword] = useState("");
14
- const [isLoading, setIsLoading] = useState(false);
15
- const [error, setError] = useState<string | null>(null);
16
-
17
- const handleLogin = async () => {
18
- setIsLoading(true);
19
- setError(null);
20
-
21
- await authClient.signIn.email(
22
- {
23
- email,
24
- password,
25
- },
26
- {
27
- onError: (error) => {
28
- setError(error.error?.message || "Failed to sign in");
29
- setIsLoading(false);
30
- },
31
- onSuccess: () => {
32
- setEmail("");
33
- setPassword("");
34
- },
35
- onFinished: () => {
36
- setIsLoading(false);
37
- },
38
- },
39
- );
40
- };
41
-
42
- return (
43
- <View className="mt-6 p-4 bg-card rounded-lg border border-border">
44
- <Text className="text-lg font-semibold text-foreground mb-4">
45
- Sign In
46
- </Text>
47
-
48
- {error && (
49
- <View className="mb-4 p-3 bg-destructive/10 rounded-md">
50
- <Text className="text-destructive text-sm">{error}</Text>
51
- </View>
52
- )}
53
-
54
- <TextInput
55
- className="mb-3 p-4 rounded-md bg-input text-foreground border border-input"
56
- placeholder="Email"
57
- value={email}
58
- onChangeText={setEmail}
59
- placeholderTextColor="#9CA3AF"
60
- keyboardType="email-address"
61
- autoCapitalize="none"
62
- />
63
-
64
- <TextInput
65
- className="mb-4 p-4 rounded-md bg-input text-foreground border border-input"
66
- placeholder="Password"
67
- value={password}
68
- onChangeText={setPassword}
69
- placeholderTextColor="#9CA3AF"
70
- secureTextEntry
71
- />
72
-
73
- <TouchableOpacity
74
- onPress={handleLogin}
75
- disabled={isLoading}
76
- className="bg-primary p-4 rounded-md flex-row justify-center items-center"
77
- >
78
- {isLoading ? (
79
- <ActivityIndicator size="small" color="#fff" />
80
- ) : (
81
- <Text className="text-primary-foreground font-medium">Sign In</Text>
82
- )}
83
- </TouchableOpacity>
84
- </View>
85
- );
86
- }
@@ -1,97 +0,0 @@
1
- import { authClient } from "@/lib/auth-client";
2
- import { useState } from "react";
3
- import {
4
- ActivityIndicator,
5
- Text,
6
- TextInput,
7
- TouchableOpacity,
8
- View,
9
- } from "react-native";
10
-
11
- export function SignUp() {
12
- const [name, setName] = useState("");
13
- const [email, setEmail] = useState("");
14
- const [password, setPassword] = useState("");
15
- const [isLoading, setIsLoading] = useState(false);
16
- const [error, setError] = useState<string | null>(null);
17
-
18
- const handleSignUp = async () => {
19
- setIsLoading(true);
20
- setError(null);
21
-
22
- await authClient.signUp.email(
23
- {
24
- name,
25
- email,
26
- password,
27
- },
28
- {
29
- onError: (error) => {
30
- setError(error.error?.message || "Failed to sign up");
31
- setIsLoading(false);
32
- },
33
- onSuccess: () => {
34
- setName("");
35
- setEmail("");
36
- setPassword("");
37
- },
38
- onFinished: () => {
39
- setIsLoading(false);
40
- },
41
- },
42
- );
43
- };
44
-
45
- return (
46
- <View className="mt-6 p-4 bg-card rounded-lg border border-border">
47
- <Text className="text-lg font-semibold text-foreground mb-4">
48
- Create Account
49
- </Text>
50
-
51
- {error && (
52
- <View className="mb-4 p-3 bg-destructive/10 rounded-md">
53
- <Text className="text-destructive text-sm">{error}</Text>
54
- </View>
55
- )}
56
-
57
- <TextInput
58
- className="mb-3 p-4 rounded-md bg-input text-foreground border border-input"
59
- placeholder="Name"
60
- value={name}
61
- onChangeText={setName}
62
- placeholderTextColor="#9CA3AF"
63
- />
64
-
65
- <TextInput
66
- className="mb-3 p-4 rounded-md bg-input text-foreground border border-input"
67
- placeholder="Email"
68
- value={email}
69
- onChangeText={setEmail}
70
- placeholderTextColor="#9CA3AF"
71
- keyboardType="email-address"
72
- autoCapitalize="none"
73
- />
74
-
75
- <TextInput
76
- className="mb-4 p-4 rounded-md bg-input text-foreground border border-input"
77
- placeholder="Password"
78
- value={password}
79
- onChangeText={setPassword}
80
- placeholderTextColor="#9CA3AF"
81
- secureTextEntry
82
- />
83
-
84
- <TouchableOpacity
85
- onPress={handleSignUp}
86
- disabled={isLoading}
87
- className="bg-primary p-4 rounded-md flex-row justify-center items-center"
88
- >
89
- {isLoading ? (
90
- <ActivityIndicator size="small" color="#fff" />
91
- ) : (
92
- <Text className="text-primary-foreground font-medium">Sign Up</Text>
93
- )}
94
- </TouchableOpacity>
95
- </View>
96
- );
97
- }