create-better-t-stack 3.6.0 → 3.6.2
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 +2 -0
- package/dist/index.js +1 -1
- package/dist/{src-CWiiwWrU.js → src-D7BpMan5.js} +32 -11
- package/package.json +1 -1
- package/templates/frontend/native/uniwind/app/(drawer)/index.tsx.hbs +98 -102
- package/templates/frontend/native/uniwind/package.json.hbs +7 -7
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -126,6 +126,7 @@ declare const TemplateSchema: z.ZodEnum<{
|
|
|
126
126
|
mern: "mern";
|
|
127
127
|
pern: "pern";
|
|
128
128
|
t3: "t3";
|
|
129
|
+
uniwind: "uniwind";
|
|
129
130
|
none: "none";
|
|
130
131
|
}>;
|
|
131
132
|
type Template = z.infer<typeof TemplateSchema>;
|
|
@@ -221,6 +222,7 @@ declare const router: {
|
|
|
221
222
|
mern: "mern";
|
|
222
223
|
pern: "pern";
|
|
223
224
|
t3: "t3";
|
|
225
|
+
uniwind: "uniwind";
|
|
224
226
|
none: "none";
|
|
225
227
|
}>>;
|
|
226
228
|
yes: z$1.ZodDefault<z$1.ZodOptional<z$1.ZodBoolean>>;
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as router, i as init, n as createBtsCli, o as sponsors, r as docs, t as builder } from "./src-
|
|
2
|
+
import { a as router, i as init, n as createBtsCli, o as sponsors, r as docs, t as builder } from "./src-D7BpMan5.js";
|
|
3
3
|
|
|
4
4
|
export { builder, createBtsCli, docs, init, router, sponsors };
|
|
@@ -295,6 +295,7 @@ const TemplateSchema = z.enum([
|
|
|
295
295
|
"mern",
|
|
296
296
|
"pern",
|
|
297
297
|
"t3",
|
|
298
|
+
"uniwind",
|
|
298
299
|
"none"
|
|
299
300
|
]).describe("Predefined project template");
|
|
300
301
|
|
|
@@ -1632,6 +1633,21 @@ const TEMPLATE_PRESETS = {
|
|
|
1632
1633
|
webDeploy: "none",
|
|
1633
1634
|
serverDeploy: "none"
|
|
1634
1635
|
},
|
|
1636
|
+
uniwind: {
|
|
1637
|
+
database: "none",
|
|
1638
|
+
orm: "none",
|
|
1639
|
+
backend: "none",
|
|
1640
|
+
runtime: "none",
|
|
1641
|
+
frontend: ["native-uniwind"],
|
|
1642
|
+
api: "none",
|
|
1643
|
+
auth: "none",
|
|
1644
|
+
payments: "none",
|
|
1645
|
+
addons: ["none"],
|
|
1646
|
+
examples: ["none"],
|
|
1647
|
+
dbSetup: "none",
|
|
1648
|
+
webDeploy: "none",
|
|
1649
|
+
serverDeploy: "none"
|
|
1650
|
+
},
|
|
1635
1651
|
none: null
|
|
1636
1652
|
};
|
|
1637
1653
|
function getTemplateConfig(template) {
|
|
@@ -1645,6 +1661,7 @@ function getTemplateDescription(template) {
|
|
|
1645
1661
|
mern: "MongoDB + Express + React + Node.js - Classic MERN stack",
|
|
1646
1662
|
pern: "PostgreSQL + Express + React + Node.js - Popular PERN stack",
|
|
1647
1663
|
t3: "T3 Stack - Next.js + tRPC + Prisma + PostgreSQL + Better Auth",
|
|
1664
|
+
uniwind: "Expo + Uniwind native app with no backend services",
|
|
1648
1665
|
none: "No template - Full customization"
|
|
1649
1666
|
}[template] || "";
|
|
1650
1667
|
}
|
|
@@ -5729,6 +5746,7 @@ async function setupDatabase(config, cliInput) {
|
|
|
5729
5746
|
const s = spinner();
|
|
5730
5747
|
const dbPackageDir = path.join(projectDir, "packages/db");
|
|
5731
5748
|
const webDir = path.join(projectDir, "apps/web");
|
|
5749
|
+
const webDirExists = await fs.pathExists(webDir);
|
|
5732
5750
|
if (!await fs.pathExists(dbPackageDir)) return;
|
|
5733
5751
|
try {
|
|
5734
5752
|
if (orm === "prisma") {
|
|
@@ -5777,7 +5795,7 @@ async function setupDatabase(config, cliInput) {
|
|
|
5777
5795
|
devDependencies: ["drizzle-kit"],
|
|
5778
5796
|
projectDir: dbPackageDir
|
|
5779
5797
|
});
|
|
5780
|
-
await addPackageDependency({
|
|
5798
|
+
if (webDirExists) await addPackageDependency({
|
|
5781
5799
|
dependencies: ["@libsql/client", "libsql"],
|
|
5782
5800
|
projectDir: webDir
|
|
5783
5801
|
});
|
|
@@ -6325,7 +6343,7 @@ async function displayPostInstallInstructions(config) {
|
|
|
6325
6343
|
const databaseInstructions = !isConvex && database !== "none" ? await getDatabaseInstructions(database, orm, runCmd, runtime, dbSetup, serverDeploy, backend) : "";
|
|
6326
6344
|
const tauriInstructions = addons?.includes("tauri") ? getTauriInstructions(runCmd) : "";
|
|
6327
6345
|
const lintingInstructions = hasHuskyOrBiome ? getLintingInstructions(runCmd) : "";
|
|
6328
|
-
const nativeInstructions = frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles") ? getNativeInstructions(isConvex, isBackendSelf, frontend || []) : "";
|
|
6346
|
+
const nativeInstructions = (frontend?.includes("native-bare") || frontend?.includes("native-uniwind") || frontend?.includes("native-unistyles")) && backend !== "none" ? getNativeInstructions(isConvex, isBackendSelf, frontend || []) : "";
|
|
6329
6347
|
const pwaInstructions = addons?.includes("pwa") && frontend?.includes("react-router") ? getPwaInstructions() : "";
|
|
6330
6348
|
const starlightInstructions = addons?.includes("starlight") ? getStarlightInstructions(runCmd) : "";
|
|
6331
6349
|
const clerkInstructions = isConvex && config.auth === "clerk" ? getClerkInstructions() : "";
|
|
@@ -6362,16 +6380,19 @@ async function displayPostInstallInstructions(config) {
|
|
|
6362
6380
|
output += `${pc.cyan(`${stepCounter++}.`)} ${runCmd} dev\n`;
|
|
6363
6381
|
}
|
|
6364
6382
|
}
|
|
6365
|
-
|
|
6366
|
-
if (hasWeb
|
|
6367
|
-
|
|
6368
|
-
|
|
6369
|
-
output += `${pc.
|
|
6370
|
-
if (
|
|
6383
|
+
const hasStandaloneBackend = backend !== "none";
|
|
6384
|
+
if (hasWeb || hasStandaloneBackend || addons?.includes("starlight") || addons?.includes("fumadocs")) {
|
|
6385
|
+
output += `${pc.bold("Your project will be available at:")}\n`;
|
|
6386
|
+
if (hasWeb) output += `${pc.cyan("•")} Frontend: http://localhost:${webPort}\n`;
|
|
6387
|
+
else if (!hasNative && !addons?.includes("starlight")) output += `${pc.yellow("NOTE:")} You are creating a backend-only app\n (no frontend selected)\n`;
|
|
6388
|
+
if (!isConvex && !isBackendSelf && hasStandaloneBackend) {
|
|
6389
|
+
output += `${pc.cyan("•")} Backend API: http://localhost:3000\n`;
|
|
6390
|
+
if (api === "orpc") output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:3000/api-reference\n`;
|
|
6391
|
+
}
|
|
6392
|
+
if (isBackendSelf && api === "orpc") output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:${webPort}/api/rpc/api-reference\n`;
|
|
6393
|
+
if (addons?.includes("starlight")) output += `${pc.cyan("•")} Docs: http://localhost:4321\n`;
|
|
6394
|
+
if (addons?.includes("fumadocs")) output += `${pc.cyan("•")} Fumadocs: http://localhost:4000\n`;
|
|
6371
6395
|
}
|
|
6372
|
-
if (isBackendSelf && api === "orpc") output += `${pc.cyan("•")} OpenAPI (Scalar UI): http://localhost:${webPort}/api/rpc/api-reference\n`;
|
|
6373
|
-
if (addons?.includes("starlight")) output += `${pc.cyan("•")} Docs: http://localhost:4321\n`;
|
|
6374
|
-
if (addons?.includes("fumadocs")) output += `${pc.cyan("•")} Fumadocs: http://localhost:4000\n`;
|
|
6375
6396
|
if (nativeInstructions) output += `\n${nativeInstructions.trim()}\n`;
|
|
6376
6397
|
if (databaseInstructions) output += `\n${databaseInstructions.trim()}\n`;
|
|
6377
6398
|
if (tauriInstructions) output += `\n${tauriInstructions.trim()}\n`;
|
package/package.json
CHANGED
|
@@ -24,128 +24,124 @@ import { SignUp } from "@/components/sign-up";
|
|
|
24
24
|
import { useQuery } from "convex/react";
|
|
25
25
|
import { api } from "@{{projectName}}/backend/convex/_generated/api";
|
|
26
26
|
{{/if}}
|
|
27
|
+
{{#unless (eq backend "none")}}
|
|
27
28
|
import { Ionicons } from "@expo/vector-icons";
|
|
29
|
+
{{/unless}}
|
|
28
30
|
import { Card, Chip, useThemeColor } from "heroui-native";
|
|
29
31
|
|
|
30
32
|
export default function Home() {
|
|
31
33
|
{{#if (eq api "orpc")}}
|
|
32
|
-
|
|
34
|
+
const healthCheck = useQuery(orpc.healthCheck.queryOptions());
|
|
33
35
|
{{/if}}
|
|
34
36
|
{{#if (eq api "trpc")}}
|
|
35
|
-
|
|
37
|
+
const healthCheck = useQuery(trpc.healthCheck.queryOptions());
|
|
36
38
|
{{/if}}
|
|
37
39
|
{{#if (and (eq backend "convex") (eq auth "clerk"))}}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
40
|
+
const { user } = useUser();
|
|
41
|
+
const healthCheck = useQuery(api.healthCheck.get);
|
|
42
|
+
const privateData = useQuery(api.privateData.get);
|
|
41
43
|
{{else if (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
const healthCheck = useQuery(api.healthCheck.get);
|
|
45
|
+
const { isAuthenticated } = useConvexAuth();
|
|
46
|
+
const user = useQuery(api.auth.getCurrentUser, isAuthenticated ? {} : "skip");
|
|
45
47
|
{{else if (eq backend "convex")}}
|
|
46
|
-
|
|
48
|
+
const healthCheck = useQuery(api.healthCheck.get);
|
|
47
49
|
{{/if}}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
50
|
+
{{#unless (eq backend "none")}}
|
|
51
|
+
const mutedColor = useThemeColor("muted");
|
|
52
|
+
const successColor = useThemeColor("success");
|
|
53
|
+
const dangerColor = useThemeColor("danger");
|
|
51
54
|
|
|
52
55
|
{{#if (eq backend "convex")}}
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
const isConnected = healthCheck === "OK";
|
|
57
|
+
const isLoading = healthCheck === undefined;
|
|
55
58
|
{{else}}
|
|
56
59
|
{{#unless (eq api "none")}}
|
|
57
|
-
|
|
58
|
-
|
|
60
|
+
const isConnected = healthCheck?.data === "OK";
|
|
61
|
+
const isLoading = healthCheck?.isLoading;
|
|
59
62
|
{{/unless}}
|
|
60
63
|
{{/if}}
|
|
64
|
+
{{/unless}}
|
|
61
65
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
{{#unless (and (eq backend "convex") (eq auth "better-auth"))}}
|
|
71
|
-
<Card variant="secondary" className="p-6">
|
|
72
|
-
<View className="flex-row items-center justify-between mb-4">
|
|
73
|
-
<Card.Title>System Status</Card.Title>
|
|
74
|
-
<Chip
|
|
75
|
-
variant="secondary"
|
|
76
|
-
color={isConnected ? "success" : "danger"}
|
|
77
|
-
size="sm"
|
|
78
|
-
>
|
|
79
|
-
<Chip.Label>
|
|
80
|
-
{isConnected ? "LIVE" : "OFFLINE"}
|
|
81
|
-
</Chip.Label>
|
|
82
|
-
</Chip>
|
|
83
|
-
</View>
|
|
84
|
-
<Card className="p-4">
|
|
85
|
-
<View className="flex-row items-center">
|
|
86
|
-
<View
|
|
87
|
-
className={`w-3 h-3 rounded-full mr-3 ${
|
|
88
|
-
isConnected ? "bg-success" : "bg-muted"
|
|
89
|
-
}`}
|
|
90
|
-
/>
|
|
91
|
-
<View className="flex-1">
|
|
92
|
-
<Text className="text-foreground font-medium mb-1">
|
|
93
|
-
{{#if (eq backend "convex")}}
|
|
94
|
-
Convex Backend
|
|
95
|
-
{{else}}
|
|
96
|
-
{{#unless (eq api "none")}}
|
|
97
|
-
{{#if (eq api "orpc")}}ORPC{{else}}TRPC{{/if}} Backend
|
|
98
|
-
{{/unless}}
|
|
99
|
-
{{/if}}
|
|
100
|
-
</Text>
|
|
101
|
-
<Card.Description>
|
|
102
|
-
{isLoading
|
|
103
|
-
? "Checking connection..."
|
|
104
|
-
: isConnected
|
|
105
|
-
? "Connected to API"
|
|
106
|
-
: "API Disconnected"}
|
|
107
|
-
</Card.Description>
|
|
108
|
-
</View>
|
|
109
|
-
{isLoading && (
|
|
110
|
-
<Ionicons name="hourglass-outline" size={20} color={mutedColor} />
|
|
111
|
-
)}
|
|
112
|
-
{!isLoading && isConnected && (
|
|
113
|
-
<Ionicons name="checkmark-circle" size={20} color={successColor} />
|
|
114
|
-
)}
|
|
115
|
-
{!isLoading && !isConnected && (
|
|
116
|
-
<Ionicons name="close-circle" size={20} color={dangerColor} />
|
|
117
|
-
)}
|
|
118
|
-
</View>
|
|
119
|
-
</Card>
|
|
120
|
-
</Card>
|
|
121
|
-
{{/unless}}
|
|
66
|
+
return (
|
|
67
|
+
<Container className="p-6">
|
|
68
|
+
<View className="py-4 mb-6">
|
|
69
|
+
<Text className="text-4xl font-bold text-foreground mb-2">
|
|
70
|
+
BETTER T STACK
|
|
71
|
+
</Text>
|
|
72
|
+
</View>
|
|
122
73
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
74
|
+
{{#unless (or (eq backend "none") (and (eq backend "convex") (eq auth "better-auth")))}}
|
|
75
|
+
<Card variant="secondary" className="p-6">
|
|
76
|
+
<View className="flex-row items-center justify-between mb-4">
|
|
77
|
+
<Card.Title>System Status</Card.Title>
|
|
78
|
+
<Chip variant="secondary" color={isConnected ? "success" : "danger" } size="sm">
|
|
79
|
+
<Chip.Label>
|
|
80
|
+
{isConnected ? "LIVE" : "OFFLINE"}
|
|
81
|
+
</Chip.Label>
|
|
82
|
+
</Chip>
|
|
83
|
+
</View>
|
|
84
|
+
<Card className="p-4">
|
|
85
|
+
<View className="flex-row items-center">
|
|
86
|
+
<View className={`w-3 h-3 rounded-full mr-3 ${ isConnected ? "bg-success" : "bg-muted" }`} />
|
|
87
|
+
<View className="flex-1">
|
|
88
|
+
<Text className="text-foreground font-medium mb-1">
|
|
89
|
+
{{#if (eq backend "convex")}}
|
|
90
|
+
Convex Backend
|
|
91
|
+
{{else}}
|
|
92
|
+
{{#unless (eq api "none")}}
|
|
93
|
+
{{#if (eq api "orpc")}}ORPC{{else}}TRPC{{/if}} Backend
|
|
94
|
+
{{/unless}}
|
|
95
|
+
{{/if}}
|
|
131
96
|
</Text>
|
|
132
|
-
<
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
</Link>
|
|
140
|
-
<Link href="/(auth)/sign-up" asChild>
|
|
141
|
-
<Text className="text-primary font-semibold">Sign up</Text>
|
|
142
|
-
</Link>
|
|
97
|
+
<Card.Description>
|
|
98
|
+
{isLoading
|
|
99
|
+
? "Checking connection..."
|
|
100
|
+
: isConnected
|
|
101
|
+
? "Connected to API"
|
|
102
|
+
: "API Disconnected"}
|
|
103
|
+
</Card.Description>
|
|
143
104
|
</View>
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
105
|
+
{isLoading && (
|
|
106
|
+
<Ionicons name="hourglass-outline" size={20} color={mutedColor} />
|
|
107
|
+
)}
|
|
108
|
+
{!isLoading && isConnected && (
|
|
109
|
+
<Ionicons name="checkmark-circle" size={20} color={successColor} />
|
|
110
|
+
)}
|
|
111
|
+
{!isLoading && !isConnected && (
|
|
112
|
+
<Ionicons name="close-circle" size={20} color={dangerColor} />
|
|
113
|
+
)}
|
|
114
|
+
</View>
|
|
115
|
+
</Card>
|
|
116
|
+
</Card>
|
|
117
|
+
{{/unless}}
|
|
118
|
+
|
|
119
|
+
{{#if (and (eq backend "convex") (eq auth "clerk"))}}
|
|
120
|
+
<Authenticated>
|
|
121
|
+
<Card variant="secondary" className="mt-6 p-4">
|
|
122
|
+
<Text className="text-foreground text-base mb-2">
|
|
123
|
+
Hello {user?.emailAddresses[0].emailAddress}
|
|
124
|
+
</Text>
|
|
125
|
+
<Text className="text-muted text-sm mb-4">
|
|
126
|
+
Private Data: {privateData?.message}
|
|
127
|
+
</Text>
|
|
128
|
+
<SignOutButton />
|
|
129
|
+
</Card>
|
|
130
|
+
</Authenticated>
|
|
131
|
+
<Unauthenticated>
|
|
132
|
+
<View className="mt-6 gap-4">
|
|
133
|
+
<Link href="/(auth)/sign-in" asChild>
|
|
134
|
+
<Text className="text-primary font-semibold">Sign in</Text>
|
|
135
|
+
</Link>
|
|
136
|
+
<Link href="/(auth)/sign-up" asChild>
|
|
137
|
+
<Text className="text-primary font-semibold">Sign up</Text>
|
|
138
|
+
</Link>
|
|
139
|
+
</View>
|
|
140
|
+
</Unauthenticated>
|
|
141
|
+
<AuthLoading>
|
|
142
|
+
<Text className="text-muted">Loading...</Text>
|
|
143
|
+
</AuthLoading>
|
|
144
|
+
{{/if}}
|
|
145
|
+
</Container>
|
|
146
|
+
);
|
|
151
147
|
}
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@expo/metro-runtime": "~6.1.2",
|
|
15
15
|
"@expo/vector-icons": "^15.0.3",
|
|
16
|
-
"@gorhom/bottom-sheet": "^5",
|
|
16
|
+
"@gorhom/bottom-sheet": "^5.2.6",
|
|
17
17
|
"@react-navigation/drawer": "^7.3.9",
|
|
18
18
|
"@react-navigation/elements": "^2.8.1",
|
|
19
19
|
{{#if (includes examples "ai")}}
|
|
@@ -29,22 +29,22 @@
|
|
|
29
29
|
"expo-router": "~6.0.14",
|
|
30
30
|
"expo-secure-store": "~15.0.7",
|
|
31
31
|
"expo-status-bar": "~3.0.8",
|
|
32
|
-
"heroui-native": "
|
|
32
|
+
"heroui-native": "1.0.0-beta.3",
|
|
33
33
|
"react": "19.1.0",
|
|
34
34
|
"react-dom": "19.1.0",
|
|
35
35
|
"react-native": "0.81.5",
|
|
36
36
|
"react-native-gesture-handler": "~2.28.0",
|
|
37
37
|
"react-native-keyboard-controller": "1.18.5",
|
|
38
|
-
"react-native-reanimated": "~4.1.
|
|
38
|
+
"react-native-reanimated": "~4.1.5",
|
|
39
39
|
"react-native-safe-area-context": "5.6.0",
|
|
40
40
|
"react-native-screens": "~4.16.0",
|
|
41
41
|
"react-native-svg": "15.12.1",
|
|
42
42
|
"react-native-web": "^0.21.0",
|
|
43
43
|
"react-native-worklets": "0.5.1",
|
|
44
|
-
"tailwind-merge": "^3.
|
|
45
|
-
"tailwind-variants": "
|
|
46
|
-
"tailwindcss": "~4.1.
|
|
47
|
-
"uniwind": "^1.0.
|
|
44
|
+
"tailwind-merge": "^3.4.0",
|
|
45
|
+
"tailwind-variants": "3.1.1",
|
|
46
|
+
"tailwindcss": "~4.1.17",
|
|
47
|
+
"uniwind": "^1.0.4"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@types/node": "^24.10.0",
|