create-velox-app 0.6.58 → 0.6.60
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/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/dist/cli.d.ts +11 -1
- package/dist/cli.js +2 -1
- package/dist/index.d.ts +19 -0
- package/dist/index.js +10 -5
- package/dist/templates/shared/root.d.ts +3 -2
- package/dist/templates/shared/root.js +20 -4
- package/dist/templates/trpc.js +2 -2
- package/package.json +1 -1
- package/src/templates/source/root/.cursorrules +126 -12
- package/src/templates/source/root/CLAUDE.trpc.md +328 -0
- package/src/templates/source/rsc/app.config.ts +2 -2
- package/src/templates/source/rsc-auth/app.config.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# create-velox-app
|
|
2
2
|
|
|
3
|
+
## 0.6.60
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- feat(create): add tRPC-specific CLAUDE.md and improve AI-native features
|
|
8
|
+
|
|
9
|
+
## 0.6.59
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- refactor(ecosystem): Laravel-style API refinements & added missing unit tests
|
|
14
|
+
|
|
3
15
|
## 0.6.58
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# create-velox-app
|
|
2
2
|
|
|
3
|
-
> **Early Preview (v0.6.x)** - APIs are stabilizing but may still change.
|
|
3
|
+
> **Early Preview (v0.6.x)** - APIs are stabilizing but may still change. Do not use in production yet.
|
|
4
4
|
|
|
5
5
|
Interactive project scaffolder for VeloxTS Framework - creates production-ready applications with batteries included. Learn more at [@veloxts/velox](https://www.npmjs.com/package/@veloxts/velox).
|
|
6
6
|
|
package/dist/cli.d.ts
CHANGED
|
@@ -5,4 +5,14 @@
|
|
|
5
5
|
* Executable entry point for the project scaffolder.
|
|
6
6
|
* Handles command-line arguments and initiates the scaffolding process.
|
|
7
7
|
*/
|
|
8
|
-
|
|
8
|
+
import type { DatabaseType, TemplateType } from './templates/index.js';
|
|
9
|
+
/** @internal Exported for testing */
|
|
10
|
+
export interface ParsedArgs {
|
|
11
|
+
projectName?: string;
|
|
12
|
+
template?: TemplateType;
|
|
13
|
+
database?: DatabaseType;
|
|
14
|
+
help: boolean;
|
|
15
|
+
version: boolean;
|
|
16
|
+
}
|
|
17
|
+
/** @internal Exported for testing */
|
|
18
|
+
export declare function parseArgs(args: string[]): ParsedArgs;
|
package/dist/cli.js
CHANGED
|
@@ -64,7 +64,8 @@ Examples:
|
|
|
64
64
|
npx create-velox-app my-app -t rsc -d postgresql # RSC with PostgreSQL
|
|
65
65
|
npx create-velox-app # Prompt for name
|
|
66
66
|
`;
|
|
67
|
-
|
|
67
|
+
/** @internal Exported for testing */
|
|
68
|
+
export function parseArgs(args) {
|
|
68
69
|
const result = {
|
|
69
70
|
help: false,
|
|
70
71
|
version: false,
|
package/dist/index.d.ts
CHANGED
|
@@ -7,7 +7,26 @@
|
|
|
7
7
|
import type { DatabaseType, TemplateType } from './templates/index.js';
|
|
8
8
|
/** Create-velox-app package version */
|
|
9
9
|
export declare const CREATE_VERSION: string;
|
|
10
|
+
/** Reserved project names that could cause issues
|
|
11
|
+
* @internal Exported for testing
|
|
12
|
+
*/
|
|
13
|
+
export declare const RESERVED_NAMES: Set<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Check if a file path is safe (no path traversal attacks)
|
|
16
|
+
* @internal Exported for testing
|
|
17
|
+
*/
|
|
18
|
+
export declare function isPathSafe(baseDir: string, targetPath: string): boolean;
|
|
10
19
|
/**
|
|
11
20
|
* Main scaffolding function that creates a new VeloxTS project
|
|
12
21
|
*/
|
|
13
22
|
export declare function createVeloxApp(initialProjectName?: string, initialTemplate?: TemplateType, initialDatabase?: DatabaseType): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Detect which package manager is being used
|
|
25
|
+
* @internal Exported for testing
|
|
26
|
+
*/
|
|
27
|
+
export declare function detectPackageManager(): 'npm' | 'pnpm' | 'yarn';
|
|
28
|
+
/**
|
|
29
|
+
* Get the install command for the package manager
|
|
30
|
+
* @internal Exported for testing
|
|
31
|
+
*/
|
|
32
|
+
export declare function getInstallCommand(packageManager: string): string;
|
package/dist/index.js
CHANGED
|
@@ -24,8 +24,10 @@ const packageJson = require('../package.json');
|
|
|
24
24
|
export const CREATE_VERSION = packageJson.version ?? '0.0.0-unknown';
|
|
25
25
|
/** Timeout for exec commands (5 minutes) */
|
|
26
26
|
const EXEC_TIMEOUT_MS = 5 * 60 * 1000;
|
|
27
|
-
/** Reserved project names that could cause issues
|
|
28
|
-
|
|
27
|
+
/** Reserved project names that could cause issues
|
|
28
|
+
* @internal Exported for testing
|
|
29
|
+
*/
|
|
30
|
+
export const RESERVED_NAMES = new Set([
|
|
29
31
|
'node_modules',
|
|
30
32
|
'test',
|
|
31
33
|
'tests',
|
|
@@ -44,8 +46,9 @@ const RESERVED_NAMES = new Set([
|
|
|
44
46
|
// ============================================================================
|
|
45
47
|
/**
|
|
46
48
|
* Check if a file path is safe (no path traversal attacks)
|
|
49
|
+
* @internal Exported for testing
|
|
47
50
|
*/
|
|
48
|
-
function isPathSafe(baseDir, targetPath) {
|
|
51
|
+
export function isPathSafe(baseDir, targetPath) {
|
|
49
52
|
const resolved = path.resolve(baseDir, targetPath);
|
|
50
53
|
const normalizedBase = path.normalize(baseDir);
|
|
51
54
|
return resolved.startsWith(normalizedBase);
|
|
@@ -222,8 +225,9 @@ async function promptProjectConfig(initialName, initialTemplate, initialDatabase
|
|
|
222
225
|
}
|
|
223
226
|
/**
|
|
224
227
|
* Detect which package manager is being used
|
|
228
|
+
* @internal Exported for testing
|
|
225
229
|
*/
|
|
226
|
-
function detectPackageManager() {
|
|
230
|
+
export function detectPackageManager() {
|
|
227
231
|
const userAgent = process.env.npm_config_user_agent || '';
|
|
228
232
|
if (userAgent.includes('pnpm'))
|
|
229
233
|
return 'pnpm';
|
|
@@ -329,8 +333,9 @@ async function installDependencies(config) {
|
|
|
329
333
|
}
|
|
330
334
|
/**
|
|
331
335
|
* Get the install command for the package manager
|
|
336
|
+
* @internal Exported for testing
|
|
332
337
|
*/
|
|
333
|
-
function getInstallCommand(packageManager) {
|
|
338
|
+
export function getInstallCommand(packageManager) {
|
|
334
339
|
switch (packageManager) {
|
|
335
340
|
case 'pnpm':
|
|
336
341
|
return 'pnpm install';
|
|
@@ -9,6 +9,7 @@ export declare function generatePnpmWorkspaceYaml(): string;
|
|
|
9
9
|
export declare function generateRootTsConfig(): string;
|
|
10
10
|
export declare function generateRootGitignore(): string;
|
|
11
11
|
export declare function generateRootReadme(config: TemplateConfig): string;
|
|
12
|
-
export
|
|
12
|
+
export type TemplateVariant = 'default' | 'auth' | 'trpc';
|
|
13
|
+
export declare function generateRootClaudeMd(config: TemplateConfig, variant: TemplateVariant | boolean): string;
|
|
13
14
|
export declare function generateRootCursorrules(config: TemplateConfig): string;
|
|
14
|
-
export declare function generateRootFiles(config: TemplateConfig,
|
|
15
|
+
export declare function generateRootFiles(config: TemplateConfig, variant?: TemplateVariant | boolean): TemplateFile[];
|
|
@@ -33,8 +33,24 @@ export function generateRootGitignore() {
|
|
|
33
33
|
export function generateRootReadme(config) {
|
|
34
34
|
return compileTemplate('root/README.md', config);
|
|
35
35
|
}
|
|
36
|
-
export function generateRootClaudeMd(config,
|
|
37
|
-
|
|
36
|
+
export function generateRootClaudeMd(config, variant) {
|
|
37
|
+
// Support legacy boolean parameter for backwards compatibility
|
|
38
|
+
let sourceFile;
|
|
39
|
+
if (typeof variant === 'boolean') {
|
|
40
|
+
sourceFile = variant ? 'root/CLAUDE.auth.md' : 'root/CLAUDE.default.md';
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
switch (variant) {
|
|
44
|
+
case 'auth':
|
|
45
|
+
sourceFile = 'root/CLAUDE.auth.md';
|
|
46
|
+
break;
|
|
47
|
+
case 'trpc':
|
|
48
|
+
sourceFile = 'root/CLAUDE.trpc.md';
|
|
49
|
+
break;
|
|
50
|
+
default:
|
|
51
|
+
sourceFile = 'root/CLAUDE.default.md';
|
|
52
|
+
}
|
|
53
|
+
}
|
|
38
54
|
return compileTemplate(sourceFile, config);
|
|
39
55
|
}
|
|
40
56
|
export function generateRootCursorrules(config) {
|
|
@@ -43,14 +59,14 @@ export function generateRootCursorrules(config) {
|
|
|
43
59
|
// ============================================================================
|
|
44
60
|
// Generate All Root Files
|
|
45
61
|
// ============================================================================
|
|
46
|
-
export function generateRootFiles(config,
|
|
62
|
+
export function generateRootFiles(config, variant = 'default') {
|
|
47
63
|
return [
|
|
48
64
|
{ path: 'package.json', content: generateRootPackageJson(config) },
|
|
49
65
|
{ path: 'pnpm-workspace.yaml', content: generatePnpmWorkspaceYaml() },
|
|
50
66
|
{ path: 'tsconfig.json', content: generateRootTsConfig() },
|
|
51
67
|
{ path: '.gitignore', content: generateRootGitignore() },
|
|
52
68
|
{ path: 'README.md', content: generateRootReadme(config) },
|
|
53
|
-
{ path: 'CLAUDE.md', content: generateRootClaudeMd(config,
|
|
69
|
+
{ path: 'CLAUDE.md', content: generateRootClaudeMd(config, variant) },
|
|
54
70
|
{ path: '.cursorrules', content: generateRootCursorrules(config) },
|
|
55
71
|
];
|
|
56
72
|
}
|
package/dist/templates/trpc.js
CHANGED
|
@@ -110,8 +110,8 @@ export function generateTrpcTemplate(config) {
|
|
|
110
110
|
content: generateDockerCompose(config),
|
|
111
111
|
});
|
|
112
112
|
}
|
|
113
|
-
// Add root workspace files (use
|
|
114
|
-
const rootFiles = generateRootFiles(config,
|
|
113
|
+
// Add root workspace files (use 'trpc' variant for tRPC-specific CLAUDE.md)
|
|
114
|
+
const rootFiles = generateRootFiles(config, 'trpc');
|
|
115
115
|
// Add web package files (use false for isAuthTemplate)
|
|
116
116
|
const webBaseFiles = generateWebBaseFiles(config, false);
|
|
117
117
|
const webStyleFiles = generateWebStyleFiles();
|
package/package.json
CHANGED
|
@@ -5,13 +5,81 @@ This is a VeloxTS full-stack TypeScript application.
|
|
|
5
5
|
## Project Type
|
|
6
6
|
|
|
7
7
|
- **Framework**: VeloxTS (Laravel-inspired TypeScript framework)
|
|
8
|
+
/* @if rsc */
|
|
9
|
+
- **Architecture**: React Server Components with Vinxi
|
|
10
|
+
- **Backend**: Fastify embedded in Vinxi (/api/* routes)
|
|
11
|
+
- **Frontend**: React 19 + RSC + file-based routing
|
|
12
|
+
/* @endif rsc */
|
|
13
|
+
/* @if !rsc */
|
|
8
14
|
- **Backend**: Fastify + VeloxTS procedures (apps/api)
|
|
9
15
|
- **Frontend**: React + Vite + TanStack Router (apps/web)
|
|
16
|
+
/* @endif !rsc */
|
|
10
17
|
- **Database**: Prisma with SQLite
|
|
11
18
|
- **Validation**: Zod schemas
|
|
12
19
|
|
|
13
20
|
## Architecture Rules
|
|
14
21
|
|
|
22
|
+
/* @if rsc */
|
|
23
|
+
### RSC Architecture (Single App)
|
|
24
|
+
|
|
25
|
+
This project uses React Server Components with a unified structure:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
app/
|
|
29
|
+
├── pages/ # File-based routing (RSC pages)
|
|
30
|
+
│ ├── index.tsx # / (home)
|
|
31
|
+
│ ├── users.tsx # /users
|
|
32
|
+
│ └── [id].tsx # Dynamic routes
|
|
33
|
+
├── layouts/ # Layout components
|
|
34
|
+
│ └── root.tsx # Root layout
|
|
35
|
+
└── actions/ # Server actions
|
|
36
|
+
└── users.ts # User actions with validated()
|
|
37
|
+
|
|
38
|
+
src/
|
|
39
|
+
├── api/ # API layer
|
|
40
|
+
│ ├── handler.ts # Fastify API handler
|
|
41
|
+
│ ├── procedures/ # Procedure definitions
|
|
42
|
+
│ └── schemas/ # Zod schemas
|
|
43
|
+
└── entry.server.tsx # Server entry
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Server Actions
|
|
47
|
+
|
|
48
|
+
Use `validated()` for secure server actions:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
// app/actions/users.ts
|
|
52
|
+
'use server';
|
|
53
|
+
import { validated, validatedMutation, validatedQuery } from '@veloxts/web/server';
|
|
54
|
+
import { z } from 'zod';
|
|
55
|
+
|
|
56
|
+
// Public query
|
|
57
|
+
export const searchUsers = validatedQuery(
|
|
58
|
+
z.object({ query: z.string().optional() }),
|
|
59
|
+
async (input) => {
|
|
60
|
+
return db.user.findMany({ where: { name: { contains: input.query } } });
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
// Protected mutation
|
|
65
|
+
export const updateUser = validatedMutation(
|
|
66
|
+
z.object({ id: z.string(), name: z.string() }),
|
|
67
|
+
async (input, ctx) => {
|
|
68
|
+
return db.user.update({ where: { id: input.id }, data: input });
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### File-Based Routing
|
|
74
|
+
|
|
75
|
+
- `app/pages/index.tsx` → `/`
|
|
76
|
+
- `app/pages/users.tsx` → `/users`
|
|
77
|
+
- `app/pages/users/[id].tsx` → `/users/:id` (dynamic)
|
|
78
|
+
- `app/pages/[...slug].tsx` → catch-all route
|
|
79
|
+
- `app/pages/(group)/page.tsx` → route groups (no URL segment)
|
|
80
|
+
/* @endif rsc */
|
|
81
|
+
|
|
82
|
+
/* @if !rsc */
|
|
15
83
|
### Backend (apps/api)
|
|
16
84
|
|
|
17
85
|
Procedures in `src/procedures/` define API endpoints. Naming conventions determine HTTP methods:
|
|
@@ -25,7 +93,17 @@ Procedures in `src/procedures/` define API endpoints. Naming conventions determi
|
|
|
25
93
|
|
|
26
94
|
Schemas in `src/schemas/` use Zod for validation.
|
|
27
95
|
|
|
28
|
-
|
|
96
|
+
### Frontend (apps/web)
|
|
97
|
+
|
|
98
|
+
Routes in `src/routes/` use TanStack Router file-based routing.
|
|
99
|
+
API calls use `@veloxts/client` hooks: `useQuery`, `useMutation`.
|
|
100
|
+
Types flow from backend automatically - no codegen needed.
|
|
101
|
+
/* @endif !rsc */
|
|
102
|
+
|
|
103
|
+
### Context Object
|
|
104
|
+
|
|
105
|
+
Available in all procedures via `ctx`:
|
|
106
|
+
|
|
29
107
|
- `ctx.db` - Prisma client
|
|
30
108
|
- `ctx.request` - Fastify request
|
|
31
109
|
- `ctx.reply` - Fastify reply
|
|
@@ -33,12 +111,6 @@ Context available in procedures:
|
|
|
33
111
|
- `ctx.user` - Authenticated user (if logged in)
|
|
34
112
|
/* @endif auth */
|
|
35
113
|
|
|
36
|
-
### Frontend (apps/web)
|
|
37
|
-
|
|
38
|
-
Routes in `src/routes/` use TanStack Router file-based routing.
|
|
39
|
-
API calls use `@veloxts/client` hooks: `useQuery`, `useMutation`.
|
|
40
|
-
Types flow from backend automatically - no codegen needed.
|
|
41
|
-
|
|
42
114
|
## Code Style
|
|
43
115
|
|
|
44
116
|
### TypeScript Strictness
|
|
@@ -135,10 +207,19 @@ __RUN_CMD__ db:studio # Open Prisma Studio
|
|
|
135
207
|
|
|
136
208
|
## File Naming Conventions
|
|
137
209
|
|
|
138
|
-
|
|
139
|
-
-
|
|
140
|
-
-
|
|
141
|
-
-
|
|
210
|
+
/* @if rsc */
|
|
211
|
+
- Pages: `app/pages/{path}.tsx` (kebab-case)
|
|
212
|
+
- Layouts: `app/layouts/{name}.tsx`
|
|
213
|
+
- Actions: `app/actions/{entity}.ts`
|
|
214
|
+
- Procedures: `src/api/procedures/{entity}.ts`
|
|
215
|
+
- Schemas: `src/api/schemas/{entity}.ts`
|
|
216
|
+
/* @endif rsc */
|
|
217
|
+
/* @if !rsc */
|
|
218
|
+
- Procedures: `apps/api/src/procedures/{entity}.ts` (plural, kebab-case)
|
|
219
|
+
- Schemas: `apps/api/src/schemas/{entity}.ts` (singular, kebab-case)
|
|
220
|
+
- Routes: `apps/web/src/routes/{path}.tsx`
|
|
221
|
+
- Components: `apps/web/src/components/{Name}.tsx` (PascalCase)
|
|
222
|
+
/* @endif !rsc */
|
|
142
223
|
|
|
143
224
|
## Import Conventions
|
|
144
225
|
|
|
@@ -150,7 +231,12 @@ import { authenticated, hasRole } from '@veloxts/auth';
|
|
|
150
231
|
/* @endif auth */
|
|
151
232
|
|
|
152
233
|
// Database client from config
|
|
234
|
+
/* @if rsc */
|
|
235
|
+
import { db } from '@/api/database';
|
|
236
|
+
/* @endif rsc */
|
|
237
|
+
/* @if !rsc */
|
|
153
238
|
import { db } from '../config/database';
|
|
239
|
+
/* @endif !rsc */
|
|
154
240
|
|
|
155
241
|
// Local schemas
|
|
156
242
|
import { UserSchema, CreateUserSchema } from '../schemas/user';
|
|
@@ -176,7 +262,21 @@ throw VeloxError.unauthorized('Login required');
|
|
|
176
262
|
throw VeloxError.forbidden('Cannot access this resource');
|
|
177
263
|
```
|
|
178
264
|
|
|
179
|
-
##
|
|
265
|
+
## AI-Powered Development
|
|
266
|
+
|
|
267
|
+
### MCP Integration
|
|
268
|
+
|
|
269
|
+
VeloxTS includes an MCP server for AI assistants:
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
# Start MCP server
|
|
273
|
+
npx @veloxts/mcp
|
|
274
|
+
|
|
275
|
+
# With debug logging
|
|
276
|
+
npx @veloxts/mcp --debug
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### JSON Output for AI
|
|
180
280
|
|
|
181
281
|
All CLI commands support `--json` for AI tooling:
|
|
182
282
|
|
|
@@ -184,4 +284,18 @@ All CLI commands support `--json` for AI tooling:
|
|
|
184
284
|
velox migrate status --json
|
|
185
285
|
velox make resource Post --json --dry-run
|
|
186
286
|
velox procedures list --json
|
|
287
|
+
velox introspect --json
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### Introspection
|
|
291
|
+
|
|
292
|
+
```bash
|
|
293
|
+
# Full project introspection
|
|
294
|
+
velox introspect all --json
|
|
295
|
+
|
|
296
|
+
# List all procedures
|
|
297
|
+
velox procedures list --json
|
|
298
|
+
|
|
299
|
+
# List all routes
|
|
300
|
+
velox routes list
|
|
187
301
|
```
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code and other AI assistants.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
**__PROJECT_NAME__** is a VeloxTS full-stack application using **tRPC-only** architecture:
|
|
8
|
+
- **Backend**: Fastify + VeloxTS + tRPC (apps/api)
|
|
9
|
+
- **Frontend**: React + Vite + TanStack Router (apps/web)
|
|
10
|
+
- **Database**: Prisma with SQLite
|
|
11
|
+
|
|
12
|
+
This template uses tRPC exclusively for type-safe internal communication. No REST adapter is included.
|
|
13
|
+
|
|
14
|
+
## Commands
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
__RUN_CMD__ dev # Start both API (__API_PORT__) and Web (__WEB_PORT__)
|
|
18
|
+
__RUN_CMD__ build # Build both apps
|
|
19
|
+
__RUN_CMD__ db:push # Push database schema
|
|
20
|
+
__RUN_CMD__ db:studio # Open Prisma Studio
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Architecture
|
|
24
|
+
|
|
25
|
+
### Workspace Structure
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
apps/
|
|
29
|
+
├── api/ # Backend (VeloxTS + Fastify + tRPC)
|
|
30
|
+
│ ├── src/
|
|
31
|
+
│ │ ├── procedures/ # tRPC procedures
|
|
32
|
+
│ │ ├── schemas/ # Zod schemas
|
|
33
|
+
│ │ ├── router.ts # tRPC router setup
|
|
34
|
+
│ │ └── config/ # App configuration
|
|
35
|
+
│ └── prisma/
|
|
36
|
+
│ └── schema.prisma
|
|
37
|
+
│
|
|
38
|
+
└── web/ # Frontend (React + Vite)
|
|
39
|
+
└── src/
|
|
40
|
+
├── routes/ # TanStack Router pages
|
|
41
|
+
├── api.ts # tRPC client
|
|
42
|
+
└── styles/ # CSS modules
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Why tRPC-Only?
|
|
46
|
+
|
|
47
|
+
| Feature | tRPC | REST |
|
|
48
|
+
|---------|------|------|
|
|
49
|
+
| Type Safety | Full inference | Manual types |
|
|
50
|
+
| Network | Single `/trpc` endpoint | Multiple endpoints |
|
|
51
|
+
| Best For | Internal frontend | Third-party integrations |
|
|
52
|
+
| Overhead | Minimal | REST adapter layer |
|
|
53
|
+
|
|
54
|
+
Choose tRPC-only when:
|
|
55
|
+
- Your React frontend is the only API consumer
|
|
56
|
+
- You want maximum type safety with zero overhead
|
|
57
|
+
- You don't need REST for external integrations
|
|
58
|
+
|
|
59
|
+
### API Development (apps/api)
|
|
60
|
+
|
|
61
|
+
**Creating a tRPC procedure:**
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
// apps/api/src/procedures/posts.ts
|
|
65
|
+
import { procedure, procedures, z } from '@veloxts/velox';
|
|
66
|
+
|
|
67
|
+
export const postProcedures = procedures('posts', {
|
|
68
|
+
// tRPC query
|
|
69
|
+
list: procedure()
|
|
70
|
+
.output(z.array(PostSchema))
|
|
71
|
+
.query(async ({ ctx }) => {
|
|
72
|
+
return ctx.db.post.findMany();
|
|
73
|
+
}),
|
|
74
|
+
|
|
75
|
+
// tRPC query with input
|
|
76
|
+
byId: procedure()
|
|
77
|
+
.input(z.object({ id: z.string().uuid() }))
|
|
78
|
+
.output(PostSchema)
|
|
79
|
+
.query(async ({ input, ctx }) => {
|
|
80
|
+
return ctx.db.post.findUnique({ where: { id: input.id } });
|
|
81
|
+
}),
|
|
82
|
+
|
|
83
|
+
// tRPC mutation
|
|
84
|
+
create: procedure()
|
|
85
|
+
.input(CreatePostSchema)
|
|
86
|
+
.output(PostSchema)
|
|
87
|
+
.mutation(async ({ input, ctx }) => {
|
|
88
|
+
return ctx.db.post.create({ data: input });
|
|
89
|
+
}),
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Then register in `src/router.ts`:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
import { createRouter } from '@veloxts/router';
|
|
97
|
+
import { postProcedures } from './procedures/posts';
|
|
98
|
+
|
|
99
|
+
export const appRouter = createRouter({
|
|
100
|
+
posts: postProcedures,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
export type AppRouter = typeof appRouter;
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Prisma 7 Configuration
|
|
107
|
+
|
|
108
|
+
This project uses Prisma 7 which has breaking changes:
|
|
109
|
+
- Database URL is configured in `prisma.config.ts`, NOT in `schema.prisma`
|
|
110
|
+
- NEVER add `url` property to the datasource block in `schema.prisma`
|
|
111
|
+
|
|
112
|
+
### Frontend Development (apps/web)
|
|
113
|
+
|
|
114
|
+
**Using tRPC client:**
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// apps/web/src/routes/posts.tsx
|
|
118
|
+
import { useQuery, useMutation } from '@tanstack/react-query';
|
|
119
|
+
import { api } from '../api';
|
|
120
|
+
|
|
121
|
+
function PostsPage() {
|
|
122
|
+
// Full type safety - types flow from backend
|
|
123
|
+
const { data: posts, isLoading } = useQuery({
|
|
124
|
+
queryKey: ['posts'],
|
|
125
|
+
queryFn: () => api.posts.list.query(),
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const createPost = useMutation({
|
|
129
|
+
mutationFn: (data) => api.posts.create.mutate(data),
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
if (isLoading) return <p>Loading...</p>;
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<ul>
|
|
136
|
+
{posts?.map(post => (
|
|
137
|
+
<li key={post.id}>{post.title}</li>
|
|
138
|
+
))}
|
|
139
|
+
</ul>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Type Safety
|
|
145
|
+
|
|
146
|
+
VeloxTS provides end-to-end type safety without code generation:
|
|
147
|
+
|
|
148
|
+
1. **Define schemas** in `apps/api/src/schemas/`
|
|
149
|
+
2. **Use in procedures** with `.input()` and `.output()`
|
|
150
|
+
3. **Import AppRouter type** in frontend
|
|
151
|
+
4. Types flow automatically through tRPC client
|
|
152
|
+
|
|
153
|
+
## tRPC Endpoint
|
|
154
|
+
|
|
155
|
+
All procedures are accessed via single tRPC endpoint:
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
POST /trpc/{namespace.procedure}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Examples:
|
|
162
|
+
- `POST /trpc/posts.list` - List posts
|
|
163
|
+
- `POST /trpc/posts.byId` - Get post by ID
|
|
164
|
+
- `POST /trpc/health.check` - Health check
|
|
165
|
+
|
|
166
|
+
## Migrating to REST (if needed later)
|
|
167
|
+
|
|
168
|
+
If you need REST endpoints for external consumers, add the REST adapter:
|
|
169
|
+
|
|
170
|
+
```typescript
|
|
171
|
+
// apps/api/src/index.ts
|
|
172
|
+
import { restAdapter } from '@veloxts/router';
|
|
173
|
+
import { appRouter } from './router';
|
|
174
|
+
|
|
175
|
+
// Add REST routes alongside tRPC
|
|
176
|
+
app.register(restAdapter(appRouter, { prefix: '/api' }));
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
This auto-generates REST endpoints from procedure names:
|
|
180
|
+
- `posts.list` → `GET /api/posts`
|
|
181
|
+
- `posts.byId` → `GET /api/posts/:id`
|
|
182
|
+
- `posts.create` → `POST /api/posts`
|
|
183
|
+
|
|
184
|
+
## Database
|
|
185
|
+
|
|
186
|
+
After schema changes:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
__RUN_CMD__ db:push # Apply changes
|
|
190
|
+
__RUN_CMD__ db:generate # Regenerate client
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Access via context: `ctx.db.post.findMany()`
|
|
194
|
+
|
|
195
|
+
## Code Generation
|
|
196
|
+
|
|
197
|
+
### Available Generators
|
|
198
|
+
|
|
199
|
+
| Generator | Alias | Description |
|
|
200
|
+
|-----------|-------|-------------|
|
|
201
|
+
| `procedure` | `p` | tRPC procedure with queries/mutations |
|
|
202
|
+
| `schema` | `s` | Zod validation schema |
|
|
203
|
+
| `model` | `m` | Prisma model definition |
|
|
204
|
+
| `test` | `t` | Unit/integration test file |
|
|
205
|
+
|
|
206
|
+
### Usage Examples
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Generate a procedure
|
|
210
|
+
__RUN_CMD__ velox make procedure Posts
|
|
211
|
+
|
|
212
|
+
# Generate a schema
|
|
213
|
+
__RUN_CMD__ velox make schema Post
|
|
214
|
+
|
|
215
|
+
# Preview without writing files
|
|
216
|
+
__RUN_CMD__ velox make --dry-run procedure Posts
|
|
217
|
+
|
|
218
|
+
# JSON output for scripting
|
|
219
|
+
__RUN_CMD__ velox make procedure Posts --json
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Error Handling
|
|
223
|
+
|
|
224
|
+
VeloxTS uses structured error codes for AI tooling:
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
// Error format: VeloxError[E1001]: Message
|
|
228
|
+
import { VeloxError } from '@veloxts/core';
|
|
229
|
+
|
|
230
|
+
const getPost = procedure()
|
|
231
|
+
.input(z.object({ id: z.string().uuid() }))
|
|
232
|
+
.query(async ({ ctx, input }) => {
|
|
233
|
+
const post = await ctx.db.post.findUnique({ where: { id: input.id } });
|
|
234
|
+
|
|
235
|
+
if (!post) {
|
|
236
|
+
throw VeloxError.notFound('Post', input.id);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return post;
|
|
240
|
+
});
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Development Workflow
|
|
244
|
+
|
|
245
|
+
### Hot Module Replacement (HMR)
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
# Default: HMR enabled
|
|
249
|
+
__RUN_CMD__ velox dev
|
|
250
|
+
|
|
251
|
+
# Disable HMR
|
|
252
|
+
__RUN_CMD__ velox dev --no-hmr
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### CLI JSON Output
|
|
256
|
+
|
|
257
|
+
All CLI commands support `--json` for scripting:
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
velox procedures list --json
|
|
261
|
+
velox introspect all --json
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## AI-Powered Development with MCP
|
|
265
|
+
|
|
266
|
+
VeloxTS includes a **Model Context Protocol (MCP) server** that gives AI assistants like Claude direct access to your project structure. This enables intelligent code assistance with full awareness of your procedures, schemas, and types.
|
|
267
|
+
|
|
268
|
+
### What You Get
|
|
269
|
+
|
|
270
|
+
- **Resources**: Real-time project introspection (procedures, schemas)
|
|
271
|
+
- **Tools**: Code generation and database migration commands
|
|
272
|
+
- **Prompts**: Best practice templates for tRPC procedures
|
|
273
|
+
|
|
274
|
+
### Setup for Claude Code (CLI)
|
|
275
|
+
|
|
276
|
+
The MCP server auto-discovers VeloxTS projects:
|
|
277
|
+
|
|
278
|
+
```bash
|
|
279
|
+
# Start the MCP server
|
|
280
|
+
npx @veloxts/mcp
|
|
281
|
+
|
|
282
|
+
# Or with debug logging
|
|
283
|
+
npx @veloxts/mcp --debug
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Setup for Claude Desktop
|
|
287
|
+
|
|
288
|
+
Add this to your Claude Desktop configuration file:
|
|
289
|
+
|
|
290
|
+
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
291
|
+
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
292
|
+
|
|
293
|
+
```json
|
|
294
|
+
{
|
|
295
|
+
"mcpServers": {
|
|
296
|
+
"veloxts": {
|
|
297
|
+
"command": "npx",
|
|
298
|
+
"args": ["@veloxts/mcp"]
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Restart Claude Desktop after adding the configuration.
|
|
305
|
+
|
|
306
|
+
### What Claude Can Do With MCP
|
|
307
|
+
|
|
308
|
+
| Capability | Description |
|
|
309
|
+
|------------|-------------|
|
|
310
|
+
| Generate Code | Create procedures, schemas, models |
|
|
311
|
+
| Run Migrations | Check status, run, rollback, fresh, reset |
|
|
312
|
+
| Access Context | List procedures, schemas, types |
|
|
313
|
+
|
|
314
|
+
### Example Prompts
|
|
315
|
+
|
|
316
|
+
1. **"Generate a CRUD procedure set for BlogPost"**
|
|
317
|
+
2. **"Show me all my tRPC procedures and their input/output types"**
|
|
318
|
+
3. **"Add pagination to the posts.list procedure"**
|
|
319
|
+
4. **"Create a schema for Comment with validation"**
|
|
320
|
+
|
|
321
|
+
### Available MCP Resources
|
|
322
|
+
|
|
323
|
+
| Resource | Description |
|
|
324
|
+
|----------|-------------|
|
|
325
|
+
| `velox://procedures` | All procedures with types |
|
|
326
|
+
| `velox://schemas` | Zod validation schemas |
|
|
327
|
+
| `velox://errors` | Error catalog with fix suggestions |
|
|
328
|
+
| `velox://project` | Project metadata and file paths |
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* All options have sensible defaults - only specify what you need to change.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { createVeloxApp } from '@veloxts/web';
|
|
9
9
|
|
|
10
|
-
export default
|
|
10
|
+
export default createVeloxApp({
|
|
11
11
|
port: __API_PORT__,
|
|
12
12
|
});
|
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* All options have sensible defaults - only specify what you need to change.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { createVeloxApp } from '@veloxts/web';
|
|
9
9
|
|
|
10
|
-
export default
|
|
10
|
+
export default createVeloxApp({
|
|
11
11
|
port: __API_PORT__,
|
|
12
12
|
});
|