@idealyst/cli 1.0.90 → 1.0.91

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 (87) hide show
  1. package/package.json +2 -2
  2. package/template/.devcontainer/Dockerfile +26 -0
  3. package/template/.devcontainer/devcontainer.json +113 -0
  4. package/template/.devcontainer/docker-compose.yml +59 -0
  5. package/template/.devcontainer/figma-mcp.sh +32 -0
  6. package/template/.devcontainer/setup.sh +45 -0
  7. package/template/.dockerignore +151 -0
  8. package/template/.env.example +36 -0
  9. package/template/.env.production +56 -0
  10. package/template/DOCKER.md +0 -0
  11. package/template/Dockerfile +111 -0
  12. package/template/README.md +233 -0
  13. package/template/docker/nginx/prod.conf +238 -0
  14. package/template/docker/nginx.conf +131 -0
  15. package/template/docker/postgres/init.sql +41 -0
  16. package/template/docker/prometheus/prometheus.yml +52 -0
  17. package/template/docker-compose.prod.yml +146 -0
  18. package/template/docker-compose.yml +143 -0
  19. package/template/jest.config.js +20 -0
  20. package/template/package.json +45 -0
  21. package/template/packages/api/.env.example +6 -0
  22. package/template/packages/api/README.md +274 -0
  23. package/template/packages/api/__tests__/api.test.ts +26 -0
  24. package/template/packages/api/jest.config.js +23 -0
  25. package/template/packages/api/jest.setup.js +9 -0
  26. package/template/packages/api/package.json +56 -0
  27. package/template/packages/api/src/context.ts +19 -0
  28. package/template/packages/api/src/controllers/TestController.ts +0 -0
  29. package/template/packages/api/src/index.ts +9 -0
  30. package/template/packages/api/src/lib/crud.ts +150 -0
  31. package/template/packages/api/src/lib/database.ts +23 -0
  32. package/template/packages/api/src/router/index.ts +163 -0
  33. package/template/packages/api/src/routers/test.ts +59 -0
  34. package/template/packages/api/src/routers/user.example.ts +83 -0
  35. package/template/packages/api/src/server.ts +50 -0
  36. package/template/packages/api/src/trpc.ts +28 -0
  37. package/template/packages/api/tsconfig.json +43 -0
  38. package/template/packages/database/README.md +162 -0
  39. package/template/packages/database/package.json +49 -0
  40. package/template/packages/database/prisma/seed.ts +64 -0
  41. package/template/packages/database/schema.prisma +107 -0
  42. package/template/packages/database/src/index.ts +15 -0
  43. package/template/packages/database/src/validators.ts +10 -0
  44. package/template/packages/database/tsconfig.json +18 -0
  45. package/template/packages/mobile/README.md +86 -0
  46. package/template/packages/mobile/__tests__/App.test.tsx +156 -0
  47. package/template/packages/mobile/__tests__/components.test.tsx +300 -0
  48. package/template/packages/mobile/app.json +5 -0
  49. package/template/packages/mobile/babel.config.js +11 -0
  50. package/template/packages/mobile/index.js +6 -0
  51. package/template/packages/mobile/jest.config.js +21 -0
  52. package/template/packages/mobile/jest.setup.js +12 -0
  53. package/template/packages/mobile/metro.config.js +27 -0
  54. package/template/packages/mobile/package.json +52 -0
  55. package/template/packages/mobile/src/App-with-trpc-and-shared.tsx +8 -0
  56. package/template/packages/mobile/src/App-with-trpc.tsx +30 -0
  57. package/template/packages/mobile/src/App.tsx +8 -0
  58. package/template/packages/mobile/src/utils/trpc.ts +7 -0
  59. package/template/packages/mobile/tsconfig.json +28 -0
  60. package/template/packages/shared/README.md +135 -0
  61. package/template/packages/shared/__tests__/shared.test.ts +51 -0
  62. package/template/packages/shared/jest.config.js +22 -0
  63. package/template/packages/shared/package.json +62 -0
  64. package/template/packages/shared/src/components/App.tsx +46 -0
  65. package/template/packages/shared/src/components/HelloWorld.tsx +304 -0
  66. package/template/packages/shared/src/components/index.ts +1 -0
  67. package/template/packages/shared/src/index.ts +14 -0
  68. package/template/packages/shared/src/navigation/AppRouter.tsx +565 -0
  69. package/template/packages/shared/src/trpc/client.ts +44 -0
  70. package/template/packages/shared/tsconfig.json +22 -0
  71. package/template/packages/web/README.md +131 -0
  72. package/template/packages/web/__tests__/App.test.tsx +342 -0
  73. package/template/packages/web/__tests__/components.test.tsx +564 -0
  74. package/template/packages/web/index.html +13 -0
  75. package/template/packages/web/jest.config.js +27 -0
  76. package/template/packages/web/jest.setup.js +24 -0
  77. package/template/packages/web/package.json +69 -0
  78. package/template/packages/web/src/App-with-trpc-and-shared.tsx +14 -0
  79. package/template/packages/web/src/App-with-trpc.tsx +32 -0
  80. package/template/packages/web/src/App.tsx +14 -0
  81. package/template/packages/web/src/components/TestDemo.tsx +164 -0
  82. package/template/packages/web/src/main.tsx +25 -0
  83. package/template/packages/web/src/utils/trpc.ts +7 -0
  84. package/template/packages/web/tsconfig.json +26 -0
  85. package/template/packages/web/vite.config.ts +98 -0
  86. package/template/setup.sh +30 -0
  87. package/template/tsconfig.json +31 -0
