create-tigra 1.0.0

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 (131) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -0
  3. package/bin/create-tigra.js +292 -0
  4. package/package.json +41 -0
  5. package/template/.agent/rules/client/01-project-structure.md +326 -0
  6. package/template/.agent/rules/client/02-component-patterns.md +249 -0
  7. package/template/.agent/rules/client/03-typescript-rules.md +226 -0
  8. package/template/.agent/rules/client/04-state-management.md +474 -0
  9. package/template/.agent/rules/client/05-api-integration.md +129 -0
  10. package/template/.agent/rules/client/06-forms-validation.md +129 -0
  11. package/template/.agent/rules/client/07-common-patterns.md +150 -0
  12. package/template/.agent/rules/client/08-color-system.md +93 -0
  13. package/template/.agent/rules/client/09-security-rules.md +97 -0
  14. package/template/.agent/rules/client/10-testing-strategy.md +370 -0
  15. package/template/.agent/rules/global/ai-edit-safety.md +38 -0
  16. package/template/.agent/rules/server/01-db-and-migrations.md +242 -0
  17. package/template/.agent/rules/server/02-general-rules.md +111 -0
  18. package/template/.agent/rules/server/03-migrations.md +20 -0
  19. package/template/.agent/rules/server/04-pagination.md +130 -0
  20. package/template/.agent/rules/server/05-project-conventions.md +71 -0
  21. package/template/.agent/rules/server/06-response-handling.md +173 -0
  22. package/template/.agent/rules/server/07-testing-strategy.md +506 -0
  23. package/template/.agent/rules/server/08-observability.md +180 -0
  24. package/template/.agent/rules/server/09-api-documentation-v2.md +168 -0
  25. package/template/.agent/rules/server/10-background-jobs-v2.md +185 -0
  26. package/template/.agent/rules/server/11-rate-limiting-v2.md +210 -0
  27. package/template/.agent/rules/server/12-performance-optimization.md +567 -0
  28. package/template/.claude/rules/client-01-project-structure.md +327 -0
  29. package/template/.claude/rules/client-02-component-patterns.md +250 -0
  30. package/template/.claude/rules/client-03-typescript-rules.md +227 -0
  31. package/template/.claude/rules/client-04-state-management.md +475 -0
  32. package/template/.claude/rules/client-05-api-integration.md +130 -0
  33. package/template/.claude/rules/client-06-forms-validation.md +130 -0
  34. package/template/.claude/rules/client-07-common-patterns.md +151 -0
  35. package/template/.claude/rules/client-08-color-system.md +94 -0
  36. package/template/.claude/rules/client-09-security-rules.md +98 -0
  37. package/template/.claude/rules/client-10-testing-strategy.md +371 -0
  38. package/template/.claude/rules/global-ai-edit-safety.md +39 -0
  39. package/template/.claude/rules/server-01-db-and-migrations.md +243 -0
  40. package/template/.claude/rules/server-02-general-rules.md +112 -0
  41. package/template/.claude/rules/server-03-migrations.md +21 -0
  42. package/template/.claude/rules/server-04-pagination.md +131 -0
  43. package/template/.claude/rules/server-05-project-conventions.md +72 -0
  44. package/template/.claude/rules/server-06-response-handling.md +174 -0
  45. package/template/.claude/rules/server-07-testing-strategy.md +507 -0
  46. package/template/.claude/rules/server-08-observability.md +181 -0
  47. package/template/.claude/rules/server-09-api-documentation-v2.md +169 -0
  48. package/template/.claude/rules/server-10-background-jobs-v2.md +186 -0
  49. package/template/.claude/rules/server-11-rate-limiting-v2.md +211 -0
  50. package/template/.claude/rules/server-12-performance-optimization.md +568 -0
  51. package/template/.cursor/rules/client-01-project-structure.mdc +327 -0
  52. package/template/.cursor/rules/client-02-component-patterns.mdc +250 -0
  53. package/template/.cursor/rules/client-03-typescript-rules.mdc +227 -0
  54. package/template/.cursor/rules/client-04-state-management.mdc +475 -0
  55. package/template/.cursor/rules/client-05-api-integration.mdc +130 -0
  56. package/template/.cursor/rules/client-06-forms-validation.mdc +130 -0
  57. package/template/.cursor/rules/client-07-common-patterns.mdc +151 -0
  58. package/template/.cursor/rules/client-08-color-system.mdc +94 -0
  59. package/template/.cursor/rules/client-09-security-rules.mdc +98 -0
  60. package/template/.cursor/rules/client-10-testing-strategy.mdc +371 -0
  61. package/template/.cursor/rules/global-ai-edit-safety.mdc +39 -0
  62. package/template/.cursor/rules/server-01-db-and-migrations.mdc +243 -0
  63. package/template/.cursor/rules/server-02-general-rules.mdc +112 -0
  64. package/template/.cursor/rules/server-03-migrations.mdc +21 -0
  65. package/template/.cursor/rules/server-04-pagination.mdc +131 -0
  66. package/template/.cursor/rules/server-05-project-conventions.mdc +72 -0
  67. package/template/.cursor/rules/server-06-response-handling.mdc +174 -0
  68. package/template/.cursor/rules/server-07-testing-strategy.mdc +507 -0
  69. package/template/.cursor/rules/server-08-observability.mdc +181 -0
  70. package/template/.cursor/rules/server-09-api-documentation-v2.mdc +169 -0
  71. package/template/.cursor/rules/server-10-background-jobs-v2.mdc +186 -0
  72. package/template/.cursor/rules/server-11-rate-limiting-v2.mdc +211 -0
  73. package/template/.cursor/rules/server-12-performance-optimization.mdc +568 -0
  74. package/template/CLAUDE.md +207 -0
  75. package/template/server/.env.example +148 -0
  76. package/template/server/.tsc-aliasrc.json +12 -0
  77. package/template/server/README.md +175 -0
  78. package/template/server/SECURITY.md +190 -0
  79. package/template/server/biome.json +42 -0
  80. package/template/server/docker-compose.yml +111 -0
  81. package/template/server/package.json +83 -0
  82. package/template/server/postman_collection.json +733 -0
  83. package/template/server/prisma/schema.prisma +92 -0
  84. package/template/server/prisma/seed.ts +142 -0
  85. package/template/server/scripts/wait-for-db.js +60 -0
  86. package/template/server/src/app.ts +74 -0
  87. package/template/server/src/config/env.ts +101 -0
  88. package/template/server/src/hooks/request-timing.hook.ts +26 -0
  89. package/template/server/src/libs/auth/authenticate.middleware.ts +22 -0
  90. package/template/server/src/libs/auth/rbac.middleware.test.ts +134 -0
  91. package/template/server/src/libs/auth/rbac.middleware.ts +147 -0
  92. package/template/server/src/libs/db.ts +76 -0
  93. package/template/server/src/libs/error-handler.ts +89 -0
  94. package/template/server/src/libs/logger.ts +60 -0
  95. package/template/server/src/libs/queue.ts +79 -0
  96. package/template/server/src/libs/redis.ts +79 -0
  97. package/template/server/src/libs/swagger-schemas.ts +16 -0
  98. package/template/server/src/modules/admin/admin.controller.ts +122 -0
  99. package/template/server/src/modules/admin/admin.routes.ts +100 -0
  100. package/template/server/src/modules/admin/admin.schemas.ts +35 -0
  101. package/template/server/src/modules/admin/admin.service.ts +167 -0
  102. package/template/server/src/modules/auth/auth.controller.ts +141 -0
  103. package/template/server/src/modules/auth/auth.integration.test.ts +150 -0
  104. package/template/server/src/modules/auth/auth.repo.ts +218 -0
  105. package/template/server/src/modules/auth/auth.routes.ts +204 -0
  106. package/template/server/src/modules/auth/auth.schemas.ts +137 -0
  107. package/template/server/src/modules/auth/auth.service.test.ts +119 -0
  108. package/template/server/src/modules/auth/auth.service.ts +329 -0
  109. package/template/server/src/modules/auth/auth.types.ts +97 -0
  110. package/template/server/src/modules/resources/resources.controller.ts +218 -0
  111. package/template/server/src/modules/resources/resources.repo.ts +253 -0
  112. package/template/server/src/modules/resources/resources.routes.ts +355 -0
  113. package/template/server/src/modules/resources/resources.schemas.ts +146 -0
  114. package/template/server/src/modules/resources/resources.service.ts +218 -0
  115. package/template/server/src/modules/resources/resources.types.ts +73 -0
  116. package/template/server/src/plugins/rate-limit.plugin.ts +21 -0
  117. package/template/server/src/plugins/security.plugin.ts +21 -0
  118. package/template/server/src/plugins/swagger.plugin.ts +41 -0
  119. package/template/server/src/routes/health.routes.ts +31 -0
  120. package/template/server/src/server.ts +142 -0
  121. package/template/server/src/test/setup.ts +38 -0
  122. package/template/server/src/types/fastify.d.ts +36 -0
  123. package/template/server/src/utils/errors.ts +108 -0
  124. package/template/server/src/utils/pagination.ts +120 -0
  125. package/template/server/src/utils/response.ts +110 -0
  126. package/template/server/src/workers/file.worker.ts +106 -0
  127. package/template/server/tsconfig.build.json +30 -0
  128. package/template/server/tsconfig.build.tsbuildinfo +1 -0
  129. package/template/server/tsconfig.json +89 -0
  130. package/template/server/tsconfig.test.json +22 -0
  131. package/template/server/vitest.config.ts +98 -0
