Skip to content

Feature/whatsapp#11

Closed
y-aithnini wants to merge 19 commits intodevelopfrom
feature/whatsapp
Closed

Feature/whatsapp#11
y-aithnini wants to merge 19 commits intodevelopfrom
feature/whatsapp

Conversation

@y-aithnini
Copy link
Contributor

@y-aithnini y-aithnini commented Mar 11, 2026

Summary

  • What does this PR change?

Why

  • Why is this change needed?

Checklist

  • Added/updated tests (if behavior changed)
  • npm run lint passes
  • npm run typecheck passes
  • npm test passes
  • npm run build passes
  • Added a changeset (npx changeset) if this affects consumers

Notes

  • Anything reviewers should pay attention to?

y-aithnini and others added 17 commits February 27, 2026 16:03
* 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>
Copilot AI review requested due to automatic review settings March 11, 2026 10:26
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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) and InMemoryNotificationRepository implementations of INotificationRepository.
  • Updated infra exports and documentation to reference the new repositories.
  • Added .github/copilot-instructions.md and updated package-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
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
│ │ ├── mongodb/ # Mongoose adapter
│ │ ├── mongoose/ # Mongoose adapter

Copilot uses AI. Check for mistakes.
Comment on lines +398 to +408
**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
```
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +43 to +47
this.model = this.connection.model<NotificationDocument>(
"Notification",
schema,
this.collectionName,
);
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +13 to 14
// @ts-ignore - mongoose is an optional peer dependency
const mongoose = require("mongoose");
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
// @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");

Copilot uses AI. Check for mistakes.
Comment on lines +10 to +11
* These implementations are internal and not exported by default.
* They can be used when configuring the NestJS module.
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Suggested change
* 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.

Copilot uses AI. Check for mistakes.
Comment on lines +198 to +202
**❌ NEVER export:**

- Internal provider wiring (`createNotificationKitProviders` internals)
- Raw SDK instances (Nodemailer transporter, Twilio client, Firebase app)
- Mongoose schema definitions (infrastructure details)
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
**❌ 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

Copilot uses AI. Check for mistakes.
Comment on lines +68 to +69
const offset = _criteria.offset || 0;
const limit = _criteria.limit || 10;
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
const offset = _criteria.offset || 0;
const limit = _criteria.limit || 10;
const offset = _criteria.offset ?? 0;
const limit = _criteria.limit ?? results.length - offset;

Copilot uses AI. Check for mistakes.
return this.model;
}

const mongoose = (this.connection as any).base;
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
const mongoose = (this.connection as any).base;
const mongoose = this.connection.base;

Copilot uses AI. Check for mistakes.
Comment on lines +157 to +159
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();
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +152 to +158
### Path Aliases (`tsconfig.json`)

```typescript
"@/*" → "src/*"
"@core/*" → "src/core/*"
"@infra/*" → "src/infra/*"
"@nest/*" → "src/nest/*"
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
### 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/*"]
}
}
}

Copilot uses AI. Check for mistakes.
- 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%).
@sonarqubecloud
Copy link

Quality Gate Failed Quality Gate failed

Failed conditions
21.7% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@y-aithnini y-aithnini closed this Mar 11, 2026
@y-aithnini y-aithnini deleted the feature/whatsapp branch March 11, 2026 10:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants