@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.
Files changed (83) hide show
  1. package/dist/content/checklists/ship-test-loop.md +16 -0
  2. package/dist/content/checklists/unified-agent-bundle-validation.md +8 -0
  3. package/dist/content/examples/ship-test-loop.md +13 -0
  4. package/dist/content/examples/unified-agent-bundle-bootstrap.md +8 -0
  5. package/dist/content/guides/animation-performance.md +30 -0
  6. package/dist/content/guides/post-create-onboarding.md +113 -0
  7. package/dist/content/patterns/api/api-routes.md +314 -0
  8. package/dist/content/patterns/api/error-handling.md +311 -0
  9. package/dist/content/patterns/database/drizzle-schema.md +280 -0
  10. package/dist/content/patterns/database/migrations.md +365 -0
  11. package/dist/content/patterns/database/query-organization.md +537 -0
  12. package/dist/content/patterns/database/relations.md +450 -0
  13. package/dist/content/patterns/deployment/build-configuration.md +452 -0
  14. package/dist/content/patterns/deployment/ci-cd-patterns.md +448 -0
  15. package/dist/content/patterns/deployment/environment-config.md +380 -0
  16. package/dist/content/patterns/deployment/hosting-setup.md +425 -0
  17. package/dist/content/patterns/project/configuration-patterns.md +459 -0
  18. package/dist/content/patterns/project/documentation-org.md +506 -0
  19. package/dist/content/patterns/project/folder-structure.md +398 -0
  20. package/dist/content/patterns/project/library-exports.md +465 -0
  21. package/dist/content/patterns/project/monorepo-structure.md +500 -0
  22. package/dist/content/patterns/routing/dynamic-routes.md +221 -0
  23. package/dist/content/patterns/routing/file-based-routing.md +186 -0
  24. package/dist/content/patterns/routing/route-groups.md +429 -0
  25. package/dist/content/patterns/state/persistence-middleware.md +521 -0
  26. package/dist/content/patterns/state/selector-hooks.md +538 -0
  27. package/dist/content/patterns/state/store-organization.md +539 -0
  28. package/dist/content/patterns/state/zustand-patterns.md +348 -0
  29. package/dist/content/patterns/styling/component-styling.md +468 -0
  30. package/dist/content/patterns/styling/responsive-patterns.md +398 -0
  31. package/dist/content/patterns/styling/theme-configuration.md +426 -0
  32. package/dist/content/patterns/styling/uniwind-setup.md +412 -0
  33. package/dist/content/prompts/continue-development.md +27 -0
  34. package/dist/content/prompts/create-expo-super-stack.md +29 -0
  35. package/dist/content/prompts/fix-seo.md +29 -0
  36. package/dist/content/prompts/onboard-new-expo-app.md +11 -0
  37. package/dist/content/prompts/prepare-deploy.md +29 -0
  38. package/dist/content/prompts/project-research-plan.md +29 -0
  39. package/dist/content/prompts/review-expo-project.md +29 -0
  40. package/dist/content/prompts/run-doctor.md +30 -0
  41. package/dist/content/prompts/ship-test-loop.md +24 -0
  42. package/dist/content/reference/create-expo-stack-uniwind.md +29 -0
  43. package/dist/content/reference/doctor-dogfood.md +42 -0
  44. package/dist/content/reference/mcp-sdk-transport.md +30 -0
  45. package/dist/content/reference/package-ci-patterns.md +24 -0
  46. package/dist/content/reference/reference-repo-evacuation.md +31 -0
  47. package/dist/content/resource-index.json +67 -0
  48. package/dist/content/rules/app-folder-architecture.md +13 -0
  49. package/dist/content/rules/env-hygiene.md +9 -0
  50. package/dist/content/rules/seo-metadata.md +7 -0
  51. package/dist/content/rules/ssr-safety.md +9 -0
  52. package/dist/content/skills/api-routes.md +33 -0
  53. package/dist/content/skills/continue-development.md +31 -0
  54. package/dist/content/skills/debugging.md +31 -0
  55. package/dist/content/skills/deployment.md +32 -0
  56. package/dist/content/skills/dev-server-management.md +31 -0
  57. package/dist/content/skills/env-vars.md +32 -0
  58. package/dist/content/skills/expo-router-architecture.md +33 -0
  59. package/dist/content/skills/expo-ssr-safety.md +32 -0
  60. package/dist/content/skills/plugin-creation.md +41 -0
  61. package/dist/content/skills/production-server-patterns.md +31 -0
  62. package/dist/content/skills/project-onboarding.md +31 -0
  63. package/dist/content/skills/research-plan-intake.md +31 -0
  64. package/dist/content/skills/seo-metadata.md +31 -0
  65. package/dist/content/skills/super-stack-startup.md +31 -0
  66. package/dist/content/skills/uniwind-theming.md +32 -0
  67. package/dist/index.d.ts +46 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +369 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/patterns/index.d.ts +78 -0
  72. package/dist/patterns/index.d.ts.map +1 -0
  73. package/dist/patterns/index.js +264 -0
  74. package/dist/patterns/index.js.map +1 -0
  75. package/dist/prompts/index.d.ts +35 -0
  76. package/dist/prompts/index.d.ts.map +1 -0
  77. package/dist/prompts/index.js +270 -0
  78. package/dist/prompts/index.js.map +1 -0
  79. package/dist/skills/index.d.ts +3 -0
  80. package/dist/skills/index.d.ts.map +1 -0
  81. package/dist/skills/index.js +2 -0
  82. package/dist/skills/index.js.map +1 -0
  83. package/package.json +50 -0
