@idealyst/cli 1.0.41 → 1.0.44

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 (78) hide show
  1. package/dist/generators/api.js +1 -2
  2. package/dist/generators/api.js.map +1 -1
  3. package/dist/generators/database.js +1 -2
  4. package/dist/generators/database.js.map +1 -1
  5. package/dist/generators/fullstack.js +371 -0
  6. package/dist/generators/fullstack.js.map +1 -0
  7. package/dist/generators/index.js +5 -0
  8. package/dist/generators/index.js.map +1 -1
  9. package/dist/generators/native.js +2 -1
  10. package/dist/generators/native.js.map +1 -1
  11. package/dist/generators/shared.js +1 -2
  12. package/dist/generators/shared.js.map +1 -1
  13. package/dist/generators/utils.js +71 -7
  14. package/dist/generators/utils.js.map +1 -1
  15. package/dist/generators/web.js +1 -2
  16. package/dist/generators/web.js.map +1 -1
  17. package/dist/generators/workspace.js +56 -2
  18. package/dist/generators/workspace.js.map +1 -1
  19. package/dist/index.js +50 -2
  20. package/dist/index.js.map +1 -1
  21. package/dist/templates/database/.env.example +1 -8
  22. package/dist/templates/database/README.md +29 -74
  23. package/dist/templates/database/package.json +20 -34
  24. package/dist/templates/database/prisma/seed.ts +11 -11
  25. package/dist/templates/database/schema.prisma +97 -0
  26. package/dist/templates/database/src/index.ts +12 -8
  27. package/dist/templates/database/tsconfig.json +9 -23
  28. package/dist/templates/native/src/App-with-trpc-and-shared.tsx +266 -0
  29. package/dist/templates/shared/package.json +28 -3
  30. package/dist/templates/shared/src/components/index.ts +392 -0
  31. package/dist/templates/shared/src/index.ts +59 -1
  32. package/dist/templates/shared/src/types/index.ts +148 -0
  33. package/dist/templates/shared/src/utils/index.ts +278 -0
  34. package/dist/templates/web/package.json +2 -2
  35. package/dist/templates/web/src/App-with-trpc-and-shared.tsx +304 -0
  36. package/dist/templates/workspace/.devcontainer/Dockerfile +1 -1
  37. package/dist/templates/workspace/.devcontainer/devcontainer.json +7 -2
  38. package/dist/templates/workspace/.devcontainer/docker-compose.yml +14 -0
  39. package/dist/templates/workspace/.devcontainer/figma-mcp.sh +32 -0
  40. package/dist/templates/workspace/.devcontainer/setup.sh +3 -0
  41. package/dist/templates/workspace/setup.sh +22 -197
  42. package/dist/templates/workspace/tsconfig.json +32 -0
  43. package/dist/types/generators/fullstack.d.ts +2 -0
  44. package/dist/types/generators/index.d.ts +1 -0
  45. package/dist/types/generators/utils.d.ts +4 -1
  46. package/dist/types/types.d.ts +3 -1
  47. package/package.json +1 -1
  48. package/templates/database/.env.example +1 -0
  49. package/templates/database/README.md +48 -0
  50. package/templates/database/package.json +21 -2
  51. package/templates/database/prisma/seed.ts +28 -0
  52. package/templates/database/schema.prisma +85 -9
  53. package/templates/database/src/index.ts +7 -7
  54. package/templates/database/src/validators.ts +10 -0
  55. package/templates/native/src/App-with-trpc-and-shared.tsx +266 -0
  56. package/templates/shared/package.json +28 -3
  57. package/templates/shared/src/components/index.ts +392 -0
  58. package/templates/shared/src/index.ts +59 -1
  59. package/templates/shared/src/types/index.ts +148 -0
  60. package/templates/shared/src/utils/index.ts +278 -0
  61. package/templates/web/package.json +1 -1
  62. package/templates/web/src/App-with-trpc-and-shared.tsx +304 -0
  63. package/templates/workspace/.devcontainer/devcontainer.json +7 -2
  64. package/templates/workspace/.devcontainer/docker-compose.yml +14 -0
  65. package/templates/workspace/.devcontainer/figma-mcp.sh +32 -0
  66. package/templates/workspace/.devcontainer/setup.sh +3 -0
  67. package/templates/workspace/setup.sh +30 -0
  68. package/templates/workspace/tsconfig.json +32 -0
  69. package/dist/templates/database/__tests__/database.test.ts +0 -14
  70. package/dist/templates/database/jest.config.js +0 -19
  71. package/dist/templates/database/jest.setup.js +0 -11
  72. package/dist/templates/database/prisma/schema.prisma +0 -21
  73. package/dist/templates/database/src/client.ts +0 -18
  74. package/dist/templates/database/src/schemas.ts +0 -26
  75. package/dist/templates/workspace/scripts/docker/db-backup.sh +0 -230
  76. package/dist/templates/workspace/scripts/docker/deploy.sh +0 -212
  77. package/dist/templates/workspace/scripts/test-runner.js +0 -120
  78. /package/{templates/database/src/validatgors.ts → dist/templates/database/src/validators.ts} +0 -0
