Conversation
* infrastructure adapters * feature/nestjs-integration * merging all features * docs : updated copilot instructions * fix: resolve SonarQube security hotspots and workflow configuration - Replace GitHub Actions version tags with full commit SHA hashes (v6 -> fd88b7d, v1 -> d304d05) - Fix SONAR_PROJECT_KEY from LoggingKit to NotificationKit - Add 'main' branch to PR trigger list for release-check workflow - Resolves 2 security hotspots (githubactions:S7637) for supply chain security * fix: resolve NotificationKit TypeScript type errors - Add explicit NotificationDocument type annotations to map callbacks - Fix mapToRecord signature to accept any type (handles both Map and Record) - Install mongoose as dev dependency for type checking - Fixes pre-push typecheck failures --------- Co-authored-by: yasser <y.aithnini@ciscod.com>
… into feature/comprehensive-testing
There was a problem hiding this comment.
Pull request overview
This PR introduces concrete repository adapters (Mongoose + in-memory) into the infra layer, updates infra documentation/comments accordingly, and adds a repository-specific Copilot guideline document.
Changes:
- Added
MongooseNotificationRepository(MongoDB) andInMemoryNotificationRepositoryimplementations ofINotificationRepository. - Updated infra exports and documentation to reference the new repositories.
- Added
.github/copilot-instructions.mdand updatedpackage-lock.json.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| src/infra/repositories/mongoose/notification.schema.ts | Adds a TS suppression comment around optional mongoose require. |
| src/infra/repositories/mongoose/mongoose.repository.ts | New Mongoose-backed repository implementation with indexing and query helpers. |
| src/infra/repositories/index.ts | Exports the new repository implementations from infra. |
| src/infra/repositories/in-memory/in-memory.repository.ts | New in-memory repository implementation intended for testing/simple usage. |
| src/infra/index.ts | Updates infra layer documentation header. |
| src/infra/README.md | Updates repository usage docs (MongoDB + in-memory). |
| package-lock.json | Large lockfile update affecting devDependencies and versions. |
| .github/copilot-instructions.md | Adds extensive contributor/Copilot guidance documentation. |
| │ │ ├── in-app/ # In-app adapter | ||
| │ │ └── webhook/ # Outbound webhook adapter | ||
| │ ├── repositories/ # Persistence adapters | ||
| │ │ ├── mongodb/ # Mongoose adapter |
There was a problem hiding this comment.
The architecture tree references src/infra/repositories/mongodb/, but the codebase currently uses src/infra/repositories/mongoose/. Please align the directory names in this guide with the actual repository structure to avoid confusion.
| │ │ ├── mongodb/ # Mongoose adapter | |
| │ │ ├── mongoose/ # Mongoose adapter |
| **Test file location:** same directory as source (`*.spec.ts`) | ||
|
|
||
| ``` | ||
| src/core/ | ||
| ├── notification.service.ts | ||
| └── notification.service.spec.ts | ||
|
|
||
| src/infra/senders/email/ | ||
| ├── email.sender.ts | ||
| └── email.sender.spec.ts | ||
| ``` |
There was a problem hiding this comment.
This guide says test files should be *.spec.ts, but the repository currently uses *.test.ts (e.g., src/core/notification.service.test.ts). Please update the testing section/examples to match the existing test file naming convention.
| this.model = this.connection.model<NotificationDocument>( | ||
| "Notification", | ||
| schema, | ||
| this.collectionName, | ||
| ); |
There was a problem hiding this comment.
The repository accepts a collectionName, but the model is always registered under the fixed name "Notification". With Mongoose’s per-connection model registry, creating another repository instance (same connection) with a different collectionName can either reuse the existing model/collection or throw an overwrite error. Use a model name derived from collectionName (or accept an injected model) to ensure collectionName is actually honored.
| // @ts-ignore - mongoose is an optional peer dependency | ||
| const mongoose = require("mongoose"); |
There was a problem hiding this comment.
Using // @ts-ignore here suppresses all TypeScript errors on the next line and can hide real issues. Prefer a targeted suppression (e.g., eslint disable for no-var-requires) and/or a type assertion like require("mongoose") as typeof import("mongoose") so the line remains type-checked while still supporting the optional peer dependency pattern.
| // @ts-ignore - mongoose is an optional peer dependency | |
| const mongoose = require("mongoose"); | |
| // eslint-disable-next-line @typescript-eslint/no-var-requires | |
| const mongoose = require("mongoose") as typeof import("mongoose"); |
| * These implementations are internal and not exported by default. | ||
| * They can be used when configuring the NestJS module. |
There was a problem hiding this comment.
The comment says infra implementations are "not exported by default", but src/index.ts re-exports ./infra, so they are part of the package’s public surface. Please update this comment to reflect the actual export behavior (or adjust exports if the intent is to keep infra internal).
| * These implementations are internal and not exported by default. | |
| * They can be used when configuring the NestJS module. | |
| * These implementations are primarily intended for internal wiring and NestJS module configuration. | |
| * They are re-exported and available to consumers, but are not the preferred abstraction layer. |
| **❌ NEVER export:** | ||
|
|
||
| - Internal provider wiring (`createNotificationKitProviders` internals) | ||
| - Raw SDK instances (Nodemailer transporter, Twilio client, Firebase app) | ||
| - Mongoose schema definitions (infrastructure details) |
There was a problem hiding this comment.
The "NEVER export" list says not to export Mongoose schema definitions, but the package currently exports notificationSchemaDefinition via src/infra/repositories/index.ts. Either update this guidance or stop exporting the schema to keep docs and actual public API consistent.
| **❌ NEVER export:** | |
| - Internal provider wiring (`createNotificationKitProviders` internals) | |
| - Raw SDK instances (Nodemailer transporter, Twilio client, Firebase app) | |
| - Mongoose schema definitions (infrastructure details) | |
| **❌ NEVER export (with one documented exception):** | |
| - Internal provider wiring (`createNotificationKitProviders` internals) | |
| - Raw SDK instances (Nodemailer transporter, Twilio client, Firebase app) | |
| - Additional Mongoose schema definitions (infrastructure details) — `notificationSchemaDefinition` is the only intentionally exported schema for advanced integrations |
| const offset = _criteria.offset || 0; | ||
| const limit = _criteria.limit || 10; |
There was a problem hiding this comment.
find() applies a default limit of 10 when _criteria.limit is not provided. This makes the in-memory implementation behave differently from the Mongoose repository (which returns all results unless a limit is specified) and can silently truncate results. Consider only slicing when limit is explicitly set (and treat offset similarly), or default limit to results.length when undefined.
| const offset = _criteria.offset || 0; | |
| const limit = _criteria.limit || 10; | |
| const offset = _criteria.offset ?? 0; | |
| const limit = _criteria.limit ?? results.length - offset; |
| return this.model; | ||
| } | ||
|
|
||
| const mongoose = (this.connection as any).base; |
There was a problem hiding this comment.
Avoid casting the Mongoose connection to any to access .base. Connection already exposes base in Mongoose typings; using any hides type errors and makes refactors riskier. Prefer this.connection.base (or destructure Schema from it) with proper typing.
| const mongoose = (this.connection as any).base; | |
| const mongoose = this.connection.base; |
| import { InMemoryNotificationRepository } from "@ciscode/notification-kit/infra"; | ||
|
|
||
| class MyCustomRepository implements INotificationRepository { | ||
| async create(data: Omit<Notification, "id" | "createdAt" | "updatedAt">): Promise<Notification> { | ||
| // Your implementation | ||
| } | ||
| const repository = new InMemoryNotificationRepository(); |
There was a problem hiding this comment.
Same issue as above: @ciscode/notification-kit/infra is not an exported subpath per package.json exports, so this import will not work for consumers. Update to @ciscode/notification-kit or add the appropriate subpath export.
| ### Path Aliases (`tsconfig.json`) | ||
|
|
||
| ```typescript | ||
| "@/*" → "src/*" | ||
| "@core/*" → "src/core/*" | ||
| "@infra/*" → "src/infra/*" | ||
| "@nest/*" → "src/nest/*" |
There was a problem hiding this comment.
This document claims path aliases like @core/*, @infra/*, etc. are configured in tsconfig.json, but the current tsconfig.json has no baseUrl/paths mappings. Either add the actual TS path mappings or remove/update this section to avoid misleading contributors.
| ### Path Aliases (`tsconfig.json`) | |
| ```typescript | |
| "@/*" → "src/*" | |
| "@core/*" → "src/core/*" | |
| "@infra/*" → "src/infra/*" | |
| "@nest/*" → "src/nest/*" | |
| ### Optional path aliases for imports | |
| If you want to use the import style shown below, add the following `compilerOptions.paths` | |
| configuration to your `tsconfig.json`: | |
| ```jsonc | |
| { | |
| "compilerOptions": { | |
| "baseUrl": "./", | |
| "paths": { | |
| "@/*": ["src/*"], | |
| "@core/*": ["src/core/*"], | |
| "@infra/*": ["src/infra/*"], | |
| "@nest/*": ["src/nest/*"] | |
| } | |
| } | |
| } |
- Create whatsapp.utils.ts with shared validation functions - Extract isValidPhoneNumber() to shared utility (removes 20+ lines duplication) - Extract validateWhatsAppRecipient() to shared utility - Extract error messages to WHATSAPP_ERRORS constants - Update TwilioWhatsAppSender to use shared utilities - Update MockWhatsAppSender to use shared utilities - Export utilities from whatsapp index.ts This refactoring reduces code duplication from 24.4% to meet SonarQube Quality Gate requirement (3%).
|


Summary
Why
Checklist
npm run lintpassesnpm run typecheckpassesnpm testpassesnpm run buildpassesnpx changeset) if this affects consumersNotes