create-velox-app 0.4.13 → 0.6.23
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/README.md +2 -43
- package/dist/cli.js +23 -13
- package/dist/cli.js.map +1 -1
- package/dist/index.js +26 -8
- package/dist/index.js.map +1 -1
- package/dist/templates/auth.d.ts.map +1 -1
- package/dist/templates/auth.js +24 -0
- package/dist/templates/auth.js.map +1 -1
- package/dist/templates/fullstack.d.ts +15 -0
- package/dist/templates/fullstack.d.ts.map +1 -0
- package/dist/templates/fullstack.js +110 -0
- package/dist/templates/fullstack.js.map +1 -0
- package/dist/templates/index.d.ts +1 -1
- package/dist/templates/index.d.ts.map +1 -1
- package/dist/templates/index.js +27 -5
- package/dist/templates/index.js.map +1 -1
- package/dist/templates/placeholders.d.ts +6 -1
- package/dist/templates/placeholders.d.ts.map +1 -1
- package/dist/templates/placeholders.js +15 -5
- package/dist/templates/placeholders.js.map +1 -1
- package/dist/templates/rsc.d.ts +15 -0
- package/dist/templates/rsc.d.ts.map +1 -0
- package/dist/templates/rsc.js +192 -0
- package/dist/templates/rsc.js.map +1 -0
- package/dist/templates/shared/root.d.ts +1 -0
- package/dist/templates/shared/root.d.ts.map +1 -1
- package/dist/templates/shared/root.js +4 -0
- package/dist/templates/shared/root.js.map +1 -1
- package/dist/templates/spa.d.ts +12 -0
- package/dist/templates/spa.d.ts.map +1 -0
- package/dist/templates/spa.js +101 -0
- package/dist/templates/spa.js.map +1 -0
- package/dist/templates/trpc.d.ts.map +1 -1
- package/dist/templates/trpc.js +16 -0
- package/dist/templates/trpc.js.map +1 -1
- package/dist/templates/types.d.ts +14 -1
- package/dist/templates/types.d.ts.map +1 -1
- package/dist/templates/types.js +35 -10
- package/dist/templates/types.js.map +1 -1
- package/package.json +3 -3
- package/src/templates/source/api/config/auth.ts +2 -2
- package/src/templates/source/api/config/database.ts +44 -10
- package/src/templates/source/api/index.auth.ts +10 -16
- package/src/templates/source/api/index.default.ts +10 -9
- package/src/templates/source/api/index.trpc.ts +9 -28
- package/src/templates/source/api/package.auth.json +7 -6
- package/src/templates/source/api/package.default.json +5 -4
- package/src/templates/source/api/prisma/schema.auth.prisma +3 -2
- package/src/templates/source/api/prisma/schema.default.prisma +3 -2
- package/src/templates/source/api/prisma.config.ts +7 -1
- package/src/templates/source/api/procedures/auth.ts +38 -66
- package/src/templates/source/api/procedures/health.ts +4 -9
- package/src/templates/source/api/procedures/users.auth.ts +7 -11
- package/src/templates/source/api/procedures/users.default.ts +7 -11
- package/src/templates/source/api/router.auth.ts +31 -0
- package/src/templates/source/api/router.default.ts +29 -0
- package/src/templates/source/api/router.trpc.ts +37 -0
- package/src/templates/source/api/router.types.auth.ts +88 -0
- package/src/templates/source/api/router.types.default.ts +73 -0
- package/src/templates/source/api/router.types.trpc.ts +73 -0
- package/src/templates/source/api/routes.auth.ts +66 -0
- package/src/templates/source/api/routes.default.ts +53 -0
- package/src/templates/source/api/schemas/auth.ts +79 -0
- package/src/templates/source/api/schemas/health.ts +21 -0
- package/src/templates/source/api/schemas/user.ts +62 -12
- package/src/templates/source/api/utils/auth.ts +157 -0
- package/src/templates/source/root/.cursorrules +187 -0
- package/src/templates/source/root/CLAUDE.auth.md +264 -0
- package/src/templates/source/root/CLAUDE.default.md +185 -0
- package/src/templates/source/root/package.json +7 -1
- package/src/templates/source/rsc/CLAUDE.md +104 -0
- package/src/templates/source/rsc/app/actions/posts.ts +93 -0
- package/src/templates/source/rsc/app/actions/users.ts +83 -0
- package/src/templates/source/rsc/app/layouts/dashboard.tsx +127 -0
- package/src/templates/source/rsc/app/layouts/marketing.tsx +25 -0
- package/src/templates/source/rsc/app/layouts/minimal.tsx +30 -0
- package/src/templates/source/rsc/app/layouts/root.tsx +241 -0
- package/src/templates/source/rsc/app/pages/(dashboard)/profile.tsx +71 -0
- package/src/templates/source/rsc/app/pages/(dashboard)/settings.tsx +104 -0
- package/src/templates/source/rsc/app/pages/(marketing)/about.tsx +52 -0
- package/src/templates/source/rsc/app/pages/_not-found.tsx +149 -0
- package/src/templates/source/rsc/app/pages/docs/[...slug].tsx +211 -0
- package/src/templates/source/rsc/app/pages/index.tsx +50 -0
- package/src/templates/source/rsc/app/pages/print.tsx +80 -0
- package/src/templates/source/rsc/app/pages/users/[id]/posts/[postId].tsx +89 -0
- package/src/templates/source/rsc/app/pages/users/[id]/posts/index.tsx +76 -0
- package/src/templates/source/rsc/app/pages/users/[id]/posts/new.tsx +79 -0
- package/src/templates/source/rsc/app/pages/users/[id].tsx +64 -0
- package/src/templates/source/rsc/app/pages/users/_layout.tsx +104 -0
- package/src/templates/source/rsc/app/pages/users.tsx +44 -0
- package/src/templates/source/rsc/app.config.ts +12 -0
- package/src/templates/source/rsc/env.example +6 -0
- package/src/templates/source/rsc/gitignore +34 -0
- package/src/templates/source/rsc/package.json +41 -0
- package/src/templates/source/rsc/prisma/schema.prisma +34 -0
- package/src/templates/source/rsc/prisma.config.ts +22 -0
- package/src/templates/source/rsc/public/favicon.svg +4 -0
- package/src/templates/source/rsc/src/api/database.ts +72 -0
- package/src/templates/source/rsc/src/api/handler.ts +53 -0
- package/src/templates/source/rsc/src/api/procedures/health.ts +48 -0
- package/src/templates/source/rsc/src/api/procedures/posts.ts +151 -0
- package/src/templates/source/rsc/src/api/procedures/users.ts +87 -0
- package/src/templates/source/rsc/src/api/schemas/post.ts +53 -0
- package/src/templates/source/rsc/src/api/schemas/user.ts +38 -0
- package/src/templates/source/rsc/src/entry.client.tsx +28 -0
- package/src/templates/source/rsc/src/entry.server.tsx +304 -0
- package/src/templates/source/rsc/tsconfig.json +24 -0
- package/src/templates/source/web/App.module.css +1 -1
- package/src/templates/source/web/api.ts +8 -1
- package/src/templates/source/web/main.tsx +4 -4
- package/src/templates/source/web/package.json +6 -6
- package/src/templates/source/web/routes/__root.tsx +2 -2
- package/src/templates/source/web/routes/index.auth.tsx +3 -0
- package/src/templates/source/web/routes/users.tsx +1 -1
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router Definition
|
|
3
|
+
*
|
|
4
|
+
* This file exports the router type for frontend type safety.
|
|
5
|
+
* It MUST NOT have any side effects (like importing dotenv) so that
|
|
6
|
+
* the frontend can safely import types from here.
|
|
7
|
+
*
|
|
8
|
+
* IMPORTANT: Do not add 'import dotenv/config' or any side-effect imports here.
|
|
9
|
+
* The server entry point (index.ts) handles environment setup.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { extractRoutes } from '@veloxts/velox';
|
|
13
|
+
|
|
14
|
+
import { authProcedures } from './procedures/auth.js';
|
|
15
|
+
import { healthProcedures } from './procedures/health.js';
|
|
16
|
+
import { userProcedures } from './procedures/users.js';
|
|
17
|
+
|
|
18
|
+
// Procedure collections for routing
|
|
19
|
+
export const collections = [healthProcedures, authProcedures, userProcedures];
|
|
20
|
+
|
|
21
|
+
// Router definition for frontend type safety
|
|
22
|
+
export const router = {
|
|
23
|
+
auth: authProcedures,
|
|
24
|
+
health: healthProcedures,
|
|
25
|
+
users: userProcedures,
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type AppRouter = typeof router;
|
|
29
|
+
|
|
30
|
+
// Route mappings for frontend client
|
|
31
|
+
export const routes = extractRoutes(collections);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router Definition
|
|
3
|
+
*
|
|
4
|
+
* This file exports the router type for frontend type safety.
|
|
5
|
+
* It MUST NOT have any side effects (like importing dotenv) so that
|
|
6
|
+
* the frontend can safely import types from here.
|
|
7
|
+
*
|
|
8
|
+
* IMPORTANT: Do not add 'import dotenv/config' or any side-effect imports here.
|
|
9
|
+
* The server entry point (index.ts) handles environment setup.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { extractRoutes } from '@veloxts/velox';
|
|
13
|
+
|
|
14
|
+
import { healthProcedures } from './procedures/health.js';
|
|
15
|
+
import { userProcedures } from './procedures/users.js';
|
|
16
|
+
|
|
17
|
+
// Procedure collections for routing
|
|
18
|
+
export const collections = [healthProcedures, userProcedures];
|
|
19
|
+
|
|
20
|
+
// Router definition for frontend type safety
|
|
21
|
+
export const router = {
|
|
22
|
+
health: healthProcedures,
|
|
23
|
+
users: userProcedures,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type AppRouter = typeof router;
|
|
27
|
+
|
|
28
|
+
// Route mappings for frontend client
|
|
29
|
+
export const routes = extractRoutes(collections);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router Definition - tRPC Hybrid Template
|
|
3
|
+
*
|
|
4
|
+
* This file exports the router type for frontend type safety.
|
|
5
|
+
* It MUST NOT have any side effects (like importing dotenv) so that
|
|
6
|
+
* the frontend can safely import types from here.
|
|
7
|
+
*
|
|
8
|
+
* IMPORTANT: Do not add 'import dotenv/config' or any side-effect imports here.
|
|
9
|
+
* The server entry point (index.ts) handles environment setup.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { healthProcedures } from './procedures/health.js';
|
|
13
|
+
import { userProcedures } from './procedures/users.js';
|
|
14
|
+
|
|
15
|
+
// Procedure collections for routing
|
|
16
|
+
export const collections = [healthProcedures, userProcedures];
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* AppRouter type for frontend type safety
|
|
20
|
+
*
|
|
21
|
+
* Constructed from procedure collections to preserve full type information.
|
|
22
|
+
* This enables type-safe API calls with full autocomplete.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* import type { AppRouter } from '../../api/src/router.js';
|
|
27
|
+
* import { createVeloxHooks } from '@veloxts/client/react';
|
|
28
|
+
*
|
|
29
|
+
* export const api = createVeloxHooks<AppRouter>();
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export const router = {
|
|
33
|
+
health: healthProcedures,
|
|
34
|
+
users: userProcedures,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export type AppRouter = typeof router;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router Types - Browser-Safe Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* BROWSER-SAFE: This file imports ONLY from schemas/ and zod.
|
|
5
|
+
* Never import from procedures/ or @veloxts/* packages here.
|
|
6
|
+
*
|
|
7
|
+
* Uses inline contract definitions for automatic type inference from Zod schemas.
|
|
8
|
+
* This provides "Great DX" - one line per procedure instead of verbose type definitions.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
|
|
13
|
+
import * as AuthSchemas from './schemas/auth.js';
|
|
14
|
+
import * as HealthSchemas from './schemas/health.js';
|
|
15
|
+
import * as UserSchemas from './schemas/user.js';
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Contract Helper (Browser-Safe)
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Type-safe contract definition helper.
|
|
23
|
+
* Provides autocomplete and type inference without importing @veloxts/router.
|
|
24
|
+
*/
|
|
25
|
+
type ContractEntry = {
|
|
26
|
+
input?: z.ZodType;
|
|
27
|
+
output?: z.ZodType;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const defineContract = <T extends Record<string, ContractEntry>>(contracts: T): T => contracts;
|
|
31
|
+
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// Health Contracts
|
|
34
|
+
// ============================================================================
|
|
35
|
+
|
|
36
|
+
export const healthContracts = defineContract({
|
|
37
|
+
getHealth: { output: HealthSchemas.HealthResponse },
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// ============================================================================
|
|
41
|
+
// User Contracts
|
|
42
|
+
// ============================================================================
|
|
43
|
+
|
|
44
|
+
export const userContracts = defineContract({
|
|
45
|
+
getUser: { input: UserSchemas.GetUserInput, output: UserSchemas.UserSchema },
|
|
46
|
+
listUsers: { input: UserSchemas.ListUsersInput, output: UserSchemas.ListUsersResponse },
|
|
47
|
+
createUser: { input: UserSchemas.CreateUserInput, output: UserSchemas.UserSchema },
|
|
48
|
+
updateUser: {
|
|
49
|
+
input: UserSchemas.UpdateUserInput.extend({ id: z.string().uuid() }),
|
|
50
|
+
output: UserSchemas.UserSchema,
|
|
51
|
+
},
|
|
52
|
+
patchUser: {
|
|
53
|
+
input: UserSchemas.UpdateUserInput.extend({ id: z.string().uuid() }),
|
|
54
|
+
output: UserSchemas.UserSchema,
|
|
55
|
+
},
|
|
56
|
+
deleteUser: {
|
|
57
|
+
input: z.object({ id: z.string().uuid() }),
|
|
58
|
+
output: z.object({ success: z.boolean() }),
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
// ============================================================================
|
|
63
|
+
// Auth Contracts
|
|
64
|
+
// ============================================================================
|
|
65
|
+
|
|
66
|
+
export const authContracts = defineContract({
|
|
67
|
+
createAccount: { input: AuthSchemas.RegisterInput, output: AuthSchemas.TokenResponse },
|
|
68
|
+
createSession: { input: AuthSchemas.LoginInput, output: AuthSchemas.TokenResponse },
|
|
69
|
+
createRefresh: { input: AuthSchemas.RefreshInput, output: AuthSchemas.TokenResponse },
|
|
70
|
+
deleteSession: { output: AuthSchemas.LogoutResponse },
|
|
71
|
+
getMe: { output: AuthSchemas.UserResponse },
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// ============================================================================
|
|
75
|
+
// AppRouter Type - Automatic Inference
|
|
76
|
+
// ============================================================================
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* The complete router type, inferred from contracts.
|
|
80
|
+
*
|
|
81
|
+
* This replaces 50+ lines of manual type definitions with automatic inference.
|
|
82
|
+
* Each contract's input/output types are automatically extracted from Zod schemas.
|
|
83
|
+
*/
|
|
84
|
+
export type AppRouter = {
|
|
85
|
+
health: typeof healthContracts;
|
|
86
|
+
users: typeof userContracts;
|
|
87
|
+
auth: typeof authContracts;
|
|
88
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router Types - Browser-Safe Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* BROWSER-SAFE: This file imports ONLY from schemas/ and zod.
|
|
5
|
+
* Never import from procedures/ or @veloxts/* packages here.
|
|
6
|
+
*
|
|
7
|
+
* Uses inline contract definitions for automatic type inference from Zod schemas.
|
|
8
|
+
* This provides "Great DX" - one line per procedure instead of verbose type definitions.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
|
|
13
|
+
import * as HealthSchemas from './schemas/health.js';
|
|
14
|
+
import * as UserSchemas from './schemas/user.js';
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Contract Helper (Browser-Safe)
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Type-safe contract definition helper.
|
|
22
|
+
* Provides autocomplete and type inference without importing @veloxts/router.
|
|
23
|
+
*/
|
|
24
|
+
type ContractEntry = {
|
|
25
|
+
input?: z.ZodType;
|
|
26
|
+
output?: z.ZodType;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const defineContract = <T extends Record<string, ContractEntry>>(contracts: T): T => contracts;
|
|
30
|
+
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Health Contracts
|
|
33
|
+
// ============================================================================
|
|
34
|
+
|
|
35
|
+
export const healthContracts = defineContract({
|
|
36
|
+
getHealth: { output: HealthSchemas.HealthResponse },
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// ============================================================================
|
|
40
|
+
// User Contracts
|
|
41
|
+
// ============================================================================
|
|
42
|
+
|
|
43
|
+
export const userContracts = defineContract({
|
|
44
|
+
getUser: { input: UserSchemas.GetUserInput, output: UserSchemas.UserSchema },
|
|
45
|
+
listUsers: { input: UserSchemas.ListUsersInput, output: UserSchemas.ListUsersResponse },
|
|
46
|
+
createUser: { input: UserSchemas.CreateUserInput, output: UserSchemas.UserSchema },
|
|
47
|
+
updateUser: {
|
|
48
|
+
input: UserSchemas.UpdateUserInput.extend({ id: z.string().uuid() }),
|
|
49
|
+
output: UserSchemas.UserSchema,
|
|
50
|
+
},
|
|
51
|
+
patchUser: {
|
|
52
|
+
input: UserSchemas.UpdateUserInput.extend({ id: z.string().uuid() }),
|
|
53
|
+
output: UserSchemas.UserSchema,
|
|
54
|
+
},
|
|
55
|
+
deleteUser: {
|
|
56
|
+
input: z.object({ id: z.string().uuid() }),
|
|
57
|
+
output: z.object({ success: z.boolean() }),
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// ============================================================================
|
|
62
|
+
// AppRouter Type - Automatic Inference
|
|
63
|
+
// ============================================================================
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The complete router type, inferred from contracts.
|
|
67
|
+
*
|
|
68
|
+
* This replaces manual type definitions with automatic inference from Zod schemas.
|
|
69
|
+
*/
|
|
70
|
+
export type AppRouter = {
|
|
71
|
+
health: typeof healthContracts;
|
|
72
|
+
users: typeof userContracts;
|
|
73
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Router Types - Browser-Safe Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* BROWSER-SAFE: This file imports ONLY from schemas/ and zod.
|
|
5
|
+
* Never import from procedures/ or @veloxts/* packages here.
|
|
6
|
+
*
|
|
7
|
+
* Uses inline contract definitions for automatic type inference from Zod schemas.
|
|
8
|
+
* This provides "Great DX" - one line per procedure instead of verbose type definitions.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
|
|
13
|
+
import * as HealthSchemas from './schemas/health.js';
|
|
14
|
+
import * as UserSchemas from './schemas/user.js';
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// Contract Helper (Browser-Safe)
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Type-safe contract definition helper.
|
|
22
|
+
* Provides autocomplete and type inference without importing @veloxts/router.
|
|
23
|
+
*/
|
|
24
|
+
type ContractEntry = {
|
|
25
|
+
input?: z.ZodType;
|
|
26
|
+
output?: z.ZodType;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const defineContract = <T extends Record<string, ContractEntry>>(contracts: T): T => contracts;
|
|
30
|
+
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Health Contracts
|
|
33
|
+
// ============================================================================
|
|
34
|
+
|
|
35
|
+
export const healthContracts = defineContract({
|
|
36
|
+
getHealth: { output: HealthSchemas.HealthResponse },
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// ============================================================================
|
|
40
|
+
// User Contracts
|
|
41
|
+
// ============================================================================
|
|
42
|
+
|
|
43
|
+
export const userContracts = defineContract({
|
|
44
|
+
getUser: { input: UserSchemas.GetUserInput, output: UserSchemas.UserSchema },
|
|
45
|
+
listUsers: { input: UserSchemas.ListUsersInput, output: UserSchemas.ListUsersResponse },
|
|
46
|
+
createUser: { input: UserSchemas.CreateUserInput, output: UserSchemas.UserSchema },
|
|
47
|
+
updateUser: {
|
|
48
|
+
input: UserSchemas.UpdateUserInput.extend({ id: z.string().uuid() }),
|
|
49
|
+
output: UserSchemas.UserSchema,
|
|
50
|
+
},
|
|
51
|
+
patchUser: {
|
|
52
|
+
input: UserSchemas.UpdateUserInput.extend({ id: z.string().uuid() }),
|
|
53
|
+
output: UserSchemas.UserSchema,
|
|
54
|
+
},
|
|
55
|
+
deleteUser: {
|
|
56
|
+
input: z.object({ id: z.string().uuid() }),
|
|
57
|
+
output: z.object({ success: z.boolean() }),
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// ============================================================================
|
|
62
|
+
// AppRouter Type - Automatic Inference
|
|
63
|
+
// ============================================================================
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The complete router type, inferred from contracts.
|
|
67
|
+
*
|
|
68
|
+
* This replaces manual type definitions with automatic inference from Zod schemas.
|
|
69
|
+
*/
|
|
70
|
+
export type AppRouter = {
|
|
71
|
+
health: typeof healthContracts;
|
|
72
|
+
users: typeof userContracts;
|
|
73
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Routes - Browser-Safe Route Definitions
|
|
3
|
+
*
|
|
4
|
+
* BROWSER-SAFE: This file contains only static route metadata.
|
|
5
|
+
* Never import from procedures/ or @veloxts/* packages here.
|
|
6
|
+
*
|
|
7
|
+
* These route mappings tell the frontend client how to call each procedure.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Route Helper (Browser-Safe)
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
15
|
+
|
|
16
|
+
type RouteEntry = {
|
|
17
|
+
method: HttpMethod;
|
|
18
|
+
path: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const defineRoutes = <T extends Record<string, RouteEntry>>(routes: T): T => routes;
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// Health Routes
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
export const healthRoutes = defineRoutes({
|
|
28
|
+
getHealth: { method: 'GET', path: '/health' },
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Auth Routes
|
|
33
|
+
// ============================================================================
|
|
34
|
+
|
|
35
|
+
export const authRoutes = defineRoutes({
|
|
36
|
+
createAccount: { method: 'POST', path: '/auth/register' },
|
|
37
|
+
createSession: { method: 'POST', path: '/auth/login' },
|
|
38
|
+
createRefresh: { method: 'POST', path: '/auth/refresh' },
|
|
39
|
+
deleteSession: { method: 'POST', path: '/auth/logout' },
|
|
40
|
+
getMe: { method: 'GET', path: '/auth/me' },
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// User Routes
|
|
45
|
+
// ============================================================================
|
|
46
|
+
|
|
47
|
+
export const userRoutes = defineRoutes({
|
|
48
|
+
getUser: { method: 'GET', path: '/users/:id' },
|
|
49
|
+
listUsers: { method: 'GET', path: '/users' },
|
|
50
|
+
createUser: { method: 'POST', path: '/users' },
|
|
51
|
+
updateUser: { method: 'PUT', path: '/users/:id' },
|
|
52
|
+
patchUser: { method: 'PATCH', path: '/users/:id' },
|
|
53
|
+
deleteUser: { method: 'DELETE', path: '/users/:id' },
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// ============================================================================
|
|
57
|
+
// Combined Routes Export
|
|
58
|
+
// ============================================================================
|
|
59
|
+
|
|
60
|
+
export const routes = {
|
|
61
|
+
health: healthRoutes,
|
|
62
|
+
auth: authRoutes,
|
|
63
|
+
users: userRoutes,
|
|
64
|
+
} as const;
|
|
65
|
+
|
|
66
|
+
export type Routes = typeof routes;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Routes - Browser-Safe Route Definitions
|
|
3
|
+
*
|
|
4
|
+
* BROWSER-SAFE: This file contains only static route metadata.
|
|
5
|
+
* Never import from procedures/ or @veloxts/* packages here.
|
|
6
|
+
*
|
|
7
|
+
* These route mappings tell the frontend client how to call each procedure.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Route Helper (Browser-Safe)
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
|
15
|
+
|
|
16
|
+
type RouteEntry = {
|
|
17
|
+
method: HttpMethod;
|
|
18
|
+
path: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const defineRoutes = <T extends Record<string, RouteEntry>>(routes: T): T => routes;
|
|
22
|
+
|
|
23
|
+
// ============================================================================
|
|
24
|
+
// Health Routes
|
|
25
|
+
// ============================================================================
|
|
26
|
+
|
|
27
|
+
export const healthRoutes = defineRoutes({
|
|
28
|
+
getHealth: { method: 'GET', path: '/health' },
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// User Routes
|
|
33
|
+
// ============================================================================
|
|
34
|
+
|
|
35
|
+
export const userRoutes = defineRoutes({
|
|
36
|
+
getUser: { method: 'GET', path: '/users/:id' },
|
|
37
|
+
listUsers: { method: 'GET', path: '/users' },
|
|
38
|
+
createUser: { method: 'POST', path: '/users' },
|
|
39
|
+
updateUser: { method: 'PUT', path: '/users/:id' },
|
|
40
|
+
patchUser: { method: 'PATCH', path: '/users/:id' },
|
|
41
|
+
deleteUser: { method: 'DELETE', path: '/users/:id' },
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
// ============================================================================
|
|
45
|
+
// Combined Routes Export
|
|
46
|
+
// ============================================================================
|
|
47
|
+
|
|
48
|
+
export const routes = {
|
|
49
|
+
health: healthRoutes,
|
|
50
|
+
users: userRoutes,
|
|
51
|
+
} as const;
|
|
52
|
+
|
|
53
|
+
export type Routes = typeof routes;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth Schemas
|
|
3
|
+
*
|
|
4
|
+
* BROWSER-SAFE: This file imports ONLY from 'zod'.
|
|
5
|
+
* Never import from @veloxts/* packages here.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Password Schema (for validation display)
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
export const PasswordSchema = z
|
|
15
|
+
.string()
|
|
16
|
+
.min(12, 'Password must be at least 12 characters')
|
|
17
|
+
.max(128, 'Password must not exceed 128 characters');
|
|
18
|
+
|
|
19
|
+
// ============================================================================
|
|
20
|
+
// Email Schema
|
|
21
|
+
// ============================================================================
|
|
22
|
+
|
|
23
|
+
export const EmailSchema = z
|
|
24
|
+
.string()
|
|
25
|
+
.email('Invalid email address')
|
|
26
|
+
.transform((email) => email.toLowerCase().trim());
|
|
27
|
+
|
|
28
|
+
// ============================================================================
|
|
29
|
+
// Input Schemas
|
|
30
|
+
// ============================================================================
|
|
31
|
+
|
|
32
|
+
export const RegisterInput = z.object({
|
|
33
|
+
name: z.string().min(2).max(100).trim(),
|
|
34
|
+
email: EmailSchema,
|
|
35
|
+
password: PasswordSchema,
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
export const LoginInput = z.object({
|
|
39
|
+
email: EmailSchema,
|
|
40
|
+
password: z.string().min(1),
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
export const RefreshInput = z.object({
|
|
44
|
+
refreshToken: z.string(),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// Response Schemas
|
|
49
|
+
// ============================================================================
|
|
50
|
+
|
|
51
|
+
export const TokenResponse = z.object({
|
|
52
|
+
accessToken: z.string(),
|
|
53
|
+
refreshToken: z.string(),
|
|
54
|
+
expiresIn: z.number(),
|
|
55
|
+
tokenType: z.literal('Bearer'),
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
export const UserResponse = z.object({
|
|
59
|
+
id: z.string(),
|
|
60
|
+
name: z.string(),
|
|
61
|
+
email: z.string(),
|
|
62
|
+
roles: z.array(z.string()),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export const LogoutResponse = z.object({
|
|
66
|
+
success: z.boolean(),
|
|
67
|
+
message: z.string(),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
// ============================================================================
|
|
71
|
+
// Type Exports
|
|
72
|
+
// ============================================================================
|
|
73
|
+
|
|
74
|
+
export type RegisterData = z.infer<typeof RegisterInput>;
|
|
75
|
+
export type LoginData = z.infer<typeof LoginInput>;
|
|
76
|
+
export type RefreshData = z.infer<typeof RefreshInput>;
|
|
77
|
+
export type TokenResponseData = z.infer<typeof TokenResponse>;
|
|
78
|
+
export type UserResponseData = z.infer<typeof UserResponse>;
|
|
79
|
+
export type LogoutResponseData = z.infer<typeof LogoutResponse>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Health Schemas
|
|
3
|
+
*
|
|
4
|
+
* BROWSER-SAFE: This file imports ONLY from 'zod'.
|
|
5
|
+
* Never import from @veloxts/* packages here.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Health Check Schema
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
export const HealthResponse = z.object({
|
|
15
|
+
status: z.literal('ok'),
|
|
16
|
+
version: z.string(),
|
|
17
|
+
timestamp: z.string().datetime(),
|
|
18
|
+
uptime: z.number(),
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
export type HealthResponseData = z.infer<typeof HealthResponse>;
|
|
@@ -1,34 +1,84 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* User Schemas
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* BROWSER-SAFE: This file imports ONLY from 'zod'.
|
|
5
|
+
* Never import from @veloxts/* packages here.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import { z } from 'zod';
|
|
9
9
|
|
|
10
|
-
//
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Timestamp Helper
|
|
12
|
+
// ============================================================================
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Schema that accepts Date or string and outputs ISO string.
|
|
16
|
+
* Handles Prisma Date objects → JSON-safe strings.
|
|
17
|
+
*/
|
|
18
|
+
const dateToString = z
|
|
19
|
+
.union([z.date(), z.string()])
|
|
20
|
+
.transform((val) => (val instanceof Date ? val.toISOString() : val));
|
|
21
|
+
|
|
22
|
+
// ============================================================================
|
|
23
|
+
// User Schema
|
|
24
|
+
// ============================================================================
|
|
25
|
+
|
|
26
|
+
export const UserSchema = z.object({
|
|
27
|
+
id: z.string().uuid(),
|
|
13
28
|
name: z.string().min(1).max(100),
|
|
14
|
-
email:
|
|
29
|
+
email: z.string().email(),
|
|
30
|
+
createdAt: dateToString,
|
|
31
|
+
updatedAt: dateToString,
|
|
15
32
|
});
|
|
16
33
|
|
|
17
|
-
// Complete schema with automatic Date → string serialization
|
|
18
|
-
export const UserSchema = withTimestamps(UserFields);
|
|
19
|
-
|
|
20
34
|
export type User = z.infer<typeof UserSchema>;
|
|
21
35
|
|
|
36
|
+
// ============================================================================
|
|
37
|
+
// Input Schemas
|
|
38
|
+
// ============================================================================
|
|
39
|
+
|
|
40
|
+
export const GetUserInput = z.object({
|
|
41
|
+
id: z.string().uuid(),
|
|
42
|
+
});
|
|
43
|
+
|
|
22
44
|
export const CreateUserInput = z.object({
|
|
23
45
|
name: z.string().min(1).max(100),
|
|
24
|
-
email:
|
|
46
|
+
email: z.string().email(),
|
|
25
47
|
});
|
|
26
48
|
|
|
27
49
|
export type CreateUserData = z.infer<typeof CreateUserInput>;
|
|
28
50
|
|
|
29
51
|
export const UpdateUserInput = z.object({
|
|
30
52
|
name: z.string().min(1).max(100).optional(),
|
|
31
|
-
email:
|
|
53
|
+
email: z.string().email().optional(),
|
|
32
54
|
});
|
|
33
55
|
|
|
34
56
|
export type UpdateUserData = z.infer<typeof UpdateUserInput>;
|
|
57
|
+
|
|
58
|
+
export const DeleteUserInput = z.object({
|
|
59
|
+
id: z.string().uuid(),
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
export const ListUsersInput = z
|
|
63
|
+
.object({
|
|
64
|
+
page: z.number().int().positive().optional(),
|
|
65
|
+
limit: z.number().int().positive().max(100).optional(),
|
|
66
|
+
})
|
|
67
|
+
.optional();
|
|
68
|
+
|
|
69
|
+
export type ListUsersData = z.infer<typeof ListUsersInput>;
|
|
70
|
+
|
|
71
|
+
// ============================================================================
|
|
72
|
+
// Response Schemas
|
|
73
|
+
// ============================================================================
|
|
74
|
+
|
|
75
|
+
export const PaginationMeta = z.object({
|
|
76
|
+
page: z.number(),
|
|
77
|
+
limit: z.number(),
|
|
78
|
+
total: z.number(),
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
export const ListUsersResponse = z.object({
|
|
82
|
+
data: z.array(UserSchema),
|
|
83
|
+
meta: PaginationMeta,
|
|
84
|
+
});
|