@@ -1,93 +1,48 @@
1
- # {{projectName}}
1
+ # Database Package
2
2
 
3
- {{description}}
3
+ This package provides database access and validation schemas for the workspace.
4
4
 
5
- A database layer built with Prisma and TypeScript, designed to be shared across multiple applications in your monorepo.
5
+ ## Setup
6
6
 
7
- ## Features
8
-
9
- - 🗄️ **Prisma ORM** - Type-safe database access
10
- - 📝 **Zod Schemas** - Runtime validation matching your database models
11
- - 📦 **Exportable Client** - Share database access across packages
12
- - 🔒 **TypeScript** - Full type safety
13
- - 🧪 **Testing Setup** - Jest configuration for database testing
14
- - 🔄 **Migration Scripts** - Database versioning and seeding
15
-
16
- ## Getting Started
17
-
18
- 1. **Environment Setup**
19
- ```bash
20
- cp .env.example .env
21
- # Edit .env with your database URL
22
- ```
7
+ 1. Install dependencies:
8
+ ```bash
9
+ yarn install
10
+ ```
23
11
 
24
- 2. **Generate Prisma Client**
25
- ```bash
26
- yarn db:generate
27
- ```
12
+ 2. Set up your environment:
13
+ ```bash
14
+ cp .env.example .env
15
+ # Edit .env with your database URL
16
+ ```
28
17
 
29
- 3. **Push Schema to Database**
30
- ```bash
31
- yarn db:push
32
- ```
18
+ 3. Generate the Prisma client:
19
+ ```bash
20
+ yarn db:generate
21
+ ```
33
22
 
34
- 4. **Open Prisma Studio** (Optional)
35
- ```bash
36
- yarn db:studio
37
- ```
23
+ 4. Push the schema to your database:
24
+ ```bash
25
+ yarn db:push
26
+ ```
38
27
 
39
28
  ## Usage
40
29
 
41
- ### In Other Packages
42
-
43
30
  ```typescript
44
- import { db, schemas } from '@your-org/{{projectName}}';
31
+ import { prisma, User, TestValidator } from '@{{workspaceScope}}/{{name}}';
45
32
 
46
33
  // Use the database client
47
- const users = await db.user.findMany();
34
+ const users = await prisma.user.findMany();
48
35
 
49
- // Use Zod schemas for validation
50
- const userData = schemas.createUser.parse(input);
36
+ // Use validators
37
+ const validatedData = TestValidator.parse(userData);
51
38
  ```
52
39
 
53
- ### Adding Models
54
-
55
- 1. Update `prisma/schema.prisma` with your models
56
- 2. Update `src/schemas.ts` with corresponding Zod schemas
57
- 3. Run `yarn db:generate` to update the client
58
- 4. Run `yarn db:push` to update the database
59
-
60
40
  ## Scripts
61
41
 
62
- - `yarn build` - Build the package for distribution
63
- - `yarn dev` - Run in development mode with file watching
64
- - `yarn test` - Run tests
65
- - `yarn test:watch` - Run tests in watch mode
66
42
  - `yarn db:generate` - Generate Prisma client
67
- - `yarn db:push` - Push schema changes to database
43
+ - `yarn db:push` - Push schema to database
44
+ - `yarn db:migrate` - Create and run migrations
68
45
  - `yarn db:studio` - Open Prisma Studio
