create-croissant 0.1.47 → 0.1.48

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 (47) hide show
  1. package/package.json +1 -1
  2. package/template/apps/platform/src/routes/api/auth/$.ts +1 -1
  3. package/template/apps/platform/src/routes/api/rpc.$.ts +2 -2
  4. package/template/package.json +2 -7
  5. package/template/tsconfig.json +1 -2
  6. package/template/apps/mobile/.vscode/extensions.json +0 -1
  7. package/template/apps/mobile/.vscode/settings.json +0 -7
  8. package/template/apps/mobile/README.md +0 -50
  9. package/template/apps/mobile/app/(tabs)/_layout.tsx +0 -43
  10. package/template/apps/mobile/app/(tabs)/account.tsx +0 -147
  11. package/template/apps/mobile/app/(tabs)/explore.tsx +0 -345
  12. package/template/apps/mobile/app/(tabs)/index.tsx +0 -112
  13. package/template/apps/mobile/app/_layout.tsx +0 -43
  14. package/template/apps/mobile/app/index.tsx +0 -129
  15. package/template/apps/mobile/app/login.tsx +0 -135
  16. package/template/apps/mobile/app/signup.tsx +0 -144
  17. package/template/apps/mobile/app.json +0 -56
  18. package/template/apps/mobile/assets/images/android-icon-background.png +0 -0
  19. package/template/apps/mobile/assets/images/android-icon-foreground.png +0 -0
  20. package/template/apps/mobile/assets/images/android-icon-monochrome.png +0 -0
  21. package/template/apps/mobile/assets/images/favicon.png +0 -0
  22. package/template/apps/mobile/assets/images/icon.png +0 -0
  23. package/template/apps/mobile/assets/images/partial-react-logo.png +0 -0
  24. package/template/apps/mobile/assets/images/react-logo.png +0 -0
  25. package/template/apps/mobile/assets/images/react-logo@2x.png +0 -0
  26. package/template/apps/mobile/assets/images/react-logo@3x.png +0 -0
  27. package/template/apps/mobile/assets/images/splash-icon.png +0 -0
  28. package/template/apps/mobile/components/external-link.tsx +0 -25
  29. package/template/apps/mobile/components/haptic-tab.tsx +0 -18
  30. package/template/apps/mobile/components/hello-wave.tsx +0 -20
  31. package/template/apps/mobile/components/parallax-scroll-view.tsx +0 -81
  32. package/template/apps/mobile/components/themed-text.tsx +0 -60
  33. package/template/apps/mobile/components/themed-view.tsx +0 -14
  34. package/template/apps/mobile/components/ui/button.tsx +0 -86
  35. package/template/apps/mobile/components/ui/collapsible.tsx +0 -46
  36. package/template/apps/mobile/components/ui/icon-symbol.ios.tsx +0 -32
  37. package/template/apps/mobile/components/ui/icon-symbol.tsx +0 -41
  38. package/template/apps/mobile/components/ui/input.tsx +0 -56
  39. package/template/apps/mobile/constants/theme.ts +0 -53
  40. package/template/apps/mobile/hooks/use-color-scheme.ts +0 -1
  41. package/template/apps/mobile/hooks/use-color-scheme.web.ts +0 -21
  42. package/template/apps/mobile/hooks/use-theme-color.ts +0 -21
  43. package/template/apps/mobile/lib/auth-client.ts +0 -14
  44. package/template/apps/mobile/lib/orpc.ts +0 -28
  45. package/template/apps/mobile/package.json +0 -57
  46. package/template/apps/mobile/scripts/reset-project.js +0 -112
  47. package/template/apps/mobile/tsconfig.json +0 -13
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-croissant",
3
- "version": "0.1.47",
3
+ "version": "0.1.48",
4
4
  "description": "Scaffold a new project using the Croissant Stack",
