@qazuor/claude-code-config 0.4.0 → 0.6.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 (64) hide show
  1. package/README.md +395 -50
  2. package/dist/bin.cjs +3207 -165
  3. package/dist/bin.cjs.map +1 -1
  4. package/dist/bin.js +3207 -165
  5. package/dist/bin.js.map +1 -1
  6. package/dist/index.cjs +75 -58
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +284 -1
  9. package/dist/index.d.ts +284 -1
  10. package/dist/index.js +75 -58
  11. package/dist/index.js.map +1 -1
  12. package/package.json +24 -24
  13. package/templates/CLAUDE.md.template +60 -5
  14. package/templates/agents/README.md +58 -39
  15. package/templates/agents/_registry.json +43 -202
  16. package/templates/agents/engineering/{hono-engineer.md → api-engineer.md} +61 -70
  17. package/templates/agents/engineering/database-engineer.md +253 -0
  18. package/templates/agents/engineering/frontend-engineer.md +302 -0
  19. package/templates/docs/_registry.json +54 -0
  20. package/templates/docs/standards/code-standards.md +20 -0
  21. package/templates/docs/standards/design-standards.md +13 -0
  22. package/templates/docs/standards/documentation-standards.md +13 -0
  23. package/templates/docs/standards/performance-standards.md +524 -0
  24. package/templates/docs/standards/security-standards.md +496 -0
  25. package/templates/docs/standards/testing-standards.md +15 -0
  26. package/templates/hooks/on-notification.sh +0 -0
  27. package/templates/scripts/add-changelogs.sh +0 -0
  28. package/templates/scripts/generate-code-registry.ts +0 -0
  29. package/templates/scripts/health-check.sh +0 -0
  30. package/templates/scripts/sync-registry.sh +0 -0
  31. package/templates/scripts/telemetry-report.ts +0 -0
  32. package/templates/scripts/validate-docs.sh +0 -0
  33. package/templates/scripts/validate-registry.sh +0 -0
  34. package/templates/scripts/validate-structure.sh +0 -0
  35. package/templates/scripts/worktree-cleanup.sh +0 -0
  36. package/templates/scripts/worktree-create.sh +0 -0
  37. package/templates/skills/README.md +99 -90
  38. package/templates/skills/_registry.json +323 -16
  39. package/templates/skills/api-frameworks/express-patterns.md +411 -0
  40. package/templates/skills/api-frameworks/fastify-patterns.md +419 -0
  41. package/templates/skills/api-frameworks/hono-patterns.md +388 -0
  42. package/templates/skills/api-frameworks/nestjs-patterns.md +497 -0
  43. package/templates/skills/database/drizzle-patterns.md +449 -0
  44. package/templates/skills/database/mongoose-patterns.md +503 -0
  45. package/templates/skills/database/prisma-patterns.md +487 -0
  46. package/templates/skills/frontend-frameworks/astro-patterns.md +415 -0
  47. package/templates/skills/frontend-frameworks/nextjs-patterns.md +470 -0
  48. package/templates/skills/frontend-frameworks/react-patterns.md +516 -0
  49. package/templates/skills/frontend-frameworks/tanstack-start-patterns.md +469 -0
  50. package/templates/skills/patterns/atdd-methodology.md +364 -0
  51. package/templates/skills/patterns/bdd-methodology.md +281 -0
  52. package/templates/skills/patterns/clean-architecture.md +444 -0
  53. package/templates/skills/patterns/hexagonal-architecture.md +567 -0
  54. package/templates/skills/patterns/vertical-slice-architecture.md +502 -0
  55. package/templates/agents/engineering/astro-engineer.md +0 -293
  56. package/templates/agents/engineering/db-drizzle-engineer.md +0 -360
  57. package/templates/agents/engineering/express-engineer.md +0 -316
  58. package/templates/agents/engineering/fastify-engineer.md +0 -399
  59. package/templates/agents/engineering/mongoose-engineer.md +0 -473
  60. package/templates/agents/engineering/nestjs-engineer.md +0 -429
  61. package/templates/agents/engineering/nextjs-engineer.md +0 -451
  62. package/templates/agents/engineering/prisma-engineer.md +0 -432
  63. package/templates/agents/engineering/react-senior-dev.md +0 -394
  64. package/templates/agents/engineering/tanstack-start-engineer.md +0 -447
