@idealyst/cli 1.0.89 → 1.0.90
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/index.js +3 -40
- package/dist/generators/index.js.map +1 -1
- package/dist/generators/init.js +273 -0
- package/dist/generators/init.js.map +1 -0
- package/dist/generators/utils.js +5 -0
- package/dist/generators/utils.js.map +1 -1
- package/dist/index.js +20 -202
- package/dist/index.js.map +1 -1
- package/dist/scripts/configure-react-native-monorepo.js +144 -0
- package/dist/scripts/configure-react-native-monorepo.js.map +1 -0
- package/dist/{templates/workspace → template}/README.md +66 -12
- package/dist/template/package.json +45 -0
- package/{templates → dist/template/packages}/api/package.json +3 -1
- package/{templates → dist/template/packages}/database/package.json +1 -1
- package/dist/{templates/native → template/packages/mobile}/babel.config.js +1 -0
- package/{templates/native → dist/template/packages/mobile}/metro.config.js +4 -4
- package/{templates/native → dist/template/packages/mobile}/package.json +5 -2
- package/{templates → dist/template/packages}/shared/package.json +2 -2
- package/{templates → dist/template/packages}/web/package.json +4 -1
- package/dist/types/generators/index.d.ts +1 -7
- package/dist/types/generators/init.d.ts +5 -0
- package/dist/types/scripts/configure-react-native-monorepo.d.ts +23 -0
- package/dist/types/types.d.ts +0 -4
- package/package.json +1 -1
- package/dist/generators/api.js +0 -31
- package/dist/generators/api.js.map +0 -1
- package/dist/generators/database.js +0 -31
- package/dist/generators/database.js.map +0 -1
- package/dist/generators/fullstack.js +0 -418
- package/dist/generators/fullstack.js.map +0 -1
- package/dist/generators/native.js +0 -112
- package/dist/generators/native.js.map +0 -1
- package/dist/generators/shared.js +0 -29
- package/dist/generators/shared.js.map +0 -1
- package/dist/generators/web.js +0 -45
- package/dist/generators/web.js.map +0 -1
- package/dist/generators/workspace.js +0 -83
- package/dist/generators/workspace.js.map +0 -1
- package/dist/templates/api/package.json +0 -54
- package/dist/templates/database/package.json +0 -49
- package/dist/templates/native/metro.config.js +0 -27
- package/dist/templates/native/package.json +0 -49
- package/dist/templates/native/src/App.tsx +0 -8
- package/dist/templates/shared/package.json +0 -62
- package/dist/templates/shared/src/components/App.tsx +0 -47
- package/dist/templates/shared/src/components/HelloWorld.tsx +0 -307
- package/dist/templates/shared/src/navigation/AppRouter.tsx +0 -98
- package/dist/templates/web/package.json +0 -66
- package/dist/templates/web/src/App.tsx +0 -14
- package/dist/templates/workspace/package.json +0 -35
- package/dist/types/generators/api.d.ts +0 -2
- package/dist/types/generators/database.d.ts +0 -2
- package/dist/types/generators/fullstack.d.ts +0 -2
- package/dist/types/generators/native.d.ts +0 -2
- package/dist/types/generators/shared.d.ts +0 -2
- package/dist/types/generators/web.d.ts +0 -2
- package/dist/types/generators/workspace.d.ts +0 -2
- package/templates/api/.env.example +0 -6
- package/templates/api/README.md +0 -274
- package/templates/api/__tests__/api.test.ts +0 -26
- package/templates/api/jest.config.js +0 -23
- package/templates/api/jest.setup.js +0 -9
- package/templates/api/src/context.ts +0 -19
- package/templates/api/src/controllers/TestController.ts +0 -0
- package/templates/api/src/index.ts +0 -9
- package/templates/api/src/lib/crud.ts +0 -150
- package/templates/api/src/lib/database.ts +0 -23
- package/templates/api/src/router/index.ts +0 -163
- package/templates/api/src/routers/test.ts +0 -59
- package/templates/api/src/routers/user.example.ts +0 -83
- package/templates/api/src/server.ts +0 -50
- package/templates/api/src/trpc.ts +0 -28
- package/templates/api/tsconfig.json +0 -43
- package/templates/database/README.md +0 -162
- package/templates/database/prisma/seed.ts +0 -64
- package/templates/database/schema.prisma +0 -107
- package/templates/database/src/index.ts +0 -15
- package/templates/database/src/validators.ts +0 -10
- package/templates/database/tsconfig.json +0 -18
- package/templates/native/README.md +0 -86
- package/templates/native/__tests__/App.test.tsx +0 -156
- package/templates/native/__tests__/components.test.tsx +0 -300
- package/templates/native/app.json +0 -5
- package/templates/native/babel.config.js +0 -10
- package/templates/native/index.js +0 -6
- package/templates/native/jest.config.js +0 -21
- package/templates/native/jest.setup.js +0 -12
- package/templates/native/src/App-with-trpc.tsx +0 -30
- package/templates/native/src/App.tsx +0 -8
- package/templates/native/src/utils/trpc.ts +0 -7
- package/templates/native/tsconfig.json +0 -28
- package/templates/shared/README.md +0 -135
- package/templates/shared/__tests__/shared.test.ts +0 -51
- package/templates/shared/jest.config.js +0 -22
- package/templates/shared/src/components/index.ts +0 -1
- package/templates/shared/src/index.ts +0 -14
- package/templates/shared/src/trpc/client.ts +0 -44
- package/templates/shared/tsconfig.json +0 -22
- package/templates/web/README.md +0 -131
- package/templates/web/__tests__/App.test.tsx +0 -342
- package/templates/web/__tests__/components.test.tsx +0 -564
- package/templates/web/index.html +0 -13
- package/templates/web/jest.config.js +0 -27
- package/templates/web/jest.setup.js +0 -24
- package/templates/web/src/App-with-trpc.tsx +0 -32
- package/templates/web/src/App.tsx +0 -14
- package/templates/web/src/components/TestDemo.tsx +0 -164
- package/templates/web/src/main.tsx +0 -25
- package/templates/web/src/utils/trpc.ts +0 -7
- package/templates/web/tsconfig.json +0 -26
- package/templates/web/vite.config.ts +0 -98
- package/templates/workspace/.devcontainer/Dockerfile +0 -26
- package/templates/workspace/.devcontainer/devcontainer.json +0 -113
- package/templates/workspace/.devcontainer/docker-compose.yml +0 -59
- package/templates/workspace/.devcontainer/figma-mcp.sh +0 -32
- package/templates/workspace/.devcontainer/setup.sh +0 -45
- package/templates/workspace/.dockerignore +0 -151
- package/templates/workspace/.env.example +0 -36
- package/templates/workspace/.env.production +0 -56
- package/templates/workspace/DOCKER.md +0 -0
- package/templates/workspace/Dockerfile +0 -111
- package/templates/workspace/README.md +0 -179
- package/templates/workspace/docker/nginx/prod.conf +0 -238
- package/templates/workspace/docker/nginx.conf +0 -131
- package/templates/workspace/docker/postgres/init.sql +0 -41
- package/templates/workspace/docker/prometheus/prometheus.yml +0 -52
- package/templates/workspace/docker-compose.prod.yml +0 -146
- package/templates/workspace/docker-compose.yml +0 -143
- package/templates/workspace/jest.config.js +0 -20
- package/templates/workspace/package.json +0 -38
- package/templates/workspace/setup.sh +0 -30
- package/templates/workspace/tsconfig.json +0 -31
- /package/dist/{templates/workspace → template}/.devcontainer/Dockerfile +0 -0
- /package/dist/{templates/workspace → template}/.devcontainer/devcontainer.json +0 -0
- /package/dist/{templates/workspace → template}/.devcontainer/docker-compose.yml +0 -0
- /package/dist/{templates/workspace → template}/.devcontainer/figma-mcp.sh +0 -0
- /package/dist/{templates/workspace → template}/.devcontainer/setup.sh +0 -0
- /package/dist/{templates/workspace → template}/.dockerignore +0 -0
- /package/dist/{templates/workspace → template}/.env.example +0 -0
- /package/dist/{templates/workspace → template}/DOCKER.md +0 -0
- /package/dist/{templates/workspace → template}/Dockerfile +0 -0
- /package/dist/{templates/workspace → template}/docker/nginx/prod.conf +0 -0
- /package/dist/{templates/workspace → template}/docker/nginx.conf +0 -0
- /package/dist/{templates/workspace → template}/docker/postgres/init.sql +0 -0
- /package/dist/{templates/workspace → template}/docker/prometheus/prometheus.yml +0 -0
- /package/dist/{templates/workspace → template}/docker-compose.prod.yml +0 -0
- /package/dist/{templates/workspace → template}/docker-compose.yml +0 -0
- /package/dist/{templates/workspace → template}/jest.config.js +0 -0
- /package/dist/{templates → template/packages}/api/.env.example +0 -0
- /package/dist/{templates → template/packages}/api/README.md +0 -0
- /package/dist/{templates → template/packages}/api/__tests__/api.test.ts +0 -0
- /package/dist/{templates → template/packages}/api/jest.config.js +0 -0
- /package/dist/{templates → template/packages}/api/jest.setup.js +0 -0
- /package/dist/{templates → template/packages}/api/src/context.ts +0 -0
- /package/dist/{templates → template/packages}/api/src/controllers/TestController.ts +0 -0
- /package/dist/{templates → template/packages}/api/src/index.ts +0 -0
- /package/dist/{templates → template/packages}/api/src/lib/crud.ts +0 -0
- /package/dist/{templates → template/packages}/api/src/lib/database.ts +0 -0
- /package/dist/{templates → template/packages}/api/src/router/index.ts +0 -0
- /package/dist/{templates → template/packages}/api/src/routers/test.ts +0 -0
- /package/dist/{templates → template/packages}/api/src/routers/user.example.ts +0 -0
- /package/dist/{templates → template/packages}/api/src/server.ts +0 -0
- /package/dist/{templates → template/packages}/api/src/trpc.ts +0 -0
- /package/dist/{templates → template/packages}/api/tsconfig.json +0 -0
- /package/dist/{templates → template/packages}/database/README.md +0 -0
- /package/dist/{templates → template/packages}/database/prisma/seed.ts +0 -0
- /package/dist/{templates → template/packages}/database/schema.prisma +0 -0
- /package/dist/{templates → template/packages}/database/src/index.ts +0 -0
- /package/dist/{templates → template/packages}/database/src/validators.ts +0 -0
- /package/dist/{templates → template/packages}/database/tsconfig.json +0 -0
- /package/dist/{templates/native → template/packages/mobile}/README.md +0 -0
- /package/dist/{templates/native → template/packages/mobile}/__tests__/App.test.tsx +0 -0
- /package/dist/{templates/native → template/packages/mobile}/__tests__/components.test.tsx +0 -0
- /package/dist/{templates/native → template/packages/mobile}/app.json +0 -0
- /package/dist/{templates/native → template/packages/mobile}/index.js +0 -0
- /package/dist/{templates/native → template/packages/mobile}/jest.config.js +0 -0
- /package/dist/{templates/native → template/packages/mobile}/jest.setup.js +0 -0
- /package/dist/{templates/native → template/packages/mobile}/src/App-with-trpc-and-shared.tsx +0 -0
- /package/dist/{templates/native → template/packages/mobile}/src/App-with-trpc.tsx +0 -0
- /package/{templates/native/src/App-with-trpc-and-shared.tsx → dist/template/packages/mobile/src/App.tsx} +0 -0
- /package/dist/{templates/native → template/packages/mobile}/src/utils/trpc.ts +0 -0
- /package/dist/{templates/native → template/packages/mobile}/tsconfig.json +0 -0
- /package/dist/{templates → template/packages}/shared/README.md +0 -0
- /package/dist/{templates → template/packages}/shared/__tests__/shared.test.ts +0 -0
- /package/dist/{templates → template/packages}/shared/jest.config.js +0 -0
- /package/{templates → dist/template/packages}/shared/src/components/App.tsx +0 -0
- /package/{templates → dist/template/packages}/shared/src/components/HelloWorld.tsx +0 -0
- /package/dist/{templates → template/packages}/shared/src/components/index.ts +0 -0
- /package/dist/{templates → template/packages}/shared/src/index.ts +0 -0
- /package/{templates → dist/template/packages}/shared/src/navigation/AppRouter.tsx +0 -0
- /package/dist/{templates → template/packages}/shared/src/trpc/client.ts +0 -0
- /package/dist/{templates → template/packages}/shared/tsconfig.json +0 -0
- /package/dist/{templates → template/packages}/web/README.md +0 -0
- /package/dist/{templates → template/packages}/web/__tests__/App.test.tsx +0 -0
- /package/dist/{templates → template/packages}/web/__tests__/components.test.tsx +0 -0
- /package/dist/{templates → template/packages}/web/index.html +0 -0
- /package/dist/{templates → template/packages}/web/jest.config.js +0 -0
- /package/dist/{templates → template/packages}/web/jest.setup.js +0 -0
- /package/dist/{templates → template/packages}/web/src/App-with-trpc-and-shared.tsx +0 -0
- /package/dist/{templates → template/packages}/web/src/App-with-trpc.tsx +0 -0
- /package/{templates/web/src/App-with-trpc-and-shared.tsx → dist/template/packages/web/src/App.tsx} +0 -0
- /package/dist/{templates → template/packages}/web/src/components/TestDemo.tsx +0 -0
- /package/dist/{templates → template/packages}/web/src/main.tsx +0 -0
- /package/dist/{templates → template/packages}/web/src/utils/trpc.ts +0 -0
- /package/dist/{templates → template/packages}/web/tsconfig.json +0 -0
- /package/dist/{templates → template/packages}/web/vite.config.ts +0 -0
- /package/dist/{templates/workspace → template}/setup.sh +0 -0
- /package/dist/{templates/workspace → template}/tsconfig.json +0 -0
package/templates/api/README.md
DELETED
|
@@ -1,274 +0,0 @@
|
|
|
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
|
-
```
|
|
@@ -1,26 +0,0 @@
|
|
|
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
|
-
});
|
|
@@ -1,23 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,9 +0,0 @@
|
|
|
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);
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { CreateExpressContextOptions } from '@trpc/server/adapters/express';
|
|
2
|
-
|
|
3
|
-
export interface Context {
|
|
4
|
-
req: CreateExpressContextOptions['req'];
|
|
5
|
-
res: CreateExpressContextOptions['res'];
|
|
6
|
-
// Add your dependencies here (e.g., database client, external services)
|
|
7
|
-
// Example: db: PrismaClient;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export const createContext = ({ req, res }: CreateExpressContextOptions): Context => {
|
|
11
|
-
return {
|
|
12
|
-
req,
|
|
13
|
-
res,
|
|
14
|
-
// Initialize your dependencies here
|
|
15
|
-
// Example: db: prisma,
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export type { CreateExpressContextOptions };
|
|
File without changes
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
// Main exports for the API
|
|
2
|
-
export { appRouter } from './router/index.js';
|
|
3
|
-
export type { AppRouter } from './router/index.js';
|
|
4
|
-
|
|
5
|
-
// Export context type for client usage
|
|
6
|
-
export type { Context } from './context.js';
|
|
7
|
-
|
|
8
|
-
// Export CRUD utilities for creating routers
|
|
9
|
-
export { createCrudRouter } from './lib/crud.js';
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import type { Prisma } from '@{{workspaceScope}}/database/client';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import { prisma } from '../lib/database.js';
|
|
4
|
-
import { publicProcedure, router } from '../trpc.js';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Creates a standard CRUD router for any Prisma model
|
|
8
|
-
*
|
|
9
|
-
* @param modelName - The name of the Prisma model (e.g., 'user', 'post', 'test')
|
|
10
|
-
* @param createSchema - Zod schema for creating new records
|
|
11
|
-
* @param updateSchema - Zod schema for updating records (optional, defaults to createSchema.partial())
|
|
12
|
-
* @returns tRPC router with standard CRUD operations
|
|
13
|
-
*/
|
|
14
|
-
export function createCrudRouter<
|
|
15
|
-
TModelName extends Prisma.ModelName,
|
|
16
|
-
TCreateInput extends Record<string, any>,
|
|
17
|
-
TUpdateInput extends Record<string, any> = Partial<TCreateInput>
|
|
18
|
-
>(
|
|
19
|
-
modelName: TModelName,
|
|
20
|
-
createSchema: z.ZodSchema<TCreateInput>,
|
|
21
|
-
updateSchema?: z.ZodSchema<TUpdateInput>
|
|
22
|
-
) {
|
|
23
|
-
const model = (prisma as any)[modelName];
|
|
24
|
-
const updateSchemaToUse = updateSchema || createSchema.partial();
|
|
25
|
-
|
|
26
|
-
return router({
|
|
27
|
-
// Get all records
|
|
28
|
-
getAll: publicProcedure
|
|
29
|
-
.input(z.object({
|
|
30
|
-
skip: z.number().min(0).optional(),
|
|
31
|
-
take: z.number().min(1).max(100).optional(),
|
|
32
|
-
orderBy: z.record(z.enum(['asc', 'desc'])).optional(),
|
|
33
|
-
}))
|
|
34
|
-
.query(async ({ input }) => {
|
|
35
|
-
return await model.findMany({
|
|
36
|
-
skip: input.skip,
|
|
37
|
-
take: input.take || 10,
|
|
38
|
-
orderBy: input.orderBy,
|
|
39
|
-
});
|
|
40
|
-
}),
|
|
41
|
-
|
|
42
|
-
// Get record by ID
|
|
43
|
-
getById: publicProcedure
|
|
44
|
-
.input(z.object({ id: z.string() }))
|
|
45
|
-
.query(async ({ input }) => {
|
|
46
|
-
const record = await model.findUnique({
|
|
47
|
-
where: { id: input.id },
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
if (!record) {
|
|
51
|
-
throw new Error(`${modelName} not found`);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return record;
|
|
55
|
-
}),
|
|
56
|
-
|
|
57
|
-
// Create new record
|
|
58
|
-
create: publicProcedure
|
|
59
|
-
.input(createSchema)
|
|
60
|
-
.mutation(async ({ input }) => {
|
|
61
|
-
return await model.create({
|
|
62
|
-
data: input,
|
|
63
|
-
});
|
|
64
|
-
}),
|
|
65
|
-
|
|
66
|
-
// Update record
|
|
67
|
-
update: publicProcedure
|
|
68
|
-
.input(z.object({
|
|
69
|
-
id: z.string(),
|
|
70
|
-
data: updateSchemaToUse,
|
|
71
|
-
}))
|
|
72
|
-
.mutation(async ({ input }) => {
|
|
73
|
-
const existingRecord = await model.findUnique({
|
|
74
|
-
where: { id: input.id },
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
if (!existingRecord) {
|
|
78
|
-
throw new Error(`${modelName} not found`);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return await model.update({
|
|
82
|
-
where: { id: input.id },
|
|
83
|
-
data: input.data,
|
|
84
|
-
});
|
|
85
|
-
}),
|
|
86
|
-
|
|
87
|
-
// Delete record
|
|
88
|
-
delete: publicProcedure
|
|
89
|
-
.input(z.object({ id: z.string() }))
|
|
90
|
-
.mutation(async ({ input }) => {
|
|
91
|
-
const existingRecord = await model.findUnique({
|
|
92
|
-
where: { id: input.id },
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
if (!existingRecord) {
|
|
96
|
-
throw new Error(`${modelName} not found`);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
return await model.delete({
|
|
100
|
-
where: { id: input.id },
|
|
101
|
-
});
|
|
102
|
-
}),
|
|
103
|
-
|
|
104
|
-
// Get count
|
|
105
|
-
count: publicProcedure
|
|
106
|
-
.input(z.object({
|
|
107
|
-
where: z.record(z.any()).optional(),
|
|
108
|
-
}))
|
|
109
|
-
.query(async ({ input }) => {
|
|
110
|
-
return await model.count({
|
|
111
|
-
where: input.where,
|
|
112
|
-
});
|
|
113
|
-
}),
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* Example usage:
|
|
119
|
-
*
|
|
120
|
-
* ```typescript
|
|
121
|
-
* import { z } from 'zod';
|
|
122
|
-
* import { createCrudRouter } from '../lib/crud.js';
|
|
123
|
-
*
|
|
124
|
-
* // Define schemas for your model
|
|
125
|
-
* const createUserSchema = z.object({
|
|
126
|
-
* email: z.string().email(),
|
|
127
|
-
* name: z.string(),
|
|
128
|
-
* });
|
|
129
|
-
*
|
|
130
|
-
* const updateUserSchema = z.object({
|
|
131
|
-
* email: z.string().email().optional(),
|
|
132
|
-
* name: z.string().optional(),
|
|
133
|
-
* });
|
|
134
|
-
*
|
|
135
|
-
* // Create the CRUD router
|
|
136
|
-
* export const userRouter = createCrudRouter(
|
|
137
|
-
* 'user',
|
|
138
|
-
* createUserSchema,
|
|
139
|
-
* updateUserSchema
|
|
140
|
-
* );
|
|
141
|
-
* ```
|
|
142
|
-
*
|
|
143
|
-
* This will generate:
|
|
144
|
-
* - users.getAll() - Get all users with pagination
|
|
145
|
-
* - users.getById({ id }) - Get user by ID
|
|
146
|
-
* - users.create({ email, name }) - Create new user
|
|
147
|
-
* - users.update({ id, data: { email?, name? } }) - Update user
|
|
148
|
-
* - users.delete({ id }) - Delete user
|
|
149
|
-
* - users.count() - Get user count
|
|
150
|
-
*/
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { PrismaClient } from '@{{workspaceScope}}/database/client';
|
|
2
|
-
|
|
3
|
-
// Initialize Prisma Client
|
|
4
|
-
declare global {
|
|
5
|
-
// eslint-disable-next-line no-var
|
|
6
|
-
var __prisma: PrismaClient | undefined;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
// Prevent multiple instances of Prisma Client in development
|
|
10
|
-
export const prisma = globalThis.__prisma || new PrismaClient({
|
|
11
|
-
log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
|
|
12
|
-
});
|
|
13
|
-
|
|
14
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
15
|
-
globalThis.__prisma = prisma;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
// Graceful shutdown
|
|
19
|
-
process.on('beforeExit', async () => {
|
|
20
|
-
await prisma.$disconnect();
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
export default prisma;
|
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { router, publicProcedure } from '../trpc.js';
|
|
3
|
-
import { testRouter } from '../routers/test.js';
|
|
4
|
-
|
|
5
|
-
export const appRouter = router({
|
|
6
|
-
// Simple hello world procedure
|
|
7
|
-
hello: publicProcedure
|
|
8
|
-
.input(z.object({ name: z.string().optional() }))
|
|
9
|
-
.query(({ input }) => {
|
|
10
|
-
return {
|
|
11
|
-
greeting: `Hello ${input.name || 'World'}!`,
|
|
12
|
-
timestamp: new Date().toISOString(),
|
|
13
|
-
};
|
|
14
|
-
}),
|
|
15
|
-
|
|
16
|
-
// Health check procedure
|
|
17
|
-
health: publicProcedure.query(() => {
|
|
18
|
-
return {
|
|
19
|
-
status: 'OK',
|
|
20
|
-
timestamp: new Date().toISOString(),
|
|
21
|
-
version: '1.0.0',
|
|
22
|
-
};
|
|
23
|
-
}),
|
|
24
|
-
|
|
25
|
-
// Test CRUD endpoints - generated automatically from Prisma model
|
|
26
|
-
test: testRouter,
|
|
27
|
-
|
|
28
|
-
// Add your model routers here
|
|
29
|
-
// Example:
|
|
30
|
-
// users: userRouter,
|
|
31
|
-
// posts: postRouter,
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
// Export type definition of API
|
|
35
|
-
export type AppRouter = typeof appRouter;
|
|
36
|
-
|
|
37
|
-
/*
|
|
38
|
-
SIMPLIFIED CRUD API SYSTEM:
|
|
39
|
-
|
|
40
|
-
This API template uses a simplified approach with automatic CRUD generation for Prisma models.
|
|
41
|
-
|
|
42
|
-
## Quick Start:
|
|
43
|
-
|
|
44
|
-
1. **Define your Prisma model** in packages/database/schema.prisma
|
|
45
|
-
2. **Create Zod schemas** for validation
|
|
46
|
-
3. **Generate CRUD router** using createCrudRouter()
|
|
47
|
-
4. **Add to main router**
|
|
48
|
-
|
|
49
|
-
## Example - Adding a User model:
|
|
50
|
-
|
|
51
|
-
### 1. Define Prisma model:
|
|
52
|
-
```prisma
|
|
53
|
-
model User {
|
|
54
|
-
id String @id @default(cuid())
|
|
55
|
-
email String @unique
|
|
56
|
-
name String
|
|
57
|
-
createdAt DateTime @default(now())
|
|
58
|
-
updatedAt DateTime @updatedAt
|
|
59
|
-
}
|
|
60
|
-
```
|
|
61
|
-
|
|
62
|
-
### 2. Create router file (src/routers/user.ts):
|
|
63
|
-
```typescript
|
|
64
|
-
import { z } from 'zod';
|
|
65
|
-
import { createCrudRouter } from '../lib/crud.js';
|
|
66
|
-
|
|
67
|
-
const createUserSchema = z.object({
|
|
68
|
-
email: z.string().email(),
|
|
69
|
-
name: z.string().min(1),
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
const updateUserSchema = z.object({
|
|
73
|
-
email: z.string().email().optional(),
|
|
74
|
-
name: z.string().min(1).optional(),
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
export const userRouter = createCrudRouter(
|
|
78
|
-
'user',
|
|
79
|
-
createUserSchema,
|
|
80
|
-
updateUserSchema
|
|
81
|
-
);
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
### 3. Add to main router:
|
|
85
|
-
```typescript
|
|
86
|
-
import { userRouter } from '../routers/user.js';
|
|
87
|
-
|
|
88
|
-
export const appRouter = router({
|
|
89
|
-
// ... other routes
|
|
90
|
-
users: userRouter,
|
|
91
|
-
});
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
### 4. Use in frontend:
|
|
95
|
-
```typescript
|
|
96
|
-
// Get all users
|
|
97
|
-
const { data: users } = trpc.users.getAll.useQuery();
|
|
98
|
-
|
|
99
|
-
// Create user
|
|
100
|
-
const createUser = trpc.users.create.useMutation();
|
|
101
|
-
await createUser.mutateAsync({
|
|
102
|
-
email: 'user@example.com',
|
|
103
|
-
name: 'John Doe'
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
// Update user
|
|
107
|
-
const updateUser = trpc.users.update.useMutation();
|
|
108
|
-
await updateUser.mutateAsync({
|
|
109
|
-
id: 'user-id',
|
|
110
|
-
data: { name: 'Jane Doe' }
|
|
111
|
-
});
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
## Available CRUD Operations:
|
|
115
|
-
|
|
116
|
-
Each generated router includes:
|
|
117
|
-
- `getAll({ skip?, take?, orderBy? })` - List with pagination
|
|
118
|
-
- `getById({ id })` - Get single record
|
|
119
|
-
- `create(data)` - Create new record
|
|
120
|
-
- `update({ id, data })` - Update existing record
|
|
121
|
-
- `delete({ id })` - Delete record
|
|
122
|
-
- `count({ where? })` - Count records
|
|
123
|
-
|
|
124
|
-
## Advanced Usage:
|
|
125
|
-
|
|
126
|
-
### Custom procedures:
|
|
127
|
-
You can extend generated routers with custom procedures:
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
import { z } from 'zod';
|
|
131
|
-
import { router, publicProcedure } from '../trpc.js';
|
|
132
|
-
import { createCrudRouter } from '../lib/crud.js';
|
|
133
|
-
import { prisma } from '../lib/database.js';
|
|
134
|
-
|
|
135
|
-
const baseCrudRouter = createCrudRouter('user', createUserSchema);
|
|
136
|
-
|
|
137
|
-
export const userRouter = router({
|
|
138
|
-
...baseCrudRouter,
|
|
139
|
-
|
|
140
|
-
// Add custom procedures
|
|
141
|
-
getByEmail: publicProcedure
|
|
142
|
-
.input(z.object({ email: z.string().email() }))
|
|
143
|
-
.query(async ({ input }) => {
|
|
144
|
-
return await prisma.user.findUnique({
|
|
145
|
-
where: { email: input.email }
|
|
146
|
-
});
|
|
147
|
-
}),
|
|
148
|
-
});
|
|
149
|
-
```
|
|
150
|
-
|
|
151
|
-
### Authentication & Authorization:
|
|
152
|
-
Use middleware for protected procedures:
|
|
153
|
-
|
|
154
|
-
```typescript
|
|
155
|
-
import { protectedProcedure } from '../trpc.js';
|
|
156
|
-
|
|
157
|
-
// Replace publicProcedure with protectedProcedure in createCrudRouter
|
|
158
|
-
// or create a custom version for authenticated routes
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
This simplified system removes the controller layer complexity while providing
|
|
162
|
-
type-safe, validated CRUD operations for all your Prisma models.
|
|
163
|
-
*/
|