@idealyst/cli 1.0.90 → 1.0.92
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/init.js +8 -13
- package/dist/generators/init.js.map +1 -1
- package/dist/generators/utils.js +3 -7
- package/dist/generators/utils.js.map +1 -1
- package/dist/template/.devcontainer/gitignore.template +2 -0
- package/dist/template/gitignore.template +56 -0
- package/dist/template/mcp.json.template +8 -0
- package/dist/template/packages/api/gitignore.template +35 -0
- package/dist/template/packages/database/gitignore.template +41 -0
- package/dist/template/packages/mobile/babel.config.js +1 -2
- package/dist/template/packages/mobile/gitignore.template +73 -0
- package/dist/template/packages/mobile/package.json +10 -2
- package/dist/template/packages/shared/gitignore.template +35 -0
- package/dist/template/packages/web/gitignore.template +35 -0
- package/dist/template/yarnrc.yml.template +4 -0
- package/package.json +2 -2
- package/template/.devcontainer/Dockerfile +26 -0
- package/template/.devcontainer/devcontainer.json +113 -0
- package/template/.devcontainer/docker-compose.yml +59 -0
- package/template/.devcontainer/figma-mcp.sh +32 -0
- package/template/.devcontainer/setup.sh +45 -0
- package/template/.dockerignore +151 -0
- package/template/.env.example +36 -0
- package/template/.env.production +56 -0
- package/template/DOCKER.md +0 -0
- package/template/Dockerfile +111 -0
- package/template/README.md +233 -0
- package/template/docker/nginx/prod.conf +238 -0
- package/template/docker/nginx.conf +131 -0
- package/template/docker/postgres/init.sql +41 -0
- package/template/docker/prometheus/prometheus.yml +52 -0
- package/template/docker-compose.prod.yml +146 -0
- package/template/docker-compose.yml +143 -0
- package/template/jest.config.js +20 -0
- package/template/package.json +45 -0
- package/template/packages/api/.env.example +6 -0
- package/template/packages/api/README.md +274 -0
- package/template/packages/api/__tests__/api.test.ts +26 -0
- package/template/packages/api/jest.config.js +23 -0
- package/template/packages/api/jest.setup.js +9 -0
- package/template/packages/api/package.json +56 -0
- package/template/packages/api/src/context.ts +19 -0
- package/template/packages/api/src/controllers/TestController.ts +0 -0
- package/template/packages/api/src/index.ts +9 -0
- package/template/packages/api/src/lib/crud.ts +150 -0
- package/template/packages/api/src/lib/database.ts +23 -0
- package/template/packages/api/src/router/index.ts +163 -0
- package/template/packages/api/src/routers/test.ts +59 -0
- package/template/packages/api/src/routers/user.example.ts +83 -0
- package/template/packages/api/src/server.ts +50 -0
- package/template/packages/api/src/trpc.ts +28 -0
- package/template/packages/api/tsconfig.json +43 -0
- package/template/packages/database/README.md +162 -0
- package/template/packages/database/package.json +49 -0
- package/template/packages/database/prisma/seed.ts +64 -0
- package/template/packages/database/schema.prisma +107 -0
- package/template/packages/database/src/index.ts +15 -0
- package/template/packages/database/src/validators.ts +10 -0
- package/template/packages/database/tsconfig.json +18 -0
- package/template/packages/mobile/README.md +86 -0
- package/template/packages/mobile/__tests__/App.test.tsx +156 -0
- package/template/packages/mobile/__tests__/components.test.tsx +300 -0
- package/template/packages/mobile/app.json +5 -0
- package/template/packages/mobile/babel.config.js +10 -0
- package/template/packages/mobile/index.js +6 -0
- package/template/packages/mobile/jest.config.js +21 -0
- package/template/packages/mobile/jest.setup.js +12 -0
- package/template/packages/mobile/metro.config.js +27 -0
- package/template/packages/mobile/package.json +60 -0
- package/template/packages/mobile/src/utils/trpc.ts +7 -0
- package/template/packages/mobile/tsconfig.json +28 -0
- package/template/packages/shared/README.md +135 -0
- package/template/packages/shared/__tests__/shared.test.ts +51 -0
- package/template/packages/shared/jest.config.js +22 -0
- package/template/packages/shared/package.json +62 -0
- package/template/packages/shared/src/components/App.tsx +46 -0
- package/template/packages/shared/src/components/HelloWorld.tsx +304 -0
- package/template/packages/shared/src/components/index.ts +1 -0
- package/template/packages/shared/src/index.ts +14 -0
- package/template/packages/shared/src/navigation/AppRouter.tsx +565 -0
- package/template/packages/shared/src/trpc/client.ts +44 -0
- package/template/packages/shared/tsconfig.json +22 -0
- package/template/packages/web/README.md +131 -0
- package/template/packages/web/__tests__/App.test.tsx +342 -0
- package/template/packages/web/__tests__/components.test.tsx +564 -0
- package/template/packages/web/index.html +13 -0
- package/template/packages/web/jest.config.js +27 -0
- package/template/packages/web/jest.setup.js +24 -0
- package/template/packages/web/package.json +69 -0
- package/template/packages/web/src/components/TestDemo.tsx +164 -0
- package/template/packages/web/src/main.tsx +25 -0
- package/template/packages/web/src/utils/trpc.ts +7 -0
- package/template/packages/web/tsconfig.json +26 -0
- package/template/packages/web/vite.config.ts +98 -0
- package/template/setup.sh +30 -0
- package/template/tsconfig.json +31 -0
- package/dist/template/packages/mobile/src/App-with-trpc.tsx +0 -30
- package/dist/template/packages/web/src/App-with-trpc.tsx +0 -32
- /package/dist/template/{.dockerignore → dockerignore.template} +0 -0
- /package/dist/template/{.env.example → env.example.template} +0 -0
- /package/dist/template/packages/api/{.env.example → env.example.template} +0 -0
- /package/{dist/template/packages/mobile/src/App-with-trpc-and-shared.tsx → template/packages/mobile/src/App.tsx} +0 -0
- /package/{dist/template/packages/web/src/App-with-trpc-and-shared.tsx → template/packages/web/src/App.tsx} +0 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Database Package
|
|
2
|
+
|
|
3
|
+
This package provides database access and validation schemas for the workspace using Prisma ORM.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
1. Install dependencies:
|
|
8
|
+
```bash
|
|
9
|
+
yarn install
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
2. Set up your environment:
|
|
13
|
+
```bash
|
|
14
|
+
cp .env.example .env
|
|
15
|
+
# Edit .env with your database URL
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
3. Generate the Prisma client:
|
|
19
|
+
```bash
|
|
20
|
+
yarn db:generate
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
4. Push the schema to your database:
|
|
24
|
+
```bash
|
|
25
|
+
yarn db:push
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
5. Seed the database with test data:
|
|
29
|
+
```bash
|
|
30
|
+
yarn db:seed
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Database Schema
|
|
34
|
+
|
|
35
|
+
### Test Model
|
|
36
|
+
|
|
37
|
+
The Test model is included for quick testing and API demonstration:
|
|
38
|
+
|
|
39
|
+
```prisma
|
|
40
|
+
model Test {
|
|
41
|
+
id String @id @default(cuid())
|
|
42
|
+
name String
|
|
43
|
+
message String
|
|
44
|
+
status String @default("active")
|
|
45
|
+
createdAt DateTime @default(now())
|
|
46
|
+
updatedAt DateTime @updatedAt
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
#### Fields:
|
|
51
|
+
- `id`: Unique identifier (CUID)
|
|
52
|
+
- `name`: Test name/title
|
|
53
|
+
- `message`: Test message content
|
|
54
|
+
- `status`: Test status (defaults to "active")
|
|
55
|
+
- `createdAt`: Record creation timestamp
|
|
56
|
+
- `updatedAt`: Record last update timestamp
|
|
57
|
+
|
|
58
|
+
### Sample Models
|
|
59
|
+
|
|
60
|
+
The schema also includes comprehensive example models for reference:
|
|
61
|
+
|
|
62
|
+
#### User Model
|
|
63
|
+
- Complete user management with authentication fields
|
|
64
|
+
- Email validation and profile information
|
|
65
|
+
- Timestamps for tracking
|
|
66
|
+
|
|
67
|
+
#### Post Model
|
|
68
|
+
- Blog post or content management
|
|
69
|
+
- User relationship for authorship
|
|
70
|
+
- Publishing status and timestamps
|
|
71
|
+
|
|
72
|
+
#### Comment Model
|
|
73
|
+
- Comment system for posts
|
|
74
|
+
- User and post relationships
|
|
75
|
+
- Moderation support
|
|
76
|
+
|
|
77
|
+
## Usage
|
|
78
|
+
|
|
79
|
+
### In API Code
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { db } from '@{{workspaceScope}}/database';
|
|
83
|
+
|
|
84
|
+
// Create a test record
|
|
85
|
+
const test = await db.test.create({
|
|
86
|
+
data: {
|
|
87
|
+
name: 'My Test',
|
|
88
|
+
message: 'This is a test message',
|
|
89
|
+
status: 'active'
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Get all tests
|
|
94
|
+
const tests = await db.test.findMany();
|
|
95
|
+
|
|
96
|
+
// Update a test
|
|
97
|
+
const updatedTest = await db.test.update({
|
|
98
|
+
where: { id: 'test-id' },
|
|
99
|
+
data: { status: 'completed' }
|
|
100
|
+
});
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Prisma Commands
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Generate client
|
|
107
|
+
yarn prisma:generate
|
|
108
|
+
|
|
109
|
+
# Run migrations
|
|
110
|
+
yarn prisma:migrate
|
|
111
|
+
|
|
112
|
+
# Reset database
|
|
113
|
+
yarn prisma:reset
|
|
114
|
+
|
|
115
|
+
# Seed database
|
|
116
|
+
yarn prisma:seed
|
|
117
|
+
|
|
118
|
+
# Open Prisma Studio
|
|
119
|
+
yarn prisma:studio
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Quick Test
|
|
123
|
+
|
|
124
|
+
The database includes a simple `Test` model for immediate testing:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
import { prisma } from '@{{workspaceScope}}/{{name}}';
|
|
128
|
+
|
|
129
|
+
// Get all test entries
|
|
130
|
+
const tests = await prisma.test.findMany();
|
|
131
|
+
|
|
132
|
+
// Create a new test entry
|
|
133
|
+
const newTest = await prisma.test.create({
|
|
134
|
+
data: {
|
|
135
|
+
name: 'My Test',
|
|
136
|
+
message: 'Testing the database connection',
|
|
137
|
+
status: 'active',
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Usage
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { prisma, User, TestValidator } from '@{{workspaceScope}}/{{name}}';
|
|
146
|
+
|
|
147
|
+
// Use the database client
|
|
148
|
+
const users = await prisma.user.findMany();
|
|
149
|
+
|
|
150
|
+
// Use validators
|
|
151
|
+
const validatedData = TestValidator.parse(userData);
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Scripts
|
|
155
|
+
|
|
156
|
+
- `yarn db:generate` - Generate Prisma client
|
|
157
|
+
- `yarn db:push` - Push schema to database
|
|
158
|
+
- `yarn db:migrate` - Create and run migrations
|
|
159
|
+
- `yarn db:studio` - Open Prisma Studio
|
|
160
|
+
- `yarn db:reset` - Reset the database
|
|
161
|
+
- `yarn build` - Build the package
|
|
162
|
+
- `yarn dev` - Build in watch mode
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@{{workspaceScope}}/database",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Database layer with Prisma",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"require": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./client": {
|
|
14
|
+
"types": "./generated/client/index.d.ts",
|
|
15
|
+
"import": "./generated/client/index.js",
|
|
16
|
+
"require": "./generated/client/index.js"
|
|
17
|
+
},
|
|
18
|
+
"./schemas": {
|
|
19
|
+
"types": "./dist/validators.d.ts",
|
|
20
|
+
"import": "./dist/validators.js",
|
|
21
|
+
"require": "./dist/validators.js"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc",
|
|
26
|
+
"dev": "tsc --watch",
|
|
27
|
+
"db:generate": "prisma generate",
|
|
28
|
+
"db:push": "prisma db push",
|
|
29
|
+
"db:migrate": "prisma migrate dev",
|
|
30
|
+
"db:studio": "prisma studio",
|
|
31
|
+
"db:seed": "tsx prisma/seed.ts",
|
|
32
|
+
"db:reset": "prisma migrate reset"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@prisma/client": "^5.19.1",
|
|
36
|
+
"zod": "^3.22.4"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@types/node": "^20.10.0",
|
|
40
|
+
"prisma": "^5.19.1",
|
|
41
|
+
"tsx": "^4.7.0",
|
|
42
|
+
"typescript": "^5.3.3"
|
|
43
|
+
},
|
|
44
|
+
"files": [
|
|
45
|
+
"dist/**/*",
|
|
46
|
+
"prisma/**/*",
|
|
47
|
+
"generated/**/*"
|
|
48
|
+
]
|
|
49
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { PrismaClient } from '../generated/client';
|
|
2
|
+
|
|
3
|
+
const prisma = new PrismaClient();
|
|
4
|
+
|
|
5
|
+
async function main() {
|
|
6
|
+
// Add your seed data here
|
|
7
|
+
console.log('🌱 Seeding database...');
|
|
8
|
+
|
|
9
|
+
// Create some test data for the Test model
|
|
10
|
+
console.log('📝 Creating test entries...');
|
|
11
|
+
|
|
12
|
+
const testEntries = await Promise.all([
|
|
13
|
+
prisma.test.create({
|
|
14
|
+
data: {
|
|
15
|
+
name: 'API Connection Test',
|
|
16
|
+
message: 'This test verifies that the API can connect to the database successfully.',
|
|
17
|
+
status: 'active',
|
|
18
|
+
},
|
|
19
|
+
}),
|
|
20
|
+
prisma.test.create({
|
|
21
|
+
data: {
|
|
22
|
+
name: 'Data Validation Test',
|
|
23
|
+
message: 'This test ensures that data validation is working correctly across the stack.',
|
|
24
|
+
status: 'active',
|
|
25
|
+
},
|
|
26
|
+
}),
|
|
27
|
+
prisma.test.create({
|
|
28
|
+
data: {
|
|
29
|
+
name: 'tRPC Integration Test',
|
|
30
|
+
message: 'This test confirms that tRPC endpoints are properly configured and accessible.',
|
|
31
|
+
status: 'active',
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
prisma.test.create({
|
|
35
|
+
data: {
|
|
36
|
+
name: 'Sample Inactive Test',
|
|
37
|
+
message: 'This is an example of an inactive test entry.',
|
|
38
|
+
status: 'inactive',
|
|
39
|
+
},
|
|
40
|
+
}),
|
|
41
|
+
]);
|
|
42
|
+
|
|
43
|
+
console.log(`✅ Created ${testEntries.length} test entries`);
|
|
44
|
+
|
|
45
|
+
// Example seed data for other models (uncommented for reference)
|
|
46
|
+
// const user = await prisma.user.create({
|
|
47
|
+
// data: {
|
|
48
|
+
// email: 'admin@example.com',
|
|
49
|
+
// name: 'Admin User',
|
|
50
|
+
// },
|
|
51
|
+
// });
|
|
52
|
+
|
|
53
|
+
console.log('✅ Seeding completed');
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
main()
|
|
57
|
+
.then(async () => {
|
|
58
|
+
await prisma.$disconnect();
|
|
59
|
+
})
|
|
60
|
+
.catch(async (e) => {
|
|
61
|
+
console.error(e);
|
|
62
|
+
await prisma.$disconnect();
|
|
63
|
+
process.exit(1);
|
|
64
|
+
});
|
|
@@ -0,0 +1,107 @@
|
|
|
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 = "postgres"
|
|
11
|
+
url = env("DATABASE_URL")
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Simple Test model for quick API testing
|
|
15
|
+
model Test {
|
|
16
|
+
id String @id @default(cuid())
|
|
17
|
+
name String
|
|
18
|
+
message String
|
|
19
|
+
status String @default("active") // "active", "inactive"
|
|
20
|
+
createdAt DateTime @default(now())
|
|
21
|
+
updatedAt DateTime @updatedAt
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Demo User model with profile information
|
|
25
|
+
model User {
|
|
26
|
+
id String @id @default(cuid())
|
|
27
|
+
email String @unique
|
|
28
|
+
name String?
|
|
29
|
+
avatar String? // URL to profile image
|
|
30
|
+
bio String? // User biography
|
|
31
|
+
location String? // User location
|
|
32
|
+
website String? // Personal website
|
|
33
|
+
|
|
34
|
+
// Posts created by this user
|
|
35
|
+
posts Post[]
|
|
36
|
+
|
|
37
|
+
// Comments made by this user
|
|
38
|
+
comments Comment[]
|
|
39
|
+
|
|
40
|
+
// User preferences and settings
|
|
41
|
+
settings UserSettings?
|
|
42
|
+
|
|
43
|
+
createdAt DateTime @default(now())
|
|
44
|
+
updatedAt DateTime @updatedAt
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Demo Post model for a simple blog/social feed
|
|
48
|
+
model Post {
|
|
49
|
+
id String @id @default(cuid())
|
|
50
|
+
title String
|
|
51
|
+
content String
|
|
52
|
+
excerpt String? // Short description
|
|
53
|
+
published Boolean @default(false)
|
|
54
|
+
tags String? // Comma-separated tag strings
|
|
55
|
+
|
|
56
|
+
// Author relationship
|
|
57
|
+
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
|
|
58
|
+
authorId String
|
|
59
|
+
|
|
60
|
+
// Comments on this post
|
|
61
|
+
comments Comment[]
|
|
62
|
+
|
|
63
|
+
// Post metadata
|
|
64
|
+
views Int @default(0)
|
|
65
|
+
likes Int @default(0)
|
|
66
|
+
|
|
67
|
+
createdAt DateTime @default(now())
|
|
68
|
+
updatedAt DateTime @updatedAt
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Demo Comment model
|
|
72
|
+
model Comment {
|
|
73
|
+
id String @id @default(cuid())
|
|
74
|
+
content String
|
|
75
|
+
|
|
76
|
+
// Author relationship
|
|
77
|
+
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
|
|
78
|
+
authorId String
|
|
79
|
+
|
|
80
|
+
// Post relationship
|
|
81
|
+
post Post @relation(fields: [postId], references: [id], onDelete: Cascade)
|
|
82
|
+
postId String
|
|
83
|
+
|
|
84
|
+
// Parent comment for nested threading
|
|
85
|
+
parent Comment? @relation("CommentThread", fields: [parentId], references: [id])
|
|
86
|
+
parentId String?
|
|
87
|
+
children Comment[] @relation("CommentThread")
|
|
88
|
+
|
|
89
|
+
createdAt DateTime @default(now())
|
|
90
|
+
updatedAt DateTime @updatedAt
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// User settings and preferences
|
|
94
|
+
model UserSettings {
|
|
95
|
+
id String @id @default(cuid())
|
|
96
|
+
theme String @default("auto") // "light", "dark", "auto"
|
|
97
|
+
notifications Boolean @default(true)
|
|
98
|
+
emailUpdates Boolean @default(false)
|
|
99
|
+
publicProfile Boolean @default(true)
|
|
100
|
+
|
|
101
|
+
// User relationship (one-to-one)
|
|
102
|
+
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
|
|
103
|
+
userId String @unique
|
|
104
|
+
|
|
105
|
+
createdAt DateTime @default(now())
|
|
106
|
+
updatedAt DateTime @updatedAt
|
|
107
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PrismaClient } from '../generated/client';
|
|
2
|
+
|
|
3
|
+
declare global {
|
|
4
|
+
var __prisma: PrismaClient | undefined;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export const prisma = globalThis.__prisma || new PrismaClient();
|
|
8
|
+
|
|
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
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["ES2020"],
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"sourceMap": true
|
|
15
|
+
},
|
|
16
|
+
"include": ["src/**/*"],
|
|
17
|
+
"exclude": ["node_modules", "dist"]
|
|
18
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# {{projectName}}
|
|
2
|
+
|
|
3
|
+
{{description}}
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
This is a React Native application built with the Idealyst Framework.
|
|
8
|
+
|
|
9
|
+
### Prerequisites
|
|
10
|
+
|
|
11
|
+
- Node.js 18+
|
|
12
|
+
- Yarn
|
|
13
|
+
- React Native development environment
|
|
14
|
+
- Android Studio (for Android development)
|
|
15
|
+
- Xcode (for iOS development)
|
|
16
|
+
|
|
17
|
+
### Installation
|
|
18
|
+
|
|
19
|
+
Install dependencies:
|
|
20
|
+
```bash
|
|
21
|
+
yarn install
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Running the App
|
|
25
|
+
|
|
26
|
+
Start the Metro bundler:
|
|
27
|
+
```bash
|
|
28
|
+
yarn start
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Run on Android:
|
|
32
|
+
```bash
|
|
33
|
+
yarn android
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Run on iOS:
|
|
37
|
+
```bash
|
|
38
|
+
yarn ios
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Project Structure
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
{{projectName}}/
|
|
45
|
+
├── src/
|
|
46
|
+
│ └── App.tsx # Main app component
|
|
47
|
+
├── android/ # Android-specific code
|
|
48
|
+
├── ios/ # iOS-specific code
|
|
49
|
+
├── babel.config.js # Babel configuration
|
|
50
|
+
├── metro.config.js # Metro configuration
|
|
51
|
+
└── tsconfig.json # TypeScript configuration
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Features
|
|
55
|
+
|
|
56
|
+
- **Idealyst Components**: Pre-built UI components
|
|
57
|
+
- **Idealyst Navigation**: Cross-platform navigation
|
|
58
|
+
- **Idealyst Theme**: Consistent theming system
|
|
59
|
+
- **TypeScript**: Full type safety
|
|
60
|
+
- **React Native 0.80.1**: Latest stable version
|
|
61
|
+
|
|
62
|
+
### Development
|
|
63
|
+
|
|
64
|
+
The app uses the Idealyst Framework for consistent UI and navigation across platforms.
|
|
65
|
+
|
|
66
|
+
Edit `src/App.tsx` to start building your application.
|
|
67
|
+
|
|
68
|
+
### Building for Production
|
|
69
|
+
|
|
70
|
+
Build Android APK:
|
|
71
|
+
```bash
|
|
72
|
+
yarn build:android
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Testing
|
|
76
|
+
|
|
77
|
+
Run tests:
|
|
78
|
+
```bash
|
|
79
|
+
yarn test
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Learn More
|
|
83
|
+
|
|
84
|
+
- [Idealyst Framework Documentation](https://github.com/your-username/idealyst-framework)
|
|
85
|
+
- [React Native Documentation](https://reactnative.dev/)
|
|
86
|
+
- [TypeScript Documentation](https://www.typescriptlang.org/)
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @format
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import React from 'react';
|
|
6
|
+
import ReactTestRenderer from 'react-test-renderer';
|
|
7
|
+
import App from '../App';
|
|
8
|
+
|
|
9
|
+
// Mock the NavigatorProvider to avoid complex navigation setup
|
|
10
|
+
jest.mock('@idealyst/navigation', () => ({
|
|
11
|
+
NavigatorProvider: ({ children }: { children?: React.ReactNode }) => (
|
|
12
|
+
React.createElement('View', { testID: 'navigator-provider' }, children || 'Navigator Content')
|
|
13
|
+
),
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
jest.mock('@idealyst/navigation/examples', () => ({
|
|
17
|
+
ExampleStackRouter: {},
|
|
18
|
+
}));
|
|
19
|
+
|
|
20
|
+
describe('App Component', () => {
|
|
21
|
+
it('renders correctly', async () => {
|
|
22
|
+
let component: ReactTestRenderer.ReactTestRenderer;
|
|
23
|
+
|
|
24
|
+
await ReactTestRenderer.act(() => {
|
|
25
|
+
component = ReactTestRenderer.create(<App />);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
expect(component!).toBeDefined();
|
|
29
|
+
expect(component!.toJSON()).toMatchSnapshot();
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it('renders without crashing', () => {
|
|
33
|
+
const tree = ReactTestRenderer.create(<App />);
|
|
34
|
+
expect(tree).toBeDefined();
|
|
35
|
+
expect(tree.root).toBeDefined();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('contains NavigatorProvider', () => {
|
|
39
|
+
const tree = ReactTestRenderer.create(<App />);
|
|
40
|
+
const navigatorProvider = tree.root.findByProps({ testID: 'navigator-provider' });
|
|
41
|
+
expect(navigatorProvider).toBeDefined();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('has proper SafeAreaView structure', () => {
|
|
45
|
+
const tree = ReactTestRenderer.create(<App />);
|
|
46
|
+
const safeAreaView = tree.root.findByType('SafeAreaView');
|
|
47
|
+
expect(safeAreaView).toBeDefined();
|
|
48
|
+
expect(safeAreaView.props.style).toEqual({ flex: 1 });
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('Sample Component Tests', () => {
|
|
53
|
+
// Example of testing a simple functional component
|
|
54
|
+
const SimpleButton = ({ title, onPress, disabled = false }: {
|
|
55
|
+
title: string;
|
|
56
|
+
onPress: () => void;
|
|
57
|
+
disabled?: boolean;
|
|
58
|
+
}) => {
|
|
59
|
+
return React.createElement(
|
|
60
|
+
'TouchableOpacity',
|
|
61
|
+
{
|
|
62
|
+
testID: 'simple-button',
|
|
63
|
+
onPress: disabled ? undefined : onPress,
|
|
64
|
+
style: { opacity: disabled ? 0.5 : 1 }
|
|
65
|
+
},
|
|
66
|
+
React.createElement('Text', null, title)
|
|
67
|
+
);
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
it('renders button with correct title', () => {
|
|
71
|
+
const mockPress = jest.fn();
|
|
72
|
+
const tree = ReactTestRenderer.create(
|
|
73
|
+
<SimpleButton title="Test Button" onPress={mockPress} />
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const textElement = tree.root.findByType('Text');
|
|
77
|
+
expect(textElement.children).toEqual(['Test Button']);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('handles press events', () => {
|
|
81
|
+
const mockPress = jest.fn();
|
|
82
|
+
const tree = ReactTestRenderer.create(
|
|
83
|
+
<SimpleButton title="Test Button" onPress={mockPress} />
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
const button = tree.root.findByProps({ testID: 'simple-button' });
|
|
87
|
+
ReactTestRenderer.act(() => {
|
|
88
|
+
button.props.onPress();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
expect(mockPress).toHaveBeenCalledTimes(1);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('disables button when disabled prop is true', () => {
|
|
95
|
+
const mockPress = jest.fn();
|
|
96
|
+
const tree = ReactTestRenderer.create(
|
|
97
|
+
<SimpleButton title="Disabled Button" onPress={mockPress} disabled={true} />
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const button = tree.root.findByProps({ testID: 'simple-button' });
|
|
101
|
+
expect(button.props.onPress).toBeUndefined();
|
|
102
|
+
expect(button.props.style.opacity).toBe(0.5);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it('handles component state changes', () => {
|
|
106
|
+
const StatefulComponent = () => {
|
|
107
|
+
const [count, setCount] = React.useState(0);
|
|
108
|
+
|
|
109
|
+
return React.createElement(
|
|
110
|
+
'View',
|
|
111
|
+
{ testID: 'stateful-component' },
|
|
112
|
+
React.createElement('Text', { testID: 'count' }, count.toString()),
|
|
113
|
+
React.createElement(
|
|
114
|
+
'TouchableOpacity',
|
|
115
|
+
{
|
|
116
|
+
testID: 'increment-button',
|
|
117
|
+
onPress: () => setCount(c => c + 1)
|
|
118
|
+
},
|
|
119
|
+
React.createElement('Text', null, 'Increment')
|
|
120
|
+
)
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const tree = ReactTestRenderer.create(<StatefulComponent />);
|
|
125
|
+
|
|
126
|
+
// Check initial state
|
|
127
|
+
const countText = tree.root.findByProps({ testID: 'count' });
|
|
128
|
+
expect(countText.children).toEqual(['0']);
|
|
129
|
+
|
|
130
|
+
// Simulate button press
|
|
131
|
+
const incrementButton = tree.root.findByProps({ testID: 'increment-button' });
|
|
132
|
+
ReactTestRenderer.act(() => {
|
|
133
|
+
incrementButton.props.onPress();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// Check updated state
|
|
137
|
+
expect(countText.children).toEqual(['1']);
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('Sample Native Tests', () => {
|
|
142
|
+
it('should pass a basic test', () => {
|
|
143
|
+
expect(1 + 1).toBe(2);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('should handle string operations', () => {
|
|
147
|
+
const greeting = 'Hello World';
|
|
148
|
+
expect(greeting).toContain('World');
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it('should work with arrays', () => {
|
|
152
|
+
const items = [1, 2, 3];
|
|
153
|
+
expect(items).toHaveLength(3);
|
|
154
|
+
expect(items).toContain(2);
|
|
155
|
+
});
|
|
156
|
+
});
|