@mr.dj2u/knowledge 0.1.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.
- package/dist/content/checklists/ship-test-loop.md +16 -0
- package/dist/content/checklists/unified-agent-bundle-validation.md +8 -0
- package/dist/content/examples/ship-test-loop.md +13 -0
- package/dist/content/examples/unified-agent-bundle-bootstrap.md +8 -0
- package/dist/content/guides/animation-performance.md +30 -0
- package/dist/content/guides/post-create-onboarding.md +113 -0
- package/dist/content/patterns/api/api-routes.md +314 -0
- package/dist/content/patterns/api/error-handling.md +311 -0
- package/dist/content/patterns/database/drizzle-schema.md +280 -0
- package/dist/content/patterns/database/migrations.md +365 -0
- package/dist/content/patterns/database/query-organization.md +537 -0
- package/dist/content/patterns/database/relations.md +450 -0
- package/dist/content/patterns/deployment/build-configuration.md +452 -0
- package/dist/content/patterns/deployment/ci-cd-patterns.md +448 -0
- package/dist/content/patterns/deployment/environment-config.md +380 -0
- package/dist/content/patterns/deployment/hosting-setup.md +425 -0
- package/dist/content/patterns/project/configuration-patterns.md +459 -0
- package/dist/content/patterns/project/documentation-org.md +506 -0
- package/dist/content/patterns/project/folder-structure.md +398 -0
- package/dist/content/patterns/project/library-exports.md +465 -0
- package/dist/content/patterns/project/monorepo-structure.md +500 -0
- package/dist/content/patterns/routing/dynamic-routes.md +221 -0
- package/dist/content/patterns/routing/file-based-routing.md +186 -0
- package/dist/content/patterns/routing/route-groups.md +429 -0
- package/dist/content/patterns/state/persistence-middleware.md +521 -0
- package/dist/content/patterns/state/selector-hooks.md +538 -0
- package/dist/content/patterns/state/store-organization.md +539 -0
- package/dist/content/patterns/state/zustand-patterns.md +348 -0
- package/dist/content/patterns/styling/component-styling.md +468 -0
- package/dist/content/patterns/styling/responsive-patterns.md +398 -0
- package/dist/content/patterns/styling/theme-configuration.md +426 -0
- package/dist/content/patterns/styling/uniwind-setup.md +412 -0
- package/dist/content/prompts/continue-development.md +27 -0
- package/dist/content/prompts/create-expo-super-stack.md +29 -0
- package/dist/content/prompts/fix-seo.md +29 -0
- package/dist/content/prompts/onboard-new-expo-app.md +11 -0
- package/dist/content/prompts/prepare-deploy.md +29 -0
- package/dist/content/prompts/project-research-plan.md +29 -0
- package/dist/content/prompts/review-expo-project.md +29 -0
- package/dist/content/prompts/run-doctor.md +30 -0
- package/dist/content/prompts/ship-test-loop.md +24 -0
- package/dist/content/reference/create-expo-stack-uniwind.md +29 -0
- package/dist/content/reference/doctor-dogfood.md +42 -0
- package/dist/content/reference/mcp-sdk-transport.md +30 -0
- package/dist/content/reference/package-ci-patterns.md +24 -0
- package/dist/content/reference/reference-repo-evacuation.md +31 -0
- package/dist/content/resource-index.json +67 -0
- package/dist/content/rules/app-folder-architecture.md +13 -0
- package/dist/content/rules/env-hygiene.md +9 -0
- package/dist/content/rules/seo-metadata.md +7 -0
- package/dist/content/rules/ssr-safety.md +9 -0
- package/dist/content/skills/api-routes.md +33 -0
- package/dist/content/skills/continue-development.md +31 -0
- package/dist/content/skills/debugging.md +31 -0
- package/dist/content/skills/deployment.md +32 -0
- package/dist/content/skills/dev-server-management.md +31 -0
- package/dist/content/skills/env-vars.md +32 -0
- package/dist/content/skills/expo-router-architecture.md +33 -0
- package/dist/content/skills/expo-ssr-safety.md +32 -0
- package/dist/content/skills/plugin-creation.md +41 -0
- package/dist/content/skills/production-server-patterns.md +31 -0
- package/dist/content/skills/project-onboarding.md +31 -0
- package/dist/content/skills/research-plan-intake.md +31 -0
- package/dist/content/skills/seo-metadata.md +31 -0
- package/dist/content/skills/super-stack-startup.md +31 -0
- package/dist/content/skills/uniwind-theming.md +32 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +369 -0
- package/dist/index.js.map +1 -0
- package/dist/patterns/index.d.ts +78 -0
- package/dist/patterns/index.d.ts.map +1 -0
- package/dist/patterns/index.js +264 -0
- package/dist/patterns/index.js.map +1 -0
- package/dist/prompts/index.d.ts +35 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +270 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/skills/index.d.ts +3 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +2 -0
- package/dist/skills/index.js.map +1 -0
- package/package.json +50 -0
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
# Drizzle Migrations Pattern
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
Migrations are TypeScript files generated by Drizzle that track database schema changes over time. They provide version control for your database structure, enabling rollback, forward migration, and reproducible deployments across environments. Migrations are auto-generated when you modify schema files and run `drizzle-kit generate`.
|
|
6
|
+
|
|
7
|
+
## When to Use
|
|
8
|
+
|
|
9
|
+
**Generate migrations when:**
|
|
10
|
+
- ✅ Adding or removing table columns
|
|
11
|
+
- ✅ Creating new tables
|
|
12
|
+
- ✅ Modifying column types or constraints
|
|
13
|
+
- ✅ Adding/removing indexes
|
|
14
|
+
- ✅ Changing relationships or foreign keys
|
|
15
|
+
- ✅ Preparing for production deployment
|
|
16
|
+
- ✅ Collaborating with team (schema changes shared via git)
|
|
17
|
+
|
|
18
|
+
## Core Concepts
|
|
19
|
+
|
|
20
|
+
**Migration Lifecycle:**
|
|
21
|
+
1. Define schema changes in TypeScript (`*Schema.ts` files)
|
|
22
|
+
2. Run `drizzle-kit generate` → generates SQL migration file
|
|
23
|
+
3. Review migration SQL (in `drizzle/` folder)
|
|
24
|
+
4. Apply migration with `drizzle-kit migrate`
|
|
25
|
+
5. Migration recorded in `__drizzle_migrations_journal__` table
|
|
26
|
+
6. Future deployments run only unapplied migrations
|
|
27
|
+
|
|
28
|
+
**Why Migrations Matter:**
|
|
29
|
+
- **Version Control**: Track all schema changes with git
|
|
30
|
+
- **Reproducibility**: Any environment can reach exact schema state
|
|
31
|
+
- **Rollback Safety**: Each migration can be reversed
|
|
32
|
+
- **Collaborative**: Team members sync schema via migrations
|
|
33
|
+
- **Auditability**: See who changed what and when
|
|
34
|
+
|
|
35
|
+
## Code Examples
|
|
36
|
+
|
|
37
|
+
### Schema Definition (Input for Migrations)
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
// File: src/db/usersSchema.ts
|
|
41
|
+
import { pgTable, uuid, text, timestamp, integer } from 'drizzle-orm/pg-core';
|
|
42
|
+
|
|
43
|
+
export const users = pgTable('users', {
|
|
44
|
+
id: uuid('id').defaultRandom().primaryKey(),
|
|
45
|
+
email: text('email').notNull().unique(),
|
|
46
|
+
username: text('username').notNull().unique(),
|
|
47
|
+
createdAt: timestamp('created_at').defaultNow().notNull(),
|
|
48
|
+
updatedAt: timestamp('updated_at').defaultNow().notNull(),
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// File: src/db/postsSchema.ts
|
|
52
|
+
export const posts = pgTable('posts', {
|
|
53
|
+
id: uuid('id').defaultRandom().primaryKey(),
|
|
54
|
+
userId: uuid('user_id')
|
|
55
|
+
.notNull()
|
|
56
|
+
.references(() => users.id, { onDelete: 'cascade' }),
|
|
57
|
+
title: text('title').notNull(),
|
|
58
|
+
content: text('content').notNull(),
|
|
59
|
+
likes: integer('likes').default(0).notNull(),
|
|
60
|
+
createdAt: timestamp('created_at').defaultNow().notNull(),
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Generated Migration File
|
|
65
|
+
|
|
66
|
+
```sql
|
|
67
|
+
-- File: drizzle/0001_create_users_table.sql
|
|
68
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
69
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
70
|
+
email TEXT NOT NULL UNIQUE,
|
|
71
|
+
username TEXT NOT NULL UNIQUE,
|
|
72
|
+
created_at TIMESTAMP NOT NULL DEFAULT now(),
|
|
73
|
+
updated_at TIMESTAMP NOT NULL DEFAULT now()
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
-- File: drizzle/0002_create_posts_table.sql
|
|
77
|
+
CREATE TABLE IF NOT EXISTS posts (
|
|
78
|
+
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
79
|
+
user_id uuid NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
80
|
+
title TEXT NOT NULL,
|
|
81
|
+
content TEXT NOT NULL,
|
|
82
|
+
likes INTEGER NOT NULL DEFAULT 0,
|
|
83
|
+
created_at TIMESTAMP NOT NULL DEFAULT now()
|
|
84
|
+
);
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Applying Migrations
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// File: src/db/migrate.ts
|
|
91
|
+
import { migrate } from 'drizzle-orm/postgres-js/migrator';
|
|
92
|
+
import { db, client } from './index';
|
|
93
|
+
import path from 'path';
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Run pending migrations
|
|
97
|
+
* This updates the database schema to match current schema files
|
|
98
|
+
*/
|
|
99
|
+
export async function runMigrations() {
|
|
100
|
+
try {
|
|
101
|
+
console.log('Running migrations...');
|
|
102
|
+
await migrate(db, {
|
|
103
|
+
migrationsFolder: path.join(process.cwd(), 'drizzle'),
|
|
104
|
+
});
|
|
105
|
+
console.log('Migrations completed!');
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.error('Migration failed:', error);
|
|
108
|
+
throw error;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// File: api-server.ts (on startup)
|
|
113
|
+
import { runMigrations } from './db/migrate';
|
|
114
|
+
|
|
115
|
+
async function startServer() {
|
|
116
|
+
try {
|
|
117
|
+
// Run migrations before starting server
|
|
118
|
+
await runMigrations();
|
|
119
|
+
|
|
120
|
+
// Start Express server
|
|
121
|
+
app.listen(PORT, () => {
|
|
122
|
+
console.log(`Server running on port ${PORT}`);
|
|
123
|
+
});
|
|
124
|
+
} catch (error) {
|
|
125
|
+
console.error('Server startup failed:', error);
|
|
126
|
+
process.exit(1);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Schema Modification Example
|
|
132
|
+
|
|
133
|
+
```typescript
|
|
134
|
+
// File: src/db/usersSchema.ts
|
|
135
|
+
// BEFORE: Original schema
|
|
136
|
+
export const users = pgTable('users', {
|
|
137
|
+
id: uuid('id').defaultRandom().primaryKey(),
|
|
138
|
+
email: text('email').notNull().unique(),
|
|
139
|
+
username: text('username').notNull().unique(),
|
|
140
|
+
createdAt: timestamp('created_at').defaultNow().notNull(),
|
|
141
|
+
updatedAt: timestamp('updated_at').defaultNow().notNull(),
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
// AFTER: Added new column
|
|
145
|
+
export const users = pgTable('users', {
|
|
146
|
+
id: uuid('id').defaultRandom().primaryKey(),
|
|
147
|
+
email: text('email').notNull().unique(),
|
|
148
|
+
username: text('username').notNull().unique(),
|
|
149
|
+
bio: text('bio'), // NEW COLUMN
|
|
150
|
+
profileImageUrl: text('profile_image_url'), // NEW COLUMN
|
|
151
|
+
createdAt: timestamp('created_at').defaultNow().notNull(),
|
|
152
|
+
updatedAt: timestamp('updated_at').defaultNow().notNull(),
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
// ✅ Run: npm run db:generate
|
|
156
|
+
// This generates migration file:
|
|
157
|
+
// drizzle/0003_add_user_profile_columns.sql
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Generated Migration for Schema Changes
|
|
161
|
+
|
|
162
|
+
```sql
|
|
163
|
+
-- File: drizzle/0003_add_user_profile_columns.sql
|
|
164
|
+
-- Migration automatically generated from schema changes
|
|
165
|
+
|
|
166
|
+
ALTER TABLE users
|
|
167
|
+
ADD COLUMN bio TEXT,
|
|
168
|
+
ADD COLUMN profile_image_url TEXT;
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Migration Workflow
|
|
172
|
+
|
|
173
|
+
### Development Workflow
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# Step 1: Modify schema file (e.g., src/db/usersSchema.ts)
|
|
177
|
+
# Add new column, new table, new index, etc.
|
|
178
|
+
|
|
179
|
+
# Step 2: Generate migration from schema changes
|
|
180
|
+
npm run db:generate
|
|
181
|
+
# Creates: drizzle/XXXX_description.sql
|
|
182
|
+
|
|
183
|
+
# Step 3: Review generated migration
|
|
184
|
+
cat drizzle/XXXX_description.sql
|
|
185
|
+
|
|
186
|
+
# Step 4: Apply migration to development database
|
|
187
|
+
npm run db:migrate
|
|
188
|
+
|
|
189
|
+
# Step 5: Test changes locally
|
|
190
|
+
|
|
191
|
+
# Step 6: Commit to git
|
|
192
|
+
git add src/db/*Schema.ts drizzle/XXXX_description.sql
|
|
193
|
+
git commit -m "feat: add bio to users table"
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### Team Collaboration
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
# Teammate pulls schema changes
|
|
200
|
+
git pull
|
|
201
|
+
|
|
202
|
+
# New migration file appears in drizzle/
|
|
203
|
+
# Run migrations to sync local database
|
|
204
|
+
npm run db:migrate
|
|
205
|
+
|
|
206
|
+
# Now both teammates have identical schema
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Production Deployment
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
# In production environment:
|
|
213
|
+
npm install # Install app + dependencies
|
|
214
|
+
npm run build # Build app
|
|
215
|
+
npm run db:migrate # Apply pending migrations
|
|
216
|
+
|
|
217
|
+
# Server starts with updated schema
|
|
218
|
+
npm run start
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
## Migration Best Practices
|
|
222
|
+
|
|
223
|
+
### ✅ DO
|
|
224
|
+
|
|
225
|
+
1. **Generate migrations for every schema change**
|
|
226
|
+
```bash
|
|
227
|
+
# After modifying schema file
|
|
228
|
+
npm run db:generate
|
|
229
|
+
|
|
230
|
+
# Creates numbered migration: drizzle/0123_change_name.sql
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
2. **Review migration SQL before applying**
|
|
234
|
+
```bash
|
|
235
|
+
# Always check generated SQL
|
|
236
|
+
cat drizzle/XXXX_change_name.sql
|
|
237
|
+
|
|
238
|
+
# Verify it matches your intent
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
3. **Commit migrations to git**
|
|
242
|
+
```bash
|
|
243
|
+
git add drizzle/0123_change_name.sql
|
|
244
|
+
git commit -m "chore: add migration for users table changes"
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
4. **Test migrations in development first**
|
|
248
|
+
```bash
|
|
249
|
+
npm run db:migrate # Test locally
|
|
250
|
+
# Verify changes work
|
|
251
|
+
# Then deploy with confidence
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
5. **Keep migration descriptions clear**
|
|
255
|
+
```
|
|
256
|
+
drizzle/0001_create_users_table.sql
|
|
257
|
+
drizzle/0002_create_posts_table.sql
|
|
258
|
+
drizzle/0003_add_likes_to_posts.sql ✅ Clear
|
|
259
|
+
drizzle/0004_xyz.sql ❌ Unclear
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### ❌ DON'T
|
|
263
|
+
|
|
264
|
+
1. **Don't manually edit generated migrations**
|
|
265
|
+
```sql
|
|
266
|
+
-- ❌ WRONG - Manual edits get overwritten
|
|
267
|
+
-- Don't modify drizzle/XXXX.sql directly
|
|
268
|
+
|
|
269
|
+
-- ✅ RIGHT - Regenerate from schema
|
|
270
|
+
// Modify src/db/schema.ts
|
|
271
|
+
// Run: npm run db:generate
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
2. **Don't skip migrations in development**
|
|
275
|
+
```bash
|
|
276
|
+
# ❌ WRONG - Database schema out of sync
|
|
277
|
+
// Modify schema file but don't run migrations
|
|
278
|
+
|
|
279
|
+
# ✅ RIGHT - Apply migrations immediately
|
|
280
|
+
npm run db:migrate
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
3. **Don't apply migrations without backup**
|
|
284
|
+
```bash
|
|
285
|
+
# ❌ WRONG - Production data at risk
|
|
286
|
+
npm run db:migrate --production
|
|
287
|
+
|
|
288
|
+
# ✅ RIGHT - Backup first
|
|
289
|
+
# Backup production database
|
|
290
|
+
npm run db:migrate --production
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
4. **Don't modify migrations after deployment**
|
|
294
|
+
```bash
|
|
295
|
+
# ❌ WRONG - Team database out of sync
|
|
296
|
+
# Applied: 0123_users_table.sql
|
|
297
|
+
# Then: Modify 0123_users_table.sql
|
|
298
|
+
|
|
299
|
+
# ✅ RIGHT - Create new migration
|
|
300
|
+
// Modify schema file
|
|
301
|
+
npm run db:generate # Creates 0124_users_fix.sql
|
|
302
|
+
npm run db:migrate
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Advanced Patterns
|
|
306
|
+
|
|
307
|
+
### Conditional Migrations
|
|
308
|
+
|
|
309
|
+
```sql
|
|
310
|
+
-- File: drizzle/0010_add_column_if_not_exists.sql
|
|
311
|
+
-- Check if column exists before adding
|
|
312
|
+
ALTER TABLE users
|
|
313
|
+
ADD COLUMN IF NOT EXISTS bio TEXT;
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Data Migrations
|
|
317
|
+
|
|
318
|
+
```typescript
|
|
319
|
+
// File: src/db/migrations/0011_populate_defaults.ts
|
|
320
|
+
// Sometimes you need to run code, not just SQL
|
|
321
|
+
|
|
322
|
+
import { db } from '../index';
|
|
323
|
+
import { users } from '../usersSchema';
|
|
324
|
+
import { eq } from 'drizzle-orm';
|
|
325
|
+
|
|
326
|
+
export async function populateDefaults() {
|
|
327
|
+
// Set default values for existing rows
|
|
328
|
+
await db
|
|
329
|
+
.update(users)
|
|
330
|
+
.set({ bio: 'New user' })
|
|
331
|
+
.where(eq(users.bio, null));
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### Rollback Handling
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
// File: src/db/migrate.ts
|
|
339
|
+
export async function rollbackMigration() {
|
|
340
|
+
// Drizzle doesn't support automatic rollback
|
|
341
|
+
// Instead, create inverse migrations:
|
|
342
|
+
|
|
343
|
+
// If migration adds column:
|
|
344
|
+
// drizzle/0123_add_column.sql
|
|
345
|
+
// ALTER TABLE users ADD COLUMN bio TEXT;
|
|
346
|
+
|
|
347
|
+
// Create rollback:
|
|
348
|
+
// drizzle/0124_remove_column.sql
|
|
349
|
+
// ALTER TABLE users DROP COLUMN bio;
|
|
350
|
+
|
|
351
|
+
// Then run forward migration:
|
|
352
|
+
// npm run db:migrate
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
## Related Patterns
|
|
357
|
+
|
|
358
|
+
- [Drizzle Schema](./drizzle-schema.md) — Schema definitions
|
|
359
|
+
- [Relations](./relations.md) — Table relationships
|
|
360
|
+
- [Query Organization](./query-organization.md) — Query patterns
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
*Pattern extracted from production repositories: PokePages, quantum-api*
|
|
365
|
+
*Files: drizzle/ directory, migration workflows from package.json scripts*
|