@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.
Files changed (103) hide show
  1. package/dist/generators/init.js +8 -13
  2. package/dist/generators/init.js.map +1 -1
  3. package/dist/generators/utils.js +3 -7
  4. package/dist/generators/utils.js.map +1 -1
  5. package/dist/template/.devcontainer/gitignore.template +2 -0
  6. package/dist/template/gitignore.template +56 -0
  7. package/dist/template/mcp.json.template +8 -0
  8. package/dist/template/packages/api/gitignore.template +35 -0
  9. package/dist/template/packages/database/gitignore.template +41 -0
  10. package/dist/template/packages/mobile/babel.config.js +1 -2
  11. package/dist/template/packages/mobile/gitignore.template +73 -0
  12. package/dist/template/packages/mobile/package.json +10 -2
  13. package/dist/template/packages/shared/gitignore.template +35 -0
  14. package/dist/template/packages/web/gitignore.template +35 -0
  15. package/dist/template/yarnrc.yml.template +4 -0
  16. package/package.json +2 -2
  17. package/template/.devcontainer/Dockerfile +26 -0
  18. package/template/.devcontainer/devcontainer.json +113 -0
  19. package/template/.devcontainer/docker-compose.yml +59 -0
  20. package/template/.devcontainer/figma-mcp.sh +32 -0
  21. package/template/.devcontainer/setup.sh +45 -0
  22. package/template/.dockerignore +151 -0
  23. package/template/.env.example +36 -0
  24. package/template/.env.production +56 -0
  25. package/template/DOCKER.md +0 -0
  26. package/template/Dockerfile +111 -0
  27. package/template/README.md +233 -0
  28. package/template/docker/nginx/prod.conf +238 -0
  29. package/template/docker/nginx.conf +131 -0
  30. package/template/docker/postgres/init.sql +41 -0
  31. package/template/docker/prometheus/prometheus.yml +52 -0
  32. package/template/docker-compose.prod.yml +146 -0
  33. package/template/docker-compose.yml +143 -0
  34. package/template/jest.config.js +20 -0
  35. package/template/package.json +45 -0
  36. package/template/packages/api/.env.example +6 -0
  37. package/template/packages/api/README.md +274 -0
  38. package/template/packages/api/__tests__/api.test.ts +26 -0
  39. package/template/packages/api/jest.config.js +23 -0
  40. package/template/packages/api/jest.setup.js +9 -0
  41. package/template/packages/api/package.json +56 -0
  42. package/template/packages/api/src/context.ts +19 -0
  43. package/template/packages/api/src/controllers/TestController.ts +0 -0
  44. package/template/packages/api/src/index.ts +9 -0
  45. package/template/packages/api/src/lib/crud.ts +150 -0
  46. package/template/packages/api/src/lib/database.ts +23 -0
  47. package/template/packages/api/src/router/index.ts +163 -0
  48. package/template/packages/api/src/routers/test.ts +59 -0
  49. package/template/packages/api/src/routers/user.example.ts +83 -0
  50. package/template/packages/api/src/server.ts +50 -0
  51. package/template/packages/api/src/trpc.ts +28 -0
  52. package/template/packages/api/tsconfig.json +43 -0
  53. package/template/packages/database/README.md +162 -0
  54. package/template/packages/database/package.json +49 -0
  55. package/template/packages/database/prisma/seed.ts +64 -0
  56. package/template/packages/database/schema.prisma +107 -0
  57. package/template/packages/database/src/index.ts +15 -0
  58. package/template/packages/database/src/validators.ts +10 -0
  59. package/template/packages/database/tsconfig.json +18 -0
  60. package/template/packages/mobile/README.md +86 -0
  61. package/template/packages/mobile/__tests__/App.test.tsx +156 -0
  62. package/template/packages/mobile/__tests__/components.test.tsx +300 -0
  63. package/template/packages/mobile/app.json +5 -0
  64. package/template/packages/mobile/babel.config.js +10 -0
  65. package/template/packages/mobile/index.js +6 -0
  66. package/template/packages/mobile/jest.config.js +21 -0
  67. package/template/packages/mobile/jest.setup.js +12 -0
  68. package/template/packages/mobile/metro.config.js +27 -0
  69. package/template/packages/mobile/package.json +60 -0
  70. package/template/packages/mobile/src/utils/trpc.ts +7 -0
  71. package/template/packages/mobile/tsconfig.json +28 -0
  72. package/template/packages/shared/README.md +135 -0
  73. package/template/packages/shared/__tests__/shared.test.ts +51 -0
  74. package/template/packages/shared/jest.config.js +22 -0
  75. package/template/packages/shared/package.json +62 -0
  76. package/template/packages/shared/src/components/App.tsx +46 -0
  77. package/template/packages/shared/src/components/HelloWorld.tsx +304 -0
  78. package/template/packages/shared/src/components/index.ts +1 -0
  79. package/template/packages/shared/src/index.ts +14 -0
  80. package/template/packages/shared/src/navigation/AppRouter.tsx +565 -0
  81. package/template/packages/shared/src/trpc/client.ts +44 -0
  82. package/template/packages/shared/tsconfig.json +22 -0
  83. package/template/packages/web/README.md +131 -0
  84. package/template/packages/web/__tests__/App.test.tsx +342 -0
  85. package/template/packages/web/__tests__/components.test.tsx +564 -0
  86. package/template/packages/web/index.html +13 -0
  87. package/template/packages/web/jest.config.js +27 -0
  88. package/template/packages/web/jest.setup.js +24 -0
  89. package/template/packages/web/package.json +69 -0
  90. package/template/packages/web/src/components/TestDemo.tsx +164 -0
  91. package/template/packages/web/src/main.tsx +25 -0
  92. package/template/packages/web/src/utils/trpc.ts +7 -0
  93. package/template/packages/web/tsconfig.json +26 -0
  94. package/template/packages/web/vite.config.ts +98 -0
  95. package/template/setup.sh +30 -0
  96. package/template/tsconfig.json +31 -0
  97. package/dist/template/packages/mobile/src/App-with-trpc.tsx +0 -30
  98. package/dist/template/packages/web/src/App-with-trpc.tsx +0 -32
  99. /package/dist/template/{.dockerignore → dockerignore.template} +0 -0
  100. /package/dist/template/{.env.example → env.example.template} +0 -0
  101. /package/dist/template/packages/api/{.env.example → env.example.template} +0 -0
  102. /package/{dist/template/packages/mobile/src/App-with-trpc-and-shared.tsx → template/packages/mobile/src/App.tsx} +0 -0
  103. /package/{dist/template/packages/web/src/App-with-trpc-and-shared.tsx → template/packages/web/src/App.tsx} +0 -0
