@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.
Files changed (121) hide show
  1. package/dist/generators/fullstack.js +61 -3
  2. package/dist/generators/fullstack.js.map +1 -1
  3. package/dist/generators/native.js +12 -0
  4. package/dist/generators/native.js.map +1 -1
  5. package/dist/generators/utils.js +64 -31
  6. package/dist/generators/utils.js.map +1 -1
  7. package/dist/templates/api/README.md +207 -130
  8. package/dist/templates/api/package.json +5 -5
  9. package/dist/templates/api/src/controllers/TestController.ts +0 -0
  10. package/dist/templates/api/src/index.ts +2 -7
  11. package/dist/templates/api/src/lib/crud.ts +150 -0
  12. package/dist/templates/api/src/lib/database.ts +23 -0
  13. package/dist/templates/api/src/router/index.ts +104 -71
  14. package/dist/templates/api/src/routers/test.ts +59 -0
  15. package/dist/templates/api/src/routers/user.example.ts +83 -0
  16. package/dist/templates/api/src/server.ts +1 -1
  17. package/dist/templates/api/tsconfig.json +0 -1
  18. package/dist/templates/database/README.md +115 -1
  19. package/dist/templates/database/package.json +2 -0
  20. package/dist/templates/database/prisma/seed.ts +37 -1
  21. package/dist/templates/database/schema.prisma +11 -1
  22. package/dist/templates/native/index.js +1 -1
  23. package/dist/templates/native/metro.config.js +1 -1
  24. package/dist/templates/native/package.json +4 -0
  25. package/dist/templates/native/src/App.tsx +16 -0
  26. package/dist/templates/native/src/utils/trpc.ts +7 -127
  27. package/dist/templates/native/tsconfig.json +0 -2
  28. package/dist/templates/shared/README.md +31 -5
  29. package/dist/templates/shared/__tests__/shared.test.ts +17 -5
  30. package/dist/templates/shared/package.json +14 -30
  31. package/dist/templates/shared/src/components/App.tsx +57 -0
  32. package/dist/templates/shared/src/components/HelloWorld.tsx +307 -0
  33. package/dist/templates/shared/src/components/index.ts +1 -392
  34. package/dist/templates/shared/src/index.ts +9 -57
  35. package/dist/templates/shared/src/trpc/client.ts +39 -0
  36. package/dist/templates/shared/tsconfig.json +4 -7
  37. package/dist/templates/web/README.md +65 -8
  38. package/dist/templates/web/package.json +3 -3
  39. package/dist/templates/web/src/App-with-trpc-and-shared.tsx +11 -299
  40. package/dist/templates/web/src/components/TestDemo.tsx +164 -0
  41. package/dist/templates/web/src/utils/trpc.ts +7 -93
  42. package/dist/templates/web/tsconfig.json +0 -1
  43. package/dist/templates/workspace/.devcontainer/devcontainer.json +4 -9
  44. package/dist/templates/workspace/.devcontainer/docker-compose.yml +1 -2
  45. package/dist/templates/workspace/.devcontainer/setup.sh +1 -1
  46. package/dist/templates/workspace/.env.example +1 -1
  47. package/dist/templates/workspace/Dockerfile +4 -4
  48. package/dist/templates/workspace/docker/nginx/prod.conf +2 -2
  49. package/dist/templates/workspace/docker/nginx.conf +1 -1
  50. package/dist/templates/workspace/docker/prometheus/prometheus.yml +1 -1
  51. package/dist/templates/workspace/docker-compose.yml +4 -5
  52. package/dist/templates/workspace/tsconfig.json +0 -1
  53. package/package.json +1 -1
  54. package/templates/api/README.md +207 -130
  55. package/templates/api/package.json +5 -5
  56. package/templates/api/src/controllers/TestController.ts +0 -0
  57. package/templates/api/src/index.ts +2 -7
  58. package/templates/api/src/lib/crud.ts +150 -0
  59. package/templates/api/src/lib/database.ts +23 -0
  60. package/templates/api/src/router/index.ts +104 -71
  61. package/templates/api/src/routers/test.ts +59 -0
  62. package/templates/api/src/routers/user.example.ts +83 -0
  63. package/templates/api/src/server.ts +1 -1
  64. package/templates/api/tsconfig.json +0 -1
  65. package/templates/database/README.md +115 -1
  66. package/templates/database/package.json +2 -0
  67. package/templates/database/prisma/seed.ts +37 -1
  68. package/templates/database/schema.prisma +11 -1
  69. package/templates/native/index.js +1 -1
  70. package/templates/native/metro.config.js +1 -1
  71. package/templates/native/package.json +4 -0
  72. package/templates/native/src/App.tsx +16 -0
  73. package/templates/native/src/utils/trpc.ts +7 -127
  74. package/templates/native/tsconfig.json +0 -2
  75. package/templates/shared/README.md +31 -5
  76. package/templates/shared/__tests__/shared.test.ts +17 -5
  77. package/templates/shared/package.json +14 -30
  78. package/templates/shared/src/components/App.tsx +57 -0
  79. package/templates/shared/src/components/HelloWorld.tsx +307 -0
  80. package/templates/shared/src/components/index.ts +1 -392
  81. package/templates/shared/src/index.ts +9 -57
  82. package/templates/shared/src/trpc/client.ts +39 -0
  83. package/templates/shared/tsconfig.json +4 -7
  84. package/templates/web/README.md +65 -8
  85. package/templates/web/package.json +3 -3
  86. package/templates/web/src/App-with-trpc-and-shared.tsx +11 -299
  87. package/templates/web/src/components/TestDemo.tsx +164 -0
  88. package/templates/web/src/utils/trpc.ts +7 -93
  89. package/templates/web/tsconfig.json +0 -1
  90. package/templates/workspace/.devcontainer/devcontainer.json +4 -9
  91. package/templates/workspace/.devcontainer/docker-compose.yml +1 -2
  92. package/templates/workspace/.devcontainer/setup.sh +1 -1
  93. package/templates/workspace/.env.example +1 -1
  94. package/templates/workspace/Dockerfile +4 -4
  95. package/templates/workspace/docker/nginx/prod.conf +2 -2
  96. package/templates/workspace/docker/nginx.conf +1 -1
  97. package/templates/workspace/docker/prometheus/prometheus.yml +1 -1
  98. package/templates/workspace/docker-compose.yml +4 -5
  99. package/templates/workspace/tsconfig.json +0 -1
  100. package/dist/templates/api/src/controllers/UserController.ts +0 -102
  101. package/dist/templates/api/src/lib/controller.ts +0 -90
  102. package/dist/templates/api/src/lib/middleware.ts +0 -170
  103. package/dist/templates/api/src/middleware/auth.ts +0 -75
  104. package/dist/templates/api/src/middleware/common.ts +0 -103
  105. package/dist/templates/database/.env.example +0 -1
  106. package/dist/templates/native/App.tsx +0 -23
  107. package/dist/templates/native/src/App-with-trpc-and-shared.tsx +0 -266
  108. package/dist/templates/shared/rollup.config.js +0 -43
  109. package/dist/templates/shared/src/types/index.ts +0 -148
  110. package/dist/templates/shared/src/utils/index.ts +0 -278
  111. package/templates/api/src/controllers/UserController.ts +0 -102
  112. package/templates/api/src/lib/controller.ts +0 -90
  113. package/templates/api/src/lib/middleware.ts +0 -170
  114. package/templates/api/src/middleware/auth.ts +0 -75
  115. package/templates/api/src/middleware/common.ts +0 -103
  116. package/templates/database/.env.example +0 -1
  117. package/templates/native/App.tsx +0 -23
  118. package/templates/native/src/App-with-trpc-and-shared.tsx +0 -266
  119. package/templates/shared/rollup.config.js +0 -43
  120. package/templates/shared/src/types/index.ts +0 -148
  121. package/templates/shared/src/utils/index.ts +0 -278