5
5
  "repository": {
6
6
  "type": "git",
@@ -2,7 +2,7 @@ import { auth } from "@workspace/auth/lib/auth";
2
2
  import { createFileRoute } from "@tanstack/react-router";
3
3
 
4
4
  const CORS_HEADERS = {
5
- "Access-Control-Allow-Origin": "http://localhost:8081",
5
+ "Access-Control-Allow-Origin": "*",
6
6
  "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
7
7
  "Access-Control-Allow-Headers": "Content-Type, Authorization",
8
8
  "Access-Control-Allow-Credentials": "true",
@@ -28,7 +28,7 @@ export const Route = createFileRoute("/api/rpc/$")({
28
28
  });
29
29
 
30
30
  if (response) {
31
- response.headers.set("Access-Control-Allow-Origin", "http://localhost:8081");
31
+ response.headers.set("Access-Control-Allow-Origin", "*");
32
32
  response.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
33
33
  response.headers.set("Access-Control-Allow-Headers", "Content-Type, Authorization");
34
34
  response.headers.set("Access-Control-Allow-Credentials", "true");
@@ -40,7 +40,7 @@ export const Route = createFileRoute("/api/rpc/$")({
40
40
  return new Response(null, {
41
41
  status: 204,
42
42
  headers: {
43
- "Access-Control-Allow-Origin": "http://localhost:8081",
43
+ "Access-Control-Allow-Origin": "*",
44
44
  "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS",
45
45
  "Access-Control-Allow-Headers": "Content-Type, Authorization",
46
46
  "Access-Control-Allow-Credentials": "true",
@@ -13,9 +13,6 @@
13
13
  "quality": "turbo quality",
14
14
  "quality:fix": "turbo quality:fix",
15
15
  "typecheck": "turbo typecheck",
16
- "dev:mobile": "turbo run dev --filter=mobile",
17
- "dev:ios": "turbo run dev --filter=mobile -- --ios",
18
- "dev:android": "turbo run dev --filter=mobile -- --android",
19
16
  "ci": "pnpm run lint && pnpm run typecheck && pnpm run build",
20
17
  "db:up": "docker compose up -d",
21
18
  "db:down": "docker compose down",
@@ -25,8 +22,7 @@
25
22
  },
26
23
  "dependencies": {
27
24
  "react": "19.2.5",
28
- "react-dom": "19.2.5",
29
- "react-native": "0.83.6"
25
+ "react-dom": "19.2.5"
30
26
  },
31
27
  "devDependencies": {
32
28
  "@better-auth/core": "^1.6.9",
@@ -46,8 +42,7 @@
46
42
  "@noble/ciphers": "2.2.0",
47
43
  "drizzle-orm": "^0.45.2",
48
44
  "react": "19.2.5",
49
- "react-dom": "19.2.5",
50
- "react-native": "0.83.6"
45
+ "react-dom": "19.2.5"
51
46
  }
52
47
  },
53
48
  "engines": {
@@ -5,6 +5,5 @@
5
5
  "moduleResolution": "bundler",
6
6
  "skipLibCheck": true,
7
7
  "strict": true
8
- },
9
- "extends": "expo/tsconfig.base"
8
+ }
10
9
  }
@@ -1 +0,0 @@
1
- { "recommendations": ["expo.vscode-expo-tools"] }
@@ -1,7 +0,0 @@
1
- {
2
- "editor.codeActionsOnSave": {
3
- "source.fixAll": "explicit",
4
- "source.organizeImports": "explicit",
5
- "source.sortMembers": "explicit"
6
- }
7
- }
@@ -1,50 +0,0 @@
1
- # Welcome to your Expo app 👋
2
-
3
- This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app).
4
-
5
- ## Get started
6
-
7
- 1. Install dependencies
8
-
9
- ```bash
10
- pnpm install
11
- ```
12
-
13
- 2. Start the app
14
-
15
- ```bash
16
- pnpm dlx expo start
17
- ```
18
-
19
- In the output, you'll find options to open the app in a
20
-
21
- - [development build](https://docs.expo.dev/develop/development-builds/introduction/)
22
- - [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/)
23
- - [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/)
24
- - [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo
25
-
26
- You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction).
27
-
28
- ## Get a fresh project
29
-
30
- When you're ready, run:
31
-
32
- ```bash
33
- pnpm run reset-project
34
- ```
35
-
36
- This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing.
37
-
38
- ## Learn more
39
-
40
- To learn more about developing your project with Expo, look at the following resources:
41
-
42
- - [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides).
43
- - [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web.
44
-
45
- ## Join the community
46
-
47
- Join our community of developers creating universal apps.
48
-
49
- - [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute.
50
- - [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions.
@@ -1,43 +0,0 @@
1
- import React from "react";
2
- import { Tabs } from "expo-router";
3
- import { Ionicons } from "@expo/vector-icons";
4
-
5
- export default function TabLayout() {
6
- return (
7
- <Tabs
8
- screenOptions={{
9
- tabBarActiveTintColor: "#000",
10
- tabBarInactiveTintColor: "#888",
11
- headerShown: true,
12
- }}
13
- >
14
- <Tabs.Screen
15
- name="index"
16
- options={{
17
- title: "Dashboard",
18
- tabBarIcon: ({ color, size }) => (
19
- <Ionicons name="home" size={size} color={color} />
20
- ),
21
- }}
22
- />
23
- <Tabs.Screen
24
- name="explore"
25
- options={{
26
- title: "Explore",
27
- tabBarIcon: ({ color, size }) => (
28
- <Ionicons name="planet" size={size} color={color} />
29
- ),
30
- }}
31
- />
32
- <Tabs.Screen
33
- name="account"
34
- options={{
35
- title: "Account",
36
- tabBarIcon: ({ color, size }) => (
37
- <Ionicons name="person" size={size} color={color} />
38
- ),
39
- }}
40
- />
41
- </Tabs>
42
- );
43
- }
@@ -1,147 +0,0 @@
1
- import { useState, useEffect } from "react";
2
- import { View, Text, StyleSheet, ScrollView, Alert, ActivityIndicator } from "react-native";
3
- import { useRouter } from "expo-router";
4
- import { authClient } from "@/lib/auth-client";
5
- import { Button } from "@/components/ui/button";
6
- import { Input } from "@/components/ui/input";
7
-
8
- export default function AccountScreen() {
9
- const router = useRouter();
10
- const { data: session, isPending } = authClient.useSession();
11
- const [updating, setUpdating] = useState(false);
12
-
13
- // Form states
14
- const [name, setName] = useState("");
15
- const [email, setEmail] = useState("");
16
-
17
- useEffect(() => {
18
- if (!isPending && !session) {
19
- router.replace("/login");
20
- return;
21
- }
22
-
23
- if (session) {
24
- setName(session.user.name);
25
- setEmail(session.user.email);
26
- }
27
- }, [session, isPending, router]);
28
-
29
- const handleUpdateProfile = async () => {
30
- if (!name) {
31
- Alert.alert("Error", "Name is required");
32
- return;
33
- }
34
-
35
- setUpdating(true);
36
- try {
37
- const { error } = await authClient.updateUser({
38
- name,
39
- });
40
-
41
- if (error) {
42
- Alert.alert("Error", error.message || "Failed to update profile");
43
- } else {
44
- Alert.alert("Success", "Profile updated successfully");
45
- }
46
- } catch (err) {
47
- Alert.alert("Error", "An unexpected error occurred");
48
- } finally {
49
- setUpdating(false);
50
- }
51
- };
52
-
53
- if (isPending) {
54
- return (
55
- <View style={styles.center}>
56
- <ActivityIndicator size="large" color="#000" />
57
- </View>
58
- );
59
- }
60
-
61
- return (
62
- <ScrollView style={styles.container} contentContainerStyle={styles.content}>
63
- <Text style={styles.title}>Account Settings</Text>
64
-
65
- <View style={styles.section}>
66
- <Text style={styles.sectionTitle}>Profile Information</Text>
67
- <View style={styles.form}>
68
- <Input
69
- label="Name"
70
- value={name}
71
- onChangeText={setName}
72
- placeholder="Your name"
73
- />
74
- <Input
75
- label="Email"
76
- value={email}
77
- editable={false}
78
- style={styles.disabledInput}
79
- />
80
- <Button
81
- onPress={handleUpdateProfile}
82
- loading={updating}
83
- style={styles.button}
84
- >
85
- Update Profile
86
- </Button>
87
- </View>
88
- </View>
89
-
90
- <View style={styles.section}>
91
- <Text style={styles.sectionTitle}>Security</Text>
92
- <Text style={styles.infoText}>
93
- Password management and other security settings are currently available on the web platform.
94
- </Text>
95
- </View>
96
- </ScrollView>
97
- );
98
- }
99
-
100
- const styles = StyleSheet.create({
101
- container: {
102
- flex: 1,
103
- backgroundColor: "#fff",
104
- },
105
- content: {
106
- padding: 24,
107
- },
108
- center: {
109
- flex: 1,
110
- justifyContent: "center",
111
- alignItems: "center",
112
- },
113
- title: {
114
- fontSize: 28,
115
- fontWeight: "bold",
116
- marginBottom: 24,
117
- },
118
- section: {
119
- marginBottom: 32,
120
- },
121
- sectionTitle: {
122
- fontSize: 18,
123
- fontWeight: "600",
124
- marginBottom: 16,
125
- color: "#333",
126
- },
127
- form: {
128
- gap: 16,
129
- },
130
- disabledInput: {
131
- backgroundColor: "#f5f5f5",
132
- color: "#888",
133
- },
134
- button: {
135
- marginTop: 8,
136
- },
137
- infoText: {
138
- fontSize: 14,
139
- color: "#666",
140
- lineHeight: 20,
141
- backgroundColor: "#f9f9f9",
142
- padding: 16,
143
- borderRadius: 8,
144
- borderWidth: 1,
145
- borderColor: "#eee",
146
- },
147
- });
@@ -1,345 +0,0 @@
1
- import { useState } from "react";
2
- import {
3
- Alert,
4
- FlatList,
5
- Modal,
6
- StyleSheet,
7
- Text,
8
- View,
9
- ActivityIndicator,
10
- ScrollView,
11
- } from "react-native";
12
- import { useQueryClient } from "@tanstack/react-query";
13
- import { useForm } from "@tanstack/react-form";
14
- import { z } from "zod";
15
- import { Button } from "@/components/ui/button";
16
- import { Input } from "@/components/ui/input";
17
- import { usePlanets, useCreatePlanet, useUpdatePlanet, useDeletePlanet } from "@workspace/orpc/react";
18
-
19
- const planetSchema = z.object({
20
- name: z.string().min(1, "Name is required"),
21
- description: z.string(),
22
- distance: z.string().refine((val) => !isNaN(parseFloat(val)), {
23
- message: "Must be a number",
24
- }),
25
- diameter: z.string().refine((val) => !isNaN(parseFloat(val)), {
26
- message: "Must be a number",
27
- }),
28
- });
29
-
30
- export default function ExploreScreen() {
31
- const [modalVisible, setModalVisible] = useState(false);
32
- const [editingId, setEditingId] = useState<number | null>(null);
33
-
34
- const { data: planets = [], isLoading } = usePlanets();
35
-
36
- const form = useForm({
37
- defaultValues: {
38
- name: "",
39
- description: "",
40
- distance: "0",
41
- diameter: "0",
42
- },
43
- validators: {
44
- onChange: planetSchema,
45
- },
46
- onSubmit: async ({ value }) => {
47
- const payload = {
48
- name: value.name,
49
- description: value.description || undefined,
50
- distanceFromSun: parseFloat(value.distance) || 0,
51
- diameter: parseFloat(value.diameter) || 0,
52
- hasRings: false,
53
- };
54
- console.log('connard')
55
-
56
- try {
57
- if (editingId) {
58
- await updateMutation.mutateAsync({ id: editingId, ...payload });
59
- } else {
60
- await createMutation.mutateAsync(payload);
61
- }
62
- closeModal();
63
- } catch (err) {
64
- // Error handled in mutation callbacks
65
- }
66
- },
67
- });
68
-
69
- const resetForm = () => {
70
- form.reset();
71
- setEditingId(null);
72
- };
73
-
74
- const createMutation = useCreatePlanet({
75
- onSuccess: () => {
76
- Alert.alert("Success", "Planet added successfully");
77
- },
78
- onError: (err) => {
79
- Alert.alert("Error", err.message || "Failed to add planet");
80
- },
81
- });
82
-
83
- const updateMutation = useUpdatePlanet({
84
- onSuccess: () => {
85
- Alert.alert("Success", "Planet updated successfully");
86
- },
87
- onError: (err) => {
88
- Alert.alert("Error", err.message || "Failed to update planet");
89
- },
90
- });
91
-
92
- const deleteMutation = useDeletePlanet({
93
- onSuccess: () => {
94
- Alert.alert("Success", "Planet deleted successfully");
95
- },
96
- onError: (err) => {
97
- Alert.alert("Error", err.message || "Failed to delete planet");
98
- },
99
- });
100
-
101
- const handleEdit = (planet: any) => {
102
- setEditingId(planet.id);
103
- form.setFieldValue("name", planet.name);
104
- form.setFieldValue("description", planet.description || "");
105
- form.setFieldValue("distance", planet.distanceFromSun.toString());
106
- form.setFieldValue("diameter", planet.diameter.toString());
107
- setModalVisible(true);
108
- };
109
-
110
- const handleDelete = (id: number) => {
111
- deleteMutation.mutateAsync({id})
112
- };
113
-
114
- const closeModal = () => {
115
- setModalVisible(false);
116
- resetForm();
117
- };
118
-
119
- if (isLoading) {
120
- return (
121
- <View style={styles.center}>
122
- <ActivityIndicator size="large" color="#000" />
123
- </View>
124
- );
125
- }
126
-
127
- return (
128
- <View style={styles.container}>
129
- <FlatList
130
- data={planets}
131
- keyExtractor={(item) => item.id.toString()}
132
- contentContainerStyle={styles.listContent}
133
- renderItem={({ item }) => (
134
- <View style={styles.planetCard}>
135
- <View style={styles.planetInfo}>
136
- <Text style={styles.planetName}>{item.name}</Text>
137
- <Text style={styles.planetDesc}>{item.description}</Text>
138
- <Text style={styles.planetDetails}>
139
- Distance: {item.distanceFromSun} AU • Diameter: {item.diameter} km
140
- </Text>
141
- </View>
142
- <View style={styles.actions}>
143
- <Button
144
- variant="outline"
145
- onPress={() => handleEdit(item)}
146
- style={styles.actionBtn}
147
- >
148
- Edit
149
- </Button>
150
- <Button
151
- variant="destructive"
152
- onPress={() => handleDelete(item.id)}
153
- style={styles.actionBtn}
154
- >
155
- Delete
156
- </Button>
157
- </View>
158
- </View>
159
- )}
160
- ListEmptyComponent={
161
- <Text style={styles.emptyText}>No planets found. Add one!</Text>
162
- }
163
- />
164
-
165
- <Button
166
- onPress={() => setModalVisible(true)}
167
- style={styles.fab}
168
- >
169
- Add Planet
170
- </Button>
171
-
172
- <Modal
173
- visible={modalVisible}
174
- animationType="slide"
175
- onRequestClose={closeModal}
176
- >
177
- <View style={styles.modalContainer}>
178
- <ScrollView contentContainerStyle={styles.modalContent}>
179
- <Text style={styles.modalTitle}>
180
- {editingId ? "Edit Planet" : "Add New Planet"}
181
- </Text>
182
-
183
- <form.Field name="name">
184
- {(field: any) => (
185
- <Input
186
- label="Name"
187
- value={field.state.value}
188
- onChangeText={field.handleChange}
189
- placeholder="Earth"
190
- error={field.state.meta.errors?.[0]?.toString()}
191
- />
192
- )}
193
- </form.Field>
194
-
195
- <form.Field name="description">
196
- {(field: any) => (
197
- <Input
198
- label="Description"
199
- value={field.state.value}
200
- onChangeText={field.handleChange}
201
- placeholder="The blue planet"
202
- />
203
- )}
204
- </form.Field>
205
-
206
- <form.Field name="distance">
207
- {(field: any) => (
208
- <Input
209
- label="Distance from Sun (AU)"
210
- value={field.state.value}
211
- onChangeText={field.handleChange}
212
- keyboardType="numeric"
213
- error={field.state.meta.errors?.[0]?.toString()}
214
- />
215
- )}
216
- </form.Field>
217
-
218
- <form.Field name="diameter">
219
- {(field: any) => (
220
- <Input
221
- label="Diameter (km)"
222
- value={field.state.value}
223
- onChangeText={field.handleChange}
224
- keyboardType="numeric"
225
- error={field.state.meta.errors?.[0]?.toString()}
226
- />
227
- )}
228
- </form.Field>
229
-
230
- <View style={styles.modalActions}>
231
- <Button
232
- variant="outline"
233
- onPress={closeModal}
234
- style={styles.modalBtn}
235
- >
236
- Cancel
237
- </Button>
238
- <Button
239
- onPress={form.handleSubmit}
240
- loading={createMutation.isPending || updateMutation.isPending}
241
- style={styles.modalBtn}
242
- >
243
- {editingId ? "Update" : "Create"}
244
- </Button>
245
- </View>
246
- </ScrollView>
247
- </View>
248
- </Modal>
249
- </View>
250
- );
251
- }
252
-
253
- const styles = StyleSheet.create({
254
- container: {
255
- flex: 1,
256
- backgroundColor: "#fff",
257
- },
258
- center: {
259
- flex: 1,
260
- justifyContent: "center",
261
- alignItems: "center",
262
- },
263
- listContent: {
264
- padding: 16,
265
- paddingBottom: 100,
266
- },
267
- planetCard: {
268
- padding: 16,
269
- borderRadius: 12,
270
- borderWidth: 1,
271
- borderColor: "#eee",
272
- marginBottom: 16,
273
- backgroundColor: "#fff",
274
- shadowColor: "#000",
275
- shadowOffset: { width: 0, height: 2 },
276
- shadowOpacity: 0.05,
277
- shadowRadius: 4,
278
- elevation: 2,
279
- },
280
- planetInfo: {
281
- marginBottom: 16,
282
- },
283
- planetName: {
284
- fontSize: 18,
285
- fontWeight: "bold",
286
- marginBottom: 4,
287
- },
288
- planetDesc: {
289
- fontSize: 14,
290
- color: "#666",
291
- marginBottom: 8,
292
- },
293
- planetDetails: {
294
- fontSize: 12,
295
- color: "#999",
296
- },
297
- actions: {
298
- flexDirection: "row",
299
- gap: 8,
300
- },
301
- actionBtn: {
302
- flex: 1,
303
- height: 36,
304
- },
305
- emptyText: {
306
- textAlign: "center",
307
- marginTop: 40,
308
- color: "#999",
309
- fontStyle: "italic",
310
- },
311
- fab: {
312
- position: "absolute",
313
- bottom: 24,
314
- left: 24,
315
- right: 24,
316
- height: 56,
317
- borderRadius: 28,
318
- shadowColor: "#000",
319
- shadowOffset: { width: 0, height: 4 },
320
- shadowOpacity: 0.2,
321
- shadowRadius: 8,
322
- elevation: 5,
323
- },
324
- modalContainer: {
325
- flex: 1,
326
- backgroundColor: "#fff",
327
- },
328
- modalContent: {
329
- padding: 24,
330
- paddingTop: 60,
331
- },
332
- modalTitle: {
333
- fontSize: 24,
334
- fontWeight: "bold",
335
- marginBottom: 32,
336
- },
337
- modalActions: {
338
- flexDirection: "row",
339
- gap: 12,
340
- marginTop: 32,
341
- },
342
- modalBtn: {
343
- flex: 1,
344
- },
345
- });