| Dimension | Shared | Only in A | Only in B | Overlap |
|---|---|---|---|---|
| Sections | 0 | 1 | 1 | 0% |
| Commands | 0 | 0 | 0 | — |
| Section tags | 1 | 1 | 0 | 50% |
What each file covers
Sections
0 shared · 1 only in A · 1 only in B- − Pull Request Rules
- + DAL Repository Rules
Commands
neither file has anySection tags
1 shared · 1 only in A · 0 only in B- − git-pr
- do-not
Line diff
novuhq/novu · .cursor/rules/pullrequest.mdc
@@ −1 @@
1---
2description: When creating a new pull request on GitHub, use this to specify the contents
3alwaysApply: false
4---
5
6### Pull Request Rules
7
8**Title format**: `type(scope): Description fixes NOV-<ticket-id>`
9
10- When creating a pull requests from any run, verify that there is a linear ticket associated with the pr (From branch name or other), if not, create the linear ticket before creating the PR and attach the linear ticket id in title (fixes NV-XXX)
11- Examples: `feat(dashboard): add workflow trigger button fixes NOV-123`, `fix(api-service): handle null subscriber case fixes NOV-456`
12
13
14**Scopes**: `dashboard`, `api-service`, `worker`, `shared`, `js`, `react`, `react-native`, `nextjs`, `providers`, `root`, `docs`
15
16**Description**: Summarize what changed and why. List breaking changes. Add screenshots for UI changes. For non-trivial logic or architecture changes, include a concise Mermaid diagram (flow, sequence, or component) so reviewers can grasp the change at a glance.
17
18**Enterprise packages**: When changes touch `enterprise/`, also open a matching PR in `novuhq/packages-enterprise` on a branch from `next`, and cross-link the two PR bodies (monorepo ↔ enterprise). The Validate Submodule Sync test will fail; this is expected when pointing to the `.source` submodule in the novuhq/novu repository. Do not fix it.
19
novuhq/novu · .cursor/rules/dal-repository.mdc
@@ +1 @@
1---
2description: Rules for working with DAL repositories in the Novu monorepo
3globs: libs/dal/**/*.ts, **/repositories/**/*.ts
4alwaysApply: false
5---
6
7### DAL Repository Rules
8
9#### Choosing a base class
10
11- **New repositories must extend `BaseRepositoryV2`** — it enforces required field selection and provides auto-inferred return types (`Pick<Entity, Keys>`).
12- **Existing repositories stay on `BaseRepository`** — `BaseRepository` is deprecated but must not be changed; all 32 existing repos continue to extend it.
13- Do NOT extend `BaseRepository` for any new repository going forward.
14
15#### BaseRepositoryV2 — required `select`
16
17- Every read method (`find`, `findOne`, `findById`, `findBatch`, `findWithCursorBasedPagination`) requires an explicit `select` argument — there is no default `SELECT *`.
18- Use array syntax as the default: `find(query, ['_id', 'name', 'status'])`. Array syntax returns exactly the listed fields — `_id` is excluded unless explicitly included.
19- Use object syntax when you need MongoDB-style projections where `_id` is included by default: `findOne(query, { name: 1, email: 1 })`, or explicitly excluded: `findOne(query, { _id: 0, name: 1 })`.
20- Exclusion projections for non-`_id` fields (e.g. `{ name: 0 }`) are intentionally unsupported — they are a compile error.
21- Return types are automatically inferred as `Pick<Entity, Keys>` — do not manually annotate the return type.
22- Use `select: '*'` to retrieve all fields with a fully-typed `Entity` return (instead of a `Pick`). All five read methods support this overload: `find(query, '*')`, `findOne(query, '*')`, `findById(id, '*')`, `findBatch(query, '*')`, and `findWithCursorBasedPagination({ select: '*', ... })`.
23- Omitting `select` entirely is still a compile error — `'*'` is the explicit opt-in for SELECT *.
24
25#### Enforcement (applies to both V1 and V2)
26
27- **Never use `_model` or `MongooseModel` directly** in repository methods. Always use the inherited methods (`update`, `find`, `findOne`, `delete`, `create`, `bulkWrite`, etc.) which enforce `_environmentId` / `_organizationId` via the `EnforceEnvOrOrgIds` type.
28- All query methods must include `_environmentId` or `_organizationId` in their filter to satisfy the enforcement type constraint.
29- When adding new repository methods that need `$push`, `$pull`, or other update operators, pass the `environmentId` as a parameter and use `this.update()` with the enforcement fields.
30- For bulk operations, use `this.bulkWrite()` instead of `this._model.updateMany()`.
31- **Transactions**: start via `repository.withTransaction(async (session) => { ... })` and pass `session` to every repo call inside it (e.g. `repo.findOne(query, select, { session })`). Run all operations sequentially — parallel execution (`Promise.all`, etc.) inside a transaction is undefined behaviour in Mongoose.
32
@@ −1 +1 @@
11 ---
2−description: When creating a new pull request on GitHub, use this to specify the contents
2+description: Rules for working with DAL repositories in the Novu monorepo
3+globs: libs/dal/**/*.ts, **/repositories/**/*.ts
34 alwaysApply: false
45 ---
56
6−### Pull Request Rules
7+### DAL Repository Rules
78
8−**Title format**: `type(scope): Description fixes NOV-<ticket-id>`
9+#### Choosing a base class
910
10−- When creating a pull requests from any run, verify that there is a linear ticket associated with the pr (From branch name or other), if not, create the linear ticket before creating the PR and attach the linear ticket id in title (fixes NV-XXX)
11−- Examples: `feat(dashboard): add workflow trigger button fixes NOV-123`, `fix(api-service): handle null subscriber case fixes NOV-456`
11+- **New repositories must extend `BaseRepositoryV2`** — it enforces required field selection and provides auto-inferred return types (`Pick<Entity, Keys>`).
12+- **Existing repositories stay on `BaseRepository`** — `BaseRepository` is deprecated but must not be changed; all 32 existing repos continue to extend it.
13+- Do NOT extend `BaseRepository` for any new repository going forward.
1214
15+#### BaseRepositoryV2 — required `select`
1316
14−**Scopes**: `dashboard`, `api-service`, `worker`, `shared`, `js`, `react`, `react-native`, `nextjs`, `providers`, `root`, `docs`
17+- Every read method (`find`, `findOne`, `findById`, `findBatch`, `findWithCursorBasedPagination`) requires an explicit `select` argument — there is no default `SELECT *`.
18+- Use array syntax as the default: `find(query, ['_id', 'name', 'status'])`. Array syntax returns exactly the listed fields — `_id` is excluded unless explicitly included.
19+- Use object syntax when you need MongoDB-style projections where `_id` is included by default: `findOne(query, { name: 1, email: 1 })`, or explicitly excluded: `findOne(query, { _id: 0, name: 1 })`.
20+- Exclusion projections for non-`_id` fields (e.g. `{ name: 0 }`) are intentionally unsupported — they are a compile error.
21+- Return types are automatically inferred as `Pick<Entity, Keys>` — do not manually annotate the return type.
22+- Use `select: '*'` to retrieve all fields with a fully-typed `Entity` return (instead of a `Pick`). All five read methods support this overload: `find(query, '*')`, `findOne(query, '*')`, `findById(id, '*')`, `findBatch(query, '*')`, and `findWithCursorBasedPagination({ select: '*', ... })`.
23+- Omitting `select` entirely is still a compile error — `'*'` is the explicit opt-in for SELECT *.
1524
16−**Description**: Summarize what changed and why. List breaking changes. Add screenshots for UI changes. For non-trivial logic or architecture changes, include a concise Mermaid diagram (flow, sequence, or component) so reviewers can grasp the change at a glance.
25+#### Enforcement (applies to both V1 and V2)
1726
18−**Enterprise packages**: When changes touch `enterprise/`, also open a matching PR in `novuhq/packages-enterprise` on a branch from `next`, and cross-link the two PR bodies (monorepo ↔ enterprise). The Validate Submodule Sync test will fail; this is expected when pointing to the `.source` submodule in the novuhq/novu repository. Do not fix it.
27+- **Never use `_model` or `MongooseModel` directly** in repository methods. Always use the inherited methods (`update`, `find`, `findOne`, `delete`, `create`, `bulkWrite`, etc.) which enforce `_environmentId` / `_organizationId` via the `EnforceEnvOrOrgIds` type.
28+- All query methods must include `_environmentId` or `_organizationId` in their filter to satisfy the enforcement type constraint.
29+- When adding new repository methods that need `$push`, `$pull`, or other update operators, pass the `environmentId` as a parameter and use `this.update()` with the enforcement fields.
30+- For bulk operations, use `this.bulkWrite()` instead of `this._model.updateMany()`.
31+- **Transactions**: start via `repository.withTransaction(async (session) => { ... })` and pass `session` to every repo call inside it (e.g. `repo.findOne(query, select, { session })`). Run all operations sequentially — parallel execution (`Promise.all`, etc.) inside a transaction is undefined behaviour in Mongoose.
1932