@@ -1,304 +1,16 @@
1
- import React, { useState } from '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';
2
+ import { App } from '@{{workspaceScope}}/shared';
7
3
 
8
- // Import shared components and utilities
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';
22
-
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
- function App() {
4
+ // Main App component using shared App wrapper
5
+ function AppWithTrpcAndShared() {
286
6
  return (
287
- <trpc.Provider client={trpcClient} queryClient={queryClient}>
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>
7
+ <App
8
+ apiUrl="http://localhost:3000/trpc"
9
+ name="{{projectName}} Developer"
10
+ platform="web"
11
+ projectName="{{projectName}}"
12
+ />
301
13
  );
302
14
  }
303
15
 
304
- export default App;
16
+ export default AppWithTrpcAndShared;
@@ -0,0 +1,164 @@
1
+ import React, { useState } from 'react';
2
+ import { View, Text, Card, Button, Input } from '@idealyst/components';
3
+ import { trpc } from '../utils/trpc';
4
+
5
+ export const TestDemo: React.FC = () => {
6
+ const [newTestName, setNewTestName] = useState('');
7
+ const [newTestMessage, setNewTestMessage] = useState('');
8
+
9
+ // tRPC queries and mutations
10
+ const { data: tests, isLoading, refetch } = trpc.test.getAll.useQuery();
11
+ const createTestMutation = trpc.test.create.useMutation({
12
+ onSuccess: () => {
13
+ refetch();
14
+ setNewTestName('');
15
+ setNewTestMessage('');
16
+ },
17
+ });
18
+ const deleteTestMutation = trpc.test.delete.useMutation({
19
+ onSuccess: () => {
20
+ refetch();
21
+ },
22
+ });
23
+
24
+ const handleCreateTest = async () => {
25
+ if (!newTestName || !newTestMessage) return;
26
+
27
+ await createTestMutation.mutateAsync({
28
+ name: newTestName,
29
+ message: newTestMessage,
30
+ status: 'active',
31
+ });
32
+ };
33
+
34
+ const handleDeleteTest = async (id: string) => {
35
+ await deleteTestMutation.mutateAsync({ id });
36
+ };
37
+
38
+ if (isLoading) {
39
+ return (
40
+ <Card variant="outlined" padding="large">
41
+ <Text size="medium">Loading tests...</Text>
42
+ </Card>
43
+ );
44
+ }
45
+
46
+ return (
47
+ <View style={{ gap: 16 }}>
48
+ {/* Header */}
49
+ <Card variant="elevated" padding="large" intent="primary">
50
+ <View style={{ alignItems: 'center' }}>
51
+ <Text style={{ fontSize: 24, marginBottom: 8 }}>🧪</Text>
52
+ <Text size="large" weight="bold" style={{ marginBottom: 8, textAlign: 'center' }}>
53
+ tRPC + Database Test
54
+ </Text>
55
+ <Text size="medium" style={{ textAlign: 'center' }}>
56
+ This demonstrates end-to-end type-safe API calls from the web app to the database.
57
+ </Text>
58
+ </View>
59
+ </Card>
60
+
61
+ {/* Create Test Form */}
62
+ <Card variant="outlined" padding="large">
63
+ <Text size="medium" weight="bold" style={{ marginBottom: 16 }}>
64
+ Create New Test
65
+ </Text>
66
+
67
+ <View style={{ gap: 12 }}>
68
+ <Input
69
+ label="Test Name"
70
+ value={newTestName}
71
+ onChangeText={setNewTestName}
72
+ placeholder="Enter test name"
73
+ />
74
+ <Input
75
+ label="Test Message"
76
+ value={newTestMessage}
77
+ onChangeText={setNewTestMessage}
78
+ placeholder="Enter test message"
79
+ multiline
80
+ />
81
+ <Button
82
+ variant="contained"
83
+ intent="primary"
84
+ onPress={handleCreateTest}
85
+ disabled={!newTestName || !newTestMessage || createTestMutation.isPending}
86
+ >
87
+ {createTestMutation.isPending ? 'Creating...' : 'Create Test'}
88
+ </Button>
89
+ </View>
90
+ </Card>
91
+
92
+ {/* Test Results */}
93
+ <Card variant="outlined" padding="large">
94
+ <Text size="medium" weight="bold" style={{ marginBottom: 16 }}>
95
+ Test Entries ({tests?.count || 0})
96
+ </Text>
97
+
98
+ {tests?.data && tests.data.length > 0 ? (
99
+ <View style={{ gap: 12 }}>
100
+ {tests.data.map((test) => (
101
+ <Card key={test.id} variant="filled" padding="medium">
102
+ <View style={{
103
+ flexDirection: 'row',
104
+ justifyContent: 'space-between',
105
+ alignItems: 'flex-start',
106
+ gap: 12
107
+ }}>
108
+ <View style={{ flex: 1 }}>
109
+ <Text size="medium" weight="semibold" style={{ marginBottom: 4 }}>
110
+ {test.name}
111
+ </Text>
112
+ <Text size="small" style={{ marginBottom: 8, opacity: 0.8 }}>
113
+ {test.message}
114
+ </Text>
115
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 8 }}>
116
+ <Card
117
+ variant="filled"
118
+ padding="small"
119
+ intent={test.status === 'active' ? 'success' : 'neutral'}
120
+ >
121
+ <Text size="small" weight="semibold">
122
+ {test.status}
123
+ </Text>
124
+ </Card>
125
+ <Text size="small" style={{ opacity: 0.6 }}>
126
+ {new Date(test.createdAt).toLocaleDateString()}
127
+ </Text>
128
+ </View>
129
+ </View>
130
+ <Button
131
+ variant="outlined"
132
+ intent="error"
133
+ size="small"
134
+ onPress={() => handleDeleteTest(test.id)}
135
+ disabled={deleteTestMutation.isPending}
136
+ >
137
+ Delete
138
+ </Button>
139
+ </View>
140
+ </Card>
141
+ ))}
142
+ </View>
143
+ ) : (
144
+ <Card variant="filled" padding="medium" style={{ opacity: 0.6 }}>
145
+ <Text size="small" style={{ textAlign: 'center' }}>
146
+ No tests found. Create one above to get started!
147
+ </Text>
148
+ </Card>
149
+ )}
150
+ </Card>
151
+
152
+ {/* Type Safety Info */}
153
+ <Card variant="filled" intent="success" padding="medium">
154
+ <Text size="small" weight="semibold" style={{ marginBottom: 4 }}>
155
+ ✨ Type Safety Features:
156
+ </Text>
157
+ <Text size="small">
158
+ • Full TypeScript types from database to frontend • tRPC ensures API type safety •
159
+ Prisma provides database schema validation • Real-time type checking across the stack
160
+ </Text>
161
+ </Card>
162
+ </View>
163
+ );
164
+ };
@@ -1,93 +1,7 @@
1
- import { createTRPCReact } from '@trpc/react-query';
2
- import { createTRPCProxyClient, httpBatchLink } from '@trpc/client';
3
-
4
- // Import your API types here when you have an API project
5
- // Example: import type { AppRouter } from '@your-workspace/api';
6
-
7
- // For now, we'll use a generic type that you can replace
8
- type AppRouter = any;
9
-
10
- // Create the tRPC React hooks
11
- export const trpc = createTRPCReact<AppRouter>();
12
-
13
- // Create a vanilla client (for use outside of React components)
14
- export const trpcClient = createTRPCProxyClient<AppRouter>({
15
- links: [
16
- httpBatchLink({
17
- url: 'http://localhost:3000/trpc', // Update this to match your API URL
18
- // Optional: Add headers
19
- // headers() {
20
- // return {
21
- // authorization: getAuthToken(),
22
- // };
23
- // },
24
- }),
25
- ],
26
- });
27
-
28
- /*
29
- Usage Examples:
30
-
31
- 1. First, install the required dependencies:
32
- yarn add @trpc/client @trpc/react-query @tanstack/react-query
33
-
34
- 2. Replace the AppRouter type import above with your actual API router:
35
- import type { AppRouter } from '@your-workspace/api';
36
-
37
- 3. Set up the tRPC provider in your App component:
38
-
39
- ```tsx
40
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
41
- import { httpBatchLink } from '@trpc/client';
42
- import { trpc } from './utils/trpc';
43
-
44
- const queryClient = new QueryClient();
45
-
46
- const trpcClient = trpc.createClient({
47
- links: [
48
- httpBatchLink({
49
- url: 'http://localhost:3000/trpc',
50
- }),
51
- ],
52
- });
53
-
54
- function App() {
55
- return (
56
- <trpc.Provider client={trpcClient} queryClient={queryClient}>
57
- <QueryClientProvider client={queryClient}>
58
- // Your app components
59
- </QueryClientProvider>
60
- </trpc.Provider>
61
- );
62
- }
63
- ```
64
-
65
- 4. Use tRPC in your components:
66
-
67
- ```tsx
68
- import { trpc } from '../utils/trpc';
69
-
70
- function UsersList() {
71
- const { data: users, isLoading } = trpc.users.getAll.useQuery();
72
- const createUser = trpc.users.create.useMutation();
73
-
74
- if (isLoading) return <div>Loading...</div>;
75
-
76
- return (
77
- <div>
78
- {users?.map(user => (
79
- <div key={user.id}>{user.name}</div>
80
- ))}
81
- <button
82
- onClick={() => createUser.mutate({
83
- email: 'test@example.com',
84
- name: 'Test User'
85
- })}
86
- >
87
- Create User
88
- </button>
89
- </div>
90
- );
91
- }
92
- ```
93
- */
1
+ // Import tRPC client utilities from shared package
2
+ export {
3
+ trpc,
4
+ createTRPCClient,
5
+ createVanillaTRPCClient
6
+ } from '@{{workspaceScope}}/shared';
7
+ export type { TRPCClientConfig, AppRouter } from '@{{workspaceScope}}/shared';
@@ -4,7 +4,6 @@
4
4
  "lib": ["ES2020", "DOM", "DOM.Iterable"],
