Module: meridian-api/src/users, meridian-api/src/tag, meridian-api/src/common
Problem
Issue #8 fixed Posts pagination, but users.controller.ts and
tag/tag.controller.ts appear to still use offset ParseIntPipe pagination with
no cursor support and no soft-delete global filter. User listing likely leaks
deactivated accounts and Tags has no uniqueness/normalization, so the same tag
("DeFi" vs "defi") fragments. There is also no N+1 guard for users' related
entities (posts, metaoptions) — common/pagination exists but isn't reused.
Deliverables
- Reuse the
common/pagination keyset implementation for UsersService and
TagsService; return { data, nextCursor, total }.
- Add a soft-delete scope so deactivated users / removed tags are excluded
by default but restorable.
- Normalize tags (lowercase/trim + unique index) and dedupe on create.
- Add
relations/join loading to kill N+1; prove with a query-count test.
- Tests for cursor pagination, soft-delete exclusion, tag normalization.
Acceptance criteria
- Cursor pagination + count assertion (no N+1) on both modules.
- Deactivated users absent from listings.
- Tag create dedupes;
nest test green.
Module:
meridian-api/src/users,meridian-api/src/tag,meridian-api/src/commonProblem
Issue #8 fixed Posts pagination, but
users.controller.tsandtag/tag.controller.tsappear to still use offsetParseIntPipepagination withno cursor support and no soft-delete global filter. User listing likely leaks
deactivated accounts and Tags has no uniqueness/normalization, so the same tag
("DeFi" vs "defi") fragments. There is also no N+1 guard for users' related
entities (posts, metaoptions) —
common/paginationexists but isn't reused.Deliverables
common/paginationkeyset implementation forUsersServiceandTagsService; return{ data, nextCursor, total }.by default but restorable.
relations/join loading to kill N+1; prove with a query-count test.Acceptance criteria
nest testgreen.