@@ -0,0 +1,56 @@
1
+ {
2
+ "name": "@{{workspaceScope}}/api",
3
+ "version": "{{version}}",
4
+ "description": "{{description}}",
5
+ "type": "module",
6
+ "main": "src/index.ts",
7
+ "types": "src/index.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./src/index.ts",
11
+ "import": "./src/index.ts"
12
+ }
13
+ },
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsx watch src/server.ts",
17
+ "start": "node dist/server.js",
18
+ "test": "jest",
19
+ "test:watch": "jest --watch",
20
+ "test:coverage": "jest --coverage",
21
+ "lint": "eslint src --ext .ts,.tsx",
22
+ "lint:fix": "eslint src --ext .ts,.tsx --fix",
23
+ "type-check": "tsc --noEmit"
24
+ },
25
+ "dependencies": {
26
+ "@{{workspaceScope}}/database": "workspace:*",
27
+ "@{{workspaceScope}}/shared": "workspace:*",
28
+ "@trpc/server": "^11.5.1",
29
+ "cors": "^2.8.5",
30
+ "dotenv": "^16.3.1",
31
+ "express": "^4.18.2",
32
+ "zod": "^3.22.4"
33
+ },
34
+ "devDependencies": {
35
+ "@types/cors": "^2.8.17",
36
+ "@types/express": "^4.17.21",
37
+ "@types/jest": "^29.5.12",
38
+ "@types/node": "^20.10.4",
39
+ "@typescript-eslint/eslint-plugin": "^6.13.1",
40
+ "@typescript-eslint/parser": "^6.13.1",
41
+ "eslint": "^8.54.0",
42
+ "jest": "^29.7.0",
43
+ "ts-jest": "^29.1.2",
44
+ "tsx": "^4.6.2",
45
+ "typescript": "^5.3.3"
46
+ },
47
+ "keywords": [
48
+ "api",
49
+ "trpc",
50
+ "zod",
51
+ "typescript",
52
+ "express"
53
+ ],
54
+ "author": "",
55
+ "license": "MIT"
56
+ }
@@ -0,0 +1,19 @@
1
+ import type { CreateExpressContextOptions } from '@trpc/server/adapters/express';
2
+
3
+ export interface Context {
4
+ req: CreateExpressContextOptions['req'];
5
+ res: CreateExpressContextOptions['res'];
6
+ // Add your dependencies here (e.g., database client, external services)
7
+ // Example: db: PrismaClient;
8
+ }
9
+
10
+ export const createContext = ({ req, res }: CreateExpressContextOptions): Context => {
11
+ return {
12
+ req,
13
+ res,
14
+ // Initialize your dependencies here
15
+ // Example: db: prisma,
16
+ };
17
+ };
18
+
19
+ export type { CreateExpressContextOptions };
@@ -0,0 +1,9 @@
1
+ // Main exports for the API
2
+ export { appRouter } from './router/index.js';
3
+ export type { AppRouter } from './router/index.js';
4
+
5
+ // Export context type for client usage
6
+ export type { Context } from './context.js';
7
+
8
+ // Export CRUD utilities for creating routers
9
+ export { createCrudRouter } from './lib/crud.js';
@@ -0,0 +1,150 @@
1
+ import type { Prisma } from '@{{workspaceScope}}/database/client';
2
+ import { z } from 'zod';
3
+ import { prisma } from '../lib/database.js';
4
+ import { publicProcedure, router } from '../trpc.js';
5
+
6
+ /**
7
+ * Creates a standard CRUD router for any Prisma model
8
+ *
9
+ * @param modelName - The name of the Prisma model (e.g., 'user', 'post', 'test')
10
+ * @param createSchema - Zod schema for creating new records
11
+ * @param updateSchema - Zod schema for updating records (optional, defaults to createSchema.partial())
12
+ * @returns tRPC router with standard CRUD operations
13
+ */
14
+ export function createCrudRouter<
15
+ TModelName extends Prisma.ModelName,
16
+ TCreateInput extends Record<string, any>,
17
+ TUpdateInput extends Record<string, any> = Partial<TCreateInput>
18
+ >(
19
+ modelName: TModelName,
20
+ createSchema: z.ZodSchema<TCreateInput>,
21
+ updateSchema?: z.ZodSchema<TUpdateInput>
22
+ ) {
23
+ const model = (prisma as any)[modelName];
24
+ const updateSchemaToUse = updateSchema || createSchema.partial();
25
+
26
+ return router({
27
+ // Get all records
28
+ getAll: publicProcedure
29
+ .input(z.object({
30
+ skip: z.number().min(0).optional(),
31
+ take: z.number().min(1).max(100).optional(),
32
+ orderBy: z.record(z.enum(['asc', 'desc'])).optional(),
33
+ }))
34
+ .query(async ({ input }) => {
35
+ return await model.findMany({
36
+ skip: input.skip,
37
+ take: input.take || 10,
38
+ orderBy: input.orderBy,
39
+ });
40
+ }),
41
+
42
+ // Get record by ID
43
+ getById: publicProcedure
44
+ .input(z.object({ id: z.string() }))
45
+ .query(async ({ input }) => {
46
+ const record = await model.findUnique({
47
+ where: { id: input.id },
48
+ });
49
+
50
+ if (!record) {
51
+ throw new Error(`${modelName} not found`);
52
+ }
53
+
54
+ return record;
55
+ }),
56
+
57
+ // Create new record
58
+ create: publicProcedure
59
+ .input(createSchema)
60
+ .mutation(async ({ input }) => {
61
+ return await model.create({
62
+ data: input,
63
+ });
64
+ }),
65
+
66
+ // Update record
67
+ update: publicProcedure
68
+ .input(z.object({
69
+ id: z.string(),
70
+ data: updateSchemaToUse,
71
+ }))
72
+ .mutation(async ({ input }) => {
73
+ const existingRecord = await model.findUnique({
74
+ where: { id: input.id },
75
+ });
76
+
77
+ if (!existingRecord) {
78
+ throw new Error(`${modelName} not found`);
79
+ }
80
+
81
+ return await model.update({
82
+ where: { id: input.id },
83
+ data: input.data,
84
+ });
85
+ }),
86
+
87
+ // Delete record
88
+ delete: publicProcedure
89
+ .input(z.object({ id: z.string() }))
90
+ .mutation(async ({ input }) => {
91
+ const existingRecord = await model.findUnique({
92
+ where: { id: input.id },
93
+ });
94
+
95
+ if (!existingRecord) {
96
+ throw new Error(`${modelName} not found`);
97
+ }
98
+
99
+ return await model.delete({
100
+ where: { id: input.id },
101
+ });
102
+ }),
103
+
104
+ // Get count
105
+ count: publicProcedure
106
+ .input(z.object({
107
+ where: z.record(z.any()).optional(),
108
+ }))
109
+ .query(async ({ input }) => {
110
+ return await model.count({
111
+ where: input.where,
112
+ });
113
+ }),
114
+ });
115
+ }
116
+
117
+ /**
118
+ * Example usage:
119
+ *
120
+ * ```typescript
121
+ * import { z } from 'zod';
122
+ * import { createCrudRouter } from '../lib/crud.js';
123
+ *
124
+ * // Define schemas for your model
125
+ * const createUserSchema = z.object({
126
+ * email: z.string().email(),
127
+ * name: z.string(),
128
+ * });
129
+ *
130
+ * const updateUserSchema = z.object({
131
+ * email: z.string().email().optional(),
132
+ * name: z.string().optional(),
133
+ * });
134
+ *
135
+ * // Create the CRUD router
136
+ * export const userRouter = createCrudRouter(
137
+ * 'user',
138
+ * createUserSchema,
139
+ * updateUserSchema
140
+ * );
141
+ * ```
142
+ *
143
+ * This will generate:
144
+ * - users.getAll() - Get all users with pagination
145
+ * - users.getById({ id }) - Get user by ID
146
+ * - users.create({ email, name }) - Create new user
147
+ * - users.update({ id, data: { email?, name? } }) - Update user
148
+ * - users.delete({ id }) - Delete user
149
+ * - users.count() - Get user count
150
+ */
@@ -0,0 +1,23 @@
1
+ import { PrismaClient } from '@{{workspaceScope}}/database/client';
2
+
3
+ // Initialize Prisma Client
4
+ declare global {
5
+ // eslint-disable-next-line no-var
6
+ var __prisma: PrismaClient | undefined;
7
+ }
8
+
9
+ // Prevent multiple instances of Prisma Client in development
10
+ export const prisma = globalThis.__prisma || new PrismaClient({
11
+ log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
12
+ });
13
+
14
+ if (process.env.NODE_ENV !== 'production') {
15
+ globalThis.__prisma = prisma;
16
+ }
17
+
18
+ // Graceful shutdown
19
+ process.on('beforeExit', async () => {
20
+ await prisma.$disconnect();
21
+ });
22
+
23
+ export default prisma;
@@ -0,0 +1,163 @@
1
+ import { z } from 'zod';
2
+ import { router, publicProcedure } from '../trpc.js';
3
+ import { testRouter } from '../routers/test.js';
4
+
5
+ export const appRouter = router({
6
+ // Simple hello world procedure
7
+ hello: publicProcedure
8
+ .input(z.object({ name: z.string().optional() }))
9
+ .query(({ input }) => {
10
+ return {
11
+ greeting: `Hello ${input.name || 'World'}!`,
12
+ timestamp: new Date().toISOString(),
13
+ };
14
+ }),
15
+
16
+ // Health check procedure
17
+ health: publicProcedure.query(() => {
18
+ return {
19
+ status: 'OK',
20
+ timestamp: new Date().toISOString(),
21
+ version: '1.0.0',
22
+ };
23
+ }),
24
+
25
+ // Test CRUD endpoints - generated automatically from Prisma model
26
+ test: testRouter,
27
+
28
+ // Add your model routers here
29
+ // Example:
30
+ // users: userRouter,
31
+ // posts: postRouter,
32
+ });
33
+
34
+ // Export type definition of API
35
+ export type AppRouter = typeof appRouter;
36
+
37
+ /*
38
+ SIMPLIFIED CRUD API SYSTEM:
39
+
40
+ This API template uses a simplified approach with automatic CRUD generation for Prisma models.
41
+
42
+ ## Quick Start:
43
+
44
+ 1. **Define your Prisma model** in packages/database/schema.prisma
45
+ 2. **Create Zod schemas** for validation
46
+ 3. **Generate CRUD router** using createCrudRouter()
47
+ 4. **Add to main router**
48
+
49
+ ## Example - Adding a User model:
50
+
51
+ ### 1. Define Prisma model:
52
+ ```prisma
53
+ model User {
54
+ id String @id @default(cuid())
55
+ email String @unique
56
+ name String
57
+ createdAt DateTime @default(now())
58
+ updatedAt DateTime @updatedAt
59
+ }
60
+ ```
61
+
62
+ ### 2. Create router file (src/routers/user.ts):
63
+ ```typescript
64
+ import { z } from 'zod';
65
+ import { createCrudRouter } from '../lib/crud.js';
66
+
67
+ const createUserSchema = z.object({
68
+ email: z.string().email(),
69
+ name: z.string().min(1),
70
+ });
71
+
72
+ const updateUserSchema = z.object({
73
+ email: z.string().email().optional(),
74
+ name: z.string().min(1).optional(),
75
+ });
76
+
77
+ export const userRouter = createCrudRouter(
78
+ 'user',
79
+ createUserSchema,
80
+ updateUserSchema
81
+ );
82
+ ```
83
+
84
+ ### 3. Add to main router:
85
+ ```typescript
86
+ import { userRouter } from '../routers/user.js';
87
+
88
+ export const appRouter = router({
89
+ // ... other routes
90
+ users: userRouter,
91
+ });
92
+ ```
93
+
94
+ ### 4. Use in frontend:
95
+ ```typescript
96
+ // Get all users
97
+ const { data: users } = trpc.users.getAll.useQuery();
98
+
99
+ // Create user
100
+ const createUser = trpc.users.create.useMutation();
101
+ await createUser.mutateAsync({
102
+ email: 'user@example.com',
103
+ name: 'John Doe'
104
+ });
105
+
106
+ // Update user
107
+ const updateUser = trpc.users.update.useMutation();
108
+ await updateUser.mutateAsync({
109
+ id: 'user-id',
110
+ data: { name: 'Jane Doe' }
111
+ });
112
+ ```
113
+
114
+ ## Available CRUD Operations:
115
+
116
+ Each generated router includes:
117
+ - `getAll({ skip?, take?, orderBy? })` - List with pagination
118
+ - `getById({ id })` - Get single record
119
+ - `create(data)` - Create new record
120
+ - `update({ id, data })` - Update existing record
121
+ - `delete({ id })` - Delete record
122
+ - `count({ where? })` - Count records
123
+
124
+ ## Advanced Usage:
125
+
126
+ ### Custom procedures:
127
+ You can extend generated routers with custom procedures:
128
+
129
+ ```typescript
130
+ import { z } from 'zod';
131
+ import { router, publicProcedure } from '../trpc.js';
132
+ import { createCrudRouter } from '../lib/crud.js';
133
+ import { prisma } from '../lib/database.js';
134
+
135
+ const baseCrudRouter = createCrudRouter('user', createUserSchema);
136
+
137
+ export const userRouter = router({
138
+ ...baseCrudRouter,
139
+
140
+ // Add custom procedures
141
+ getByEmail: publicProcedure
142
+ .input(z.object({ email: z.string().email() }))
143
+ .query(async ({ input }) => {
144
+ return await prisma.user.findUnique({
145
+ where: { email: input.email }
146
+ });
147
+ }),
148
+ });
149
+ ```
150
+
151
+ ### Authentication & Authorization:
152
+ Use middleware for protected procedures:
153
+
154
+ ```typescript
155
+ import { protectedProcedure } from '../trpc.js';
156
+
157
+ // Replace publicProcedure with protectedProcedure in createCrudRouter
158
+ // or create a custom version for authenticated routes
159
+ ```
160
+
161
+ This simplified system removes the controller layer complexity while providing
162
+ type-safe, validated CRUD operations for all your Prisma models.
163
+ */
@@ -0,0 +1,59 @@
1
+ import { z } from "zod";
2
+ import { createCrudRouter } from "../lib/crud.js";
3
+
4
+ // Define Zod schemas for the Test model based on the Prisma schema
5
+ const createTestSchema = z.object({
6
+ name: z.string().min(1, "Name is required"),
7
+ message: z.string().min(1, "Message is required"),
8
+ status: z.string().optional().default("active"),
9
+ });
10
+
11
+ const updateTestSchema = z.object({
12
+ name: z.string().min(1, "Name is required").optional(),
13
+ message: z.string().min(1, "Message is required").optional(),
14
+ status: z.string().optional(),
15
+ });
16
+
17
+ // Create the CRUD router for the Test model
18
+ export const testRouter = createCrudRouter(
19
+ "Test",
20
+ createTestSchema,
21
+ updateTestSchema
22
+ );
23
+
24
+ /**
25
+ * This generates the following endpoints:
26
+ *
27
+ * - test.getAll({ skip?, take?, orderBy? }) - Get all test records with pagination
28
+ * - test.getById({ id }) - Get test record by ID
29
+ * - test.create({ name, message, status? }) - Create new test record
30
+ * - test.update({ id, data: { name?, message?, status? } }) - Update test record
31
+ * - test.delete({ id }) - Delete test record
32
+ * - test.count({ where? }) - Get test record count
33
+ *
34
+ * Example usage in frontend:
35
+ *
36
+ * ```typescript
37
+ * // Get all tests
38
+ * const { data: tests } = trpc.test.getAll.useQuery({ take: 10 });
39
+ *
40
+ * // Create a new test
41
+ * const createTest = trpc.test.create.useMutation();
42
+ * await createTest.mutateAsync({
43
+ * name: 'My Test',
44
+ * message: 'This is a test message',
45
+ * status: 'active'
46
+ * });
47
+ *
48
+ * // Update a test
49
+ * const updateTest = trpc.test.update.useMutation();
50
+ * await updateTest.mutateAsync({
51
+ * id: 'test-id',
52
+ * data: { name: 'Updated Test' }
53
+ * });
54
+ *
55
+ * // Delete a test
56
+ * const deleteTest = trpc.test.delete.useMutation();
57
+ * await deleteTest.mutateAsync({ id: 'test-id' });
58
+ * ```
59
+ */
@@ -0,0 +1,83 @@
1
+ import { z } from 'zod';
2
+ import { createCrudRouter } from '../lib/crud.js';
3
+
4
+ // Define Zod schemas for the User model
5
+ const createUserSchema = z.object({
6
+ email: z.string().email('Invalid email format'),
7
+ name: z.string().min(1, 'Name is required'),
8
+ });
9
+
10
+ const updateUserSchema = z.object({
11
+ email: z.string().email('Invalid email format').optional(),
12
+ name: z.string().min(1, 'Name is required').optional(),
13
+ });
14
+
15
+ // Create the CRUD router for the User model
16
+ export const userRouter = createCrudRouter(
17
+ 'user',
18
+ createUserSchema,
19
+ updateUserSchema
20
+ );
21
+
22
+ /**
23
+ * This generates the following endpoints:
24
+ *
25
+ * - users.getAll({ skip?, take?, orderBy? }) - Get all users with pagination
26
+ * - users.getById({ id }) - Get user by ID
27
+ * - users.create({ name, email }) - Create new user
28
+ * - users.update({ id, data: { name?, email? } }) - Update user
29
+ * - users.delete({ id }) - Delete user
30
+ * - users.count({ where? }) - Get user count
31
+ *
32
+ * To use this router:
33
+ *
34
+ * 1. First add a User model to your Prisma schema:
35
+ *
36
+ * ```prisma
37
+ * model User {
38
+ * id String @id @default(cuid())
39
+ * email String @unique
40
+ * name String
41
+ * createdAt DateTime @default(now())
42
+ * updatedAt DateTime @updatedAt
43
+ * }
44
+ * ```
45
+ *
46
+ * 2. Run `yarn db:migrate` to apply the schema changes
47
+ *
48
+ * 3. Uncomment the users router in src/router/index.ts:
49
+ *
50
+ * ```typescript
51
+ * import { userRouter } from '../routers/user.js';
52
+ *
53
+ * export const appRouter = router({
54
+ * // ... other routes
55
+ * users: userRouter,
56
+ * });
57
+ * ```
58
+ *
59
+ * 4. Use in your frontend:
60
+ *
61
+ * ```typescript
62
+ * // Get all users
63
+ * const { data: users } = trpc.users.getAll.useQuery({ take: 10 });
64
+ *
65
+ * // Create a new user
66
+ * const createUser = trpc.users.create.useMutation();
67
+ * await createUser.mutateAsync({
68
+ * name: 'John Doe',
69
+ * email: 'john@example.com'
70
+ * });
71
+ *
72
+ * // Update a user
73
+ * const updateUser = trpc.users.update.useMutation();
74
+ * await updateUser.mutateAsync({
75
+ * id: 'user-id',
76
+ * data: { name: 'Jane Doe' }
77
+ * });
78
+ *
79
+ * // Delete a user
80
+ * const deleteUser = trpc.users.delete.useMutation();
81
+ * await deleteUser.mutateAsync({ id: 'user-id' });
82
+ * ```
83
+ */
@@ -0,0 +1,50 @@
1
+ import express from 'express';
2
+ import cors from 'cors';
3
+ import { createExpressMiddleware } from '@trpc/server/adapters/express';
4
+ import { appRouter } from './router/index.js';
5
+ import { createContext } from './context.js';
6
+ import dotenv from 'dotenv';
7
+
8
+ // Load environment variables
9
+ dotenv.config();
10
+
11
+ const app = express();
12
+ const PORT = process.env.PORT || 3000;
13
+
14
+ // CORS configuration
15
+ app.use(cors({
16
+ origin: process.env.CORS_ORIGIN || 'http://localhost:5173',
17
+ credentials: true,
18
+ }));
19
+
20
+ // Health check endpoint
21
+ app.get('/health', (req, res) => {
22
+ res.json({ status: 'OK', timestamp: new Date().toISOString() });
23
+ });
24
+
25
+ // tRPC middleware
26
+ app.use(
27
+ '/trpc',
28
+ createExpressMiddleware({
29
+ router: appRouter,
30
+ createContext,
31
+ })
32
+ );
33
+
34
+ // Default route
35
+ app.get('/', (req, res) => {
36
+ res.json({
37
+ message: 'Welcome to {{projectName}} API',
38
+ endpoints: {
39
+ health: '/health',
40
+ trpc: '/trpc',
41
+ playground: '/trpc-playground' // Available in development
42
+ }
43
+ });
44
+ });
45
+
46
+ app.listen(PORT, () => {
47
+ console.log(`🚀 Server running on http://localhost:${PORT}`);
48
+ console.log(`📡 tRPC API available at http://localhost:${PORT}/trpc`);
49
+ console.log(`🏥 Health check at http://localhost:${PORT}/health`);
50
+ });
@@ -0,0 +1,28 @@
1
+ import { initTRPC } from '@trpc/server';
2
+ import { type Context } from './context.js';
3
+ import { ZodError } from 'zod';
4
+
5
+ const t = initTRPC.context<Context>().create({
6
+ errorFormatter({ shape, error }) {
7
+ return {
8
+ ...shape,
9
+ data: {
10
+ ...shape.data,
11
+ zodError:
12
+ error.cause instanceof ZodError ? error.cause.flatten() : null,
13
+ },
14
+ };
15
+ },
16
+ });
17
+
18
+ // Export reusable router and procedure helpers
19
+ export const router = t.router;
20
+ export const publicProcedure = t.procedure;
21
+
22
+ // You can create additional procedures with middleware here
23
+ // For example, a protected procedure that requires authentication:
24
+ // export const protectedProcedure = t.procedure.use(async ({ ctx, next }) => {
25
+ // // Add your authentication logic here
26
+ // // Example: check for valid session/token
27
+ // return next({ ctx: { ...ctx, user: { id: 'user-id' } } });
28
+ // });
@@ -0,0 +1,43 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "ESNext",
5
+ "allowSyntheticDefaultImports": true,
6
+ "esModuleInterop": true,
7
+ "allowJs": true,
8
+ "checkJs": false,
9
+ "jsx": "preserve",
10
+ "declaration": true,
11
+ "declarationMap": true,
12
+ "sourceMap": true,
13
+ "outDir": "./dist",
14
+ "rootDir": "./src",
15
+ "removeComments": false,
16
+ "strict": true,
17
+ "noImplicitAny": true,
18
+ "strictNullChecks": true,
19
+ "strictFunctionTypes": true,
20
+ "noImplicitThis": true,
21
+ "useUnknownInCatchVariables": true,
22
+ "noImplicitReturns": true,
23
+ "noFallthroughCasesInSwitch": true,
24
+ "noUncheckedIndexedAccess": true,
25
+ "exactOptionalPropertyTypes": true,
26
+ "noPropertyAccessFromIndexSignature": false,
27
+ "resolveJsonModule": true,
28
+ "isolatedModules": true,
29
+ "forceConsistentCasingInFileNames": true,
30
+ "skipLibCheck": true
31
+ },
32
+ "include": [
33
+ "src/**/*"
34
+ ],
35
+ "exclude": [
36
+ "node_modules",
37
+ "dist",
38
+ "**/*.test.ts"
39
+ ],
40
+ "ts-node": {
41
+ "esm": true
42
+ }
43
+ }