@idealyst/cli 1.0.45 → 1.0.46
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/templates/native/src/App-with-trpc-and-shared.tsx +4 -258
- package/dist/templates/shared/README.md +31 -5
- package/dist/templates/shared/__tests__/shared.test.ts +17 -5
- package/dist/templates/shared/package.json +7 -28
- package/dist/templates/shared/src/components/HelloWorld.tsx +117 -0
- package/dist/templates/shared/src/components/index.ts +1 -392
- package/dist/templates/shared/src/index.ts +6 -58
- package/dist/templates/shared/tsconfig.json +3 -6
- package/dist/templates/web/src/App-with-trpc-and-shared.tsx +4 -296
- package/package.json +1 -1
- package/templates/native/src/App-with-trpc-and-shared.tsx +4 -258
- package/templates/shared/README.md +31 -5
- package/templates/shared/__tests__/shared.test.ts +17 -5
- package/templates/shared/package.json +7 -28
- package/templates/shared/src/components/HelloWorld.tsx +117 -0
- package/templates/shared/src/components/index.ts +1 -392
- package/templates/shared/src/index.ts +6 -58
- package/templates/shared/tsconfig.json +3 -6
- package/templates/web/src/App-with-trpc-and-shared.tsx +4 -296
- 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/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,303 +1,11 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
3
|
-
import { httpBatchLink } from '@trpc/client';
|
|
4
|
-
import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
|
|
5
|
-
import { trpc } from './utils/trpc';
|
|
6
|
-
import { Screen, Text, View, Button, ScrollView } from '@idealyst/components';
|
|
1
|
+
import React from 'react';
|
|
7
2
|
|
|
8
|
-
// Import shared components
|
|
9
|
-
import {
|
|
10
|
-
UserCard,
|
|
11
|
-
PostCard,
|
|
12
|
-
LoadingSpinner,
|
|
13
|
-
ErrorMessage,
|
|
14
|
-
FeatureCard,
|
|
15
|
-
DEMO_USERS,
|
|
16
|
-
DEMO_POSTS,
|
|
17
|
-
formatRelativeTime,
|
|
18
|
-
type User,
|
|
19
|
-
type Post,
|
|
20
|
-
type PostWithAuthor
|
|
21
|
-
} from '{{workspaceScope}}/shared';
|
|
3
|
+
// Import shared components
|
|
4
|
+
import { HelloWorld } from '@{{workspaceScope}}/shared';
|
|
22
5
|
|
|
23
|
-
// Create tRPC client
|
|
24
|
-
const queryClient = new QueryClient();
|
|
25
|
-
|
|
26
|
-
const trpcClient = trpc.createClient({
|
|
27
|
-
links: [
|
|
28
|
-
httpBatchLink({
|
|
29
|
-
url: 'http://localhost:3001/trpc', // Updated to match API port
|
|
30
|
-
// Optional: Add headers for authentication
|
|
31
|
-
// headers() {
|
|
32
|
-
// return {
|
|
33
|
-
// authorization: getAuthToken(),
|
|
34
|
-
// };
|
|
35
|
-
// },
|
|
36
|
-
}),
|
|
37
|
-
],
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// Navigation Component
|
|
41
|
-
function Navigation() {
|
|
42
|
-
return (
|
|
43
|
-
<View style={{
|
|
44
|
-
flexDirection: 'row',
|
|
45
|
-
padding: 16,
|
|
46
|
-
backgroundColor: '#f8f9fa',
|
|
47
|
-
borderBottomWidth: 1,
|
|
48
|
-
borderBottomColor: '#e9ecef'
|
|
49
|
-
}}>
|
|
50
|
-
<Text variant="h2" style={{ marginRight: 24 }}>{{projectName}}</Text>
|
|
51
|
-
<View style={{ flexDirection: 'row', gap: 16 }}>
|
|
52
|
-
<Link to="/" style={{ textDecoration: 'none' }}>
|
|
53
|
-
<Text style={{ color: '#007bff' }}>Home</Text>
|
|
54
|
-
</Link>
|
|
55
|
-
<Link to="/users" style={{ textDecoration: 'none' }}>
|
|
56
|
-
<Text style={{ color: '#007bff' }}>Users</Text>
|
|
57
|
-
</Link>
|
|
58
|
-
<Link to="/posts" style={{ textDecoration: 'none' }}>
|
|
59
|
-
<Text style={{ color: '#007bff' }}>Posts</Text>
|
|
60
|
-
</Link>
|
|
61
|
-
</View>
|
|
62
|
-
</View>
|
|
63
|
-
);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Home Page Component
|
|
67
|
-
function HomePage() {
|
|
68
|
-
// Example tRPC usage
|
|
69
|
-
const { data: helloData, isLoading: helloLoading, error: helloError } = trpc.hello.useQuery({ name: 'Web User' });
|
|
70
|
-
const { data: usersData, isLoading: usersLoading } = trpc.users.getAll.useQuery();
|
|
71
|
-
const { data: postsData, isLoading: postsLoading } = trpc.posts.getAll.useQuery();
|
|
72
|
-
|
|
73
|
-
return (
|
|
74
|
-
<ScrollView style={{ flex: 1 }}>
|
|
75
|
-
<View style={{ padding: 20 }}>
|
|
76
|
-
{/* Welcome Section */}
|
|
77
|
-
<View style={{ marginBottom: 32, textAlign: 'center' }}>
|
|
78
|
-
<Text variant="h1" style={{ marginBottom: 16 }}>
|
|
79
|
-
Welcome to {{projectName}}! 🚀
|
|
80
|
-
</Text>
|
|
81
|
-
<Text variant="body" style={{ marginBottom: 16, fontSize: 18 }}>
|
|
82
|
-
A full-stack application built with the Idealyst Framework
|
|
83
|
-
</Text>
|
|
84
|
-
|
|
85
|
-
{/* tRPC Connection Test */}
|
|
86
|
-
<View style={{
|
|
87
|
-
padding: 16,
|
|
88
|
-
backgroundColor: '#e3f2fd',
|
|
89
|
-
borderRadius: 8,
|
|
90
|
-
marginBottom: 24
|
|
91
|
-
}}>
|
|
92
|
-
<Text variant="h3" style={{ marginBottom: 8 }}>🔗 API Connection:</Text>
|
|
93
|
-
{helloLoading && <Text>Testing connection...</Text>}
|
|
94
|
-
{helloError && <Text style={{ color: 'red' }}>Error: {helloError.message}</Text>}
|
|
95
|
-
{helloData && <Text style={{ color: 'green' }}>✅ {helloData.greeting}</Text>}
|
|
96
|
-
</View>
|
|
97
|
-
</View>
|
|
98
|
-
|
|
99
|
-
{/* Features Overview */}
|
|
100
|
-
<View style={{ marginBottom: 32 }}>
|
|
101
|
-
<Text variant="h2" style={{ marginBottom: 16 }}>🏗️ Architecture Overview</Text>
|
|
102
|
-
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 16 }}>
|
|
103
|
-
<FeatureCard
|
|
104
|
-
icon="🗄️"
|
|
105
|
-
title="Database Layer"
|
|
106
|
-
description="Prisma ORM with SQLite, user management, posts, and comments"
|
|
107
|
-
/>
|
|
108
|
-
<FeatureCard
|
|
109
|
-
icon="🚀"
|
|
110
|
-
title="API Server"
|
|
111
|
-
description="tRPC API with type-safe endpoints and real-time capabilities"
|
|
112
|
-
/>
|
|
113
|
-
<FeatureCard
|
|
114
|
-
icon="🌐"
|
|
115
|
-
title="Web Application"
|
|
116
|
-
description="React web app with Idealyst components and responsive design"
|
|
117
|
-
/>
|
|
118
|
-
<FeatureCard
|
|
119
|
-
icon="📱"
|
|
120
|
-
title="Mobile App"
|
|
121
|
-
description="React Native app with shared components and unified styling"
|
|
122
|
-
/>
|
|
123
|
-
<FeatureCard
|
|
124
|
-
icon="📦"
|
|
125
|
-
title="Shared Library"
|
|
126
|
-
description="Cross-platform components, utilities, and type definitions"
|
|
127
|
-
/>
|
|
128
|
-
<FeatureCard
|
|
129
|
-
icon="🔗"
|
|
130
|
-
title="Full Integration"
|
|
131
|
-
description="End-to-end type safety and unified development workflow"
|
|
132
|
-
/>
|
|
133
|
-
</View>
|
|
134
|
-
</View>
|
|
135
|
-
|
|
136
|
-
{/* Live Data Preview */}
|
|
137
|
-
<View style={{ marginBottom: 32 }}>
|
|
138
|
-
<Text variant="h2" style={{ marginBottom: 16 }}>📊 Live Data Preview</Text>
|
|
139
|
-
|
|
140
|
-
{/* Users Section */}
|
|
141
|
-
<View style={{ marginBottom: 24 }}>
|
|
142
|
-
<Text variant="h3" style={{ marginBottom: 12 }}>👥 Users ({usersLoading ? '...' : usersData?.length || DEMO_USERS.length})</Text>
|
|
143
|
-
{usersLoading ? (
|
|
144
|
-
<LoadingSpinner message="Loading users..." />
|
|
145
|
-
) : (
|
|
146
|
-
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 12 }}>
|
|
147
|
-
{(usersData || DEMO_USERS.slice(0, 3)).map((user: User) => (
|
|
148
|
-
<View key={user.id} style={{ width: '300px' }}>
|
|
149
|
-
<UserCard
|
|
150
|
-
user={user}
|
|
151
|
-
showBio={false}
|
|
152
|
-
onPress={() => console.log('View profile:', user.name)}
|
|
153
|
-
/>
|
|
154
|
-
</View>
|
|
155
|
-
))}
|
|
156
|
-
</View>
|
|
157
|
-
)}
|
|
158
|
-
</View>
|
|
159
|
-
|
|
160
|
-
{/* Posts Section */}
|
|
161
|
-
<View style={{ marginBottom: 24 }}>
|
|
162
|
-
<Text variant="h3" style={{ marginBottom: 12 }}>📝 Recent Posts ({postsLoading ? '...' : postsData?.length || DEMO_POSTS.length})</Text>
|
|
163
|
-
{postsLoading ? (
|
|
164
|
-
<LoadingSpinner message="Loading posts..." />
|
|
165
|
-
) : (
|
|
166
|
-
<View>
|
|
167
|
-
{(postsData || DEMO_POSTS.slice(0, 2)).map((post: Post) => {
|
|
168
|
-
const author = DEMO_USERS.find(u => u.id === post.authorId);
|
|
169
|
-
return (
|
|
170
|
-
<PostCard
|
|
171
|
-
key={post.id}
|
|
172
|
-
post={post}
|
|
173
|
-
author={author}
|
|
174
|
-
onPress={() => console.log('Read post:', post.title)}
|
|
175
|
-
onLike={() => console.log('Like post:', post.title)}
|
|
176
|
-
/>
|
|
177
|
-
);
|
|
178
|
-
})}
|
|
179
|
-
</View>
|
|
180
|
-
)}
|
|
181
|
-
</View>
|
|
182
|
-
</View>
|
|
183
|
-
|
|
184
|
-
{/* Quick Start Section */}
|
|
185
|
-
<View style={{
|
|
186
|
-
padding: 20,
|
|
187
|
-
backgroundColor: '#f8f9fa',
|
|
188
|
-
borderRadius: 8,
|
|
189
|
-
marginBottom: 24
|
|
190
|
-
}}>
|
|
191
|
-
<Text variant="h2" style={{ marginBottom: 16 }}>🚀 Quick Start</Text>
|
|
192
|
-
<Text variant="body" style={{ marginBottom: 12 }}>
|
|
193
|
-
Your full-stack workspace is ready! Here's what you can do:
|
|
194
|
-
</Text>
|
|
195
|
-
<View style={{ marginLeft: 16 }}>
|
|
196
|
-
<Text style={{ marginBottom: 4 }}>• 🗄️ Add your models in <code>packages/database/schema.prisma</code></Text>
|
|
197
|
-
<Text style={{ marginBottom: 4 }}>• 🚀 Create API endpoints in <code>packages/api/src/routers/</code></Text>
|
|
198
|
-
<Text style={{ marginBottom: 4 }}>• 📦 Build shared components in <code>packages/shared/src/</code></Text>
|
|
199
|
-
<Text style={{ marginBottom: 4 }}>• 🌐 Customize this web app in <code>packages/web/src/</code></Text>
|
|
200
|
-
<Text style={{ marginBottom: 4 }}>• 📱 Update the mobile app in <code>packages/mobile/src/</code></Text>
|
|
201
|
-
</View>
|
|
202
|
-
</View>
|
|
203
|
-
|
|
204
|
-
{/* Development Commands */}
|
|
205
|
-
<View style={{
|
|
206
|
-
padding: 20,
|
|
207
|
-
backgroundColor: '#e8f5e8',
|
|
208
|
-
borderRadius: 8,
|
|
209
|
-
marginBottom: 24
|
|
210
|
-
}}>
|
|
211
|
-
<Text variant="h3" style={{ marginBottom: 12 }}>💻 Development Commands</Text>
|
|
212
|
-
<View style={{ fontFamily: 'monospace', fontSize: 14 }}>
|
|
213
|
-
<Text style={{ marginBottom: 4 }}>yarn dev # Start all servers</Text>
|
|
214
|
-
<Text style={{ marginBottom: 4 }}>yarn web:dev # Start web app only</Text>
|
|
215
|
-
<Text style={{ marginBottom: 4 }}>yarn mobile:start # Start mobile bundler</Text>
|
|
216
|
-
<Text style={{ marginBottom: 4 }}>yarn api:dev # Start API server only</Text>
|
|
217
|
-
<Text style={{ marginBottom: 4 }}>yarn db:push # Update database schema</Text>
|
|
218
|
-
<Text style={{ marginBottom: 4 }}>yarn db:studio # Open database admin</Text>
|
|
219
|
-
</View>
|
|
220
|
-
</View>
|
|
221
|
-
</View>
|
|
222
|
-
</ScrollView>
|
|
223
|
-
);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// Users Page Component
|
|
227
|
-
function UsersPage() {
|
|
228
|
-
const { data: users, isLoading, error } = trpc.users.getAll.useQuery();
|
|
229
|
-
|
|
230
|
-
if (isLoading) return <LoadingSpinner message="Loading users..." />;
|
|
231
|
-
if (error) return <ErrorMessage message={error.message} />;
|
|
232
|
-
|
|
233
|
-
const allUsers = users || DEMO_USERS;
|
|
234
|
-
|
|
235
|
-
return (
|
|
236
|
-
<ScrollView style={{ flex: 1, padding: 20 }}>
|
|
237
|
-
<Text variant="h1" style={{ marginBottom: 20 }}>👥 Users ({allUsers.length})</Text>
|
|
238
|
-
<View style={{ flexDirection: 'row', flexWrap: 'wrap', gap: 16 }}>
|
|
239
|
-
{allUsers.map((user: User) => (
|
|
240
|
-
<View key={user.id} style={{ width: '400px' }}>
|
|
241
|
-
<UserCard
|
|
242
|
-
user={user}
|
|
243
|
-
showBio={true}
|
|
244
|
-
onPress={() => console.log('View profile:', user.name)}
|
|
245
|
-
/>
|
|
246
|
-
</View>
|
|
247
|
-
))}
|
|
248
|
-
</View>
|
|
249
|
-
</ScrollView>
|
|
250
|
-
);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
// Posts Page Component
|
|
254
|
-
function PostsPage() {
|
|
255
|
-
const { data: posts, isLoading, error } = trpc.posts.getAll.useQuery();
|
|
256
|
-
|
|
257
|
-
if (isLoading) return <LoadingSpinner message="Loading posts..." />;
|
|
258
|
-
if (error) return <ErrorMessage message={error.message} />;
|
|
259
|
-
|
|
260
|
-
const allPosts = posts || DEMO_POSTS;
|
|
261
|
-
|
|
262
|
-
return (
|
|
263
|
-
<ScrollView style={{ flex: 1, padding: 20 }}>
|
|
264
|
-
<Text variant="h1" style={{ marginBottom: 20 }}>📝 Posts ({allPosts.length})</Text>
|
|
265
|
-
<View>
|
|
266
|
-
{allPosts.map((post: Post) => {
|
|
267
|
-
const author = DEMO_USERS.find(u => u.id === post.authorId);
|
|
268
|
-
return (
|
|
269
|
-
<PostCard
|
|
270
|
-
key={post.id}
|
|
271
|
-
post={post}
|
|
272
|
-
author={author}
|
|
273
|
-
showFullContent={false}
|
|
274
|
-
onPress={() => console.log('Read post:', post.title)}
|
|
275
|
-
onLike={() => console.log('Like post:', post.title)}
|
|
276
|
-
/>
|
|
277
|
-
);
|
|
278
|
-
})}
|
|
279
|
-
</View>
|
|
280
|
-
</ScrollView>
|
|
281
|
-
);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
// Main App Component
|
|
285
6
|
function App() {
|
|
286
7
|
return (
|
|
287
|
-
<
|
|
288
|
-
<QueryClientProvider client={queryClient}>
|
|
289
|
-
<BrowserRouter>
|
|
290
|
-
<Screen>
|
|
291
|
-
<Navigation />
|
|
292
|
-
<Routes>
|
|
293
|
-
<Route path="/" element={<HomePage />} />
|
|
294
|
-
<Route path="/users" element={<UsersPage />} />
|
|
295
|
-
<Route path="/posts" element={<PostsPage />} />
|
|
296
|
-
</Routes>
|
|
297
|
-
</Screen>
|
|
298
|
-
</BrowserRouter>
|
|
299
|
-
</QueryClientProvider>
|
|
300
|
-
</trpc.Provider>
|
|
8
|
+
<HelloWorld name="{{projectName}} Developer" platform="web" projectName="{{projectName}}" />
|
|
301
9
|
);
|
|
302
10
|
}
|
|
303
11
|
|
package/package.json
CHANGED
|
@@ -1,265 +1,11 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
3
|
-
import { httpBatchLink } from '@trpc/client';
|
|
4
|
-
import { Screen, Text, View, Button, ScrollView } from '@idealyst/components';
|
|
5
|
-
import { trpc } from './utils/trpc';
|
|
1
|
+
import React from 'react';
|
|
6
2
|
|
|
7
|
-
// Import shared components
|
|
8
|
-
import {
|
|
9
|
-
UserCard,
|
|
10
|
-
PostCard,
|
|
11
|
-
LoadingSpinner,
|
|
12
|
-
ErrorMessage,
|
|
13
|
-
FeatureCard,
|
|
14
|
-
TabButton,
|
|
15
|
-
DEMO_USERS,
|
|
16
|
-
DEMO_POSTS,
|
|
17
|
-
formatRelativeTime,
|
|
18
|
-
type User,
|
|
19
|
-
type Post
|
|
20
|
-
} from '{{workspaceScope}}/shared';
|
|
21
|
-
|
|
22
|
-
// Create tRPC client
|
|
23
|
-
const queryClient = new QueryClient();
|
|
24
|
-
|
|
25
|
-
const trpcClient = trpc.createClient({
|
|
26
|
-
links: [
|
|
27
|
-
httpBatchLink({
|
|
28
|
-
url: 'http://localhost:3001/trpc', // Update this to your API URL
|
|
29
|
-
// For device testing, you might need: 'http://192.168.1.xxx:3001/trpc'
|
|
30
|
-
// Optional: Add headers for authentication
|
|
31
|
-
// headers() {
|
|
32
|
-
// return {
|
|
33
|
-
// authorization: getAuthToken(),
|
|
34
|
-
// };
|
|
35
|
-
// },
|
|
36
|
-
}),
|
|
37
|
-
],
|
|
38
|
-
});
|
|
3
|
+
// Import shared components
|
|
4
|
+
import { HelloWorld } from '@{{workspaceScope}}/shared';
|
|
39
5
|
|
|
40
6
|
function App() {
|
|
41
|
-
const [currentTab, setCurrentTab] = useState<'home' | 'users' | 'posts'>('home');
|
|
42
|
-
|
|
43
|
-
// Example tRPC usage
|
|
44
|
-
const { data: helloData, isLoading: helloLoading, error: helloError } = trpc.hello.useQuery({ name: 'Mobile User' });
|
|
45
|
-
const { data: usersData, isLoading: usersLoading } = trpc.users.getAll.useQuery();
|
|
46
|
-
const { data: postsData, isLoading: postsLoading } = trpc.posts.getAll.useQuery();
|
|
47
|
-
|
|
48
|
-
const renderHome = () => (
|
|
49
|
-
<ScrollView style={{ flex: 1 }}>
|
|
50
|
-
<View style={{ padding: 20 }}>
|
|
51
|
-
{/* Welcome Section */}
|
|
52
|
-
<View style={{ marginBottom: 32, alignItems: 'center' }}>
|
|
53
|
-
<Text variant="h1" style={{ textAlign: 'center', marginBottom: 16 }}>
|
|
54
|
-
Welcome to {{appName}}! 📱
|
|
55
|
-
</Text>
|
|
56
|
-
<Text variant="body" style={{ textAlign: 'center', marginBottom: 16, fontSize: 18 }}>
|
|
57
|
-
A cross-platform mobile app built with React Native and the Idealyst Framework
|
|
58
|
-
</Text>
|
|
59
|
-
|
|
60
|
-
{/* tRPC Connection Test */}
|
|
61
|
-
<View style={{
|
|
62
|
-
padding: 16,
|
|
63
|
-
backgroundColor: '#e3f2fd',
|
|
64
|
-
borderRadius: 8,
|
|
65
|
-
marginBottom: 24,
|
|
66
|
-
width: '100%'
|
|
67
|
-
}}>
|
|
68
|
-
<Text variant="h3" style={{ marginBottom: 8, textAlign: 'center' }}>🔗 API Connection</Text>
|
|
69
|
-
{helloLoading && <Text style={{ textAlign: 'center' }}>Testing connection...</Text>}
|
|
70
|
-
{helloError && <Text style={{ color: 'red', textAlign: 'center' }}>Error: {helloError.message}</Text>}
|
|
71
|
-
{helloData && <Text style={{ color: 'green', textAlign: 'center' }}>✅ {helloData.greeting}</Text>}
|
|
72
|
-
</View>
|
|
73
|
-
</View>
|
|
74
|
-
|
|
75
|
-
{/* Features Overview */}
|
|
76
|
-
<View style={{ marginBottom: 32 }}>
|
|
77
|
-
<Text variant="h2" style={{ marginBottom: 16, textAlign: 'center' }}>🏗️ What's Included</Text>
|
|
78
|
-
<FeatureCard
|
|
79
|
-
icon="🔗"
|
|
80
|
-
title="Full Integration"
|
|
81
|
-
description="Connected to your database and API with end-to-end type safety"
|
|
82
|
-
/>
|
|
83
|
-
<FeatureCard
|
|
84
|
-
icon="📦"
|
|
85
|
-
title="Shared Components"
|
|
86
|
-
description="Cross-platform UI components that work on web and mobile"
|
|
87
|
-
/>
|
|
88
|
-
<FeatureCard
|
|
89
|
-
icon="🎨"
|
|
90
|
-
title="Idealyst Design"
|
|
91
|
-
description="Beautiful, consistent styling with the Idealyst component library"
|
|
92
|
-
/>
|
|
93
|
-
<FeatureCard
|
|
94
|
-
icon="⚡"
|
|
95
|
-
title="Real-time Updates"
|
|
96
|
-
description="tRPC provides instant synchronization with your backend"
|
|
97
|
-
/>
|
|
98
|
-
</View>
|
|
99
|
-
|
|
100
|
-
{/* Quick Data Preview */}
|
|
101
|
-
<View style={{ marginBottom: 32 }}>
|
|
102
|
-
<Text variant="h2" style={{ marginBottom: 16, textAlign: 'center' }}>📊 Live Data</Text>
|
|
103
|
-
|
|
104
|
-
{/* Users Preview */}
|
|
105
|
-
<View style={{ marginBottom: 20 }}>
|
|
106
|
-
<Text variant="h3" style={{ marginBottom: 12 }}>👥 Users ({usersLoading ? '...' : usersData?.length || DEMO_USERS.length})</Text>
|
|
107
|
-
{usersLoading ? (
|
|
108
|
-
<LoadingSpinner message="Loading users..." />
|
|
109
|
-
) : (
|
|
110
|
-
<View>
|
|
111
|
-
{(usersData || DEMO_USERS.slice(0, 2)).map((user: User) => (
|
|
112
|
-
<UserCard
|
|
113
|
-
key={user.id}
|
|
114
|
-
user={user}
|
|
115
|
-
showBio={false}
|
|
116
|
-
onPress={() => console.log('View profile:', user.name)}
|
|
117
|
-
/>
|
|
118
|
-
))}
|
|
119
|
-
</View>
|
|
120
|
-
)}
|
|
121
|
-
</View>
|
|
122
|
-
|
|
123
|
-
{/* Posts Preview */}
|
|
124
|
-
<View style={{ marginBottom: 20 }}>
|
|
125
|
-
<Text variant="h3" style={{ marginBottom: 12 }}>📝 Recent Posts ({postsLoading ? '...' : postsData?.length || DEMO_POSTS.length})</Text>
|
|
126
|
-
{postsLoading ? (
|
|
127
|
-
<LoadingSpinner message="Loading posts..." />
|
|
128
|
-
) : (
|
|
129
|
-
<View>
|
|
130
|
-
{(postsData || DEMO_POSTS.slice(0, 1)).map((post: Post) => {
|
|
131
|
-
const author = DEMO_USERS.find(u => u.id === post.authorId);
|
|
132
|
-
return (
|
|
133
|
-
<PostCard
|
|
134
|
-
key={post.id}
|
|
135
|
-
post={post}
|
|
136
|
-
author={author}
|
|
137
|
-
onPress={() => console.log('Read post:', post.title)}
|
|
138
|
-
onLike={() => console.log('Like post:', post.title)}
|
|
139
|
-
/>
|
|
140
|
-
);
|
|
141
|
-
})}
|
|
142
|
-
</View>
|
|
143
|
-
)}
|
|
144
|
-
</View>
|
|
145
|
-
</View>
|
|
146
|
-
|
|
147
|
-
{/* Development Info */}
|
|
148
|
-
<View style={{
|
|
149
|
-
padding: 20,
|
|
150
|
-
backgroundColor: '#f8f9fa',
|
|
151
|
-
borderRadius: 8,
|
|
152
|
-
marginBottom: 24
|
|
153
|
-
}}>
|
|
154
|
-
<Text variant="h3" style={{ marginBottom: 12, textAlign: 'center' }}>🚀 Development</Text>
|
|
155
|
-
<Text variant="body" style={{ textAlign: 'center', marginBottom: 12 }}>
|
|
156
|
-
This app is part of your full-stack workspace. Make changes to see them reflected instantly!
|
|
157
|
-
</Text>
|
|
158
|
-
<Text variant="caption" style={{ textAlign: 'center', fontStyle: 'italic' }}>
|
|
159
|
-
Edit packages/mobile/src/App.tsx to customize this screen
|
|
160
|
-
</Text>
|
|
161
|
-
</View>
|
|
162
|
-
</View>
|
|
163
|
-
</ScrollView>
|
|
164
|
-
);
|
|
165
|
-
|
|
166
|
-
const renderUsers = () => {
|
|
167
|
-
const { data: users, isLoading, error } = trpc.users.getAll.useQuery();
|
|
168
|
-
|
|
169
|
-
if (isLoading) return <LoadingSpinner message="Loading users..." />;
|
|
170
|
-
if (error) return <ErrorMessage message={error.message} />;
|
|
171
|
-
|
|
172
|
-
const allUsers = users || DEMO_USERS;
|
|
173
|
-
|
|
174
|
-
return (
|
|
175
|
-
<ScrollView style={{ flex: 1, padding: 20 }}>
|
|
176
|
-
<Text variant="h1" style={{ marginBottom: 20, textAlign: 'center' }}>👥 All Users ({allUsers.length})</Text>
|
|
177
|
-
<View>
|
|
178
|
-
{allUsers.map((user: User) => (
|
|
179
|
-
<UserCard
|
|
180
|
-
key={user.id}
|
|
181
|
-
user={user}
|
|
182
|
-
showBio={true}
|
|
183
|
-
onPress={() => console.log('View profile:', user.name)}
|
|
184
|
-
/>
|
|
185
|
-
))}
|
|
186
|
-
</View>
|
|
187
|
-
</ScrollView>
|
|
188
|
-
);
|
|
189
|
-
};
|
|
190
|
-
|
|
191
|
-
const renderPosts = () => {
|
|
192
|
-
const { data: posts, isLoading, error } = trpc.posts.getAll.useQuery();
|
|
193
|
-
|
|
194
|
-
if (isLoading) return <LoadingSpinner message="Loading posts..." />;
|
|
195
|
-
if (error) return <ErrorMessage message={error.message} />;
|
|
196
|
-
|
|
197
|
-
const allPosts = posts || DEMO_POSTS;
|
|
198
|
-
|
|
199
|
-
return (
|
|
200
|
-
<ScrollView style={{ flex: 1, padding: 20 }}>
|
|
201
|
-
<Text variant="h1" style={{ marginBottom: 20, textAlign: 'center' }}>📝 All Posts ({allPosts.length})</Text>
|
|
202
|
-
<View>
|
|
203
|
-
{allPosts.map((post: Post) => {
|
|
204
|
-
const author = DEMO_USERS.find(u => u.id === post.authorId);
|
|
205
|
-
return (
|
|
206
|
-
<PostCard
|
|
207
|
-
key={post.id}
|
|
208
|
-
post={post}
|
|
209
|
-
author={author}
|
|
210
|
-
showFullContent={false}
|
|
211
|
-
onPress={() => console.log('Read post:', post.title)}
|
|
212
|
-
onLike={() => console.log('Like post:', post.title)}
|
|
213
|
-
/>
|
|
214
|
-
);
|
|
215
|
-
})}
|
|
216
|
-
</View>
|
|
217
|
-
</ScrollView>
|
|
218
|
-
);
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
const renderTabBar = () => (
|
|
222
|
-
<View style={{
|
|
223
|
-
flexDirection: 'row',
|
|
224
|
-
backgroundColor: '#f8f9fa',
|
|
225
|
-
borderTopWidth: 1,
|
|
226
|
-
borderTopColor: '#e9ecef',
|
|
227
|
-
paddingVertical: 10
|
|
228
|
-
}}>
|
|
229
|
-
<TabButton
|
|
230
|
-
title="Home"
|
|
231
|
-
icon="🏠"
|
|
232
|
-
active={currentTab === 'home'}
|
|
233
|
-
onPress={() => setCurrentTab('home')}
|
|
234
|
-
/>
|
|
235
|
-
<TabButton
|
|
236
|
-
title="Users"
|
|
237
|
-
icon="👥"
|
|
238
|
-
active={currentTab === 'users'}
|
|
239
|
-
onPress={() => setCurrentTab('users')}
|
|
240
|
-
/>
|
|
241
|
-
<TabButton
|
|
242
|
-
title="Posts"
|
|
243
|
-
icon="📝"
|
|
244
|
-
active={currentTab === 'posts'}
|
|
245
|
-
onPress={() => setCurrentTab('posts')}
|
|
246
|
-
/>
|
|
247
|
-
</View>
|
|
248
|
-
);
|
|
249
|
-
|
|
250
7
|
return (
|
|
251
|
-
<
|
|
252
|
-
<QueryClientProvider client={queryClient}>
|
|
253
|
-
<Screen>
|
|
254
|
-
<View style={{ flex: 1 }}>
|
|
255
|
-
{currentTab === 'home' && renderHome()}
|
|
256
|
-
{currentTab === 'users' && renderUsers()}
|
|
257
|
-
{currentTab === 'posts' && renderPosts()}
|
|
258
|
-
{renderTabBar()}
|
|
259
|
-
</View>
|
|
260
|
-
</Screen>
|
|
261
|
-
</QueryClientProvider>
|
|
262
|
-
</trpc.Provider>
|
|
8
|
+
<HelloWorld name="{{projectName}} Mobile User" platform="mobile" projectName="{{projectName}}" />
|
|
263
9
|
);
|
|
264
10
|
}
|
|
265
11
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## Getting Started
|
|
6
6
|
|
|
7
|
-
This is a shared library built with the Idealyst Framework that can be used across React Native and React web applications.
|
|
7
|
+
This is a shared component library built with the Idealyst Framework that can be used across React Native and React web applications. It exports source TypeScript files directly for seamless integration in monorepo setups.
|
|
8
8
|
|
|
9
9
|
### Prerequisites
|
|
10
10
|
|
|
@@ -20,14 +20,40 @@ yarn install
|
|
|
20
20
|
|
|
21
21
|
### Development
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Run tests:
|
|
24
24
|
```bash
|
|
25
|
-
yarn
|
|
25
|
+
yarn test
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
Type checking:
|
|
29
29
|
```bash
|
|
30
|
-
yarn
|
|
30
|
+
yarn type-check
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
Import the HelloWorld component in your React or React Native app:
|
|
36
|
+
|
|
37
|
+
```typescript
|
|
38
|
+
import { HelloWorld } from '@{{workspaceName}}/shared';
|
|
39
|
+
|
|
40
|
+
function App() {
|
|
41
|
+
return <HelloWorld name="Developer" />;
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Component
|
|
46
|
+
|
|
47
|
+
### HelloWorld
|
|
48
|
+
|
|
49
|
+
A simple welcome component that works on both web and mobile platforms.
|
|
50
|
+
|
|
51
|
+
**Props:**
|
|
52
|
+
- `name?: string` - Name to display in the greeting (defaults to "World")
|
|
53
|
+
|
|
54
|
+
**Example:**
|
|
55
|
+
```typescript
|
|
56
|
+
<HelloWorld name="Alice" />
|
|
31
57
|
```
|
|
32
58
|
|
|
33
59
|
### Project Structure
|
|
@@ -1,10 +1,22 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HelloWorld } from '../src/index';
|
|
2
2
|
|
|
3
3
|
describe('Shared Library', () => {
|
|
4
|
-
it('should export
|
|
5
|
-
expect(
|
|
6
|
-
expect(typeof
|
|
7
|
-
|
|
4
|
+
it('should export HelloWorld component', () => {
|
|
5
|
+
expect(HelloWorld).toBeDefined();
|
|
6
|
+
expect(typeof HelloWorld).toBe('function');
|
|
7
|
+
});
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
describe('HelloWorld Component', () => {
|
|
11
|
+
it('should be a React component', () => {
|
|
12
|
+
expect(HelloWorld).toBeDefined();
|
|
13
|
+
expect(typeof HelloWorld).toBe('function');
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('should accept props', () => {
|
|
17
|
+
// Test that the component function exists and can be called
|
|
18
|
+
// Note: Full component testing would require a React testing environment
|
|
19
|
+
expect(() => HelloWorld({ name: 'Test' })).not.toThrow();
|
|
8
20
|
});
|
|
9
21
|
});
|
|
10
22
|
|