@@ -0,0 +1,503 @@
1
+ # Mongoose Patterns
2
+
3
+ ## Overview
4
+
5
+ Mongoose is an ODM (Object Document Mapper) for MongoDB. This skill provides patterns for database operations with Mongoose.
6
+
7
+ ---
8
+
9
+ ## Schema Definition
10
+
11
+ ### Basic Schema with Validation
12
+
13
+ ```typescript
14
+ import mongoose, { Schema, Document, Model } from 'mongoose';
15
+
16
+ // Interface
17
+ export interface IUser {
18
+ email: string;
19
+ name?: string;
20
+ passwordHash: string;
21
+ role: 'user' | 'admin';
22
+ items: mongoose.Types.ObjectId[];
23
+ createdAt: Date;
24
+ updatedAt: Date;
25
+ deletedAt?: Date;
26
+ }
27
+
28
+ export interface IUserDocument extends IUser, Document {}
29
+
30
+ // Schema
31
+ const userSchema = new Schema<IUserDocument>(
32
+ {
33
+ email: {
34
+ type: String,
35
+ required: true,
36
+ unique: true,
37
+ lowercase: true,
38
+ trim: true,
39
+ index: true,
40
+ },
41
+ name: {
42
+ type: String,
43
+ trim: true,
44
+ maxlength: 255,
45
+ },
46
+ passwordHash: {
47
+ type: String,
48
+ required: true,
49
+ select: false, // Don't include in queries by default
50
+ },
51
+ role: {
52
+ type: String,
53
+ enum: ['user', 'admin'],
54
+ default: 'user',
55
+ },
56
+ items: [{
57
+ type: Schema.Types.ObjectId,
58
+ ref: 'Item',
59
+ }],
60
+ deletedAt: {
61
+ type: Date,
62
+ default: null,
63
+ },
64
+ },
65
+ {
66
+ timestamps: true, // Adds createdAt and updatedAt
67
+ toJSON: {
68
+ virtuals: true,
69
+ transform: (doc, ret) => {
70
+ delete ret.__v;
71
+ delete ret.passwordHash;
72
+ return ret;
73
+ },
74
+ },
75
+ }
76
+ );
77
+
78
+ export const User = mongoose.model<IUserDocument>('User', userSchema);
79
+ ```
80
+
81
+ ### Schema with Relations
82
+
83
+ ```typescript
84
+ export interface IItem {
85
+ title: string;
86
+ description?: string;
87
+ status: 'active' | 'archived';
88
+ price: number;
89
+ author: mongoose.Types.ObjectId;
90
+ tags: mongoose.Types.ObjectId[];
91
+ createdAt: Date;
92
+ updatedAt: Date;
93
+ deletedAt?: Date;
94
+ }
95
+
96
+ export interface IItemDocument extends IItem, Document {}
97
+
98
+ const itemSchema = new Schema<IItemDocument>(
99
+ {
100
+ title: {
101
+ type: String,
102
+ required: true,
103
+ trim: true,
104
+ maxlength: 255,
105
+ },
106
+ description: {
107
+ type: String,
108
+ trim: true,
109
+ },
110
+ status: {
111
+ type: String,
112
+ enum: ['active', 'archived'],
113
+ default: 'active',
114
+ index: true,
115
+ },
116
+ price: {
117
+ type: Number,
118
+ required: true,
119
+ min: [0, 'Price must be positive'],
120
+ },
121
+ author: {
122
+ type: Schema.Types.ObjectId,
123
+ ref: 'User',
124
+ required: true,
125
+ index: true,
126
+ },
127
+ tags: [{
128
+ type: Schema.Types.ObjectId,
129
+ ref: 'Tag',
130
+ }],
131
+ deletedAt: {
132
+ type: Date,
133
+ default: null,
134
+ },
135
+ },
136
+ {
137
+ timestamps: true,
138
+ }
139
+ );
140
+
141
+ // Compound index
142
+ itemSchema.index({ author: 1, status: 1 });
143
+
144
+ // Virtual for URL
145
+ itemSchema.virtual('url').get(function () {
146
+ return `/items/${this._id}`;
147
+ });
148
+
149
+ export const Item = mongoose.model<IItemDocument>('Item', itemSchema);
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Query Patterns
155
+
156
+ ### Basic CRUD
157
+
158
+ ```typescript
159
+ // Create
160
+ const item = await Item.create({
161
+ title: 'New Item',
162
+ price: 100,
163
+ author: userId,
164
+ });
165
+
166
+ // Read one with population
167
+ const item = await Item.findById(itemId)
168
+ .populate('author', 'name email')
169
+ .populate('tags', 'name')
170
+ .lean();
171
+
172
+ // Read many with filters
173
+ const items = await Item.find({
174
+ status: 'active',
175
+ deletedAt: null,
176
+ })
177
+ .populate('author', 'name')
178
+ .sort({ createdAt: -1 })
179
+ .limit(10)
180
+ .lean();
181
+
182
+ // Update
183
+ const updated = await Item.findByIdAndUpdate(
184
+ itemId,
185
+ { title: 'Updated Title' },
186
+ { new: true, runValidators: true }
187
+ );
188
+
189
+ // Delete
190
+ await Item.findByIdAndDelete(itemId);
191
+ ```
192
+
193
+ ### Pagination
194
+
195
+ ```typescript
196
+ async function findPaginated(input: {
197
+ page: number;
198
+ pageSize: number;
199
+ status?: string;
200
+ }) {
201
+ const { page, pageSize, status } = input;
202
+ const skip = (page - 1) * pageSize;
203
+
204
+ const filter = {
205
+ deletedAt: null,
206
+ ...(status && { status }),
207
+ };
208
+
209
+ const [items, total] = await Promise.all([
210
+ Item.find(filter)
211
+ .populate('author', 'name')
212
+ .sort({ createdAt: -1 })
213
+ .skip(skip)
214
+ .limit(pageSize)
215
+ .lean(),
216
+ Item.countDocuments(filter),
217
+ ]);
218
+
219
+ return {
220
+ data: items,
221
+ pagination: {
222
+ total,
223
+ page,
224
+ pageSize,
225
+ totalPages: Math.ceil(total / pageSize),
226
+ },
227
+ };
228
+ }
229
+ ```
230
+
231
+ ### Aggregation
232
+
233
+ ```typescript
234
+ // Items count by status
235
+ const stats = await Item.aggregate([
236
+ { $match: { deletedAt: null } },
237
+ {
238
+ $group: {
239
+ _id: '$status',
240
+ count: { $sum: 1 },
241
+ avgPrice: { $avg: '$price' },
242
+ },
243
+ },
244
+ ]);
245
+
246
+ // Items with author details
247
+ const itemsWithAuthors = await Item.aggregate([
248
+ { $match: { status: 'active' } },
249
+ {
250
+ $lookup: {
251
+ from: 'users',
252
+ localField: 'author',
253
+ foreignField: '_id',
254
+ as: 'authorDetails',
255
+ },
256
+ },
257
+ { $unwind: '$authorDetails' },
258
+ {
259
+ $project: {
260
+ title: 1,
261
+ price: 1,
262
+ 'authorDetails.name': 1,
263
+ 'authorDetails.email': 1,
264
+ },
265
+ },
266
+ ]);
267
+ ```
268
+
269
+ ### Soft Delete
270
+
271
+ ```typescript
272
+ // Soft delete
273
+ await Item.findByIdAndUpdate(itemId, {
274
+ deletedAt: new Date(),
275
+ });
276
+
277
+ // Restore
278
+ await Item.findByIdAndUpdate(itemId, {
279
+ deletedAt: null,
280
+ });
281
+
282
+ // Query middleware for automatic filtering
283
+ itemSchema.pre(/^find/, function (next) {
284
+ // Skip if explicitly including deleted
285
+ if (this.getOptions().includeDeleted) {
286
+ return next();
287
+ }
288
+ this.where({ deletedAt: null });
289
+ next();
290
+ });
291
+ ```
292
+
293
+ ### Transactions
294
+
295
+ ```typescript
296
+ const session = await mongoose.startSession();
297
+
298
+ try {
299
+ session.startTransaction();
300
+
301
+ const item = await Item.create(
302
+ [{ title: 'New', price: 100, author: userId }],
303
+ { session }
304
+ );
305
+
306
+ await User.findByIdAndUpdate(
307
+ userId,
308
+ { $push: { items: item[0]._id } },
309
+ { session }
310
+ );
311
+
312
+ await session.commitTransaction();
313
+ return item[0];
314
+ } catch (error) {
315
+ await session.abortTransaction();
316
+ throw error;
317
+ } finally {
318
+ session.endSession();
319
+ }
320
+ ```
321
+
322
+ ---
323
+
324
+ ## Model Methods
325
+
326
+ ### Static Methods
327
+
328
+ ```typescript
329
+ // Add static methods to schema
330
+ itemSchema.statics.findByAuthor = function (authorId: string) {
331
+ return this.find({ author: authorId, deletedAt: null })
332
+ .sort({ createdAt: -1 });
333
+ };
334
+
335
+ itemSchema.statics.findActive = function () {
336
+ return this.find({ status: 'active', deletedAt: null });
337
+ };
338
+
339
+ // Interface for model with statics
340
+ interface IItemModel extends Model<IItemDocument> {
341
+ findByAuthor(authorId: string): Promise<IItemDocument[]>;
342
+ findActive(): Promise<IItemDocument[]>;
343
+ }
344
+
345
+ export const Item = mongoose.model<IItemDocument, IItemModel>('Item', itemSchema);
346
+
347
+ // Usage
348
+ const items = await Item.findByAuthor(userId);
349
+ ```
350
+
351
+ ### Instance Methods
352
+
353
+ ```typescript
354
+ // Add instance methods
355
+ itemSchema.methods.softDelete = function () {
356
+ this.deletedAt = new Date();
357
+ return this.save();
358
+ };
359
+
360
+ itemSchema.methods.restore = function () {
361
+ this.deletedAt = null;
362
+ return this.save();
363
+ };
364
+
365
+ itemSchema.methods.archive = function () {
366
+ this.status = 'archived';
367
+ return this.save();
368
+ };
369
+
370
+ // Usage
371
+ const item = await Item.findById(itemId);
372
+ await item.softDelete();
373
+ ```
374
+
375
+ ---
376
+
377
+ ## Connection Setup
378
+
379
+ ```typescript
380
+ // db/connection.ts
381
+ import mongoose from 'mongoose';
382
+
383
+ const MONGODB_URI = process.env.MONGODB_URI!;
384
+
385
+ let cached = global as typeof globalThis & {
386
+ mongoose: { conn: typeof mongoose | null; promise: Promise<typeof mongoose> | null };
387
+ };
388
+
389
+ if (!cached.mongoose) {
390
+ cached.mongoose = { conn: null, promise: null };
391
+ }
392
+
393
+ export async function connectDB() {
394
+ if (cached.mongoose.conn) {
395
+ return cached.mongoose.conn;
396
+ }
397
+
398
+ if (!cached.mongoose.promise) {
399
+ cached.mongoose.promise = mongoose.connect(MONGODB_URI, {
400
+ bufferCommands: false,
401
+ });
402
+ }
403
+
404
+ cached.mongoose.conn = await cached.mongoose.promise;
405
+ return cached.mongoose.conn;
406
+ }
407
+
408
+ // Graceful shutdown
409
+ process.on('SIGINT', async () => {
410
+ await mongoose.connection.close();
411
+ process.exit(0);
412
+ });
413
+ ```
414
+
415
+ ---
416
+
417
+ ## Testing
418
+
419
+ ```typescript
420
+ import { describe, it, expect, beforeAll, beforeEach, afterAll } from 'vitest';
421
+ import mongoose from 'mongoose';
422
+ import { MongoMemoryServer } from 'mongodb-memory-server';
423
+ import { Item } from '../models/item.model';
424
+ import { User } from '../models/user.model';
425
+
426
+ let mongoServer: MongoMemoryServer;
427
+
428
+ beforeAll(async () => {
429
+ mongoServer = await MongoMemoryServer.create();
430
+ await mongoose.connect(mongoServer.getUri());
431
+ });
432
+
433
+ afterAll(async () => {
434
+ await mongoose.disconnect();
435
+ await mongoServer.stop();
436
+ });
437
+
438
+ beforeEach(async () => {
439
+ await Item.deleteMany({});
440
+ await User.deleteMany({});
441
+ });
442
+
443
+ describe('Item Model', () => {
444
+ it('should create item with valid data', async () => {
445
+ const user = await User.create({
446
+ email: 'test@example.com',
447
+ passwordHash: 'hash',
448
+ });
449
+
450
+ const item = await Item.create({
451
+ title: 'Test Item',
452
+ price: 100,
453
+ author: user._id,
454
+ });
455
+
456
+ expect(item._id).toBeDefined();
457
+ expect(item.title).toBe('Test Item');
458
+ });
459
+
460
+ it('should fail without required fields', async () => {
461
+ await expect(
462
+ Item.create({ title: 'No Price' })
463
+ ).rejects.toThrow();
464
+ });
465
+
466
+ it('should populate author', async () => {
467
+ const user = await User.create({
468
+ email: 'test@example.com',
469
+ passwordHash: 'hash',
470
+ name: 'Test User',
471
+ });
472
+
473
+ const item = await Item.create({
474
+ title: 'Test',
475
+ price: 100,
476
+ author: user._id,
477
+ });
478
+
479
+ const populated = await Item.findById(item._id).populate('author', 'name');
480
+ expect(populated?.author.name).toBe('Test User');
481
+ });
482
+ });
483
+ ```
484
+
485
+ ---
486
+
487
+ ## Best Practices
488
+
489
+ ### Good
490
+
491
+ - Use lean() for read-only queries (better performance)
492
+ - Use indexes for frequently queried fields
493
+ - Use timestamps option instead of manual dates
494
+ - Use virtuals for computed properties
495
+ - Use select: false for sensitive fields
496
+
497
+ ### Bad
498
+
499
+ - Not using indexes (poor query performance)
500
+ - Populating everything (performance issues)
501
+ - Manual _id generation (use ObjectId)
502
+ - Not handling connection errors
503
+ - Storing references when embedding is better