feat(subscriptions): topic-level updates (PR 5/7)#517
Conversation
…gory) Adds the two topic/category-scoped subscription writes. Each entry in the payload sets the subscription state for a single (topic, mode) or (category, mode) pair. UPDATE_TOPIC reuses the same URL as GET_ALL — POST vs GET differentiates. Adds TopicSubscriptionUpdate and CategorySubscriptionUpdate types, response types, oauth-scopes entries, and unit + integration tests (updateTopic round-trip; updateCategory unit-only because it needs richer tenant fixtures). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| it('should propagate errors', async () => { | ||
| mockApiClient.post.mockRejectedValue(createMockError(TEST_CONSTANTS.ERROR_MESSAGE)); |
There was a problem hiding this comment.
The updateCategory error test uses the generic TEST_CONSTANTS.ERROR_MESSAGE while the parallel updateTopic error test (line 174) correctly uses NOTIFICATION_TEST_CONSTANTS.ERROR_SUBSCRIPTION_INVALID. Per conventions, TEST_CONSTANTS.ERROR_MESSAGE is only acceptable for collection methods like getAll — mutation methods should use domain-specific error constants.
| it('should propagate errors', async () => { | |
| mockApiClient.post.mockRejectedValue(createMockError(TEST_CONSTANTS.ERROR_MESSAGE)); | |
| it('should propagate errors', async () => { | |
| mockApiClient.post.mockRejectedValue(createMockError(NOTIFICATION_TEST_CONSTANTS.ERROR_SUBSCRIPTION_INVALID)); |
There was a problem hiding this comment.
Addressed in a2057e0 — switched to NOTIFICATION_TEST_CONSTANTS.ERROR_SUBSCRIPTION_INVALID.
| notificationMode: NotificationMode.InApp, | ||
| }, | ||
| ]) | ||
| ).rejects.toThrow(TEST_CONSTANTS.ERROR_MESSAGE); |
There was a problem hiding this comment.
| ).rejects.toThrow(TEST_CONSTANTS.ERROR_MESSAGE); | |
| ).rejects.toThrow(NOTIFICATION_TEST_CONSTANTS.ERROR_SUBSCRIPTION_INVALID); |
There was a problem hiding this comment.
Addressed in a2057e0 — switched to NOTIFICATION_TEST_CONSTANTS.ERROR_SUBSCRIPTION_INVALID.
|
Review findings (1 issue): New finding posted:
|
…ory test Matches the parallel updateTopic error test on the same suite. Addresses review comment on PR #517. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
All findings addressed in the latest commit on this branch. Inline reply threads are resolved with commit references. |
…scopes entries Same internal-scope treatment. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PR 5/7 in the Notification SDK stack. Stacked on top of #516.
Adds the topic-scoped subscription writes. Each method takes an array of update entries, letting callers batch many subscription toggles into one request.
Methods Added
subscriptions.updateTopic()updateTopic(tenantId: string, subscriptions: TopicSubscriptionUpdate[]): Promise<SubscriptionUpdateTopicResponse>subscriptions.updateCategory()updateCategory(tenantId: string, subscriptions: CategorySubscriptionUpdate[]): Promise<SubscriptionUpdateCategoryResponse>Endpoints Called
updateTopic()notificationservice_/usersubscriptionservice/api/v1/UserSubscriptionNotificationServiceupdateCategory()notificationservice_/usersubscriptionservice/api/v1/UserSubscription/CategorySubscriptionNotificationServiceUPDATE_TOPICreuses the same URL asGET_ALL— POST vs GET differentiates the operation. Documented inline in the endpoint constants.updateTopicsends{ userSubscriptions: [...] };updateCategorysends{ categorySubscriptions: [...] }.(topicId|publisherId, isSubscribed, notificationMode)triple.Example Usage
API Response vs SDK Response
updateTopic{ success: true, data: { subscriptions } }(echoes input)updateCategory{ success: true, data: { subscriptions } }(echoes input)Verification
npm run typechecknpm run lintnpm run test:unitIntegration:
updateTopicround-trip — flip a non-mandatory topic's mode, then restore.updateCategoryis unit-only because it needs richer tenant fixtures (multi-topic category coverage).Files
src/utils/constants/endpoints/notification.ts(UPDATE_TOPIC,UPDATE_CATEGORY)src/models/notification/subscriptions.types.ts(TopicSubscriptionUpdate,CategorySubscriptionUpdate)src/models/notification/subscriptions.models.ts(response types + ServiceModel methods)src/services/notification/subscriptions.tstests/unit/services/notification/subscriptions.test.ts(+4 tests)tests/integration/shared/notification/subscriptions.integration.test.ts(+1 round-trip test)tests/utils/constants/notification.ts(ERROR_SUBSCRIPTION_INVALID)docs/oauth-scopes.mdPR Stack
feat/notifications-sdkfeat/notifications-mark-readfeat/notifications-deletefeat/subscriptions-sdkfeat/subscriptions-topic-updates(this PR)feat/subscriptions-publisher-updatesfeat/subscriptions-mode-reset🤖 Generated with Claude Code