@@ -0,0 +1,371 @@
1
+ ---
2
+ trigger: always_on
3
+ globs: "client/**/*"
4
+ ---
5
+
6
+ > **SCOPE**: These rules apply specifically to the **client** directory.
7
+
8
+ # Client Testing Strategy
9
+
10
+ ## Stack
11
+
12
+ ```json
13
+ {
14
+ "devDependencies": {
15
+ "vitest": "^1.0.0",
16
+ "@testing-library/react": "^14.0.0",
17
+ "@testing-library/user-event": "^14.5.0",
18
+ "@testing-library/jest-dom": "^6.1.0",
19
+ "msw": "^2.0.0"
20
+ }
21
+ }
22
+ ```
23
+
24
+ ## Setup
25
+
26
+ ```typescript
27
+ // src/test/setup.ts
28
+ import { expect, afterEach } from 'vitest';
29
+ import { cleanup } from '@testing-library/react';
30
+ import matchers from '@testing-library/jest-dom/matchers';
31
+
32
+ expect.extend(matchers);
33
+ afterEach(() => cleanup());
34
+
35
+ // Mock window.matchMedia
36
+ Object.defineProperty(window, 'matchMedia', {
37
+ writable: true,
38
+ value: vi.fn().mockImplementation((query) => ({
39
+ matches: false,
40
+ media: query,
41
+ addEventListener: vi.fn(),
42
+ removeEventListener: vi.fn(),
43
+ })),
44
+ });
45
+ ```
46
+
47
+ ```typescript
48
+ // vite.config.ts
49
+ export default defineConfig({
50
+ test: {
51
+ globals: true,
52
+ environment: 'jsdom',
53
+ setupFiles: './src/test/setup.ts',
54
+ },
55
+ });
56
+ ```
57
+
58
+ ## Test Utilities
59
+
60
+ ```typescript
61
+ // src/test/utils.tsx
62
+ import { render } from '@testing-library/react';
63
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
64
+ import { BrowserRouter } from 'react-router-dom';
65
+ import { Provider } from 'react-redux';
66
+ import { store } from '@/store';
67
+
68
+ const createTestQueryClient = () =>
69
+ new QueryClient({
70
+ defaultOptions: { queries: { retry: false } },
71
+ });
72
+
73
+ export function renderWithProviders(ui: React.ReactElement, options = {}) {
74
+ const queryClient = createTestQueryClient();
75
+
76
+ function Wrapper({ children }: { children: React.ReactNode }) {
77
+ return (
78
+ <Provider store={store}>
79
+ <QueryClientProvider client={queryClient}>
80
+ <BrowserRouter>{children}</BrowserRouter>
81
+ </QueryClientProvider>
82
+ </Provider>
83
+ );
84
+ }
85
+
86
+ return { ...render(ui, { wrapper: Wrapper, ...options }), queryClient };
87
+ }
88
+
89
+ export * from '@testing-library/react';
90
+ export { renderWithProviders as render };
91
+ ```
92
+
93
+ ## API Mocking (MSW)
94
+
95
+ ```typescript
96
+ // src/test/mocks/handlers.ts
97
+ import { http, HttpResponse } from 'msw';
98
+
99
+ export const handlers = [
100
+ http.post('/api/v1/auth/login', async ({ request }) => {
101
+ const { email, password } = await request.json();
102
+
103
+ if (email === 'user@test.com' && password === 'password') {
104
+ return HttpResponse.json({
105
+ success: true,
106
+ data: {
107
+ user: { id: '1', email: 'user@test.com' },
108
+ tokens: { accessToken: 'fake-token' },
109
+ },
110
+ });
111
+ }
112
+
113
+ return HttpResponse.json(
114
+ { success: false, error: { code: 'INVALID_CREDENTIALS' } },
115
+ { status: 401 }
116
+ );
117
+ }),
118
+
119
+ http.get('/api/v1/resources', () => {
120
+ return HttpResponse.json({
121
+ success: true,
122
+ data: {
123
+ items: [
124
+ { id: '1', title: 'Resource 1', price: 100 },
125
+ { id: '2', title: 'Resource 2', price: 200 },
126
+ ],
127
+ pagination: { page: 1, totalPages: 1, hasNextPage: false },
128
+ },
129
+ });
130
+ }),
131
+ ];
132
+ ```
133
+
134
+ ```typescript
135
+ // src/test/mocks/server.ts
136
+ import { setupServer } from 'msw/node';
137
+ import { handlers } from './handlers';
138
+
139
+ export const server = setupServer(...handlers);
140
+ ```
141
+
142
+ ```typescript
143
+ // src/test/setup.ts (add to existing)
144
+ import { server } from './mocks/server';
145
+
146
+ beforeAll(() => server.listen());
147
+ afterEach(() => server.resetHandlers());
148
+ afterAll(() => server.close());
149
+ ```
150
+
151
+ ## Testing Patterns
152
+
153
+ ### 1. Component Tests
154
+
155
+ ```typescript
156
+ // ResourceCard.test.tsx
157
+ import { describe, it, expect, vi } from 'vitest';
158
+ import { render, screen } from '@/test/utils';
159
+ import { ResourceCard } from './ResourceCard';
160
+
161
+ describe('ResourceCard', () => {
162
+ const mockResource = {
163
+ id: '1',
164
+ title: 'Test Resource',
165
+ price: 99.99,
166
+ };
167
+
168
+ it('renders resource information', () => {
169
+ render(<ResourceCard resource={mockResource} />);
170
+
171
+ expect(screen.getByText('Test Resource')).toBeInTheDocument();
172
+ expect(screen.getByText('$99.99')).toBeInTheDocument();
173
+ });
174
+
175
+ it('calls onClick when clicked', async () => {
176
+ const handleClick = vi.fn();
177
+ const { user } = render(
178
+ <ResourceCard resource={mockResource} onClick={handleClick} />
179
+ );
180
+
181
+ await user.click(screen.getByRole('button'));
182
+ expect(handleClick).toHaveBeenCalledWith('1');
183
+ });
184
+ });
185
+ ```
186
+
187
+ ### 2. Page/Container Tests
188
+
189
+ ```typescript
190
+ // ResourcesPage.test.tsx
191
+ import { render, screen, waitFor } from '@/test/utils';
192
+
193
+ describe('ResourcesPage', () => {
194
+ it('displays loading state initially', () => {
195
+ render(<ResourcesPage />);
196
+ expect(screen.getByRole('status')).toBeInTheDocument();
197
+ });
198
+
199
+ it('renders resources after loading', async () => {
200
+ render(<ResourcesPage />);
201
+
202
+ await waitFor(() => {
203
+ expect(screen.getByText('Resource 1')).toBeInTheDocument();
204
+ });
205
+ });
206
+
207
+ it('handles API errors', async () => {
208
+ server.use(
209
+ http.get('/api/v1/resources', () => {
210
+ return HttpResponse.json(
211
+ { success: false, error: { message: 'Error' } },
212
+ { status: 500 }
213
+ );
214
+ })
215
+ );
216
+
217
+ render(<ResourcesPage />);
218
+
219
+ await waitFor(() => {
220
+ expect(screen.getByText(/error/i)).toBeInTheDocument();
221
+ });
222
+ });
223
+ });
224
+ ```
225
+
226
+ ### 3. Form Tests
227
+
228
+ ```typescript
229
+ // ResourceForm.test.tsx
230
+ import userEvent from '@testing-library/user-event';
231
+
232
+ describe('ResourceForm', () => {
233
+ it('submits valid form data', async () => {
234
+ const handleSubmit = vi.fn();
235
+ const user = userEvent.setup();
236
+
237
+ render(<ResourceForm onSubmit={handleSubmit} />);
238
+
239
+ await user.type(screen.getByLabelText(/title/i), 'New Resource');
240
+ await user.type(screen.getByLabelText(/price/i), '99.99');
241
+ await user.click(screen.getByRole('button', { name: /submit/i }));
242
+
243
+ await waitFor(() => {
244
+ expect(handleSubmit).toHaveBeenCalledWith({
245
+ title: 'New Resource',
246
+ price: 99.99,
247
+ });
248
+ });
249
+ });
250
+
251
+ it('displays validation errors', async () => {
252
+ const user = userEvent.setup();
253
+ render(<ResourceForm onSubmit={vi.fn()} />);
254
+
255
+ await user.click(screen.getByRole('button', { name: /submit/i }));
256
+
257
+ await waitFor(() => {
258
+ expect(screen.getByText(/title is required/i)).toBeInTheDocument();
259
+ });
260
+ });
261
+ });
262
+ ```
263
+
264
+ ### 4. Hook Tests
265
+
266
+ ```typescript
267
+ // useResources.test.tsx
268
+ import { renderHook, waitFor } from '@testing-library/react';
269
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
270
+
271
+ const createWrapper = () => {
272
+ const queryClient = new QueryClient({
273
+ defaultOptions: { queries: { retry: false } },
274
+ });
275
+
276
+ return ({ children }) => (
277
+ <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
278
+ );
279
+ };
280
+
281
+ describe('useResources', () => {
282
+ it('fetches resources successfully', async () => {
283
+ const { result } = renderHook(() => useResources(), {
284
+ wrapper: createWrapper(),
285
+ });
286
+
287
+ expect(result.current.isLoading).toBe(true);
288
+
289
+ await waitFor(() => {
290
+ expect(result.current.isSuccess).toBe(true);
291
+ });
292
+
293
+ expect(result.current.data).toHaveLength(2);
294
+ });
295
+ });
296
+ ```
297
+
298
+ ### 5. User Flow Tests
299
+
300
+ ```typescript
301
+ // login-flow.test.tsx
302
+ describe('Login Flow', () => {
303
+ it('allows user to login', async () => {
304
+ const user = userEvent.setup();
305
+ render(<App />, { initialRoute: '/login' });
306
+
307
+ await user.type(screen.getByLabelText(/email/i), 'user@test.com');
308
+ await user.type(screen.getByLabelText(/password/i), 'password');
309
+ await user.click(screen.getByRole('button', { name: /login/i }));
310
+
311
+ await waitFor(() => {
312
+ expect(screen.getByText(/dashboard/i)).toBeInTheDocument();
313
+ });
314
+ });
315
+ });
316
+ ```
317
+
318
+ ## Best Practices
319
+
320
+ ### ✅ DO:
321
+ ```typescript
322
+ // Test what user sees
323
+ expect(screen.getByText('Resource 1')).toBeInTheDocument();
324
+
325
+ // Use user-event for interactions
326
+ await user.click(screen.getByRole('button'));
327
+
328
+ // Wait for async updates
329
+ await waitFor(() => {
330
+ expect(screen.getByText('Success')).toBeInTheDocument();
331
+ });
332
+ ```
333
+
334
+ ### ❌ DON'T:
335
+ ```typescript
336
+ // Don't test implementation details
337
+ expect(component.state.isLoading).toBe(false); // BAD
338
+
339
+ // Don't use test IDs unnecessarily
340
+ screen.getByTestId('card'); // Prefer semantic queries
341
+
342
+ // Don't test third-party libraries
343
+ expect(mockRouter.navigate).toHaveBeenCalled(); // BAD
344
+ ```
345
+
346
+ ## Coverage Requirements
347
+
348
+ ```json
349
+ {
350
+ "scripts": {
351
+ "test": "vitest run",
352
+ "test:watch": "vitest",
353
+ "test:coverage": "vitest run --coverage"
354
+ }
355
+ }
356
+ ```
357
+
358
+ **Minimum:**
359
+ - Hooks: 80%
360
+ - Components: 70%
361
+ - Utils: 90%
362
+ - Overall: 70%
363
+
364
+ ## Checklist
365
+
366
+ - [ ] Test setup configured (RTL + MSW)
367
+ - [ ] All critical user flows tested
368
+ - [ ] Forms validated and tested
369
+ - [ ] API mocking for endpoints
370
+ - [ ] 70%+ code coverage
371
+ - [ ] Tests run in CI
@@ -0,0 +1,39 @@
1
+ ---
2
+ trigger: always_on
3
+ globs: "**/*"
4
+ ---
5
+
6
+ > **SCOPE**: These rules apply to the entire workspace (**server** and **client**).
7
+
8
+ # API Server – Safe Editing Rules
9
+
10
+ ## General safety
11
+
12
+ - Assume this is a real production project. Avoid destructive or experimental changes.
13
+ - Never delete or radically restructure large parts of the codebase unless explicitly requested.
14
+
15
+ ## When modifying existing code
16
+
17
+ - Keep changes as **small and focused** as possible.
18
+ - Do not change:
19
+ - Existing function signatures unless explicitly asked.
20
+ - Existing exports/imports that other modules depend on.
21
+ - If you must introduce a breaking change, call it out clearly in the explanation.
22
+
23
+ ## Backwards compatibility
24
+
25
+ - When adding new features, prefer extending modules over rewiring everything.
26
+ - Preserve existing behavior for:
27
+ - Auth
28
+ - Core business flows
29
+ - Payment flows
30
+
31
+ ## Comments & TODOs
32
+
33
+ - If something is ambiguous, add a `// TODO:` comment with a short note.
34
+ - Do NOT leave half-implemented features without a TODO or explanation.
35
+
36
+ ## Logs & debugging
37
+
38
+ - Do not add noisy debug logs.
39
+ - If temporary logs are necessary, clearly mark them with `// TODO: remove debug log` so they can be cleaned up.
@@ -0,0 +1,243 @@
1
+ ---
2
+ trigger: always_on
3
+ globs: "server/**/*"
4
+ ---
5
+
6
+ > **SCOPE**: These rules apply specifically to the **server** directory.
7
+
8
+ # API Server – Database & Migrations Rules
9
+
10
+ ## 🎯 Core Principles
11
+
12
+ - **Primary Database**: MySQL 8.0+
13
+ - **ORM**: Prisma (version 6.x - DO NOT upgrade to 7.x without testing)
14
+ - **Migration Philosophy**:
15
+ - Development: Fast iteration with resets
16
+ - Production: Safe, forward-only migrations
17
+ - **Schema Source of Truth**: `prisma/schema.prisma`
18
+
19
+ ---
20
+
21
+ ## 🚫 CRITICAL RULES - NEVER BREAK THESE
22
+
23
+ ### Rule 1: NO Manual Schema Changes
24
+ ❌ **NEVER** run raw SQL to change schema (CREATE TABLE, ALTER TABLE, etc.)
25
+ ✅ **ALWAYS** use Prisma migrations for schema changes
26
+ ✅ **EXCEPTION**: Data changes (INSERT, UPDATE, DELETE) can be raw SQL
27
+
28
+ ### Rule 2: Development vs Production Workflows
29
+ **Development** (when iterating on schema):
30
+ ```bash
31
+ npm run prisma:reset # Drops everything, reruns migrations
32
+ npm run prisma:seed # Repopulate test data
33
+ ```
34
+
35
+ **Production** (deployed servers):
36
+ ```bash
37
+ npm run prisma:migrate deploy # Only applies new migrations, NEVER resets
38
+ ```
39
+
40
+ ### Rule 3: Migration Conflicts = Reset
41
+ When you get migration errors in **development**:
42
+ - ❌ DON'T try to fix migration files manually
43
+ - ❌ DON'T delete migration folders
44
+ - ✅ DO run `npm run prisma:reset` to start clean
45
+
46
+ ### Rule 4: Never Use `prisma db push` in Production
47
+ - `prisma db push` = Quick prototyping, no migration history
48
+ - `prisma migrate dev` = Proper migrations with history
49
+ - Use `db push` ONLY when rapidly prototyping new features
50
+
51
+ ---
52
+
53
+ ## 📁 Naming Conventions
54
+
55
+ ### Tables
56
+ - Format: `snake_case` plural
57
+ - Examples: `users`, `posts`, `categories`
58
+
59
+ ### Columns
60
+ - Format: `snake_case`
61
+ - Timestamps: `created_at`, `updated_at`, `deleted_at`
62
+ - Foreign keys: `<table_singular>_id`
63
+ - Example: `user_id`, `category_id`
64
+
65
+ ### Prisma Models
66
+ - Format: `PascalCase` singular
67
+ - Example: `User`, `Post`, `Category`
68
+
69
+ ---
70
+
71
+ ## 🗄️ Required Fields for Every Table
72
+
73
+ Every main entity table MUST have:
74
+ ```prisma
75
+ model EntityName {
76
+ id String @id @default(uuid())
77
+ createdAt DateTime @default(now())
78
+ updatedAt DateTime @updatedAt
79
+ }
80
+ ```
81
+
82
+ Optional but recommended:
83
+ ```prisma
84
+ deletedAt DateTime? // For soft deletes
85
+ isActive Boolean @default(true) // For disabling without deleting
86
+ ```
87
+
88
+ ---
89
+
90
+ ## 🔗 Architecture Relationships
91
+
92
+ ### Core Entities (Example)
93
+ ```
94
+ users (1) ──→ (many) posts
95
+ users (1) ──→ (1) profiles
96
+ categories (1) ──→ (many) posts
97
+ ```
98
+
99
+ ### Media Attachments
100
+ For images/files attached to multiple entity types:
101
+ ```prisma
102
+ model Media {
103
+ id String @id @default(uuid())
104
+ entityType String // 'post', 'user', 'product'
105
+ entityId String // ID of the related entity
106
+ url String
107
+ type String // 'image', 'video', 'document'
108
+ order Int // For sorting galleries
109
+
110
+ @@index([entityType, entityId])
111
+ }
112
+ ```
113
+
114
+ ---
115
+
116
+ ## ⚡ Indexing Strategy
117
+
118
+ ### Always Index These:
119
+ 1. **Foreign Keys** - Prisma auto-indexes, but verify:
120
+ ```prisma
121
+ @@index([userId])
122
+ ```
123
+
124
+ 2. **Filter Columns** - Fields used in WHERE clauses:
125
+ ```prisma
126
+ @@index([isActive])
127
+ @@index([status])
128
+ ```
129
+
130
+ 3. **Composite Indexes** - Multiple columns filtered together:
131
+ ```prisma
132
+ @@index([categoryId, isActive])
133
+ ```
134
+
135
+ 4. **Unique Constraints** - Business logic requirements:
136
+ ```prisma
137
+ @@unique([email])
138
+ @@unique([slug])
139
+ ```
140
+
141
+ ### When NOT to Index:
142
+ - Low-cardinality boolean fields used alone (e.g., `isActive` by itself)
143
+ - Text/blob columns
144
+ - Fields never used in WHERE/ORDER BY
145
+
146
+ ---
147
+
148
+ ## 🔄 Migration Workflow
149
+
150
+ ### When Making Schema Changes:
151
+
152
+ #### Step 1: Edit `prisma/schema.prisma`
153
+ ```prisma
154
+ model Resource {
155
+ id String @id @default(uuid())
156
+ title String
157
+ description String? @db.Text // NEW FIELD
158
+ // ... rest of fields
159
+ }
160
+ ```
161
+
162
+ #### Step 2: Create Migration (Development)
163
+ ```bash
164
+ # Option A: With descriptive name
165
+ npm run prisma:migrate dev --name add_resource_description
166
+
167
+ # Option B: If migration conflicts occur
168
+ npm run prisma:reset # Nuclear option - drops everything
169
+ npm run prisma:seed # Repopulate test data
170
+ ```
171
+
172
+ ---
173
+
174
+ ## 🚀 Production Deployment Workflow
175
+
176
+ ### Pre-Deployment Checklist:
177
+ 1. ✅ All migrations tested locally
178
+ 2. ✅ Seed data runs successfully
179
+ 3. ✅ No pending schema changes in `schema.prisma`
180
+ 4. ✅ Migration files committed to git
181
+
182
+ ### Deployment Commands:
183
+ ```bash
184
+ # On production server:
185
+ npm run prisma:migrate deploy # Applies pending migrations only
186
+ npm run prisma:generate # Regenerates client with new schema
187
+ npm start # Restart application
188
+ ```
189
+
190
+ ---
191
+
192
+ ## 📊 Data Integrity Rules
193
+
194
+ ### Foreign Keys
195
+ - ✅ **USE** foreign keys for core relationships
196
+ - ✅ **USE** `onDelete: Cascade` for dependent data
197
+ ```prisma
198
+ user User @relation(fields: [userId], references: [id], onDelete: Cascade)
199
+ ```
200
+
201
+ ### Soft Deletes
202
+ Prefer soft deletes for user-generated content:
203
+ ```prisma
204
+ model Resource {
205
+ deletedAt DateTime?
206
+ // Query helper: where: { deletedAt: null }
207
+ }
208
+ ```
209
+
210
+ ---
211
+
212
+ ## 🛠️ Troubleshooting Guide
213
+
214
+ ### Issue: "Environment variable not found: DATABASE_URL"
215
+ **Solution:**
216
+ ```bash
217
+ # Verify .env exists and has:
218
+ DATABASE_URL="mysql://user:pass@localhost:3306/dbname"
219
+ ```
220
+
221
+ ### Issue: "Prisma Client is not generated"
222
+ **Solution:**
223
+ ```bash
224
+ npm run prisma:generate
225
+ ```
226
+
227
+ ---
228
+
229
+ ## 🎯 Best Practices Summary
230
+
231
+ ### ✅ DO:
232
+ - Use Prisma migrations for ALL schema changes
233
+ - Reset database freely in development
234
+ - Test migrations in staging before production
235
+ - Add indexes for frequently queried fields
236
+ - Use soft deletes for user content
237
+ - Commit migration files to git
238
+
239
+ ### ❌ DON'T:
240
+ - Manually edit database schema
241
+ - Use `prisma:reset` in production
242
+ - Skip migrations and use `db push` in production
243
+ - Delete migration files