@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,537 @@
1
+ # Query Organization Pattern
2
+
3
+ ## Description
4
+
5
+ Query organization involves structuring database query functions into dedicated files (`*Queries.ts`) for each schema. This pattern provides a clean data access layer where queries are type-safe, reusable, and organized by domain (users, posts, comments, etc.).
6
+
7
+ ## When to Use
8
+
9
+ **Organize queries when:**
10
+ - ✅ Executing SELECT, INSERT, UPDATE, DELETE operations
11
+ - ✅ Need to reuse complex queries across components
12
+ - ✅ Want centralized data access logic
13
+ - ✅ Building filters, pagination, sorting
14
+ - ✅ Implementing complex WHERE clauses
15
+ - ✅ Ensuring type safety across application
16
+
17
+ ## Core Concepts
18
+
19
+ **Query Organization Structure:**
20
+ ```
21
+ src/db/
22
+ ├── *Schema.ts # Schema definitions
23
+ ├── relations.ts # Relationship definitions
24
+ ├── *Queries.ts # Query functions (one file per schema)
25
+ ├── queryHelpers.ts # Shared query utilities
26
+ └── index.ts # Exports all queries
27
+ ```
28
+
29
+ **Principles:**
30
+ 1. One `*Queries.ts` file per schema domain
31
+ 2. Export type-safe async functions
32
+ 3. Use Drizzle ORM for type inference
33
+ 4. Centralize WHERE clauses and filters
34
+ 5. Enable selective column loading
35
+ 6. Support pagination and sorting
36
+
37
+ ## Code Examples
38
+
39
+ ### Basic Query Organization
40
+
41
+ ```typescript
42
+ // File: src/db/profilesSchema.ts
43
+ import { pgTable, uuid, text, timestamp } from 'drizzle-orm/pg-core';
44
+
45
+ export const profiles = pgTable('profiles', {
46
+ id: uuid('id').defaultRandom().primaryKey(),
47
+ username: text('username').notNull().unique(),
48
+ email: text('email').notNull().unique(),
49
+ bio: text('bio'),
50
+ profileImage: text('profile_image'),
51
+ createdAt: timestamp('created_at').defaultNow().notNull(),
52
+ updatedAt: timestamp('updated_at').defaultNow().notNull(),
53
+ });
54
+
55
+ export type Profile = typeof profiles.$inferSelect;
56
+ export type NewProfile = typeof profiles.$inferInsert;
57
+
58
+ // File: src/db/profilesQueries.ts
59
+ import { db } from './index';
60
+ import { profiles, type Profile, type NewProfile } from './profilesSchema';
61
+ import { eq, ilike, desc, asc } from 'drizzle-orm';
62
+
63
+ /**
64
+ * Get profile by ID
65
+ */
66
+ export async function getProfileById(id: string): Promise<Profile | undefined> {
67
+ const [profile] = await db
68
+ .select()
69
+ .from(profiles)
70
+ .where(eq(profiles.id, id))
71
+ .limit(1);
72
+
73
+ return profile;
74
+ }
75
+
76
+ /**
77
+ * Get profile by username
78
+ */
79
+ export async function getProfileByUsername(username: string): Promise<Profile | undefined> {
80
+ const [profile] = await db
81
+ .select()
82
+ .from(profiles)
83
+ .where(eq(profiles.username, username))
84
+ .limit(1);
85
+
86
+ return profile;
87
+ }
88
+
89
+ /**
90
+ * Get all profiles
91
+ */
92
+ export async function getAllProfiles(): Promise<Profile[]> {
93
+ return await db
94
+ .select()
95
+ .from(profiles)
96
+ .orderBy(desc(profiles.createdAt));
97
+ }
98
+
99
+ /**
100
+ * Create new profile
101
+ */
102
+ export async function createProfile(data: NewProfile): Promise<Profile> {
103
+ const [profile] = await db
104
+ .insert(profiles)
105
+ .values(data)
106
+ .returning();
107
+
108
+ return profile;
109
+ }
110
+
111
+ /**
112
+ * Update profile
113
+ */
114
+ export async function updateProfile(
115
+ id: string,
116
+ data: Partial<NewProfile>
117
+ ): Promise<Profile> {
118
+ const [profile] = await db
119
+ .update(profiles)
120
+ .set({
121
+ ...data,
122
+ updatedAt: new Date(),
123
+ })
124
+ .where(eq(profiles.id, id))
125
+ .returning();
126
+
127
+ return profile;
128
+ }
129
+
130
+ /**
131
+ * Delete profile
132
+ */
133
+ export async function deleteProfile(id: string): Promise<void> {
134
+ await db.delete(profiles).where(eq(profiles.id, id));
135
+ }
136
+ ```
137
+
138
+ ### Advanced Queries: Filtering & Pagination
139
+
140
+ ```typescript
141
+ // File: src/db/postsQueries.ts
142
+ import { db } from './index';
143
+ import { posts, profiles } from './schemas';
144
+ import { eq, desc, and, or, ilike, gt, lt } from 'drizzle-orm';
145
+
146
+ /**
147
+ * Get posts by user with pagination
148
+ */
149
+ export async function getUserPosts(
150
+ userId: string,
151
+ limit: number = 20,
152
+ offset: number = 0
153
+ ): Promise<Post[]> {
154
+ return await db
155
+ .select()
156
+ .from(posts)
157
+ .where(eq(posts.userId, userId))
158
+ .orderBy(desc(posts.createdAt))
159
+ .limit(limit)
160
+ .offset(offset);
161
+ }
162
+
163
+ /**
164
+ * Search posts by title or content
165
+ */
166
+ export async function searchPosts(query: string): Promise<Post[]> {
167
+ return await db
168
+ .select()
169
+ .from(posts)
170
+ .where(
171
+ or(
172
+ ilike(posts.title, `%${query}%`),
173
+ ilike(posts.content, `%${query}%`)
174
+ )
175
+ )
176
+ .orderBy(desc(posts.createdAt));
177
+ }
178
+
179
+ /**
180
+ * Get trending posts (by like count and date)
181
+ */
182
+ export async function getTrendingPosts(hours: number = 24): Promise<Post[]> {
183
+ const since = new Date(Date.now() - hours * 60 * 60 * 1000);
184
+
185
+ return await db
186
+ .select()
187
+ .from(posts)
188
+ .where(gt(posts.createdAt, since))
189
+ .orderBy((p) => desc(p.likes))
190
+ .limit(10);
191
+ }
192
+
193
+ /**
194
+ * Get posts with filters
195
+ */
196
+ interface PostFilters {
197
+ userId?: string;
198
+ published?: boolean;
199
+ createdAfter?: Date;
200
+ createdBefore?: Date;
201
+ searchQuery?: string;
202
+ }
203
+
204
+ export async function getPostsWithFilters(
205
+ filters: PostFilters,
206
+ limit: number = 20,
207
+ offset: number = 0
208
+ ): Promise<Post[]> {
209
+ const conditions = [];
210
+
211
+ if (filters.userId) {
212
+ conditions.push(eq(posts.userId, filters.userId));
213
+ }
214
+
215
+ if (filters.published !== undefined) {
216
+ conditions.push(eq(posts.published, filters.published));
217
+ }
218
+
219
+ if (filters.createdAfter) {
220
+ conditions.push(gt(posts.createdAt, filters.createdAfter));
221
+ }
222
+
223
+ if (filters.createdBefore) {
224
+ conditions.push(lt(posts.createdAt, filters.createdBefore));
225
+ }
226
+
227
+ if (filters.searchQuery) {
228
+ conditions.push(
229
+ or(
230
+ ilike(posts.title, `%${filters.searchQuery}%`),
231
+ ilike(posts.content, `%${filters.searchQuery}%`)
232
+ )
233
+ );
234
+ }
235
+
236
+ return await db
237
+ .select()
238
+ .from(posts)
239
+ .where(conditions.length > 0 ? and(...conditions) : undefined)
240
+ .orderBy(desc(posts.createdAt))
241
+ .limit(limit)
242
+ .offset(offset);
243
+ }
244
+ ```
245
+
246
+ ### Queries with Relations
247
+
248
+ ```typescript
249
+ // File: src/db/postsQueries.ts
250
+
251
+ /**
252
+ * Get post with author
253
+ */
254
+ export async function getPostWithAuthor(postId: string) {
255
+ return await db.query.posts.findFirst({
256
+ where: eq(posts.id, postId),
257
+ with: {
258
+ author: true, // Loads profile data
259
+ },
260
+ });
261
+ }
262
+
263
+ /**
264
+ * Get posts with authors and comment count
265
+ */
266
+ export async function getPostsWithAuthors(limit: number = 20) {
267
+ return await db.query.posts.findMany({
268
+ orderBy: desc(posts.createdAt),
269
+ limit,
270
+ with: {
271
+ author: {
272
+ columns: {
273
+ id: true,
274
+ username: true,
275
+ profileImage: true,
276
+ },
277
+ },
278
+ },
279
+ });
280
+ }
281
+
282
+ /**
283
+ * Get profile with posts
284
+ */
285
+ export async function getProfileWithPosts(profileId: string) {
286
+ return await db.query.profiles.findFirst({
287
+ where: eq(profiles.id, profileId),
288
+ with: {
289
+ posts: {
290
+ orderBy: desc(posts.createdAt),
291
+ limit: 10,
292
+ },
293
+ },
294
+ });
295
+ }
296
+ ```
297
+
298
+ ### Aggregation Queries
299
+
300
+ ```typescript
301
+ // File: src/db/aggregateQueries.ts
302
+ import { count, sum, avg, max, min } from 'drizzle-orm';
303
+
304
+ /**
305
+ * Get post statistics
306
+ */
307
+ export async function getPostStats(userId: string) {
308
+ const [stats] = await db
309
+ .select({
310
+ totalPosts: count(posts.id),
311
+ totalLikes: sum(posts.likes),
312
+ avgLikes: avg(posts.likes),
313
+ maxLikes: max(posts.likes),
314
+ minLikes: min(posts.likes),
315
+ })
316
+ .from(posts)
317
+ .where(eq(posts.userId, userId));
318
+
319
+ return stats;
320
+ }
321
+
322
+ /**
323
+ * Get user activity metrics
324
+ */
325
+ export async function getUserMetrics(userId: string) {
326
+ const [metrics] = await db
327
+ .select({
328
+ postsCount: count(posts.id),
329
+ commentsCount: count(comments.id),
330
+ likesReceived: sum(posts.likes),
331
+ })
332
+ .from(posts)
333
+ .leftJoin(comments, eq(comments.postId, posts.id))
334
+ .where(eq(posts.userId, userId));
335
+
336
+ return metrics;
337
+ }
338
+ ```
339
+
340
+ ### Batch Operations
341
+
342
+ ```typescript
343
+ // File: src/db/batchQueries.ts
344
+
345
+ /**
346
+ * Create multiple posts
347
+ */
348
+ export async function createManyPosts(posts: NewPost[]): Promise<Post[]> {
349
+ return await db
350
+ .insert(posts)
351
+ .values(posts)
352
+ .returning();
353
+ }
354
+
355
+ /**
356
+ * Update multiple posts (bulk update)
357
+ */
358
+ export async function updateManyPosts(
359
+ ids: string[],
360
+ data: Partial<NewPost>
361
+ ): Promise<void> {
362
+ await db
363
+ .update(posts)
364
+ .set({
365
+ ...data,
366
+ updatedAt: new Date(),
367
+ })
368
+ .where(inArray(posts.id, ids));
369
+ }
370
+
371
+ /**
372
+ * Delete multiple posts
373
+ */
374
+ export async function deleteManyPosts(ids: string[]): Promise<void> {
375
+ await db
376
+ .delete(posts)
377
+ .where(inArray(posts.id, ids));
378
+ }
379
+ ```
380
+
381
+ ### Query Helper Functions
382
+
383
+ ```typescript
384
+ // File: src/db/queryHelpers.ts
385
+
386
+ /**
387
+ * Pagination helper - returns paginated results + total count
388
+ */
389
+ export async function paginate<T>(
390
+ query: any,
391
+ page: number = 1,
392
+ limit: number = 20
393
+ ) {
394
+ const offset = (page - 1) * limit;
395
+
396
+ const results = await query.limit(limit).offset(offset);
397
+ const [{ total }] = await db
398
+ .select({ total: count() })
399
+ .from(/* table */);
400
+
401
+ return {
402
+ results,
403
+ total,
404
+ page,
405
+ limit,
406
+ totalPages: Math.ceil(total / limit),
407
+ };
408
+ }
409
+
410
+ /**
411
+ * Sort helper - standardize sorting
412
+ */
413
+ export function buildSort(sortBy?: string, order: 'asc' | 'desc' = 'desc') {
414
+ const sortMap: Record<string, any> = {
415
+ 'recent': desc(posts.createdAt),
416
+ 'popular': desc(posts.likes),
417
+ 'oldest': asc(posts.createdAt),
418
+ };
419
+
420
+ return sortMap[sortBy] || sortMap['recent'];
421
+ }
422
+ ```
423
+
424
+ ## Query Organization Best Practices
425
+
426
+ ### ✅ DO
427
+
428
+ 1. **Organize queries by schema**
429
+ ```typescript
430
+ // ✅ RIGHT - One file per domain
431
+ src/db/
432
+ ├── profilesQueries.ts
433
+ ├── postsQueries.ts
434
+ ├── commentsQueries.ts
435
+ ```
436
+
437
+ 2. **Export from central index**
438
+ ```typescript
439
+ // src/db/index.ts
440
+ export * from './profilesQueries';
441
+ export * from './postsQueries';
442
+ export * from './commentsQueries';
443
+ ```
444
+
445
+ 3. **Use type-safe results**
446
+ ```typescript
447
+ // ✅ RIGHT - Explicit return types
448
+ export async function getProfile(id: string): Promise<Profile | undefined> {
449
+ return await db.select().from(profiles).where(eq(profiles.id, id)).limit(1);
450
+ }
451
+ ```
452
+
453
+ 4. **Load only needed columns**
454
+ ```typescript
455
+ // ✅ RIGHT - Select specific columns
456
+ export async function getProfilePreview(id: string) {
457
+ return await db
458
+ .select({
459
+ id: profiles.id,
460
+ username: profiles.username,
461
+ profileImage: profiles.profileImage,
462
+ })
463
+ .from(profiles)
464
+ .where(eq(profiles.id, id))
465
+ .limit(1);
466
+ }
467
+ ```
468
+
469
+ ### ❌ DON'T
470
+
471
+ 1. **Don't mix query logic in components**
472
+ ```typescript
473
+ // ❌ WRONG - Query logic in React component
474
+ export function ProfileCard() {
475
+ const [profile, setProfile] = useState(null);
476
+
477
+ useEffect(() => {
478
+ db.select().from(profiles).where(...).then(setProfile);
479
+ }, []);
480
+ }
481
+
482
+ // ✅ RIGHT - Query in dedicated file, use hook
483
+ // src/db/profilesQueries.ts
484
+ export async function getProfile(id: string) { ... }
485
+
486
+ // src/hooks/useProfile.ts
487
+ export function useProfile(id: string) {
488
+ return useQuery(() => getProfile(id));
489
+ }
490
+ ```
491
+
492
+ 2. **Don't load unnecessary relations**
493
+ ```typescript
494
+ // ❌ WRONG - Loading everything
495
+ const post = await db.query.posts.findFirst({
496
+ where: eq(posts.id, postId),
497
+ with: {
498
+ author: true,
499
+ comments: { with: { author: true } },
500
+ likes: true,
501
+ tags: true,
502
+ },
503
+ });
504
+
505
+ // ✅ RIGHT - Load only needed relations
506
+ const post = await db.query.posts.findFirst({
507
+ where: eq(posts.id, postId),
508
+ with: {
509
+ author: true,
510
+ },
511
+ });
512
+ ```
513
+
514
+ 3. **Don't repeat queries across files**
515
+ ```typescript
516
+ // ❌ WRONG - Query logic duplicated
517
+ // Component A
518
+ const user = await db.select().from(profiles).where(eq(profiles.id, id));
519
+
520
+ // Component B
521
+ const user = await db.select().from(profiles).where(eq(profiles.id, id));
522
+
523
+ // ✅ RIGHT - Centralize in query file
524
+ // src/db/profilesQueries.ts
525
+ export async function getProfileById(id: string) { ... }
526
+ ```
527
+
528
+ ## Related Patterns
529
+
530
+ - [Drizzle Schema](./drizzle-schema.md) — Schema definitions
531
+ - [Migrations](./migrations.md) — Schema versioning
532
+ - [Relations](./relations.md) — Table relationships
533
+
534
+ ---
535
+
536
+ *Pattern extracted from production repositories: core-monorepo, PokePages, quantum-api*
537
+ *Files: src/db/*Queries.ts, query builders, aggregation patterns*