5
5
  "module": "ESNext",
6
6
  "skipLibCheck": true,
7
- "moduleResolution": "node",
8
7
  "allowImportingTsExtensions": true,
9
8
  "isolatedModules": true,
10
9
  "moduleDetection": "force",
@@ -6,10 +6,9 @@
6
6
 
7
7
  // Forward ports
8
8
  "forwardPorts": [
9
- 3000, // Web dev server
10
- 3001, // API server
9
+ 3000, // Api server
11
10
  5173, // Vite dev server
12
- 8080, // Additional dev server
11
+ 8081, // Metro Bundler
13
12
  19006, // Expo dev tools
14
13
  5432, // PostgreSQL
15
14
  6379, // Redis
@@ -19,10 +18,6 @@
19
18
  // Port attributes
20
19
  "portsAttributes": {
21
20
  "3000": {
22
- "label": "Web App",
23
- "onAutoForward": "openBrowser"
24
- },
25
- "3001": {
26
21
  "label": "API Server",
27
22
  "onAutoForward": "notify"
28
23
  },
@@ -30,8 +25,8 @@
30
25
  "label": "Vite Dev Server",
31
26
  "onAutoForward": "openBrowser"
32
27
  },
33
- "8080": {
34
- "label": "Additional Dev Server",
28
+ "8081": {
29
+ "label": "Metro Bundler",
35
30
  "onAutoForward": "notify"
36
31
  },
37
32
  "19006": {
@@ -30,9 +30,8 @@ services:
30
30
  REDIS_URL: redis://redis:6379
31
31
  ports:
32
32
  - "3000:3000"
33
- - "3001:3001"
34
33
  - "5173:5173"
35
- - "8080:8080"
34
+ - "8081:8081"
36
35
  - "19006:19006"
37
36
  volumes:
38
37
  - ..:/workspace
@@ -20,7 +20,7 @@ POSTGRES_PASSWORD=postgres
20
20
  REDIS_URL=redis://redis:6379
21
21
 
22
22
  # API Configuration
23
- API_PORT=3001
23
+ API_PORT=3000
24
24
  JWT_SECRET=your-jwt-secret-here
25
25
 
26
26
  # Web Configuration
@@ -15,7 +15,7 @@ POSTGRES_PORT=5432
15
15
  REDIS_PORT=6379
16
16
 
17
17
  # API Configuration
18
- API_PORT=3001
18
+ API_PORT=3000
19
19
  JWT_SECRET=your-jwt-secret-change-this-in-production
20
20
 
21
21
  # Web Configuration
@@ -45,13 +45,13 @@ COPY --from=builder /app/node_modules ./node_modules
45
45
  COPY --from=builder /app/package.json ./
46
46
 
47
47
  USER apiuser
48
- EXPOSE 3001
48
+ EXPOSE 3000
49
49
  ENV NODE_ENV=production
50
- ENV PORT=3001
50
+ ENV PORT=3000
51
51
 
52
52
  # Health check for API
53
53
  HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
54
- CMD node -e "require('http').get('http://localhost:3001/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) })"
54
+ CMD node -e "require('http').get('http://localhost:3000/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1) })"
55
55
 
56
56
  CMD ["node", "packages/api/dist/server.js"]
57
57
 
@@ -98,7 +98,7 @@ COPY --chown=devuser:devuser packages/web/package.json ./packages/web/
98
98
  # Install dependencies including dev dependencies
99
99
  RUN yarn install
100
100
 
101
- EXPOSE 3000 3001 5173 8080 19006
101
+ EXPOSE 3000 5173 1 19006
102
102
 
103
103
  CMD ["tail", "-f", "/dev/null"]
104
104