69
- - `yarn db:migrate` - Create and apply migrations
70
- - `yarn db:reset` - Reset database and apply migrations
71
- - `yarn db:seed` - Seed the database
72
-
73
- ## Project Structure
74
-
75
- ```
76
- src/
77
- ├── index.ts # Main exports
78
- ├── client.ts # Prisma client setup
79
- └── schemas.ts # Zod validation schemas
80
- prisma/
81
- ├── schema.prisma # Database schema
82
- └── migrations/ # Database migrations
83
- __tests__/
84
- └── database.test.ts # Database tests
85
- ```
86
-
87
- ## Best Practices
88
-
89
- - Always update Zod schemas when changing Prisma models
90
- - Use meaningful migration names
91
- - Test database operations
92
- - Export only what's needed from the main index
93
- - Keep the client singleton pattern for performance
46
+ - `yarn db:reset` - Reset the database
47
+ - `yarn build` - Build the package
48
+ - `yarn dev` - Build in watch mode
@@ -1,61 +1,47 @@
1
1
  {
2
2
  "name": "{{packageName}}",
3
- "version": "{{version}}",
4
- "description": "{{description}}",
5
- "type": "module",
3
+ "version": "1.0.0",
4
+ "description": "Database layer with Prisma",
6
5
  "main": "dist/index.js",
7
6
  "types": "dist/index.d.ts",
8
7
  "exports": {
9
8
  ".": {
10
9
  "types": "./dist/index.d.ts",
11
- "import": "./dist/index.js"
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.js"
12
12
  },
13
13
  "./client": {
14
- "types": "./dist/client.d.ts",
15
- "import": "./dist/client.js"
14
+ "types": "./generated/client/index.d.ts",
15
+ "import": "./generated/client/index.js",
16
+ "require": "./generated/client/index.js"
16
17
  },
17
18
  "./schemas": {
18
- "types": "./dist/schemas.d.ts",
19
- "import": "./dist/schemas.js"
19
+ "types": "./dist/validators.d.ts",
20
+ "import": "./dist/validators.js",
21
+ "require": "./dist/validators.js"
20
22
  }
21
23
  },
22
24
  "scripts": {
23
25
  "build": "tsc",
24
- "test": "jest",
25
- "test:watch": "jest --watch",
26
- "test:coverage": "jest --coverage",
26
+ "dev": "tsc --watch",
27
27
  "db:generate": "prisma generate",
28
28
  "db:push": "prisma db push",
29
- "db:studio": "prisma studio",
30
29
  "db:migrate": "prisma migrate dev",
31
- "db:reset": "prisma migrate reset",
32
- "db:seed": "tsx prisma/seed.ts",
33
- "lint": "eslint src --ext .ts,.tsx",
34
- "lint:fix": "eslint src --ext .ts,.tsx --fix",
35
- "type-check": "tsc --noEmit",
36
- "dev": "tsx watch src/index.ts"
30
+ "db:studio": "prisma studio",
31
+ "db:reset": "prisma migrate reset"
37
32
  },
38
33
  "dependencies": {
39
- "@prisma/client": "^5.7.1",
34
+ "@prisma/client": "^5.19.1",
40
35
  "zod": "^3.22.4"
41
36
  },
42
37
  "devDependencies": {
43
- "@types/jest": "^29.5.12",
44
- "@types/node": "^20.10.4",
45
- "@typescript-eslint/eslint-plugin": "^6.13.1",
46
- "@typescript-eslint/parser": "^6.13.1",
47
- "dotenv": "^16.3.1",
48
- "eslint": "^8.54.0",
49
- "jest": "^29.7.0",
50
- "prisma": "^5.7.1",
51
- "ts-jest": "^29.1.2",
52
- "tsx": "^4.6.2",
38
+ "@types/node": "^20.10.0",
39
+ "prisma": "^5.19.1",
53
40
  "typescript": "^5.3.3"
54
41
  },
55
- "keywords": [
56
- "database",
57
- "prisma",
58
- "typescript",
59
- "orm"
42
+ "files": [
43
+ "dist/**/*",
44
+ "prisma/**/*",
45
+ "generated/**/*"
60
46
  ]
61
47
  }
@@ -1,28 +1,28 @@
1
- import { PrismaClient } from '@prisma/client';
1
+ import { PrismaClient } from '../generated/client';
2
2
 
3
3
  const prisma = new PrismaClient();
4
4
 
5
5
  async function main() {
6
- console.log('🌱 Seeding database...');
7
-
8
6
  // Add your seed data here
9
- // Example:
7
+ console.log('🌱 Seeding database...');
8
+
9
+ // Example seed data
10
10
  // const user = await prisma.user.create({
11
11
  // data: {
12
12
  // email: 'admin@example.com',
13
13
  // name: 'Admin User',
14
14
  // },
15
15
  // });
16
- // console.log('Created user:', user);
17
-
18
- console.log('✅ Database seeded successfully!');
16
+
17
+ console.log('✅ Seeding completed');
19
18
  }
20
19
 
21
20
  main()
22
- .catch((e) => {
23
- console.error('❌ Error seeding database:', e);
24
- process.exit(1);
21
+ .then(async () => {
22
+ await prisma.$disconnect();
25
23
  })
26
- .finally(async () => {
24
+ .catch(async (e) => {
25
+ console.error(e);
27
26
  await prisma.$disconnect();
27
+ process.exit(1);
28
28
  });
@@ -0,0 +1,97 @@
1
+ // This is your Prisma schema file,
2
+ // learn more about it in the docs: https://pris.ly/d/prisma-schema
3
+
4
+ generator client {
5
+ provider = "prisma-client-js"
6
+ output = "./generated/client"
7
+ }
8
+
9
+ datasource db {
10
+ provider = "sqlite"
11
+ url = env("DATABASE_URL")
12
+ }
13
+
14
+ // Demo User model with profile information
15
+ model User {
16
+ id String @id @default(cuid())
17
+ email String @unique
18
+ name String?
19
+ avatar String? // URL to profile image
20
+ bio String? // User biography
21
+ location String? // User location
22
+ website String? // Personal website
23
+
24
+ // Posts created by this user
25
+ posts Post[]
26
+
27
+ // Comments made by this user
28
+ comments Comment[]
29
+
30
+ // User preferences and settings
31
+ settings UserSettings?
32
+
33
+ createdAt DateTime @default(now())
34
+ updatedAt DateTime @updatedAt
35
+ }
36
+
37
+ // Demo Post model for a simple blog/social feed
38
+ model Post {
39
+ id String @id @default(cuid())
40
+ title String
41
+ content String
42
+ excerpt String? // Short description
43
+ published Boolean @default(false)
44
+ tags String? // Comma-separated tag strings
45
+
46
+ // Author relationship
47
+ author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
48
+ authorId String
49
+
50
+ // Comments on this post
51
+ comments Comment[]
52
+
53
+ // Post metadata
54
+ views Int @default(0)
55
+ likes Int @default(0)
56
+
57
+ createdAt DateTime @default(now())
58
+ updatedAt DateTime @updatedAt
59
+ }
60
+
61
+ // Demo Comment model
62
+ model Comment {
63
+ id String @id @default(cuid())
64
+ content String
65
+
66
+ // Author relationship
67
+ author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
68
+ authorId String
69
+
70
+ // Post relationship
71
+ post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
72
+ postId String
73
+
74
+ // Parent comment for nested threading
75
+ parent Comment? @relation("CommentThread", fields: [parentId], references: [id])
76
+ parentId String?
77
+ children Comment[] @relation("CommentThread")
78
+
79
+ createdAt DateTime @default(now())
80
+ updatedAt DateTime @updatedAt
81
+ }
82
+
83
+ // User settings and preferences
84
+ model UserSettings {
85
+ id String @id @default(cuid())
86
+ theme String @default("auto") // "light", "dark", "auto"
87
+ notifications Boolean @default(true)
88
+ emailUpdates Boolean @default(false)
89
+ publicProfile Boolean @default(true)
90
+
91
+ // User relationship (one-to-one)
92
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
93
+ userId String @unique
94
+
95
+ createdAt DateTime @default(now())
96
+ updatedAt DateTime @updatedAt
97
+ }
@@ -1,11 +1,15 @@
1
- // Export Prisma client
2
- export { PrismaClient } from '@prisma/client';
1
+ import { PrismaClient } from '../generated/client';
3
2
 
4
- // Export database client instance
5
- export { default as db } from './client';
3
+ declare global {
4
+ var __prisma: PrismaClient | undefined;
5
+ }
6
6
 
7
- // Export Zod schemas
8
- export * from './schemas';
7
+ export const prisma = globalThis.__prisma || new PrismaClient();
9
8
 
10
- // Export types from Prisma
11
- export type * from '@prisma/client';
9
+ if (process.env.NODE_ENV !== 'production') {
10
+ globalThis.__prisma = prisma;
11
+ }
12
+
13
+ export * from './validators';
14
+ export * from '../generated/client';
15
+ export default prisma;
@@ -1,32 +1,18 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "ES2020",
4
+ "module": "commonjs",
4
5
  "lib": ["ES2020"],
5
- "module": "ESNext",
6
- "moduleResolution": "node",
7
- "allowSyntheticDefaultImports": true,
8
- "esModuleInterop": true,
9
- "forceConsistentCasingInFileNames": true,
6
+ "outDir": "./dist",
7
+ "rootDir": "./src",
10
8
  "strict": true,
9
+ "esModuleInterop": true,
11
10
  "skipLibCheck": true,
11
+ "forceConsistentCasingInFileNames": true,
12
12
  "declaration": true,
13
13
  "declarationMap": true,
14
- "sourceMap": true,
15
- "outDir": "./dist",
16
- "rootDir": "./src",
17
- "resolveJsonModule": true,
18
- "allowJs": false,
19
- "noUncheckedIndexedAccess": true,
20
- "experimentalDecorators": true,
21
- "emitDecoratorMetadata": true
14
+ "sourceMap": true
22
15
  },
23
- "include": [
24
- "src/**/*",
25
- "prisma/**/*"
26
- ],
27
- "exclude": [
28
- "node_modules",
29
- "dist",
30
- "__tests__"
31
- ]
32
- }
16
+ "include": ["src/**/*"],
17
+ "exclude": ["node_modules", "dist"]
18
+ }
@@ -0,0 +1,266 @@
1
+ import React, { useState } from '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';
6
+
7
+ // Import shared components and utilities
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
+ });
39
+
40
+ 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
+ return (
251
+ <trpc.Provider client={trpcClient} queryClient={queryClient}>
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>
263
+ );
264
+ }
265
+
266
+ export default App;