@@ -0,0 +1,146 @@
1
+ version: '3.8'
2
+
3
+ # Production overrides for docker-compose.yml
4
+ # Usage: docker-compose -f docker-compose.yml -f docker-compose.prod.yml up
5
+
6
+ services:
7
+ postgres:
8
+ environment:
9
+ POSTGRES_DB: ${POSTGRES_DB}
10
+ POSTGRES_USER: ${POSTGRES_USER}
11
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
12
+ volumes:
13
+ - postgres_prod_data:/var/lib/postgresql/data
14
+ deploy:
15
+ resources:
16
+ limits:
17
+ memory: 1G
18
+ cpus: '0.5'
19
+ reservations:
20
+ memory: 512M
21
+ cpus: '0.25'
22
+
23
+ redis:
24
+ volumes:
25
+ - redis_prod_data:/data
26
+ deploy:
27
+ resources:
28
+ limits:
29
+ memory: 256M
30
+ cpus: '0.25'
31
+ reservations:
32
+ memory: 128M
33
+ cpus: '0.1'
34
+
35
+ api:
36
+ environment:
37
+ NODE_ENV: production
38
+ LOG_LEVEL: info
39
+ RATE_LIMIT_WINDOW_MS: 900000
40
+ RATE_LIMIT_MAX_REQUESTS: 100
41
+ deploy:
42
+ replicas: 2
43
+ resources:
44
+ limits:
45
+ memory: 512M
46
+ cpus: '0.5'
47
+ reservations:
48
+ memory: 256M
49
+ cpus: '0.25'
50
+ restart_policy:
51
+ condition: on-failure
52
+ delay: 5s
53
+ max_attempts: 3
54
+ window: 120s
55
+
56
+ web:
57
+ deploy:
58
+ replicas: 2
59
+ resources:
60
+ limits:
61
+ memory: 128M
62
+ cpus: '0.25'
63
+ reservations:
64
+ memory: 64M
65
+ cpus: '0.1'
66
+ restart_policy:
67
+ condition: on-failure
68
+ delay: 5s
69
+ max_attempts: 3
70
+ window: 120s
71
+
72
+ # Load balancer for production
73
+ nginx:
74
+ image: nginx:alpine
75
+ container_name: ${PROJECT_NAME:-idealyst}-nginx
76
+ ports:
77
+ - "80:80"
78
+ - "443:443"
79
+ volumes:
80
+ - ./docker/nginx/prod.conf:/etc/nginx/nginx.conf:ro
81
+ - ./docker/nginx/ssl:/etc/nginx/ssl:ro
82
+ - ./logs/nginx:/var/log/nginx
83
+ depends_on:
84
+ - api
85
+ - web
86
+ restart: unless-stopped
87
+ deploy:
88
+ resources:
89
+ limits:
90
+ memory: 128M
91
+ cpus: '0.25'
92
+ reservations:
93
+ memory: 64M
94
+ cpus: '0.1'
95
+ networks:
96
+ - idealyst-network
97
+
98
+ # Monitoring with Prometheus (optional)
99
+ prometheus:
100
+ image: prom/prometheus:latest
101
+ container_name: ${PROJECT_NAME:-idealyst}-prometheus
102
+ ports:
103
+ - "9090:9090"
104
+ volumes:
105
+ - ./docker/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
106
+ - prometheus_data:/prometheus
107
+ command:
108
+ - '--config.file=/etc/prometheus/prometheus.yml'
109
+ - '--storage.tsdb.path=/prometheus'
110
+ - '--web.console.libraries=/etc/prometheus/console_libraries'
111
+ - '--web.console.templates=/etc/prometheus/consoles'
112
+ - '--storage.tsdb.retention.time=200h'
113
+ - '--web.enable-lifecycle'
114
+ restart: unless-stopped
115
+ networks:
116
+ - idealyst-network
117
+ profiles:
118
+ - monitoring
119
+
120
+ # Log aggregation with Grafana (optional)
121
+ grafana:
122
+ image: grafana/grafana:latest
123
+ container_name: ${PROJECT_NAME:-idealyst}-grafana
124
+ ports:
125
+ - "3002:3000"
126
+ volumes:
127
+ - grafana_data:/var/lib/grafana
128
+ - ./docker/grafana/provisioning:/etc/grafana/provisioning
129
+ environment:
130
+ GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD:-admin}
131
+ GF_USERS_ALLOW_SIGN_UP: false
132
+ restart: unless-stopped
133
+ networks:
134
+ - idealyst-network
135
+ profiles:
136
+ - monitoring
137
+
138
+ volumes:
139
+ postgres_prod_data:
140
+ redis_prod_data:
141
+ prometheus_data:
142
+ grafana_data:
143
+
144
+ networks:
145
+ idealyst-network:
146
+ driver: bridge
@@ -0,0 +1,143 @@
1
+ version: '3.8'
2
+
3
+ services:
4
+ # PostgreSQL Database
5
+ postgres:
6
+ image: postgres:15-alpine
7
+ container_name: ${PROJECT_NAME:-idealyst}-postgres
8
+ environment:
9
+ POSTGRES_DB: ${POSTGRES_DB:-idealyst_db}
10
+ POSTGRES_USER: ${POSTGRES_USER:-postgres}
11
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-postgres}
12
+ ports:
13
+ - "${POSTGRES_PORT:-5432}:5432"
14
+ volumes:
15
+ - postgres_data:/var/lib/postgresql/data
16
+ - ./docker/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
17
+ healthcheck:
18
+ test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}"]
19
+ interval: 30s
20
+ timeout: 10s
21
+ retries: 5
22
+ networks:
23
+ - idealyst-network
24
+
25
+ # Redis Cache
26
+ redis:
27
+ image: redis:7-alpine
28
+ container_name: ${PROJECT_NAME:-idealyst}-redis
29
+ ports:
30
+ - "${REDIS_PORT:-6379}:6379"
31
+ volumes:
32
+ - redis_data:/data
33
+ healthcheck:
34
+ test: ["CMD", "redis-cli", "ping"]
35
+ interval: 30s
36
+ timeout: 10s
37
+ retries: 5
38
+ networks:
39
+ - idealyst-network
40
+
41
+ # API Service
42
+ api:
43
+ build:
44
+ context: .
45
+ dockerfile: Dockerfile
46
+ target: api-runner
47
+ container_name: ${PROJECT_NAME:-idealyst}-api
48
+ environment:
49
+ NODE_ENV: ${NODE_ENV:-production}
50
+ PORT: 3000
51
+ DATABASE_URL: postgresql://${POSTGRES_USER:-postgres}:${POSTGRES_PASSWORD:-postgres}@postgres:5432/${POSTGRES_DB:-idealyst_db}
52
+ REDIS_URL: redis://redis:6379
53
+ ports:
54
+ - "${API_PORT:-3000}:3000"
55
+ depends_on:
56
+ postgres:
57
+ condition: service_healthy
58
+ redis:
59
+ condition: service_healthy
60
+ volumes:
61
+ - ./uploads:/app/uploads
62
+ restart: unless-stopped
63
+ healthcheck:
64
+ test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
65
+ interval: 30s
66
+ timeout: 10s
67
+ retries: 5
68
+ networks:
69
+ - idealyst-network
70
+
71
+ # Web Application
72
+ web:
73
+ build:
74
+ context: .
75
+ dockerfile: Dockerfile
76
+ target: web-runner
77
+ container_name: ${PROJECT_NAME:-idealyst}-web
78
+ ports:
79
+ - "${WEB_PORT:-80}:80"
80
+ depends_on:
81
+ - api
82
+ restart: unless-stopped
83
+ healthcheck:
84
+ test: ["CMD", "curl", "-f", "http://localhost"]
85
+ interval: 30s
86
+ timeout: 10s
87
+ retries: 5
88
+ networks:
89
+ - idealyst-network
90
+
91
+ # Development Service (for local development)
92
+ dev:
93
+ build:
94
+ context: .
95
+ dockerfile: Dockerfile
96
+ target: dev
97
+ container_name: ${PROJECT_NAME:-idealyst}-dev
98
+ environment:
99
+ NODE_ENV: development
100
+ ports:
101
+ - "3000:3000" # API dev server
102
+ - "5173:5173" # Vite dev server
103
+ - "8080:8080" # Additional dev server
104
+ - "19006:19006" # Expo dev tools
105
+ volumes:
106
+ - .:/app
107
+ - /app/node_modules
108
+ - /var/run/docker.sock:/var/run/docker.sock:ro
109
+ depends_on:
110
+ postgres:
111
+ condition: service_healthy
112
+ redis:
113
+ condition: service_healthy
114
+ networks:
115
+ - idealyst-network
116
+ tty: true
117
+ stdin_open: true
118
+
119
+ # Test Runner
120
+ test:
121
+ build:
122
+ context: .
123
+ dockerfile: Dockerfile
124
+ target: test-runner
125
+ container_name: ${PROJECT_NAME:-idealyst}-test
126
+ environment:
127
+ NODE_ENV: test
128
+ CI: true
129
+ volumes:
130
+ - .:/app
131
+ - /app/node_modules
132
+ networks:
133
+ - idealyst-network
134
+ profiles:
135
+ - testing
136
+
137
+ volumes:
138
+ postgres_data:
139
+ redis_data:
140
+
141
+ networks:
142
+ idealyst-network:
143
+ driver: bridge
@@ -0,0 +1,20 @@
1
+ /** @type {import('jest').Config} */
2
+ module.exports = {
3
+ projects: [
4
+ '<rootDir>/packages/*/jest.config.js',
5
+ ],
6
+ collectCoverage: true,
7
+ collectCoverageFrom: [
8
+ 'packages/*/src/**/*.{ts,tsx}',
9
+ '!packages/*/src/**/*.d.ts',
10
+ '!packages/*/src/**/index.ts',
11
+ ],
12
+ coverageDirectory: '<rootDir>/coverage',
13
+ coverageReporters: ['text', 'lcov', 'html'],
14
+ testTimeout: 30000,
15
+ // Ignore template files in node_modules
16
+ testPathIgnorePatterns: [
17
+ '/node_modules/',
18
+ '/templates/',
19
+ ],
20
+ };
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "{{packageName}}",
3
+ "version": "{{version}}",
4
+ "description": "{{description}}",
5
+ "private": true,
6
+ "workspaces": [
7
+ "packages/*"
8
+ ],
9
+ "packageManager": "yarn@4.1.0",
10
+ "scripts": {
11
+ "dev": "concurrently \"yarn api:dev\" \"yarn web:dev\" \"yarn mobile:start\"",
12
+ "build": "yarn build:packages && yarn api:build && yarn web:build",
13
+ "build:packages": "yarn workspace @{{workspaceScope}}/database build && yarn workspace @{{workspaceScope}}/shared build",
14
+ "api:dev": "yarn workspace @{{workspaceScope}}/api dev",
15
+ "api:build": "yarn workspace @{{workspaceScope}}/api build",
16
+ "web:dev": "yarn workspace @{{workspaceScope}}/web dev",
17
+ "web:build": "yarn workspace @{{workspaceScope}}/web build",
18
+ "mobile:start": "yarn workspace @{{workspaceScope}}/mobile start",
19
+ "mobile:android": "yarn workspace @{{workspaceScope}}/mobile android",
20
+ "mobile:ios": "yarn workspace @{{workspaceScope}}/mobile ios",
21
+ "db:generate": "yarn workspace @{{workspaceScope}}/database db:generate",
22
+ "db:push": "yarn workspace @{{workspaceScope}}/database db:push",
23
+ "db:migrate": "yarn workspace @{{workspaceScope}}/database db:migrate",
24
+ "db:studio": "yarn workspace @{{workspaceScope}}/database db:studio",
25
+ "test": "yarn workspaces foreach --include '@/*' run test",
26
+ "test:watch": "yarn workspaces foreach --include '@/*' run test:watch",
27
+ "test:coverage": "yarn workspaces foreach --include '@/*' run test:coverage",
28
+ "test:ci": "yarn workspaces foreach --include '@/*' --parallel run test --passWithNoTests",
29
+ "type-check": "yarn workspaces run type-check"
30
+ },
31
+ "devDependencies": {
32
+ "@babel/core": "^7.28.0",
33
+ "@babel/preset-env": "^7.28.0",
34
+ "@babel/preset-react": "^7.27.1",
35
+ "@babel/preset-typescript": "^7.27.1",
36
+ "@idealyst/mcp-server": "^{{idealystVersion}}",
37
+ "@mobilenext/mobile-mcp": "^0.0.34",
38
+ "@playwright/mcp": "^0.0.45",
39
+ "@types/jest": "^29.5.12",
40
+ "concurrently": "^8.2.2",
41
+ "jest": "^29.7.0",
42
+ "ts-jest": "^29.1.2",
43
+ "typescript": "^5.0.0"
44
+ }
45
+ }
@@ -0,0 +1,6 @@
1
+ # Server Configuration
2
+ PORT=3000
3
+ NODE_ENV=development
4
+
5
+ # Add your environment variables here
6
+ # Example: API keys, external service URLs, etc.
@@ -0,0 +1,274 @@
1
+ # {{projectName}} API
2
+
3
+ {{description}}
4
+
5
+ A simplified tRPC API with automatic CRUD generation for Prisma models.
6
+
7
+ This API project is built with:
8
+ - **tRPC** - End-to-end```typescript
9
+ import { z } from 'zod';
10
+ import { router, publicProcedure } from '../trpc.js';
11
+ import { createCrudRouter } from '../lib/crud.js';
12
+ import { prisma } from '../lib/database.js';
13
+
14
+ const baseCrudRouter = createCrudRouter('user', createUserSchema);
15
+
16
+ export const userRouter = router({
17
+ ...baseCrudRouter,
18
+
19
+ // Add custom procedures
20
+ getByEmail: publicProcedure
21
+ .input(z.object({ email: z.string().email() }))
22
+ .query(async ({ input }) => {
23
+ return await prisma.user.findUnique({
24
+ where: { email: input.email }
25
+ });
26
+ }),
27
+ });
28
+ ```Zod** - TypeScript-first schema validation
29
+ - **Express.js** - Web framework for Node.js
30
+ - **TypeScript** - Type-safe JavaScript
31
+ - **Prisma** - Next-generation ORM for database access
32
+
33
+ ## Quick Start
34
+
35
+ 1. **Setup environment variables:**
36
+ ```bash
37
+ cp .env.example .env
38
+ ```
39
+
40
+ 2. **Install dependencies:**
41
+ ```bash
42
+ yarn install
43
+ ```
44
+
45
+ 3. **Setup database:**
46
+ ```bash
47
+ # Generate Prisma client
48
+ yarn prisma:generate
49
+
50
+ # Run migrations
51
+ yarn prisma:migrate
52
+
53
+ # Seed database with sample data
54
+ yarn prisma:seed
55
+ ```
56
+
57
+ 4. **Start development server:**
58
+ ```bash
59
+ yarn dev
60
+ ```
61
+
62
+ The API will be available at `http://localhost:3000`
63
+
64
+ ## Creating CRUD APIs
65
+
66
+ This template provides a simple way to create type-safe APIs with automatic CRUD operations for your Prisma models.
67
+
68
+ ### 1. Define Your Prisma Model
69
+
70
+ Add models to `packages/database/schema.prisma`:
71
+
72
+ ```prisma
73
+ model User {
74
+ id String @id @default(cuid())
75
+ email String @unique
76
+ name String
77
+ createdAt DateTime @default(now())
78
+ updatedAt DateTime @updatedAt
79
+ }
80
+ ```
81
+
82
+ ### 2. Create a Router
83
+
84
+ Create `src/routers/user.ts`:
85
+
86
+ ```typescript
87
+ import { z } from 'zod';
88
+ import { createCrudRouter } from '../lib/crud.js';
89
+
90
+ const createUserSchema = z.object({
91
+ email: z.string().email(),
92
+ name: z.string().min(1),
93
+ });
94
+
95
+ const updateUserSchema = z.object({
96
+ email: z.string().email().optional(),
97
+ name: z.string().min(1).optional(),
98
+ });
99
+
100
+ export const userRouter = createCrudRouter(
101
+ 'user',
102
+ createUserSchema,
103
+ updateUserSchema
104
+ );
105
+ ```
106
+
107
+ ### 3. Add to Main Router
108
+
109
+ Update `src/router/index.ts`:
110
+
111
+ ```typescript
112
+ import { userRouter } from '../routers/user.js';
113
+
114
+ export const appRouter = router({
115
+ // ... existing routes
116
+ users: userRouter,
117
+ });
118
+ ```
119
+
120
+ ### 4. Use in Frontend
121
+
122
+ ```typescript
123
+ // Get all users
124
+ const { data: users } = trpc.users.getAll.useQuery();
125
+
126
+ // Create user
127
+ const createUser = trpc.users.create.useMutation();
128
+ await createUser.mutateAsync({
129
+ email: 'user@example.com',
130
+ name: 'John Doe'
131
+ });
132
+
133
+ // Update user
134
+ const updateUser = trpc.users.update.useMutation();
135
+ await updateUser.mutateAsync({
136
+ id: 'user-id',
137
+ data: { name: 'Jane Doe' }
138
+ });
139
+
140
+ // Delete user
141
+ const deleteUser = trpc.users.delete.useMutation();
142
+ await deleteUser.mutateAsync({ id: 'user-id' });
143
+ ```
144
+
145
+ ## Generated CRUD Operations
146
+
147
+ Each `createCrudRouter` call generates:
148
+
149
+ - `getAll({ skip?, take?, orderBy? })` - List with pagination
150
+ - `getById({ id })` - Get single record
151
+ - `create(data)` - Create new record
152
+ - `update({ id, data })` - Update existing record
153
+ - `delete({ id })` - Delete record
154
+ - `count({ where? })` - Count records
155
+
156
+ ## Available Scripts
157
+
158
+ - `yarn dev` - Start development server with hot reload
159
+ - `yarn build` - Build production bundle
160
+ - `yarn start` - Start production server
161
+ - `yarn test` - Run tests
162
+ - `yarn lint` - Lint code
163
+ - `yarn type-check` - Check TypeScript types
164
+
165
+ ## Project Structure
166
+
167
+ ```
168
+ src/
169
+ ├── router/
170
+ │ └── index.ts # Main router definition
171
+ ├── routers/
172
+ │ ├── test.ts # Example CRUD router for Test model
173
+ │ └── user.example.ts # Example CRUD router for User model
174
+ ├── lib/
175
+ │ ├── crud.ts # CRUD router generator
176
+ │ └── database.ts # Database connection
177
+ ├── context.ts # tRPC context
178
+ ├── trpc.ts # tRPC setup
179
+ └── server.ts # Express server setup
180
+ ```
181
+
182
+ ## Advanced Usage
183
+
184
+ ### Custom Procedures
185
+
186
+ Extend generated routers with custom procedures:
187
+
188
+ ```typescript
189
+ import { router, publicProcedure } from '../trpc.js';
190
+ import { createCrudRouter } from '../lib/crud.js';
191
+
192
+ const baseCrudRouter = createCrudRouter('user', createUserSchema);
193
+
194
+ export const userRouter = router({
195
+ ...baseCrudRouter,
196
+
197
+ // Add custom procedures
198
+ getByEmail: publicProcedure
199
+ .input(z.object({ email: z.string().email() }))
200
+ .query(async ({ input }) => {
201
+ return await db.user.findUnique({
202
+ where: { email: input.email }
203
+ });
204
+ }),
205
+ });
206
+ ```
207
+
208
+ ### Authentication
209
+
210
+ For protected routes, you can add authentication middleware to the tRPC setup or create protected procedures:
211
+
212
+ ```typescript
213
+ import { protectedProcedure } from '../trpc.js';
214
+
215
+ // Use protectedProcedure instead of publicProcedure in your CRUD router
216
+ ```
217
+
218
+ ## Development
219
+
220
+ 1. **Add New Model**:
221
+ - Add to Prisma schema
222
+ - Run `yarn db:migrate`
223
+ - Create router with `createCrudRouter`
224
+ - Add to main router
225
+
226
+ 2. **Test API**:
227
+ - Start development: `yarn dev`
228
+ - API available at `http://localhost:3000/trpc`
229
+
230
+ 3. **Type Safety**:
231
+ - All operations are fully type-safe
232
+ - Frontend gets autocomplete and validation
233
+ - Schemas ensure data integrity
234
+
235
+ This simplified approach removes controller complexity while maintaining full type safety and providing powerful CRUD operations for all your Prisma models.
236
+
237
+ ## Environment Variables
238
+
239
+ Create a `.env` file with:
240
+
241
+ ```env
242
+ # Database
243
+ DATABASE_URL="file:./dev.db"
244
+
245
+ # API
246
+ PORT=3000
247
+ NODE_ENV=development
248
+
249
+ # Add your environment variables here
250
+ ```
251
+
252
+ ## Testing
253
+
254
+ The project includes Jest for testing:
255
+
256
+ ```typescript
257
+ import { createContext } from '../src/context.js';
258
+ import { appRouter } from '../src/router/index.js';
259
+
260
+ describe('API Tests', () => {
261
+ test('should get test records', async () => {
262
+ const ctx = createContext({} as any);
263
+ const caller = appRouter.createCaller(ctx);
264
+
265
+ const tests = await caller.test.getAll({});
266
+ expect(tests).toBeDefined();
267
+ });
268
+ });
269
+ ```
270
+
271
+ Run tests with:
272
+ ```bash
273
+ yarn test
274
+ ```
@@ -0,0 +1,26 @@
1
+ import { describe, it, expect } from '@jest/globals';
2
+ import { appRouter } from '../src/router/index.js';
3
+
4
+ describe('API Router', () => {
5
+ it('should have a valid router configuration', () => {
6
+ expect(appRouter).toBeDefined();
7
+ expect(typeof appRouter).toBe('object');
8
+ });
9
+
10
+ it('should export the expected router structure', () => {
11
+ // Test that the router has the expected structure
12
+ expect(appRouter._def).toBeDefined();
13
+ expect(appRouter._def.router).toBe(true);
14
+ });
15
+ });
16
+
17
+ describe('Sample API Test', () => {
18
+ it('should pass a basic test', () => {
19
+ expect(1 + 1).toBe(2);
20
+ });
21
+
22
+ it('should handle async operations', async () => {
23
+ const result = await Promise.resolve('test');
24
+ expect(result).toBe('test');
25
+ });
26
+ });
@@ -0,0 +1,23 @@
1
+ /** @type {import('jest').Config} */
2
+ module.exports = {
3
+ preset: 'ts-jest',
4
+ testEnvironment: 'node',
5
+ roots: ['<rootDir>/src', '<rootDir>/__tests__'],
6
+ testMatch: [
7
+ '**/__tests__/**/*.{ts,tsx,js}',
8
+ '**/*.{test,spec}.{ts,tsx,js}'
9
+ ],
10
+ transform: {
11
+ '^.+\\.tsx?$': 'ts-jest',
12
+ },
13
+ collectCoverageFrom: [
14
+ 'src/**/*.{ts,tsx}',
15
+ '!src/**/*.d.ts',
16
+ '!src/**/index.ts',
17
+ ],
18
+ coverageDirectory: 'coverage',
19
+ coverageReporters: ['text', 'lcov'],
20
+ testTimeout: 10000,
21
+ moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
22
+ setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
23
+ };
@@ -0,0 +1,9 @@
1
+ // Global test setup for API tests
2
+ // This file runs before all tests
3
+
4
+ // Mock environment variables for testing
5
+ process.env.NODE_ENV = 'test';
6
+ process.env.DATABASE_URL = 'file:./test.db';
7
+
8
+ // Increase timeout for async operations
9
+ jest.setTimeout(10000);