@idealyst/cli 1.0.45 → 1.0.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.
- package/dist/generators/fullstack.js +61 -3
- package/dist/generators/fullstack.js.map +1 -1
- package/dist/generators/native.js +12 -0
- package/dist/generators/native.js.map +1 -1
- package/dist/generators/utils.js +64 -31
- package/dist/generators/utils.js.map +1 -1
- package/dist/templates/api/README.md +207 -130
- package/dist/templates/api/package.json +5 -5
- package/dist/templates/api/src/controllers/TestController.ts +0 -0
- package/dist/templates/api/src/index.ts +2 -7
- package/dist/templates/api/src/lib/crud.ts +150 -0
- package/dist/templates/api/src/lib/database.ts +23 -0
- package/dist/templates/api/src/router/index.ts +104 -71
- package/dist/templates/api/src/routers/test.ts +59 -0
- package/dist/templates/api/src/routers/user.example.ts +83 -0
- package/dist/templates/api/src/server.ts +1 -1
- package/dist/templates/api/tsconfig.json +0 -1
- package/dist/templates/database/README.md +115 -1
- package/dist/templates/database/package.json +2 -0
- package/dist/templates/database/prisma/seed.ts +37 -1
- package/dist/templates/database/schema.prisma +11 -1
- package/dist/templates/native/index.js +1 -1
- package/dist/templates/native/metro.config.js +1 -1
- package/dist/templates/native/package.json +4 -0
- package/dist/templates/native/src/App.tsx +16 -0
- package/dist/templates/native/src/utils/trpc.ts +7 -127
- package/dist/templates/native/tsconfig.json +0 -2
- package/dist/templates/shared/README.md +31 -5
- package/dist/templates/shared/__tests__/shared.test.ts +17 -5
- package/dist/templates/shared/package.json +14 -30
- package/dist/templates/shared/src/components/App.tsx +57 -0
- package/dist/templates/shared/src/components/HelloWorld.tsx +307 -0
- package/dist/templates/shared/src/components/index.ts +1 -392
- package/dist/templates/shared/src/index.ts +9 -57
- package/dist/templates/shared/src/trpc/client.ts +39 -0
- package/dist/templates/shared/tsconfig.json +4 -7
- package/dist/templates/web/README.md +65 -8
- package/dist/templates/web/package.json +3 -3
- package/dist/templates/web/src/App-with-trpc-and-shared.tsx +11 -299
- package/dist/templates/web/src/components/TestDemo.tsx +164 -0
- package/dist/templates/web/src/utils/trpc.ts +7 -93
- package/dist/templates/web/tsconfig.json +0 -1
- package/dist/templates/workspace/.devcontainer/devcontainer.json +4 -9
- package/dist/templates/workspace/.devcontainer/docker-compose.yml +1 -2
- package/dist/templates/workspace/.devcontainer/setup.sh +1 -1
- package/dist/templates/workspace/.env.example +1 -1
- package/dist/templates/workspace/Dockerfile +4 -4
- package/dist/templates/workspace/docker/nginx/prod.conf +2 -2
- package/dist/templates/workspace/docker/nginx.conf +1 -1
- package/dist/templates/workspace/docker/prometheus/prometheus.yml +1 -1
- package/dist/templates/workspace/docker-compose.yml +4 -5
- package/dist/templates/workspace/tsconfig.json +0 -1
- package/package.json +1 -1
- package/templates/api/README.md +207 -130
- package/templates/api/package.json +5 -5
- package/templates/api/src/controllers/TestController.ts +0 -0
- package/templates/api/src/index.ts +2 -7
- package/templates/api/src/lib/crud.ts +150 -0
- package/templates/api/src/lib/database.ts +23 -0
- package/templates/api/src/router/index.ts +104 -71
- package/templates/api/src/routers/test.ts +59 -0
- package/templates/api/src/routers/user.example.ts +83 -0
- package/templates/api/src/server.ts +1 -1
- package/templates/api/tsconfig.json +0 -1
- package/templates/database/README.md +115 -1
- package/templates/database/package.json +2 -0
- package/templates/database/prisma/seed.ts +37 -1
- package/templates/database/schema.prisma +11 -1
- package/templates/native/index.js +1 -1
- package/templates/native/metro.config.js +1 -1
- package/templates/native/package.json +4 -0
- package/templates/native/src/App.tsx +16 -0
- package/templates/native/src/utils/trpc.ts +7 -127
- package/templates/native/tsconfig.json +0 -2
- package/templates/shared/README.md +31 -5
- package/templates/shared/__tests__/shared.test.ts +17 -5
- package/templates/shared/package.json +14 -30
- package/templates/shared/src/components/App.tsx +57 -0
- package/templates/shared/src/components/HelloWorld.tsx +307 -0
- package/templates/shared/src/components/index.ts +1 -392
- package/templates/shared/src/index.ts +9 -57
- package/templates/shared/src/trpc/client.ts +39 -0
- package/templates/shared/tsconfig.json +4 -7
- package/templates/web/README.md +65 -8
- package/templates/web/package.json +3 -3
- package/templates/web/src/App-with-trpc-and-shared.tsx +11 -299
- package/templates/web/src/components/TestDemo.tsx +164 -0
- package/templates/web/src/utils/trpc.ts +7 -93
- package/templates/web/tsconfig.json +0 -1
- package/templates/workspace/.devcontainer/devcontainer.json +4 -9
- package/templates/workspace/.devcontainer/docker-compose.yml +1 -2
- package/templates/workspace/.devcontainer/setup.sh +1 -1
- package/templates/workspace/.env.example +1 -1
- package/templates/workspace/Dockerfile +4 -4
- package/templates/workspace/docker/nginx/prod.conf +2 -2
- package/templates/workspace/docker/nginx.conf +1 -1
- package/templates/workspace/docker/prometheus/prometheus.yml +1 -1
- package/templates/workspace/docker-compose.yml +4 -5
- package/templates/workspace/tsconfig.json +0 -1
- package/dist/templates/api/src/controllers/UserController.ts +0 -102
- package/dist/templates/api/src/lib/controller.ts +0 -90
- package/dist/templates/api/src/lib/middleware.ts +0 -170
- package/dist/templates/api/src/middleware/auth.ts +0 -75
- package/dist/templates/api/src/middleware/common.ts +0 -103
- package/dist/templates/database/.env.example +0 -1
- package/dist/templates/native/App.tsx +0 -23
- package/dist/templates/native/src/App-with-trpc-and-shared.tsx +0 -266
- package/dist/templates/shared/rollup.config.js +0 -43
- package/dist/templates/shared/src/types/index.ts +0 -148
- package/dist/templates/shared/src/utils/index.ts +0 -278
- package/templates/api/src/controllers/UserController.ts +0 -102
- package/templates/api/src/lib/controller.ts +0 -90
- package/templates/api/src/lib/middleware.ts +0 -170
- package/templates/api/src/middleware/auth.ts +0 -75
- package/templates/api/src/middleware/common.ts +0 -103
- package/templates/database/.env.example +0 -1
- package/templates/native/App.tsx +0 -23
- package/templates/native/src/App-with-trpc-and-shared.tsx +0 -266
- package/templates/shared/rollup.config.js +0 -43
- package/templates/shared/src/types/index.ts +0 -148
- package/templates/shared/src/utils/index.ts +0 -278
|
@@ -1,392 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import { View, Text, Button, Image } from '@idealyst/components';
|
|
3
|
-
import type { User, Post, Comment } from '../types';
|
|
4
|
-
|
|
5
|
-
interface UserCardProps {
|
|
6
|
-
user: User;
|
|
7
|
-
onPress?: () => void;
|
|
8
|
-
showBio?: boolean;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const UserCard: React.FC<UserCardProps> = ({
|
|
12
|
-
user,
|
|
13
|
-
onPress,
|
|
14
|
-
showBio = false
|
|
15
|
-
}) => {
|
|
16
|
-
return (
|
|
17
|
-
<View
|
|
18
|
-
style={{
|
|
19
|
-
padding: 16,
|
|
20
|
-
borderRadius: 8,
|
|
21
|
-
backgroundColor: 'white',
|
|
22
|
-
shadowColor: '#000',
|
|
23
|
-
shadowOffset: { width: 0, height: 2 },
|
|
24
|
-
shadowOpacity: 0.1,
|
|
25
|
-
shadowRadius: 4,
|
|
26
|
-
elevation: 2,
|
|
27
|
-
marginBottom: 8
|
|
28
|
-
}}
|
|
29
|
-
>
|
|
30
|
-
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
|
31
|
-
{user.avatar && (
|
|
32
|
-
<Image
|
|
33
|
-
source={{ uri: user.avatar }}
|
|
34
|
-
style={{
|
|
35
|
-
width: 50,
|
|
36
|
-
height: 50,
|
|
37
|
-
borderRadius: 25,
|
|
38
|
-
marginRight: 12
|
|
39
|
-
}}
|
|
40
|
-
/>
|
|
41
|
-
)}
|
|
42
|
-
<View style={{ flex: 1 }}>
|
|
43
|
-
<Text variant="h3" style={{ marginBottom: 4 }}>
|
|
44
|
-
{user.name || 'Anonymous User'}
|
|
45
|
-
</Text>
|
|
46
|
-
<Text variant="caption" style={{ color: 'gray' }}>
|
|
47
|
-
{user.email}
|
|
48
|
-
</Text>
|
|
49
|
-
{user.location && (
|
|
50
|
-
<Text variant="caption" style={{ color: 'gray', marginTop: 2 }}>
|
|
51
|
-
📍 {user.location}
|
|
52
|
-
</Text>
|
|
53
|
-
)}
|
|
54
|
-
</View>
|
|
55
|
-
{onPress && (
|
|
56
|
-
<Button
|
|
57
|
-
title="View Profile"
|
|
58
|
-
onPress={onPress}
|
|
59
|
-
size="small"
|
|
60
|
-
/>
|
|
61
|
-
)}
|
|
62
|
-
</View>
|
|
63
|
-
|
|
64
|
-
{showBio && user.bio && (
|
|
65
|
-
<Text variant="body" style={{ marginTop: 12, fontStyle: 'italic' }}>
|
|
66
|
-
{user.bio}
|
|
67
|
-
</Text>
|
|
68
|
-
)}
|
|
69
|
-
|
|
70
|
-
{user.website && (
|
|
71
|
-
<Text variant="caption" style={{ marginTop: 8, color: 'blue' }}>
|
|
72
|
-
🌐 {user.website}
|
|
73
|
-
</Text>
|
|
74
|
-
)}
|
|
75
|
-
</View>
|
|
76
|
-
);
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
interface PostCardProps {
|
|
80
|
-
post: Post;
|
|
81
|
-
author?: User;
|
|
82
|
-
onPress?: () => void;
|
|
83
|
-
onLike?: () => void;
|
|
84
|
-
showFullContent?: boolean;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export const PostCard: React.FC<PostCardProps> = ({
|
|
88
|
-
post,
|
|
89
|
-
author,
|
|
90
|
-
onPress,
|
|
91
|
-
onLike,
|
|
92
|
-
showFullContent = false
|
|
93
|
-
}) => {
|
|
94
|
-
const content = showFullContent ? post.content : (post.excerpt || post.content.substring(0, 150) + '...');
|
|
95
|
-
|
|
96
|
-
return (
|
|
97
|
-
<View
|
|
98
|
-
style={{
|
|
99
|
-
padding: 16,
|
|
100
|
-
borderRadius: 8,
|
|
101
|
-
backgroundColor: 'white',
|
|
102
|
-
shadowColor: '#000',
|
|
103
|
-
shadowOffset: { width: 0, height: 2 },
|
|
104
|
-
shadowOpacity: 0.1,
|
|
105
|
-
shadowRadius: 4,
|
|
106
|
-
elevation: 2,
|
|
107
|
-
marginBottom: 12
|
|
108
|
-
}}
|
|
109
|
-
>
|
|
110
|
-
{/* Post Header */}
|
|
111
|
-
{author && (
|
|
112
|
-
<View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 12 }}>
|
|
113
|
-
{author.avatar && (
|
|
114
|
-
<Image
|
|
115
|
-
source={{ uri: author.avatar }}
|
|
116
|
-
style={{
|
|
117
|
-
width: 32,
|
|
118
|
-
height: 32,
|
|
119
|
-
borderRadius: 16,
|
|
120
|
-
marginRight: 8
|
|
121
|
-
}}
|
|
122
|
-
/>
|
|
123
|
-
)}
|
|
124
|
-
<View>
|
|
125
|
-
<Text variant="body" style={{ fontWeight: 'bold' }}>
|
|
126
|
-
{author.name || 'Anonymous'}
|
|
127
|
-
</Text>
|
|
128
|
-
<Text variant="caption" style={{ color: 'gray' }}>
|
|
129
|
-
{new Date(post.createdAt).toLocaleDateString()}
|
|
130
|
-
</Text>
|
|
131
|
-
</View>
|
|
132
|
-
</View>
|
|
133
|
-
)}
|
|
134
|
-
|
|
135
|
-
{/* Post Content */}
|
|
136
|
-
<Text variant="h2" style={{ marginBottom: 8 }}>
|
|
137
|
-
{post.title}
|
|
138
|
-
</Text>
|
|
139
|
-
|
|
140
|
-
<Text variant="body" style={{ marginBottom: 12 }}>
|
|
141
|
-
{content}
|
|
142
|
-
</Text>
|
|
143
|
-
|
|
144
|
-
{/* Tags */}
|
|
145
|
-
{post.tags.length > 0 && (
|
|
146
|
-
<View style={{ flexDirection: 'row', flexWrap: 'wrap', marginBottom: 12 }}>
|
|
147
|
-
{post.tags.map((tag, index) => (
|
|
148
|
-
<View
|
|
149
|
-
key={index}
|
|
150
|
-
style={{
|
|
151
|
-
backgroundColor: '#e3f2fd',
|
|
152
|
-
paddingHorizontal: 8,
|
|
153
|
-
paddingVertical: 4,
|
|
154
|
-
borderRadius: 12,
|
|
155
|
-
marginRight: 6,
|
|
156
|
-
marginBottom: 4
|
|
157
|
-
}}
|
|
158
|
-
>
|
|
159
|
-
<Text variant="caption" style={{ color: '#1976d2' }}>
|
|
160
|
-
#{tag}
|
|
161
|
-
</Text>
|
|
162
|
-
</View>
|
|
163
|
-
))}
|
|
164
|
-
</View>
|
|
165
|
-
)}
|
|
166
|
-
|
|
167
|
-
{/* Post Stats and Actions */}
|
|
168
|
-
<View style={{ flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center' }}>
|
|
169
|
-
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
|
|
170
|
-
<Text variant="caption" style={{ color: 'gray', marginRight: 12 }}>
|
|
171
|
-
👁️ {post.views} views
|
|
172
|
-
</Text>
|
|
173
|
-
<Text variant="caption" style={{ color: 'gray' }}>
|
|
174
|
-
❤️ {post.likes} likes
|
|
175
|
-
</Text>
|
|
176
|
-
</View>
|
|
177
|
-
|
|
178
|
-
<View style={{ flexDirection: 'row' }}>
|
|
179
|
-
{onLike && (
|
|
180
|
-
<Button
|
|
181
|
-
title="Like"
|
|
182
|
-
onPress={onLike}
|
|
183
|
-
size="small"
|
|
184
|
-
variant="outline"
|
|
185
|
-
style={{ marginRight: 8 }}
|
|
186
|
-
/>
|
|
187
|
-
)}
|
|
188
|
-
{onPress && (
|
|
189
|
-
<Button
|
|
190
|
-
title="Read More"
|
|
191
|
-
onPress={onPress}
|
|
192
|
-
size="small"
|
|
193
|
-
/>
|
|
194
|
-
)}
|
|
195
|
-
</View>
|
|
196
|
-
</View>
|
|
197
|
-
</View>
|
|
198
|
-
);
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
interface CommentCardProps {
|
|
202
|
-
comment: Comment;
|
|
203
|
-
author?: User;
|
|
204
|
-
onReply?: () => void;
|
|
205
|
-
level?: number;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
export const CommentCard: React.FC<CommentCardProps> = ({
|
|
209
|
-
comment,
|
|
210
|
-
author,
|
|
211
|
-
onReply,
|
|
212
|
-
level = 0
|
|
213
|
-
}) => {
|
|
214
|
-
const indentStyle = {
|
|
215
|
-
marginLeft: level * 20,
|
|
216
|
-
maxWidth: level > 2 ? '90%' : '100%'
|
|
217
|
-
};
|
|
218
|
-
|
|
219
|
-
return (
|
|
220
|
-
<View
|
|
221
|
-
style={[
|
|
222
|
-
{
|
|
223
|
-
padding: 12,
|
|
224
|
-
borderRadius: 6,
|
|
225
|
-
backgroundColor: level === 0 ? 'white' : '#f8f9fa',
|
|
226
|
-
borderLeftWidth: level > 0 ? 3 : 0,
|
|
227
|
-
borderLeftColor: '#e3f2fd',
|
|
228
|
-
marginBottom: 8
|
|
229
|
-
},
|
|
230
|
-
indentStyle
|
|
231
|
-
]}
|
|
232
|
-
>
|
|
233
|
-
{/* Comment Header */}
|
|
234
|
-
{author && (
|
|
235
|
-
<View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 8 }}>
|
|
236
|
-
{author.avatar && (
|
|
237
|
-
<Image
|
|
238
|
-
source={{ uri: author.avatar }}
|
|
239
|
-
style={{
|
|
240
|
-
width: 24,
|
|
241
|
-
height: 24,
|
|
242
|
-
borderRadius: 12,
|
|
243
|
-
marginRight: 6
|
|
244
|
-
}}
|
|
245
|
-
/>
|
|
246
|
-
)}
|
|
247
|
-
<Text variant="body" style={{ fontWeight: 'bold', fontSize: 14 }}>
|
|
248
|
-
{author.name || 'Anonymous'}
|
|
249
|
-
</Text>
|
|
250
|
-
<Text variant="caption" style={{ color: 'gray', marginLeft: 8 }}>
|
|
251
|
-
{new Date(comment.createdAt).toLocaleDateString()}
|
|
252
|
-
</Text>
|
|
253
|
-
</View>
|
|
254
|
-
)}
|
|
255
|
-
|
|
256
|
-
{/* Comment Content */}
|
|
257
|
-
<Text variant="body" style={{ marginBottom: 8 }}>
|
|
258
|
-
{comment.content}
|
|
259
|
-
</Text>
|
|
260
|
-
|
|
261
|
-
{/* Comment Actions */}
|
|
262
|
-
{onReply && level < 3 && (
|
|
263
|
-
<Button
|
|
264
|
-
title="Reply"
|
|
265
|
-
onPress={onReply}
|
|
266
|
-
size="small"
|
|
267
|
-
variant="outline"
|
|
268
|
-
/>
|
|
269
|
-
)}
|
|
270
|
-
</View>
|
|
271
|
-
);
|
|
272
|
-
};
|
|
273
|
-
|
|
274
|
-
interface LoadingSpinnerProps {
|
|
275
|
-
size?: 'small' | 'medium' | 'large';
|
|
276
|
-
message?: string;
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
export const LoadingSpinner: React.FC<LoadingSpinnerProps> = ({
|
|
280
|
-
size = 'medium',
|
|
281
|
-
message
|
|
282
|
-
}) => {
|
|
283
|
-
const sizeMap = {
|
|
284
|
-
small: 20,
|
|
285
|
-
medium: 40,
|
|
286
|
-
large: 60
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
return (
|
|
290
|
-
<View style={{ alignItems: 'center', justifyContent: 'center', padding: 20 }}>
|
|
291
|
-
<View
|
|
292
|
-
style={{
|
|
293
|
-
width: sizeMap[size],
|
|
294
|
-
height: sizeMap[size],
|
|
295
|
-
borderRadius: sizeMap[size] / 2,
|
|
296
|
-
borderWidth: 3,
|
|
297
|
-
borderColor: '#e3f2fd',
|
|
298
|
-
borderTopColor: '#1976d2',
|
|
299
|
-
// Animation would be handled by the platform-specific implementation
|
|
300
|
-
}}
|
|
301
|
-
/>
|
|
302
|
-
{message && (
|
|
303
|
-
<Text variant="body" style={{ marginTop: 12, textAlign: 'center' }}>
|
|
304
|
-
{message}
|
|
305
|
-
</Text>
|
|
306
|
-
)}
|
|
307
|
-
</View>
|
|
308
|
-
);
|
|
309
|
-
};
|
|
310
|
-
|
|
311
|
-
interface ErrorMessageProps {
|
|
312
|
-
message: string;
|
|
313
|
-
onRetry?: () => void;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
export const ErrorMessage: React.FC<ErrorMessageProps> = ({ message, onRetry }) => {
|
|
317
|
-
return (
|
|
318
|
-
<View
|
|
319
|
-
style={{
|
|
320
|
-
padding: 16,
|
|
321
|
-
backgroundColor: '#ffebee',
|
|
322
|
-
borderRadius: 8,
|
|
323
|
-
borderLeftWidth: 4,
|
|
324
|
-
borderLeftColor: '#f44336',
|
|
325
|
-
margin: 16
|
|
326
|
-
}}
|
|
327
|
-
>
|
|
328
|
-
<Text variant="body" style={{ color: '#c62828', marginBottom: onRetry ? 12 : 0 }}>
|
|
329
|
-
⚠️ {message}
|
|
330
|
-
</Text>
|
|
331
|
-
{onRetry && (
|
|
332
|
-
<Button
|
|
333
|
-
title="Try Again"
|
|
334
|
-
onPress={onRetry}
|
|
335
|
-
size="small"
|
|
336
|
-
style={{ backgroundColor: '#f44336' }}
|
|
337
|
-
/>
|
|
338
|
-
)}
|
|
339
|
-
</View>
|
|
340
|
-
);
|
|
341
|
-
};
|
|
342
|
-
|
|
343
|
-
// Feature Card Component - reusable for both web and native
|
|
344
|
-
interface FeatureCardProps {
|
|
345
|
-
icon: string;
|
|
346
|
-
title: string;
|
|
347
|
-
description: string;
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
export const FeatureCard: React.FC<FeatureCardProps> = ({ icon, title, description }) => {
|
|
351
|
-
return (
|
|
352
|
-
<View style={{
|
|
353
|
-
padding: 16,
|
|
354
|
-
backgroundColor: 'white',
|
|
355
|
-
borderRadius: 8,
|
|
356
|
-
shadowColor: '#000',
|
|
357
|
-
shadowOffset: { width: 0, height: 2 },
|
|
358
|
-
shadowOpacity: 0.1,
|
|
359
|
-
shadowRadius: 4,
|
|
360
|
-
elevation: 2,
|
|
361
|
-
marginBottom: 12
|
|
362
|
-
}}>
|
|
363
|
-
<Text style={{ fontSize: 24, marginBottom: 8, textAlign: 'center' }}>{icon}</Text>
|
|
364
|
-
<Text variant="h4" style={{ marginBottom: 8, textAlign: 'center' }}>{title}</Text>
|
|
365
|
-
<Text variant="body" style={{ color: '#666', textAlign: 'center' }}>{description}</Text>
|
|
366
|
-
</View>
|
|
367
|
-
);
|
|
368
|
-
};
|
|
369
|
-
|
|
370
|
-
// Tab Button Component - for navigation tabs in mobile/web apps
|
|
371
|
-
interface TabButtonProps {
|
|
372
|
-
title: string;
|
|
373
|
-
icon: string;
|
|
374
|
-
active: boolean;
|
|
375
|
-
onPress: () => void;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
export const TabButton: React.FC<TabButtonProps> = ({ title, icon, active, onPress }) => {
|
|
379
|
-
return (
|
|
380
|
-
<Button
|
|
381
|
-
title={`${icon} ${title}`}
|
|
382
|
-
onPress={onPress}
|
|
383
|
-
variant={active ? 'primary' : 'outline'}
|
|
384
|
-
style={{
|
|
385
|
-
flex: 1,
|
|
386
|
-
marginHorizontal: 4,
|
|
387
|
-
backgroundColor: active ? '#007bff' : 'transparent',
|
|
388
|
-
borderColor: active ? '#007bff' : '#ccc'
|
|
389
|
-
}}
|
|
390
|
-
/>
|
|
391
|
-
);
|
|
392
|
-
};
|
|
1
|
+
export { App } from './App';
|
|
@@ -1,59 +1,11 @@
|
|
|
1
|
-
// Export
|
|
2
|
-
export
|
|
1
|
+
// Export the unified App component
|
|
2
|
+
export { App } from './components';
|
|
3
3
|
|
|
4
|
-
// Export
|
|
5
|
-
export
|
|
4
|
+
// Export tRPC client utilities
|
|
5
|
+
export { trpc, createTRPCClient, createVanillaTRPCClient } from './trpc/client';
|
|
6
|
+
export type { TRPCClientConfig, AppRouter } from './trpc/client';
|
|
6
7
|
|
|
7
|
-
//
|
|
8
|
-
export
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
export type {
|
|
12
|
-
User,
|
|
13
|
-
Post,
|
|
14
|
-
Comment,
|
|
15
|
-
UserSettings,
|
|
16
|
-
CreateUser,
|
|
17
|
-
CreatePost,
|
|
18
|
-
CreateComment,
|
|
19
|
-
PostWithAuthor,
|
|
20
|
-
CommentWithAuthor,
|
|
21
|
-
ApiResponse,
|
|
22
|
-
PaginatedResponse,
|
|
23
|
-
Theme,
|
|
24
|
-
LoadingState,
|
|
25
|
-
PaginationParams
|
|
26
|
-
} from './types';
|
|
27
|
-
|
|
28
|
-
export {
|
|
29
|
-
UserCard,
|
|
30
|
-
PostCard,
|
|
31
|
-
CommentCard,
|
|
32
|
-
LoadingSpinner,
|
|
33
|
-
ErrorMessage,
|
|
34
|
-
FeatureCard,
|
|
35
|
-
TabButton
|
|
36
|
-
} from './components';
|
|
37
|
-
|
|
38
|
-
export {
|
|
39
|
-
formatDate,
|
|
40
|
-
formatDateTime,
|
|
41
|
-
formatRelativeTime,
|
|
42
|
-
truncateText,
|
|
43
|
-
capitalizeFirst,
|
|
44
|
-
slugify,
|
|
45
|
-
paginate,
|
|
46
|
-
sortBy,
|
|
47
|
-
pick,
|
|
48
|
-
omit,
|
|
49
|
-
isValidEmail,
|
|
50
|
-
isValidUrl,
|
|
51
|
-
storage,
|
|
52
|
-
debounce,
|
|
53
|
-
getSystemTheme,
|
|
54
|
-
getErrorMessage,
|
|
55
|
-
isWeb,
|
|
56
|
-
isMobile,
|
|
57
|
-
DEMO_USERS,
|
|
58
|
-
DEMO_POSTS
|
|
59
|
-
} from './utils';
|
|
8
|
+
// Simple type for the HelloWorld component props
|
|
9
|
+
export interface HelloWorldProps {
|
|
10
|
+
name?: string;
|
|
11
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { createTRPCReact } from '@trpc/react-query';
|
|
2
|
+
import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
|
|
3
|
+
import type { AppRouter } from '@{{workspaceScope}}/api';
|
|
4
|
+
|
|
5
|
+
// Create the tRPC React hooks with full type safety
|
|
6
|
+
export const trpc = createTRPCReact<AppRouter>();
|
|
7
|
+
|
|
8
|
+
// Configuration for tRPC client
|
|
9
|
+
export interface TRPCClientConfig {
|
|
10
|
+
apiUrl: string;
|
|
11
|
+
headers?: () => Record<string, string>;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Create tRPC client factory
|
|
15
|
+
export function createTRPCClient(config: TRPCClientConfig) {
|
|
16
|
+
return trpc.createClient({
|
|
17
|
+
links: [
|
|
18
|
+
httpBatchLink({
|
|
19
|
+
url: config.apiUrl,
|
|
20
|
+
headers: config.headers,
|
|
21
|
+
}),
|
|
22
|
+
],
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Create a vanilla client (for use outside of React components)
|
|
27
|
+
export function createVanillaTRPCClient(config: TRPCClientConfig) {
|
|
28
|
+
return createTRPCProxyClient<AppRouter>({
|
|
29
|
+
links: [
|
|
30
|
+
httpBatchLink({
|
|
31
|
+
url: config.apiUrl,
|
|
32
|
+
headers: config.headers,
|
|
33
|
+
}),
|
|
34
|
+
],
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Export types
|
|
39
|
+
export type { AppRouter } from '@{{workspaceScope}}/api';
|
|
@@ -2,24 +2,21 @@
|
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"target": "ES2020",
|
|
4
4
|
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
5
6
|
"lib": ["ES2020"],
|
|
6
|
-
"moduleResolution": "node",
|
|
7
7
|
"esModuleInterop": true,
|
|
8
8
|
"allowSyntheticDefaultImports": true,
|
|
9
9
|
"strict": true,
|
|
10
10
|
"skipLibCheck": true,
|
|
11
11
|
"forceConsistentCasingInFileNames": true,
|
|
12
12
|
"declaration": true,
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"rootDir": "./src",
|
|
16
|
-
"jsx": "react-jsx"
|
|
13
|
+
"jsx": "react-jsx",
|
|
14
|
+
"noEmit": true
|
|
17
15
|
},
|
|
18
16
|
"include": [
|
|
19
17
|
"src/**/*"
|
|
20
18
|
],
|
|
21
19
|
"exclude": [
|
|
22
|
-
"node_modules"
|
|
23
|
-
"dist"
|
|
20
|
+
"node_modules"
|
|
24
21
|
]
|
|
25
22
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## Getting Started
|
|
6
6
|
|
|
7
|
-
This is a React web application built with the Idealyst Framework and Vite.
|
|
7
|
+
This is a React web application built with the Idealyst Framework and Vite, with full-stack capabilities including database and API integration.
|
|
8
8
|
|
|
9
9
|
### Prerequisites
|
|
10
10
|
|
|
@@ -18,15 +18,53 @@ Install dependencies:
|
|
|
18
18
|
yarn install
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
+
### Database Setup
|
|
22
|
+
|
|
23
|
+
If your project includes a database, set it up:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Navigate to the database package
|
|
27
|
+
cd packages/database
|
|
28
|
+
|
|
29
|
+
# Install dependencies
|
|
30
|
+
yarn install
|
|
31
|
+
|
|
32
|
+
# Generate Prisma client
|
|
33
|
+
yarn prisma:generate
|
|
34
|
+
|
|
35
|
+
# Run database migrations
|
|
36
|
+
yarn prisma:migrate
|
|
37
|
+
|
|
38
|
+
# Seed the database with sample data
|
|
39
|
+
yarn prisma:seed
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### API Setup
|
|
43
|
+
|
|
44
|
+
If your project includes an API, start the API server:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Navigate to the API package
|
|
48
|
+
cd packages/api
|
|
49
|
+
|
|
50
|
+
# Install dependencies
|
|
51
|
+
yarn install
|
|
52
|
+
|
|
53
|
+
# Start the API server (usually on port 3000)
|
|
54
|
+
yarn dev
|
|
55
|
+
```
|
|
56
|
+
|
|
21
57
|
### Development
|
|
22
58
|
|
|
23
|
-
Start the development server:
|
|
59
|
+
Start the web development server:
|
|
24
60
|
```bash
|
|
25
61
|
yarn dev
|
|
26
62
|
```
|
|
27
63
|
|
|
28
64
|
The app will be available at `http://localhost:3000`
|
|
29
65
|
|
|
66
|
+
If you have both database and API packages, make sure to start them first before starting the web app for full functionality.
|
|
67
|
+
|
|
30
68
|
### Building for Production
|
|
31
69
|
|
|
32
70
|
Build the app:
|
|
@@ -43,24 +81,41 @@ yarn preview
|
|
|
43
81
|
|
|
44
82
|
```
|
|
45
83
|
{{projectName}}/
|
|
84
|
+
├── packages/
|
|
85
|
+
│ ├── database/ # Database schema and migrations (if included)
|
|
86
|
+
│ ├── api/ # tRPC API server (if included)
|
|
87
|
+
│ ├── shared/ # Shared components and utilities
|
|
88
|
+
│ └── web/ # React web application
|
|
46
89
|
├── src/
|
|
47
|
-
│ ├── App.tsx
|
|
48
|
-
│
|
|
49
|
-
├──
|
|
50
|
-
|
|
51
|
-
|
|
90
|
+
│ ├── App.tsx # Main app component
|
|
91
|
+
│ ├── main.tsx # App entry point
|
|
92
|
+
│ ├── components/ # React components
|
|
93
|
+
│ └── utils/ # Utility functions and tRPC client
|
|
94
|
+
├── index.html # HTML template
|
|
95
|
+
├── vite.config.ts # Vite configuration
|
|
96
|
+
└── tsconfig.json # TypeScript configuration
|
|
52
97
|
```
|
|
53
98
|
|
|
54
99
|
### Features
|
|
55
100
|
|
|
101
|
+
- **Full-Stack Type Safety**: End-to-end TypeScript from database to frontend
|
|
102
|
+
- **tRPC Integration**: Type-safe API calls with automatic TypeScript inference
|
|
103
|
+
- **Database Integration**: Prisma ORM with SQLite for development
|
|
56
104
|
- **Idealyst Components**: Cross-platform UI components
|
|
57
105
|
- **Idealyst Navigation**: Consistent navigation system
|
|
58
106
|
- **Idealyst Theme**: Unified theming across platforms
|
|
59
107
|
- **React 19.1**: Latest React version
|
|
60
108
|
- **Vite**: Fast build tool and dev server
|
|
61
|
-
- **TypeScript**: Full type safety
|
|
62
109
|
- **React Native Web**: Use React Native components on the web
|
|
63
110
|
|
|
111
|
+
### API Demo
|
|
112
|
+
|
|
113
|
+
If your project includes the API demo, you can access it at `/test-demo` to see:
|
|
114
|
+
- Real-time database queries
|
|
115
|
+
- CRUD operations (Create, Read, Update, Delete)
|
|
116
|
+
- Type-safe tRPC integration
|
|
117
|
+
- Form handling with validation
|
|
118
|
+
|
|
64
119
|
### Development
|
|
65
120
|
|
|
66
121
|
The app uses the Idealyst Framework for consistent UI and navigation that works across web and mobile platforms.
|
|
@@ -86,5 +141,7 @@ const styles = createStyleSheet({
|
|
|
86
141
|
### Learn More
|
|
87
142
|
|
|
88
143
|
- [Idealyst Framework Documentation](https://github.com/your-username/idealyst-framework)
|
|
144
|
+
- [tRPC Documentation](https://trpc.io/)
|
|
145
|
+
- [Prisma Documentation](https://prisma.io/)
|
|
89
146
|
- [React Documentation](https://react.dev/)
|
|
90
147
|
- [Vite Documentation](https://vitejs.dev/)
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"@mdi/react": "^1.6.1",
|
|
21
21
|
"@react-native/normalize-colors": "^0.80.1",
|
|
22
22
|
"@tanstack/react-query": "^5.83.0",
|
|
23
|
-
"@trpc/client": "^11.
|
|
24
|
-
"@trpc/react-query": "^11.
|
|
25
|
-
"@trpc/server": "^11.
|
|
23
|
+
"@trpc/client": "^11.5.1",
|
|
24
|
+
"@trpc/react-query": "^11.5.1",
|
|
25
|
+
"@trpc/server": "^11.5.1",
|
|
26
26
|
"@types/react-router-dom": "^5.3.3",
|
|
27
27
|
"compression": "^1.7.4",
|
|
28
28
|
"express": "^4.18.2",
|