create-velox-app 0.4.14 → 0.6.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/README.md +2 -43
  2. package/dist/cli.js +23 -13
  3. package/dist/cli.js.map +1 -1
  4. package/dist/index.js +26 -8
  5. package/dist/index.js.map +1 -1
  6. package/dist/templates/auth.d.ts.map +1 -1
  7. package/dist/templates/auth.js +24 -0
  8. package/dist/templates/auth.js.map +1 -1
  9. package/dist/templates/fullstack.d.ts +15 -0
  10. package/dist/templates/fullstack.d.ts.map +1 -0
  11. package/dist/templates/fullstack.js +110 -0
  12. package/dist/templates/fullstack.js.map +1 -0
  13. package/dist/templates/index.d.ts +1 -1
  14. package/dist/templates/index.d.ts.map +1 -1
  15. package/dist/templates/index.js +27 -5
  16. package/dist/templates/index.js.map +1 -1
  17. package/dist/templates/placeholders.d.ts +6 -1
  18. package/dist/templates/placeholders.d.ts.map +1 -1
  19. package/dist/templates/placeholders.js +15 -5
  20. package/dist/templates/placeholders.js.map +1 -1
  21. package/dist/templates/rsc.d.ts +15 -0
  22. package/dist/templates/rsc.d.ts.map +1 -0
  23. package/dist/templates/rsc.js +192 -0
  24. package/dist/templates/rsc.js.map +1 -0
  25. package/dist/templates/shared/root.d.ts +1 -0
  26. package/dist/templates/shared/root.d.ts.map +1 -1
  27. package/dist/templates/shared/root.js +4 -0
  28. package/dist/templates/shared/root.js.map +1 -1
  29. package/dist/templates/spa.d.ts +12 -0
  30. package/dist/templates/spa.d.ts.map +1 -0
  31. package/dist/templates/spa.js +101 -0
  32. package/dist/templates/spa.js.map +1 -0
  33. package/dist/templates/trpc.d.ts.map +1 -1
  34. package/dist/templates/trpc.js +16 -0
  35. package/dist/templates/trpc.js.map +1 -1
  36. package/dist/templates/types.d.ts +14 -1
  37. package/dist/templates/types.d.ts.map +1 -1
  38. package/dist/templates/types.js +35 -10
  39. package/dist/templates/types.js.map +1 -1
  40. package/package.json +3 -3
  41. package/src/templates/source/api/config/auth.ts +2 -2
  42. package/src/templates/source/api/config/database.ts +44 -10
  43. package/src/templates/source/api/index.auth.ts +10 -16
  44. package/src/templates/source/api/index.default.ts +10 -9
  45. package/src/templates/source/api/index.trpc.ts +9 -28
  46. package/src/templates/source/api/package.auth.json +7 -6
  47. package/src/templates/source/api/package.default.json +5 -4
  48. package/src/templates/source/api/prisma/schema.auth.prisma +3 -2
  49. package/src/templates/source/api/prisma/schema.default.prisma +3 -2
  50. package/src/templates/source/api/prisma.config.ts +7 -1
  51. package/src/templates/source/api/procedures/auth.ts +38 -66
  52. package/src/templates/source/api/procedures/health.ts +4 -9
  53. package/src/templates/source/api/procedures/users.auth.ts +7 -11
  54. package/src/templates/source/api/procedures/users.default.ts +7 -11
  55. package/src/templates/source/api/router.auth.ts +31 -0
  56. package/src/templates/source/api/router.default.ts +29 -0
  57. package/src/templates/source/api/router.trpc.ts +37 -0
  58. package/src/templates/source/api/router.types.auth.ts +88 -0
  59. package/src/templates/source/api/router.types.default.ts +73 -0
  60. package/src/templates/source/api/router.types.trpc.ts +73 -0
  61. package/src/templates/source/api/routes.auth.ts +66 -0
  62. package/src/templates/source/api/routes.default.ts +53 -0
  63. package/src/templates/source/api/schemas/auth.ts +79 -0
  64. package/src/templates/source/api/schemas/health.ts +21 -0
  65. package/src/templates/source/api/schemas/user.ts +62 -12
  66. package/src/templates/source/api/utils/auth.ts +157 -0
  67. package/src/templates/source/root/.cursorrules +187 -0
  68. package/src/templates/source/root/CLAUDE.auth.md +264 -0
  69. package/src/templates/source/root/CLAUDE.default.md +185 -0
  70. package/src/templates/source/root/package.json +7 -1
  71. package/src/templates/source/rsc/CLAUDE.md +104 -0
  72. package/src/templates/source/rsc/app/actions/posts.ts +93 -0
  73. package/src/templates/source/rsc/app/actions/users.ts +83 -0
  74. package/src/templates/source/rsc/app/layouts/dashboard.tsx +127 -0
  75. package/src/templates/source/rsc/app/layouts/marketing.tsx +25 -0
  76. package/src/templates/source/rsc/app/layouts/minimal.tsx +30 -0
  77. package/src/templates/source/rsc/app/layouts/root.tsx +241 -0
  78. package/src/templates/source/rsc/app/pages/(dashboard)/profile.tsx +71 -0
  79. package/src/templates/source/rsc/app/pages/(dashboard)/settings.tsx +104 -0
  80. package/src/templates/source/rsc/app/pages/(marketing)/about.tsx +52 -0
  81. package/src/templates/source/rsc/app/pages/_not-found.tsx +149 -0
  82. package/src/templates/source/rsc/app/pages/docs/[...slug].tsx +211 -0
  83. package/src/templates/source/rsc/app/pages/index.tsx +50 -0
  84. package/src/templates/source/rsc/app/pages/print.tsx +80 -0
  85. package/src/templates/source/rsc/app/pages/users/[id]/posts/[postId].tsx +89 -0
  86. package/src/templates/source/rsc/app/pages/users/[id]/posts/index.tsx +76 -0
  87. package/src/templates/source/rsc/app/pages/users/[id]/posts/new.tsx +79 -0
  88. package/src/templates/source/rsc/app/pages/users/[id].tsx +64 -0
  89. package/src/templates/source/rsc/app/pages/users/_layout.tsx +104 -0
  90. package/src/templates/source/rsc/app/pages/users.tsx +44 -0
  91. package/src/templates/source/rsc/app.config.ts +12 -0
  92. package/src/templates/source/rsc/env.example +6 -0
  93. package/src/templates/source/rsc/gitignore +34 -0
  94. package/src/templates/source/rsc/package.json +41 -0
  95. package/src/templates/source/rsc/prisma/schema.prisma +34 -0
  96. package/src/templates/source/rsc/prisma.config.ts +22 -0
  97. package/src/templates/source/rsc/public/favicon.svg +4 -0
  98. package/src/templates/source/rsc/src/api/database.ts +72 -0
  99. package/src/templates/source/rsc/src/api/handler.ts +53 -0
  100. package/src/templates/source/rsc/src/api/procedures/health.ts +48 -0
  101. package/src/templates/source/rsc/src/api/procedures/posts.ts +151 -0
  102. package/src/templates/source/rsc/src/api/procedures/users.ts +87 -0
  103. package/src/templates/source/rsc/src/api/schemas/post.ts +53 -0
  104. package/src/templates/source/rsc/src/api/schemas/user.ts +38 -0
  105. package/src/templates/source/rsc/src/entry.client.tsx +28 -0
  106. package/src/templates/source/rsc/src/entry.server.tsx +304 -0
  107. package/src/templates/source/rsc/tsconfig.json +24 -0
  108. package/src/templates/source/web/App.module.css +1 -1
  109. package/src/templates/source/web/api.ts +8 -1
  110. package/src/templates/source/web/main.tsx +4 -4
  111. package/src/templates/source/web/package.json +6 -6
  112. package/src/templates/source/web/routes/__root.tsx +2 -2
  113. package/src/templates/source/web/routes/index.auth.tsx +3 -0
@@ -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
- * Uses withTimestamps() for automatic Date string serialization.
5
- * No manual transformation needed in procedure handlers.
4
+ * BROWSER-SAFE: This file imports ONLY from 'zod'.
5
+ * Never import from @veloxts/* packages here.
6
6
  */
7
7
 
8
- import { createIdSchema, emailSchema, withTimestamps, z } from '@veloxts/velox';
8
+ import { z } from 'zod';
9
9
 
10
- // Business fields only - timestamps added separately
11
- const UserFields = z.object({
12
- id: createIdSchema('uuid'),
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: emailSchema,
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: emailSchema,
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: emailSchema.optional(),
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
+ });