create-velox-app 0.6.64 → 0.6.65

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.
@@ -0,0 +1,416 @@
1
+ # VeloxTS Troubleshooting Guide
2
+
3
+ ## MCP Server vs CLI
4
+
5
+ VeloxTS provides two ways to run generators and commands:
6
+
7
+ ### CLI (Terminal)
8
+
9
+ Use directly in your terminal:
10
+
11
+ ```bash
12
+ pnpm velox make resource Post --crud
13
+ pnpm velox migrate status
14
+ pnpm velox db seed
15
+ ```
16
+
17
+ ### MCP Server (AI Assistants)
18
+
19
+ For Claude Desktop or other MCP-compatible assistants, the `@veloxts/mcp` server provides the same functionality through a protocol interface.
20
+
21
+ **Setup** (Claude Desktop config):
22
+ ```json
23
+ {
24
+ "mcpServers": {
25
+ "veloxts": {
26
+ "command": "npx",
27
+ "args": ["@veloxts/mcp"],
28
+ "cwd": "/path/to/your/project"
29
+ }
30
+ }
31
+ }
32
+ ```
33
+
34
+ **Key difference**: MCP needs the `cwd` path to find your project. The CLI auto-detects it.
35
+
36
+ **If MCP says "Not in a VeloxTS project"**:
37
+ 1. Check that `cwd` points to your project root (where `package.json` is)
38
+ 2. Ensure the project has VeloxTS dependencies installed
39
+ 3. Fallback: Use CLI directly via terminal
40
+
41
+ ---
42
+
43
+ ## Procedure Errors
44
+
45
+ ### "useQuery is not a function"
46
+
47
+ **Cause**: Procedure name doesn't follow query naming conventions.
48
+
49
+ ```typescript
50
+ // BAD - "fetchUsers" is not recognized as a query
51
+ const { data } = api.users.fetchUsers.useQuery({});
52
+
53
+ // GOOD - Use standard prefixes
54
+ const { data } = api.users.listUsers.useQuery({});
55
+ const { data } = api.users.getUser.useQuery({ id });
56
+ const { data } = api.users.findUsers.useQuery({ search });
57
+ ```
58
+
59
+ **Query prefixes**: `get*`, `list*`, `find*`
60
+
61
+ **Mutation prefixes**: `create*`, `add*`, `update*`, `edit*`, `patch*`, `delete*`, `remove*`
62
+
63
+ ### "procedure.input is not a function"
64
+
65
+ **Cause**: Missing parentheses after `procedure`.
66
+
67
+ ```typescript
68
+ // BAD
69
+ getUser: procedure.input(z.object({ id: z.string() }))
70
+
71
+ // GOOD
72
+ getUser: procedure().input(z.object({ id: z.string() }))
73
+ ```
74
+
75
+ ### "Cannot read property 'query' of undefined"
76
+
77
+ **Cause**: Procedure not registered in router.
78
+
79
+ **Fix**:
80
+ 1. Check `src/procedures/index.ts` exports your procedure
81
+ 2. Check `src/index.ts` includes it in collections array
82
+
83
+ ```typescript
84
+ // src/procedures/index.ts
85
+ export * from './users.js';
86
+ export * from './posts.js'; // Add this
87
+
88
+ // src/index.ts
89
+ import { userProcedures, postProcedures } from './procedures/index.js';
90
+ const collections = [userProcedures, postProcedures]; // Add here
91
+ ```
92
+
93
+ ### "Input validation failed"
94
+
95
+ **Cause**: Request data doesn't match Zod schema.
96
+
97
+ **Debug**:
98
+ ```typescript
99
+ // Temporarily log input to see what's being sent
100
+ createUser: procedure()
101
+ .input(CreateUserSchema)
102
+ .mutation(async ({ input }) => {
103
+ console.log('Received input:', input);
104
+ // ...
105
+ }),
106
+ ```
107
+
108
+ **Common issues**:
109
+ - Missing required fields
110
+ - Wrong field types (string vs number)
111
+ - Invalid format (email, uuid, date)
112
+
113
+ ---
114
+
115
+ ## Prisma Errors
116
+
117
+ ### "Unknown property datasourceUrl"
118
+
119
+ **Cause**: Using Prisma 7 with deprecated connection syntax.
120
+
121
+ **Fix**: Use driver adapters in `apps/api/src/config/database.ts`:
122
+
123
+ ```typescript
124
+ // BAD - Prisma 7 removed this
125
+ const db = new PrismaClient({
126
+ datasourceUrl: process.env.DATABASE_URL, // Error!
127
+ });
128
+
129
+ // GOOD - Use driver adapter
130
+ import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3';
131
+
132
+ const adapter = new PrismaBetterSqlite3({ url: process.env.DATABASE_URL });
133
+ const db = new PrismaClient({ adapter });
134
+ ```
135
+
136
+ ### Prisma Decimal validation fails
137
+
138
+ **Cause**: Prisma returns `Decimal` objects, not numbers.
139
+
140
+ **Fix**: Use transforms in Zod schemas:
141
+
142
+ ```typescript
143
+ // Input - coerce string/number to number
144
+ price: z.coerce.number().positive()
145
+
146
+ // Output - transform Decimal to number
147
+ price: z.any().transform((val) => Number(val))
148
+ ```
149
+
150
+ ### "Cannot find module '.prisma/client'"
151
+
152
+ **Cause**: Prisma client not generated.
153
+
154
+ **Fix**:
155
+ ```bash
156
+ pnpm db:generate
157
+ # or
158
+ npx prisma generate
159
+ ```
160
+
161
+ ### Database URL not found
162
+
163
+ **Cause**: Environment variable not loaded.
164
+
165
+ **Fix**: Check `.env` file exists and has `DATABASE_URL`:
166
+
167
+ ```env
168
+ # .env
169
+ DATABASE_URL="file:./dev.db"
170
+ ```
171
+
172
+ For Prisma 7, database URL goes in `prisma.config.ts`, NOT in `schema.prisma`.
173
+
174
+ ---
175
+
176
+ ## REST Route Errors
177
+
178
+ ### "Route not found" (404)
179
+
180
+ **Check**:
181
+ 1. Procedure is registered in collections
182
+ 2. Procedure name follows naming conventions
183
+ 3. Correct HTTP method is being used
184
+
185
+ ```bash
186
+ # Check registered routes
187
+ curl http://localhost:3030/api/health
188
+ ```
189
+
190
+ ### Double `/api/api/` in URL
191
+
192
+ **Cause**: Including `/api` prefix in `.rest()` override.
193
+
194
+ ```typescript
195
+ // BAD - Results in /api/api/posts/:id/publish
196
+ .rest({ method: 'POST', path: '/api/posts/:id/publish' })
197
+
198
+ // GOOD - Prefix is auto-added
199
+ .rest({ method: 'POST', path: '/posts/:id/publish' })
200
+ ```
201
+
202
+ ### Path parameter not in input
203
+
204
+ **Cause**: REST path params (`:id`) are NOT auto-extracted.
205
+
206
+ ```typescript
207
+ // The :id in the path is informational only
208
+ // You must pass id in the request body
209
+ .rest({ method: 'POST', path: '/posts/:id/publish' })
210
+ .input(z.object({ id: z.string().uuid() })) // Required!
211
+ ```
212
+
213
+ ---
214
+
215
+ ## Authentication Errors
216
+
217
+ ### "Unauthorized" (401)
218
+
219
+ **Cause**: Request missing or invalid auth token.
220
+
221
+ **Check**:
222
+ 1. Token is being sent in Authorization header
223
+ 2. Token format: `Authorization: Bearer <token>`
224
+ 3. Token hasn't expired
225
+
226
+ ```typescript
227
+ // Frontend
228
+ const response = await fetch('/api/users/me', {
229
+ headers: {
230
+ Authorization: `Bearer ${token}`,
231
+ },
232
+ });
233
+ ```
234
+
235
+ ### "Forbidden" (403)
236
+
237
+ **Cause**: User authenticated but lacks permission.
238
+
239
+ **Check**:
240
+ 1. User has required role/permission
241
+ 2. Guard logic is correct
242
+
243
+ ```typescript
244
+ // Debug: log user info
245
+ .guard(hasRole('admin'))
246
+ .query(({ ctx }) => {
247
+ console.log('User:', ctx.user);
248
+ console.log('Roles:', ctx.user?.roles);
249
+ // ...
250
+ }),
251
+ ```
252
+
253
+ ### Session not persisting
254
+
255
+ **Cause**: Cookie not being set or sent.
256
+
257
+ **Check**:
258
+ 1. Cookie settings match your domain
259
+ 2. `credentials: 'include'` in fetch requests
260
+ 3. CORS allows credentials
261
+
262
+ ```typescript
263
+ // Frontend fetch
264
+ const response = await fetch('/api/auth/login', {
265
+ method: 'POST',
266
+ credentials: 'include', // Required for cookies
267
+ body: JSON.stringify(data),
268
+ });
269
+ ```
270
+
271
+ ---
272
+
273
+ ## Generator Errors
274
+
275
+ ### "Not in a VeloxTS project"
276
+
277
+ **Cause**: CLI can't find project root.
278
+
279
+ **Fix**:
280
+ 1. Run from project root directory
281
+ 2. Ensure `package.json` exists with VeloxTS dependencies
282
+ 3. For MCP: set `cwd` in config
283
+
284
+ ```bash
285
+ # Run from correct directory
286
+ cd /path/to/your-velox-project
287
+ pnpm velox make resource Post
288
+ ```
289
+
290
+ ### "File already exists"
291
+
292
+ **Cause**: Generator won't overwrite existing files.
293
+
294
+ **Fix**: Use `--force` flag:
295
+
296
+ ```bash
297
+ pnpm velox make resource Post --force
298
+ ```
299
+
300
+ ### "Model already exists in schema"
301
+
302
+ **Cause**: Prisma model with same name already defined.
303
+
304
+ **Options**:
305
+ 1. Use a different name
306
+ 2. Use `namespace` generator (doesn't inject Prisma)
307
+ 3. Manually remove existing model first
308
+
309
+ ---
310
+
311
+ ## Build Errors
312
+
313
+ ### TypeScript errors in generated code
314
+
315
+ **Cause**: Generated code doesn't match your types.
316
+
317
+ **Fix**:
318
+ 1. Regenerate Prisma client: `pnpm db:generate`
319
+ 2. Check schema matches Prisma model
320
+ 3. Ensure imports are correct
321
+
322
+ ### "Cannot find module '@veloxts/velox'"
323
+
324
+ **Cause**: Dependencies not installed.
325
+
326
+ **Fix**:
327
+ ```bash
328
+ pnpm install
329
+ ```
330
+
331
+ ### Module resolution errors
332
+
333
+ **Cause**: Missing `.js` extension in imports.
334
+
335
+ **Fix**: Use `.js` extension for local imports:
336
+
337
+ ```typescript
338
+ // BAD
339
+ import { userProcedures } from './procedures/users';
340
+
341
+ // GOOD
342
+ import { userProcedures } from './procedures/users.js';
343
+ ```
344
+
345
+ ---
346
+
347
+ ## Development Server Errors
348
+
349
+ ### Port already in use
350
+
351
+ **Cause**: Another process using port 3030.
352
+
353
+ **Fix**:
354
+ ```bash
355
+ # Find process
356
+ lsof -i :3030
357
+
358
+ # Kill it
359
+ kill -9 <PID>
360
+
361
+ # Or use different port
362
+ pnpm velox dev --port 4000
363
+ ```
364
+
365
+ ### HMR not working
366
+
367
+ **Check**:
368
+ 1. `hot-hook` is installed
369
+ 2. `hotHook` config in `package.json`
370
+ 3. Try `--no-hmr` to diagnose
371
+
372
+ ```bash
373
+ # Disable HMR to compare
374
+ pnpm velox dev --no-hmr
375
+ ```
376
+
377
+ ### Slow startup
378
+
379
+ **Try**:
380
+ ```bash
381
+ # Enable verbose timing
382
+ pnpm velox dev --verbose
383
+ ```
384
+
385
+ Look for which phase is slow (dependency loading, Prisma, etc.)
386
+
387
+ ---
388
+
389
+ ## Quick Fixes Checklist
390
+
391
+ When something doesn't work:
392
+
393
+ 1. **Regenerate Prisma**: `pnpm db:generate`
394
+ 2. **Restart dev server**: `Ctrl+C` then `pnpm dev`
395
+ 3. **Clear node_modules**: `rm -rf node_modules && pnpm install`
396
+ 4. **Check imports**: Ensure `.js` extensions
397
+ 5. **Check registration**: Procedure in `index.ts` exports and collections
398
+ 6. **Check naming**: Procedure names follow conventions
399
+ 7. **Check env**: `.env` file has required variables
400
+
401
+ ---
402
+
403
+ ## Getting Help
404
+
405
+ 1. **Check this guide** for common issues
406
+ 2. **Read error codes**: VeloxTS uses structured error codes (E1xxx, E2xxx, etc.)
407
+ 3. **Use `--verbose`**: Most commands support verbose output
408
+ 4. **Use `--dry-run`**: Preview changes before applying
409
+
410
+ ```bash
411
+ # Verbose output
412
+ pnpm velox migrate status --verbose
413
+
414
+ # Dry run
415
+ pnpm velox make resource Post --dry-run
416
+ ```
@@ -131,16 +131,48 @@ JWT_SECRET=<64+ chars> # Generate: openssl rand -base64 64
131
131
  JWT_REFRESH_SECRET=<64+ chars> # Generate: openssl rand -base64 64
132
132
  ```
133
133
 
134
- ## Procedure Naming Conventions
134
+ ## Procedure Naming Conventions (CRITICAL)
135
+
136
+ VeloxTS uses naming conventions to determine both HTTP methods and React Query hook types.
137
+
138
+ ### HTTP Method Mapping
135
139
 
136
140
  | Procedure Name | HTTP Method | Route |
137
141
  |----------------|-------------|-------|
138
142
  | `getUser` | GET | `/users/:id` |
139
143
  | `listUsers` | GET | `/users` |
144
+ | `findUsers` | GET | `/users` (search) |
140
145
  | `createUser` | POST | `/users` |
146
+ | `addUser` | POST | `/users` |
141
147
  | `updateUser` | PUT | `/users/:id` |
148
+ | `editUser` | PUT | `/users/:id` |
142
149
  | `patchUser` | PATCH | `/users/:id` |
143
150
  | `deleteUser` | DELETE | `/users/:id` |
151
+ | `removeUser` | DELETE | `/users/:id` |
152
+
153
+ ### React Query Hook Mapping
154
+
155
+ **Query procedures** (use `useQuery`, `useSuspenseQuery`):
156
+ - Prefixes: `get*`, `list*`, `find*`
157
+ - Example: `api.users.getUser.useQuery({ id })` ✅
158
+ - Example: `api.users.listUsers.useSuspenseQuery({})` ✅
159
+
160
+ **Mutation procedures** (use `useMutation`):
161
+ - Prefixes: `create*`, `add*`, `update*`, `edit*`, `patch*`, `delete*`, `remove*`
162
+ - Example: `api.users.createUser.useMutation()` ✅
163
+ - Example: `api.posts.updatePost.useMutation()` ✅
164
+
165
+ ### Common Mistake
166
+
167
+ If you see "useSuspenseQuery is not a function" or similar errors, your procedure name doesn't follow the convention:
168
+
169
+ ```typescript
170
+ // ❌ Wrong - "fetchCampaigns" is not a query prefix, treated as mutation
171
+ const { data } = api.campaigns.fetchCampaigns.useQuery({}); // Error!
172
+
173
+ // ✅ Correct - "listCampaigns" is a query prefix
174
+ const { data } = api.campaigns.listCampaigns.useQuery({});
175
+ ```
144
176
 
145
177
  ## Common Gotchas (IMPORTANT)
146
178
 
@@ -111,16 +111,48 @@ VeloxTS provides end-to-end type safety without code generation:
111
111
  3. **Import in frontend** via `@veloxts/client` hooks
112
112
  4. Types flow automatically from backend to frontend
113
113
 
114
- ## Procedure Naming Conventions
114
+ ## Procedure Naming Conventions (CRITICAL)
115
+
116
+ VeloxTS uses naming conventions to determine both HTTP methods and React Query hook types.
117
+
118
+ ### HTTP Method Mapping
115
119
 
116
120
  | Procedure Name | HTTP Method | Route |
117
121
  |----------------|-------------|-------|
118
122
  | `getUser` | GET | `/users/:id` |
119
123
  | `listUsers` | GET | `/users` |
124
+ | `findUsers` | GET | `/users` (search) |
120
125
  | `createUser` | POST | `/users` |
126
+ | `addUser` | POST | `/users` |
121
127
  | `updateUser` | PUT | `/users/:id` |
128
+ | `editUser` | PUT | `/users/:id` |
122
129
  | `patchUser` | PATCH | `/users/:id` |
123
130
  | `deleteUser` | DELETE | `/users/:id` |
131
+ | `removeUser` | DELETE | `/users/:id` |
132
+
133
+ ### React Query Hook Mapping
134
+
135
+ **Query procedures** (use `useQuery`, `useSuspenseQuery`):
136
+ - Prefixes: `get*`, `list*`, `find*`
137
+ - Example: `api.users.getUser.useQuery({ id })` ✅
138
+ - Example: `api.users.listUsers.useSuspenseQuery({})` ✅
139
+
140
+ **Mutation procedures** (use `useMutation`):
141
+ - Prefixes: `create*`, `add*`, `update*`, `edit*`, `patch*`, `delete*`, `remove*`
142
+ - Example: `api.users.createUser.useMutation()` ✅
143
+ - Example: `api.posts.updatePost.useMutation()` ✅
144
+
145
+ ### Common Mistake
146
+
147
+ If you see "useSuspenseQuery is not a function" or similar errors, your procedure name doesn't follow the convention:
148
+
149
+ ```typescript
150
+ // ❌ Wrong - "fetchUsers" is not a query prefix, treated as mutation
151
+ const { data } = api.users.fetchUsers.useQuery({}); // Error!
152
+
153
+ // ✅ Correct - "listUsers" is a query prefix
154
+ const { data } = api.users.listUsers.useQuery({});
155
+ ```
124
156
 
125
157
  ## Common Gotchas (IMPORTANT)
126
158
 
@@ -200,6 +200,26 @@ list: procedure
200
200
  .output(schema)
201
201
  ```
202
202
 
203
+ ### Procedure Naming Conventions
204
+
205
+ VeloxTS uses naming conventions to determine procedure type in REST adapter mode. Even in tRPC-only mode, follow these conventions for consistency and potential future REST migration:
206
+
207
+ **Query procedures** (read operations):
208
+ - Prefixes: `get*`, `list*`, `find*`
209
+ - Use `.query()` builder
210
+
211
+ **Mutation procedures** (write operations):
212
+ - Prefixes: `create*`, `add*`, `update*`, `edit*`, `patch*`, `delete*`, `remove*`
213
+ - Use `.mutation()` builder
214
+
215
+ ```typescript
216
+ // Good - clear intent from naming
217
+ listPosts: procedure().query(...) // Query
218
+ getPostById: procedure().query(...) // Query
219
+ createPost: procedure().mutation(...) // Mutation
220
+ updatePost: procedure().mutation(...) // Mutation
221
+ ```
222
+
203
223
  ### Handling Prisma Decimals in Zod Schemas
204
224
 
205
225
  Prisma returns `Decimal` objects for decimal fields. Standard Zod validation fails.
@@ -176,6 +176,25 @@ getPost: procedure
176
176
  .input(schema)
177
177
  ```
178
178
 
179
+ ### Procedure Naming Conventions
180
+
181
+ VeloxTS uses naming conventions to determine HTTP methods for REST endpoints:
182
+
183
+ | Procedure Name | HTTP Method | Route |
184
+ |----------------|-------------|-------|
185
+ | `getUser` | GET | `/users/:id` |
186
+ | `listUsers` | GET | `/users` |
187
+ | `findUsers` | GET | `/users` (search) |
188
+ | `createUser` | POST | `/users` |
189
+ | `addUser` | POST | `/users` |
190
+ | `updateUser` | PUT | `/users/:id` |
191
+ | `editUser` | PUT | `/users/:id` |
192
+ | `patchUser` | PATCH | `/users/:id` |
193
+ | `deleteUser` | DELETE | `/users/:id` |
194
+ | `removeUser` | DELETE | `/users/:id` |
195
+
196
+ Follow these conventions for consistency across procedures and server actions.
197
+
179
198
  ### Custom REST Routes
180
199
 
181
200
  When using `.rest()` to override routes, do NOT include the API prefix:
@@ -249,6 +249,25 @@ getUser: procedure
249
249
  .guard(authenticated)
250
250
  ```
251
251
 
252
+ ### Procedure Naming Conventions
253
+
254
+ VeloxTS uses naming conventions to determine HTTP methods for REST endpoints:
255
+
256
+ | Procedure Name | HTTP Method | Route |
257
+ |----------------|-------------|-------|
258
+ | `getUser` | GET | `/users/:id` |
259
+ | `listUsers` | GET | `/users` |
260
+ | `findUsers` | GET | `/users` (search) |
261
+ | `createUser` | POST | `/users` |
262
+ | `addUser` | POST | `/users` |
263
+ | `updateUser` | PUT | `/users/:id` |
264
+ | `editUser` | PUT | `/users/:id` |
265
+ | `patchUser` | PATCH | `/users/:id` |
266
+ | `deleteUser` | DELETE | `/users/:id` |
267
+ | `removeUser` | DELETE | `/users/:id` |
268
+
269
+ Follow these conventions for consistency across procedures and server actions.
270
+
252
271
  ### Custom REST Routes
253
272
 
254
273
  When using `.rest()` to override routes, do NOT include the API prefix:
@@ -23,13 +23,12 @@
23
23
  import { createVeloxHooks } from '@veloxts/client/react';
24
24
 
25
25
  /**
26
- * AppRouter type imported from the type-only router file.
26
+ * AppRouter type imported from the router definition.
27
27
  *
28
- * The router.types.ts file contains ONLY type imports and declarations,
29
- * which are completely erased at compile time. This means Vite never
30
- * scans the @veloxts/* packages when building the frontend.
28
+ * Using `import type` ensures this is erased at compile time.
29
+ * Vite never bundles @veloxts/* packages in the frontend build.
31
30
  */
32
- import type { AppRouter } from '../../api/src/router.types.js';
31
+ import type { AppRouter } from '../../api/src/router.js';
33
32
 
34
33
  /**
35
34
  * Type-safe API hooks with full autocomplete
@@ -6,8 +6,8 @@ import { createRoot } from 'react-dom/client';
6
6
  import { routeTree } from './routeTree.gen';
7
7
  import './styles/global.css';
8
8
 
9
- // Import router type from browser-safe types file
10
- import type { AppRouter } from '../../api/src/router.types.js';
9
+ // Import router type (type-only import is erased at compile time)
10
+ import type { AppRouter } from '../../api/src/router.js';
11
11
  /* @if auth */
12
12
  // Import routes from browser-safe routes file
13
13
  import { routes } from '../../api/src/routes.js';
@@ -2,7 +2,7 @@ import { createRootRoute, Link, Outlet } from '@tanstack/react-router';
2
2
  /* @if auth */
3
3
  import { useQuery } from '@veloxts/client/react';
4
4
 
5
- import type { AppRouter } from '../../../api/src/router.types.js';
5
+ import type { AppRouter } from '../../../api/src/router.js';
6
6
  /* @endif auth */
7
7
  import styles from '@/App.module.css';
8
8