@idealyst/cli 1.0.40 → 1.0.43
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/api.js +1 -2
- package/dist/generators/api.js.map +1 -1
- package/dist/generators/database.js +1 -2
- package/dist/generators/database.js.map +1 -1
- package/dist/generators/fullstack.js +371 -0
- package/dist/generators/fullstack.js.map +1 -0
- package/dist/generators/index.js +5 -0
- package/dist/generators/index.js.map +1 -1
- package/dist/generators/native.js +2 -1
- package/dist/generators/native.js.map +1 -1
- package/dist/generators/shared.js +1 -2
- package/dist/generators/shared.js.map +1 -1
- package/dist/generators/utils.js +71 -7
- package/dist/generators/utils.js.map +1 -1
- package/dist/generators/web.js +1 -2
- package/dist/generators/web.js.map +1 -1
- package/dist/generators/workspace.js +56 -2
- package/dist/generators/workspace.js.map +1 -1
- package/dist/index.js +50 -2
- package/dist/index.js.map +1 -1
- package/dist/templates/database/.env.example +1 -8
- package/dist/templates/database/README.md +29 -74
- package/dist/templates/database/package.json +20 -34
- package/dist/templates/database/prisma/seed.ts +11 -11
- package/dist/templates/database/schema.prisma +97 -0
- package/dist/templates/database/src/index.ts +12 -8
- package/dist/templates/database/src/validators.ts +10 -0
- package/dist/templates/database/tsconfig.json +9 -23
- package/dist/templates/native/src/App-with-trpc-and-shared.tsx +266 -0
- package/dist/templates/shared/package.json +28 -3
- package/dist/templates/shared/src/components/index.ts +392 -0
- package/dist/templates/shared/src/index.ts +59 -1
- package/dist/templates/shared/src/types/index.ts +148 -0
- package/dist/templates/shared/src/utils/index.ts +278 -0
- package/dist/templates/web/package.json +2 -2
- package/dist/templates/web/src/App-with-trpc-and-shared.tsx +304 -0
- package/dist/templates/workspace/.devcontainer/Dockerfile +1 -1
- package/dist/templates/workspace/.devcontainer/devcontainer.json +7 -2
- package/dist/templates/workspace/.devcontainer/docker-compose.yml +14 -0
- package/dist/templates/workspace/.devcontainer/figma-mcp.sh +32 -0
- package/dist/templates/workspace/.devcontainer/setup.sh +3 -0
- package/dist/templates/workspace/setup.sh +22 -197
- package/dist/templates/workspace/tsconfig.json +32 -0
- package/dist/types/generators/fullstack.d.ts +2 -0
- package/dist/types/generators/index.d.ts +1 -0
- package/dist/types/generators/utils.d.ts +4 -1
- package/dist/types/types.d.ts +3 -1
- package/package.json +1 -1
- package/templates/database/.env.example +1 -8
- package/templates/database/README.md +29 -74
- package/templates/database/package.json +20 -34
- package/templates/database/prisma/seed.ts +11 -11
- package/templates/database/schema.prisma +97 -0
- package/templates/database/src/index.ts +12 -8
- package/templates/database/src/validators.ts +10 -0
- package/templates/database/tsconfig.json +9 -23
- package/templates/native/src/App-with-trpc-and-shared.tsx +266 -0
- package/templates/shared/package.json +28 -3
- package/templates/shared/src/components/index.ts +392 -0
- package/templates/shared/src/index.ts +59 -1
- package/templates/shared/src/types/index.ts +148 -0
- package/templates/shared/src/utils/index.ts +278 -0
- package/templates/web/package.json +1 -1
- package/templates/web/src/App-with-trpc-and-shared.tsx +304 -0
- package/templates/workspace/.devcontainer/devcontainer.json +7 -2
- package/templates/workspace/.devcontainer/docker-compose.yml +14 -0
- package/templates/workspace/.devcontainer/figma-mcp.sh +32 -0
- package/templates/workspace/.devcontainer/setup.sh +3 -0
- package/templates/workspace/setup.sh +22 -197
- package/templates/workspace/tsconfig.json +32 -0
- package/dist/templates/database/__tests__/database.test.ts +0 -14
- package/dist/templates/database/jest.config.js +0 -19
- package/dist/templates/database/jest.setup.js +0 -11
- package/dist/templates/database/prisma/schema.prisma +0 -21
- package/dist/templates/database/src/client.ts +0 -18
- package/dist/templates/database/src/schemas.ts +0 -26
- package/dist/templates/workspace/scripts/docker/db-backup.sh +0 -230
- package/dist/templates/workspace/scripts/docker/deploy.sh +0 -212
- package/dist/templates/workspace/scripts/test-runner.js +0 -120
- package/templates/database/__tests__/database.test.ts +0 -14
- package/templates/database/jest.config.js +0 -19
- package/templates/database/jest.setup.js +0 -11
- package/templates/database/prisma/schema.prisma +0 -21
- package/templates/database/src/client.ts +0 -18
- package/templates/database/src/schemas.ts +0 -26
- package/templates/workspace/scripts/docker/db-backup.sh +0 -230
- package/templates/workspace/scripts/docker/deploy.sh +0 -212
- package/templates/workspace/scripts/docker-build.sh +0 -151
- package/templates/workspace/scripts/test-runner.js +0 -120
|
@@ -1,93 +1,48 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Database Package
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
This package provides database access and validation schemas for the workspace.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Setup
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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.
|
|
25
|
-
|
|
26
|
-
|
|
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.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
18
|
+
3. Generate the Prisma client:
|
|
19
|
+
```bash
|
|
20
|
+
yarn db:generate
|
|
21
|
+
```
|
|
33
22
|
|
|
34
|
-
4.
|
|
35
|
-
|
|
36
|
-
|
|
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 {
|
|
31
|
+
import { prisma, User, TestValidator } from '@{{workspaceScope}}/{{name}}';
|
|
45
32
|
|
|
46
33
|
// Use the database client
|
|
47
|
-
const users = await
|
|
34
|
+
const users = await prisma.user.findMany();
|
|
48
35
|
|
|
49
|
-
// Use
|
|
50
|
-
const
|
|
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
|
|
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:
|
|
70
|
-
- `yarn
|
|
71
|
-
- `yarn
|
|
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": "
|
|
4
|
-
"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": "./
|
|
15
|
-
"import": "./
|
|
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/
|
|
19
|
-
"import": "./dist/
|
|
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
|
-
"
|
|
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:
|
|
32
|
-
"db:
|
|
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.
|
|
34
|
+
"@prisma/client": "^5.19.1",
|
|
40
35
|
"zod": "^3.22.4"
|
|
41
36
|
},
|
|
42
37
|
"devDependencies": {
|
|
43
|
-
"@types/
|
|
44
|
-
"
|
|
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
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"prisma",
|
|
58
|
-
"
|
|
59
|
-
"orm"
|
|
42
|
+
"files": [
|
|
43
|
+
"dist/**/*",
|
|
44
|
+
"prisma/**/*",
|
|
45
|
+
"generated/**/*"
|
|
60
46
|
]
|
|
61
47
|
}
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
import { PrismaClient } from '
|
|
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
|
-
|
|
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
|
-
|
|
17
|
-
|
|
18
|
-
console.log('✅ Database seeded successfully!');
|
|
16
|
+
|
|
17
|
+
console.log('✅ Seeding completed');
|
|
19
18
|
}
|
|
20
19
|
|
|
21
20
|
main()
|
|
22
|
-
.
|
|
23
|
-
|
|
24
|
-
process.exit(1);
|
|
21
|
+
.then(async () => {
|
|
22
|
+
await prisma.$disconnect();
|
|
25
23
|
})
|
|
26
|
-
.
|
|
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
|
-
|
|
2
|
-
export { PrismaClient } from '@prisma/client';
|
|
1
|
+
import { PrismaClient } from '../generated/client';
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
declare global {
|
|
4
|
+
var __prisma: PrismaClient | undefined;
|
|
5
|
+
}
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
export * from './schemas';
|
|
7
|
+
export const prisma = globalThis.__prisma || new PrismaClient();
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
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;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Create model validators for each model defined in the Prisma schema using Zod
|
|
2
|
+
// E.g
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
|
|
5
|
+
export const TestValidator = z.object({
|
|
6
|
+
id: z.string().uuid(),
|
|
7
|
+
email: z.string().email(),
|
|
8
|
+
name: z.string().min(2).max(100),
|
|
9
|
+
age: z.number().min(0).optional()
|
|
10
|
+
});
|
|
@@ -1,32 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"compilerOptions": {
|
|
3
3
|
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
4
5
|
"lib": ["ES2020"],
|
|
5
|
-
"
|
|
6
|
-
"
|
|
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
|
-
|
|
25
|
-
|
|
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;
|