@@ -0,0 +1,450 @@
1
+ # Table Relations Pattern
2
+
3
+ ## Description
4
+
5
+ Relations define how tables connect through foreign keys and reference relationships in Drizzle ORM. The `relations.ts` file explicitly declares one-to-many, many-to-one, and one-to-one relationships, enabling type-safe queries that fetch related data with full TypeScript inference.
6
+
7
+ ## When to Use
8
+
9
+ **Define relations when:**
10
+ - ✅ Table A references Table B (foreign key)
11
+ - ✅ Need to query parent + child data together
12
+ - ✅ Want type-safe relationship loading
13
+ - ✅ Implementing nested/relational queries
14
+ - ✅ Ensuring referential integrity
15
+ - ✅ Building flexible association patterns
16
+
17
+ ## Core Concepts
18
+
19
+ **Relationship Types:**
20
+ 1. **One-to-Many**: One profile has many posts
21
+ 2. **Many-to-One**: Many posts belong to one profile
22
+ 3. **One-to-One**: One profile has one settings
23
+ 4. **Many-to-Many**: Many users have many groups (junction table)
24
+
25
+ **Relation Declaration:**
26
+ ```typescript
27
+ // Foreign key in database:
28
+ posts.user_id → profiles.id
29
+
30
+ // In relations.ts:
31
+ export const profilesRelations = relations(profiles, ({ many }) => ({
32
+ posts: many(posts), // One profile can have many posts
33
+ }));
34
+
35
+ export const postsRelations = relations(posts, ({ one }) => ({
36
+ author: one(profiles, {
37
+ fields: [posts.userId],
38
+ references: [profiles.id],
39
+ }),
40
+ }));
41
+ ```
42
+
43
+ **Type Safety:**
44
+ - Zustand stores for state: `User | null`
45
+ - Drizzle types from schema: `typeof profiles.$inferSelect`
46
+ - Relations enable: `profile.posts` with full type checking
47
+
48
+ ## Code Examples
49
+
50
+ ### Basic One-to-Many Relations
51
+
52
+ ```typescript
53
+ // File: src/db/profilesSchema.ts
54
+ import { pgTable, uuid, text, timestamp } from 'drizzle-orm/pg-core';
55
+
56
+ export const profiles = pgTable('profiles', {
57
+ id: uuid('id').defaultRandom().primaryKey(),
58
+ username: text('username').notNull().unique(),
59
+ email: text('email').notNull().unique(),
60
+ bio: text('bio'),
61
+ createdAt: timestamp('created_at').defaultNow().notNull(),
62
+ });
63
+
64
+ export type Profile = typeof profiles.$inferSelect;
65
+
66
+ // File: src/db/postsSchema.ts
67
+ export const posts = pgTable('posts', {
68
+ id: uuid('id').defaultRandom().primaryKey(),
69
+ userId: uuid('user_id')
70
+ .notNull()
71
+ .references(() => profiles.id, { onDelete: 'cascade' }),
72
+ title: text('title').notNull(),
73
+ content: text('content').notNull(),
74
+ createdAt: timestamp('created_at').defaultNow().notNull(),
75
+ });
76
+
77
+ export type Post = typeof posts.$inferSelect;
78
+
79
+ // File: src/db/relations.ts
80
+ import { relations } from 'drizzle-orm';
81
+ import { profiles, posts } from './schemas';
82
+
83
+ /**
84
+ * One profile has many posts
85
+ */
86
+ export const profilesRelations = relations(profiles, ({ many }) => ({
87
+ posts: many(posts),
88
+ }));
89
+
90
+ /**
91
+ * Many posts belong to one profile
92
+ */
93
+ export const postsRelations = relations(posts, ({ one }) => ({
94
+ author: one(profiles, {
95
+ fields: [posts.userId],
96
+ references: [profiles.id],
97
+ }),
98
+ }));
99
+ ```
100
+
101
+ ### Query with Relations
102
+
103
+ ```typescript
104
+ // File: src/db/postsQueries.ts
105
+ import { db } from './index';
106
+ import { posts, profiles } from './schemas';
107
+ import { eq } from 'drizzle-orm';
108
+
109
+ /**
110
+ * Get post with author data
111
+ */
112
+ export async function getPostWithAuthor(postId: string) {
113
+ return await db.query.posts.findFirst({
114
+ where: eq(posts.id, postId),
115
+ with: {
116
+ author: true, // Load related profile
117
+ },
118
+ });
119
+ }
120
+
121
+ // Result type:
122
+ // {
123
+ // id: string;
124
+ // title: string;
125
+ // content: string;
126
+ // userId: string;
127
+ // createdAt: Date;
128
+ // author: {
129
+ // id: string;
130
+ // username: string;
131
+ // email: string;
132
+ // bio: string | null;
133
+ // createdAt: Date;
134
+ // }
135
+ // }
136
+ ```
137
+
138
+ ### Complex Relations: Many-to-Many
139
+
140
+ ```typescript
141
+ // File: src/db/usersSchema.ts
142
+ export const users = pgTable('users', {
143
+ id: uuid('id').defaultRandom().primaryKey(),
144
+ username: text('username').notNull().unique(),
145
+ });
146
+
147
+ // File: src/db/groupsSchema.ts
148
+ export const groups = pgTable('groups', {
149
+ id: uuid('id').defaultRandom().primaryKey(),
150
+ name: text('name').notNull(),
151
+ });
152
+
153
+ // File: src/db/userGroupsSchema.ts (Junction table)
154
+ export const userGroups = pgTable('user_groups', {
155
+ userId: uuid('user_id')
156
+ .notNull()
157
+ .references(() => users.id, { onDelete: 'cascade' }),
158
+ groupId: uuid('group_id')
159
+ .notNull()
160
+ .references(() => groups.id, { onDelete: 'cascade' }),
161
+ });
162
+
163
+ // File: src/db/relations.ts
164
+ export const usersRelations = relations(users, ({ many }) => ({
165
+ userGroups: many(userGroups), // Users have many group memberships
166
+ }));
167
+
168
+ export const groupsRelations = relations(groups, ({ many }) => ({
169
+ userGroups: many(userGroups), // Groups have many user members
170
+ }));
171
+
172
+ export const userGroupsRelations = relations(userGroups, ({ one }) => ({
173
+ user: one(users, {
174
+ fields: [userGroups.userId],
175
+ references: [users.id],
176
+ }),
177
+ group: one(groups, {
178
+ fields: [userGroups.groupId],
179
+ references: [groups.id],
180
+ }),
181
+ }));
182
+
183
+ // Query usage:
184
+ const userWithGroups = await db.query.users.findFirst({
185
+ where: eq(users.id, userId),
186
+ with: {
187
+ userGroups: {
188
+ with: {
189
+ group: true, // Nested relations
190
+ },
191
+ },
192
+ },
193
+ });
194
+ ```
195
+
196
+ ### One-to-One Relations
197
+
198
+ ```typescript
199
+ // File: src/db/userSettingsSchema.ts
200
+ export const userSettings = pgTable('user_settings', {
201
+ id: uuid('id').defaultRandom().primaryKey(),
202
+ userId: uuid('user_id')
203
+ .notNull()
204
+ .unique() // One-to-one: unique constraint
205
+ .references(() => users.id, { onDelete: 'cascade' }),
206
+ theme: text('theme').default('auto'),
207
+ notificationsEnabled: boolean('notifications_enabled').default(true),
208
+ });
209
+
210
+ // File: src/db/relations.ts
211
+ export const usersRelations = relations(users, ({ one }) => ({
212
+ settings: one(userSettings, {
213
+ fields: [users.id],
214
+ references: [userSettings.userId],
215
+ }),
216
+ }));
217
+
218
+ export const userSettingsRelations = relations(userSettings, ({ one }) => ({
219
+ user: one(users, {
220
+ fields: [userSettings.userId],
221
+ references: [users.id],
222
+ }),
223
+ }));
224
+
225
+ // Query:
226
+ const userWithSettings = await db.query.users.findFirst({
227
+ where: eq(users.id, userId),
228
+ with: {
229
+ settings: true,
230
+ },
231
+ });
232
+ ```
233
+
234
+ ### Nested Relations Query
235
+
236
+ ```typescript
237
+ // File: src/db/queriesAdvanced.ts
238
+
239
+ /**
240
+ * Get user with posts, comments, and comment authors
241
+ * Deeply nested relations
242
+ */
243
+ export async function getUserWithContent(userId: string) {
244
+ return await db.query.users.findFirst({
245
+ where: eq(users.id, userId),
246
+ with: {
247
+ // User's posts
248
+ posts: {
249
+ with: {
250
+ // Posts' comments
251
+ comments: {
252
+ with: {
253
+ // Comments' authors
254
+ author: true,
255
+ },
256
+ },
257
+ },
258
+ },
259
+ },
260
+ });
261
+ }
262
+
263
+ // Result structure:
264
+ // {
265
+ // id: string;
266
+ // username: string;
267
+ // posts: [
268
+ // {
269
+ // id: string;
270
+ // title: string;
271
+ // comments: [
272
+ // {
273
+ // id: string;
274
+ // text: string;
275
+ // author: {
276
+ // id: string;
277
+ // username: string;
278
+ // }
279
+ // }
280
+ // ]
281
+ // }
282
+ // ]
283
+ // }
284
+ ```
285
+
286
+ ### Filtering with Relations
287
+
288
+ ```typescript
289
+ // File: src/db/queriesWithFilters.ts
290
+
291
+ /**
292
+ * Get profiles that have published posts
293
+ */
294
+ export async function getProfilesWithPosts() {
295
+ return await db.query.profiles.findMany({
296
+ with: {
297
+ posts: {
298
+ where: eq(posts.published, true),
299
+ },
300
+ },
301
+ });
302
+ }
303
+
304
+ /**
305
+ * Get recent posts with author (active authors only)
306
+ */
307
+ export async function getRecentPosts() {
308
+ return await db.query.posts.findMany({
309
+ orderBy: (posts) => desc(posts.createdAt),
310
+ limit: 10,
311
+ with: {
312
+ author: {
313
+ columns: {
314
+ username: true,
315
+ profileImage: true,
316
+ },
317
+ },
318
+ },
319
+ });
320
+ }
321
+ ```
322
+
323
+ ## Relation Best Practices
324
+
325
+ ### ✅ DO
326
+
327
+ 1. **Define relations in dedicated file**
328
+ ```typescript
329
+ // ✅ RIGHT - src/db/relations.ts
330
+ export const profilesRelations = relations(...);
331
+ export const postsRelations = relations(...);
332
+
333
+ // ✅ Import in index.ts
334
+ import { profilesRelations, postsRelations } from './relations';
335
+ ```
336
+
337
+ 2. **Export from index.ts**
338
+ ```typescript
339
+ // File: src/db/index.ts
340
+ export { db } from './client';
341
+ export { profiles, posts } from './schemas';
342
+ export * from './relations'; // Make relations available
343
+ ```
344
+
345
+ 3. **Use type-safe queries**
346
+ ```typescript
347
+ // ✅ RIGHT - Full type inference
348
+ const postWithAuthor = await db.query.posts.findFirst({
349
+ where: eq(posts.id, postId),
350
+ with: {
351
+ author: true, // TypeScript knows author: Profile
352
+ },
353
+ });
354
+ ```
355
+
356
+ 4. **Name relations descriptively**
357
+ ```typescript
358
+ // ✅ RIGHT - Clear relationship names
359
+ profiles: many(posts); // Posts written by profile
360
+ author: one(profiles); // Profile who wrote this post
361
+
362
+ // ❌ WRONG - Unclear
363
+ items: many(posts);
364
+ owner: one(profiles);
365
+ ```
366
+
367
+ ### ❌ DON'T
368
+
369
+ 1. **Don't define relations in schema files**
370
+ ```typescript
371
+ // ❌ WRONG - Mixing concerns
372
+ // src/db/profilesSchema.ts
373
+ export const profilesRelations = relations(...);
374
+
375
+ // ✅ RIGHT - Dedicated relations.ts
376
+ // src/db/relations.ts
377
+ export const profilesRelations = relations(...);
378
+ ```
379
+
380
+ 2. **Don't forget to import relations in db/index.ts**
381
+ ```typescript
382
+ // ❌ WRONG - Relations not exported
383
+ // src/db/index.ts
384
+ export { db } from './client';
385
+ // (relations.ts exists but not imported)
386
+
387
+ // ✅ RIGHT
388
+ import * from './relations'; // Make relations available
389
+ ```
390
+
391
+ 3. **Don't load unnecessary relations**
392
+ ```typescript
393
+ // ❌ WRONG - Loading relation you don't use
394
+ const post = await db.query.posts.findFirst({
395
+ where: eq(posts.id, postId),
396
+ with: {
397
+ author: true,
398
+ comments: true,
399
+ tags: true,
400
+ relatedPosts: true,
401
+ },
402
+ });
403
+ // Only using post.author
404
+
405
+ // ✅ RIGHT - Load only needed relations
406
+ const post = await db.query.posts.findFirst({
407
+ where: eq(posts.id, postId),
408
+ with: {
409
+ author: true,
410
+ },
411
+ });
412
+ ```
413
+
414
+ ## Referential Integrity
415
+
416
+ ### Foreign Key Constraints
417
+
418
+ ```typescript
419
+ // File: src/db/postsSchema.ts
420
+
421
+ export const posts = pgTable('posts', {
422
+ id: uuid('id').defaultRandom().primaryKey(),
423
+ userId: uuid('user_id')
424
+ .notNull()
425
+ .references(() => profiles.id, {
426
+ onDelete: 'cascade', // Delete posts when user deleted
427
+ onUpdate: 'cascade', // Update userId when user.id changes
428
+ }),
429
+ title: text('title').notNull(),
430
+ content: text('content').notNull(),
431
+ });
432
+ ```
433
+
434
+ ### ON DELETE Options
435
+
436
+ - `cascade`: Delete child records when parent deleted
437
+ - `restrict`: Prevent parent deletion if children exist
438
+ - `set null`: Set foreign key to NULL when parent deleted
439
+ - `no action`: Raise error (requires manual cleanup)
440
+
441
+ ## Related Patterns
442
+
443
+ - [Drizzle Schema](./drizzle-schema.md) — Schema definitions
444
+ - [Migrations](./migrations.md) — Schema versioning
445
+ - [Query Organization](./query-organization.md) — Query patterns
446
+
447
+ ---
448
+
449
+ *Pattern extracted from production repositories: core-monorepo, PokePages, quantum-api*
450
+ *Files: src/db/relations.ts, query builders with nested relations*