Skip to content

feat(notifications): add Notifications and Subscriptions services#500

Closed
sarthak688 wants to merge 2 commits into
mainfrom
feat/notification-service-sdk
Closed

feat(notifications): add Notifications and Subscriptions services#500
sarthak688 wants to merge 2 commits into
mainfrom
feat/notification-service-sdk

Conversation

@sarthak688

@sarthak688 sarthak688 commented Jun 9, 2026

Copy link
Copy Markdown

Onboards the user-facing Notification platform as a new modular subpath @uipath/uipath-typescript/notifications with two services: Notifications (inbox) and Subscriptions (preferences). 15 methods total, no folder context, no method binding. Spec source: Design Document — Notification Service CLI Tool & SDK Integration for Coding Agents.

Methods Added

Notifications (6 methods)

Layer Method Signature
Service notifications.getAll() getAll<T extends NotificationGetAllOptions>(tenantId: string, options?: T): Promise<T extends HasPaginationOptions<T> ? PaginatedResponse<NotificationGetResponse> : NonPaginatedResponse<NotificationGetResponse>>
Service notifications.markRead() markRead(tenantId: string, notificationIds: string[]): Promise<NotificationUpdateReadResponse>
Service notifications.markUnread() markUnread(tenantId: string, notificationIds: string[]): Promise<NotificationUpdateReadResponse>
Service notifications.markAllRead() markAllRead(tenantId: string): Promise<NotificationMarkAllReadResponse>
Service notifications.deleteNotifications() deleteNotifications(tenantId: string, notificationIds: string[]): Promise<NotificationDeleteResponse>
Service notifications.deleteAll() deleteAll(tenantId: string): Promise<NotificationDeleteAllResponse>

Subscriptions (9 methods)

Layer Method Signature
Service subscriptions.getAll() getAll(tenantId: string, options?: SubscriptionGetAllOptions): Promise<SubscriptionGetResponse>
Service subscriptions.getPublishers() getPublishers(tenantId: string, options?: SubscriptionGetPublishersOptions): Promise<SubscriptionGetResponse>
Service subscriptions.getSupportedChannels() getSupportedChannels(tenantId: string): Promise<SubscriptionGetSupportedChannelsResponse>
Service subscriptions.updateTopic() updateTopic(tenantId: string, subscriptions: TopicSubscriptionUpdate[]): Promise<SubscriptionUpdateTopicResponse>
Service subscriptions.updateCategory() updateCategory(tenantId: string, subscriptions: CategorySubscriptionUpdate[]): Promise<SubscriptionUpdateCategoryResponse>
Service subscriptions.updatePublisher() updatePublisher(tenantId: string, subscriptions: PublisherSubscriptionUpdate[]): Promise<SubscriptionUpdatePublisherResponse>
Service subscriptions.updateTopicGroup() updateTopicGroup(tenantId: string, subscriptions: TopicGroupSubscriptionUpdate[]): Promise<SubscriptionUpdateTopicGroupResponse>
Service subscriptions.updateMode() updateMode(tenantId: string, publisherId: string, mode: AllowedMode): Promise<SubscriptionUpdateModeResponse>
Service subscriptions.reset() reset(tenantId: string, publisherId: string): Promise<SubscriptionGetResponse>

Endpoints Called

Method HTTP Endpoint OAuth Scope
notifications.getAll() GET notificationservice_/notificationserviceapi/odata/v1/NotificationEntry NotificationService
notifications.markRead() / markUnread() / markAllRead() POST notificationservice_/notificationserviceapi/odata/v1/NotificationEntry/UiPath.NotificationService.Api.UpdateRead NotificationService
notifications.deleteNotifications() / deleteAll() POST notificationservice_/notificationserviceapi/odata/v1/NotificationEntry/UiPath.NotificationService.Api.DeleteBulk NotificationService
subscriptions.getAll() GET notificationservice_/usersubscriptionservice/api/v1/UserSubscription NotificationService
subscriptions.getPublishers() GET notificationservice_/usersubscriptionservice/api/v1/UserSubscription/GetPublishers NotificationService
subscriptions.getSupportedChannels() GET notificationservice_/usersubscriptionservice/api/v1/UserSubscription/GetSupportedChannelStatus NotificationService
subscriptions.updateTopic() POST notificationservice_/usersubscriptionservice/api/v1/UserSubscription NotificationService
subscriptions.updateCategory() POST notificationservice_/usersubscriptionservice/api/v1/UserSubscription/CategorySubscription NotificationService
subscriptions.updatePublisher() POST notificationservice_/usersubscriptionservice/api/v1/UserSubscription/PublisherSubscription NotificationService
subscriptions.updateTopicGroup() POST notificationservice_/usersubscriptionservice/api/v1/UserSubscription/TopicGroupSubscription NotificationService
subscriptions.updateMode() POST notificationservice_/usersubscriptionservice/api/v1/UserSubscription/UpdateMode NotificationService
subscriptions.reset() POST notificationservice_/usersubscriptionservice/api/v1/UserSubscription/Reset NotificationService
  • Both services extend BaseService — UserContext auth, no folder header.
  • notifications.getAll() supports OData pagination via PaginationHelpers.getAll ($top, $skip, $count) and OData query options (filter, orderby).
  • $select is not exposed (the API returns HTTP 500 when $select is supplied — verified live).
  • All 15 public methods carry an @track(...) telemetry decorator.

Critical design point #1: tenantId as a per-call argument

The Notification API does not include the tenant in the URL path. Instead, it identifies the acting tenant via the X-UIPATH-Internal-TenantId header, which expects a tenant GUID (not the configured tenantName). Two design options were considered:

  1. Resolve tenantNametenantId in an SDK-internal cache (calling a portal lookup endpoint on first NS use). Rejected — added a runtime API dependency, a cache key/eviction strategy, and a failure mode (resolver outage poisons every NS call) for what is a static value the caller already has.
  2. Take tenantId as the first positional argument on every NS/Subscriptions method. Chosen — explicit, deterministic, mirrors how folder-scoped Orchestrator services already require folderId from the caller. The SDK forwards tenantId into X-UIPATH-Internal-TenantId via createHeaders() on each call.

The argument is required and positional, in line with the convention from agent_docs/conventions.md:

Required values (IDs, keys, data) are positional arguments. Options objects are reserved for optional parameters only.

Critical design point #2: URL traversal for tenant-less routing

The notification service routes at the organization level — its URLs do NOT include a tenant segment, unlike most UiPath services. ApiClient always inserts ${orgName}/${tenantName}/${path}, so the endpoint constants use a ../ prefix to collapse the tenant segment:

// src/utils/constants/endpoints/base.ts
export const NOTIFICATION_BASE = '../notificationservice_';

${orgName}/${tenantName}/../notificationservice_/... resolves via new URL() normalization to ${orgName}/notificationservice_/.... The NOTIFICATION_BASE JSDoc documents this in detail. Verified live:

  • alpha.uipath.com/testmanagerdev/notificationservice_/... → HTTP 200
  • alpha.uipath.com/testmanagerdev/TestManagerDevTenant/notificationservice_/... → 302 /portal_/unregistered

Example Usage

import { UiPath } from '@uipath/uipath-typescript/core';
import { Notifications, Subscriptions, NotificationMode } from '@uipath/uipath-typescript/notifications';

const sdk = new UiPath(config);
await sdk.initialize();

const notifications = new Notifications(sdk);
const subscriptions = new Subscriptions(sdk);

const tenantId = '<tenant-guid>';

// List unread, most recent first
const unread = await notifications.getAll(tenantId, {
  filter: 'isRead eq false',
  orderby: 'publishedOn desc',
  pageSize: 20,
});

// Mark some read
await notifications.markRead(tenantId, [unread.items[0].id]);

// List user's subscription state for one publisher
const { publishers } = await subscriptions.getAll(tenantId, { publishers: ['Orchestrator'] });

// Unsubscribe a single topic from email
await subscriptions.updateTopic(tenantId, [
  { topicId: '<topicId>', isSubscribed: false, notificationMode: NotificationMode.Email },
]);

// Reset a publisher to defaults
await subscriptions.reset(tenantId, '<publisherId>');

API Response vs SDK Response

Transform pipeline (notifications.getAll() only)

PaginationHelpers.getAlltransformFn: stripInternalNotificationFields → returned to consumer.

The API already returns camelCase, so pascalToCamelCaseKeys() is not applied. There are no semantic field renames in NotificationEntryMap. The only transform is dropping internal/transport-layer fields.

Field-strip (dropped from NotificationGetResponse)

Dropped field Reason
entityOrgName, entityTenantName Internal routing metadata
serviceRegistryName Internal infrastructure
messageTemplateKey, messageVersion Internal templating
publicationId Internal publish-event id
correlationId Internal tracing
partitionKey Storage detail (was readOnly: true in spec)

All other 5 service-layer methods on Notifications and 9 on Subscriptions are pass-through (no transform) — they wrap the API response in OperationResponse<T> ({ success, data }) where applicable.

Sample SDK Responses

notifications.getAll(tenantId, { pageSize: 1 })
{
  "items": [
    {
      "id": "9a3b0db5-9b8b-44a7-9b6a-08de0a17b4e2",
      "message": "A new model is now available for your product.",
      "isRead": false,
      "publisherName": "LlmGateway",
      "publisherId": "adc041d6-3098-4766-ae45-08dd3ac994aa",
      "topicName": "New model available for product",
      "topicKeyName": "New.Model.Available",
      "topicId": "66e76b72-5ef1-4567-6a00-08dd3ac994ba",
      "userId": "9ABFE2B8-F30F-4917-9F7F-A91D28F7B23C",
      "userEmail": null,
      "tenantId": null,
      "priority": "Low",
      "category": "Info",
      "messageParam": null,
      "redirectionUrl": "https://alpha.uipath.com/.../portal_/admin/ai-trust-layer/llm-configurations",
      "publishedOn": 1780413050
    }
  ],
  "totalCount": 500,
  "hasNextPage": true,
  "supportsPageJump": true,
  "currentPage": 1
}

Note: publishedOn is Unix epoch seconds (not milliseconds). Internal fields (entityOrgName, partitionKey, correlationId, etc.) are stripped before the SDK consumer sees the response.

subscriptions.getSupportedChannels(tenantId)
{
  "channels": [
    { "name": "Email", "isEnabled": true },
    { "name": "Slack", "isEnabled": false },
    { "name": "Teams", "isEnabled": false }
  ]
}

InApp is intentionally not listed by the API — it is always implicitly available.

subscriptions.getPublishers(tenantId, { name: 'Apps' })
{
  "publishers": [
    {
      "id": "3b5c8128-8af0-46ec-eb1d-08da31909e0f",
      "name": "Apps",
      "displayName": "Apps",
      "topics": [
        { "id": "b3f9b2fd-122f-4d40-3d88-08da31909e1a", "name": "Apps.Shared",          "displayName": "Apps Shared",         "description": "Apps is Shared",         "group": "Apps Activities" },
        { "id": "7a647eb5-381e-4712-55de-08db6be7681e", "name": "Apps.Cloned",          "displayName": "App Duplicated",       "description": "App is Duplicated",      "group": "Apps Activities" },
        { "id": "334659c0-d908-4078-7620-08db7be3133c", "name": "Apps.CloneFailed",     "displayName": "App Duplication failed", "description": "App Duplication has failed", "group": "Apps Activities" }
      ]
    }
  ]
}

Note: the discovery endpoint returns only id/name/displayName/description/group on each topic. Use getAll() for the full topic shape with subscription state (isSubscribed, modes, category, etc.).

subscriptions.getAll(tenantId, { publishers: ['Apps'] })
{
  "publishers": [
    {
      "id": "3b5c8128-8af0-46ec-eb1d-08da31909e0f",
      "name": "Apps",
      "displayName": "Apps",
      "redirectionUrl": "https://alpha.uipath.com/",
      "retentionDays": 30,
      "addToSummary": false,
      "isUserOptin": true,
      "modes": [
        { "name": "InApp", "isActive": true },
        { "name": "Email", "isActive": true }
      ],
      "topics": [
        {
          "id": "b3f9b2fd-122f-4d40-3d88-08da31909e1a",
          "name": "Apps.Shared",
          "displayName": "Apps Shared",
          "description": "Apps is Shared",
          "group": "Apps Activities",
          "parentGroup": null,
          "category": "Success",
          "retentionDays": 30,
          "orderingSequence": 1,
          "isSubscribed": true,
          "isMandatory": false,
          "isVisible": true,
          "isDefault": true,
          "isAllowedToBeDispatchedInBatch": false,
          "isInfrequent": false,
          "modes": [
            { "name": "InApp", "isSubscribed": true, "isSubscribedByDefault": true },
            { "name": "Email", "isSubscribed": true, "isSubscribedByDefault": true }
          ]
        }
      ]
    }
  ]
}

Verification

Check Status
npm run typecheck ✅ clean
npm run lint ✅ 0 warnings, 0 errors
npm run test:unit ✅ 61 files / 1752 tests (36 in this service: 14 + 22)
npm run build dist/notifications/index.{mjs,cjs,d.ts} produced
E2E (Node) ✅ Imports resolve, both services instantiate, all 15 methods present, enums export, URL traversal verified end-to-end against built tarball

Live API curl confirmed all 5 read endpoints + write endpoints work against alpha/testmanagerdev. The ../ URL-traversal trick is the only unconventional element and is documented in the JSDoc on NOTIFICATION_BASE.

Files

Area Files
Endpoint constants src/utils/constants/endpoints/notification.ts (new), src/utils/constants/endpoints/base.ts (NOTIFICATION_BASE), src/utils/constants/endpoints/index.ts
Types src/models/notification/notifications.types.ts, subscriptions.types.ts
Internal types src/models/notification/notifications.internal-types.ts
Models src/models/notification/notifications.models.ts, subscriptions.models.ts, index.ts
Services src/services/notification/notifications.ts, subscriptions.ts, index.ts
Build package.json (subpath ./notifications), rollup.config.js (notifications entry)
Unit tests tests/unit/services/notification/notifications.test.ts (14 tests), subscriptions.test.ts (22 tests)
Integration tests tests/integration/shared/notification/notifications.integration.test.ts (6 tests), subscriptions.integration.test.ts (8 tests) — v1 mode only
Integration wiring tests/integration/config/test-config.ts (notificationTenantId), tests/integration/config/unified-setup.ts, tests/.env.integration.example (NOTIFICATION_TEST_TENANT_ID)
Test utils tests/utils/constants/notification.ts (incl. TENANT_ID), tests/utils/mocks/notification.ts (+ barrel updates)
Docs docs/oauth-scopes.md, docs/pagination.md, mkdocs.yml

Follow-up

  • Cloudflare Workers whitelist: the 5 distinct endpoint patterns under notificationservice_/ should be added to ALLOWED_API_PATTERNS in apps-dev-tools for browser-based consumers using alpha.api.uipath.com. Local Vite proxies still work for SDK E2E tests.
  • Tenant-less routing in ApiClient is currently solved with the ../ trick. A cleaner long-term fix would be a skipTenant option on ApiClient/BaseService — left as future refactor since this PR's scope is the notification SDK only.

🤖 Generated with Claude Code

@sarthak688 sarthak688 requested a review from a team June 9, 2026 05:54
Comment thread src/utils/constants/endpoints/notification.ts
Comment thread tests/utils/mocks/notification.ts
@claude

claude Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review findings

Two issues found this run:

  1. src/utils/constants/endpoints/notification.ts:31SUBSCRIPTION_ENDPOINTS.UPDATE_TOPIC and SUBSCRIPTION_ENDPOINTS.GET_ALL are identical strings with no comment explaining the intentional duplication. Convention requires either reusing the constant or adding an explicit comment (the HTTP-method difference is resolved at the call site, not in the constant).

  2. tests/utils/mocks/notification.ts:51createBasicNotificationEntry sets 7 of the 8 INTERNAL_NOTIFICATION_FIELDS but omits partitionKey. The strip test's not.toHaveProperty('partitionKey') assertion therefore passes vacuously — the deletion is never exercised.

Co-Authored-By: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sarthak688 sarthak688 force-pushed the feat/notification-service-sdk branch from 5eeeac4 to f433f25 Compare June 9, 2026 07:37
GET_PUBLISHERS: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription/GetPublishers`,
// Intentional duplicate of GET_ALL: same URL, POST vs GET differentiates the operation.
UPDATE_TOPIC: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription`,
UPDATE_TOPIC: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copy-paste artifact from the previous fix: this line is a duplicate UPDATE_TOPIC key — it should be GET_SUPPORTED_CHANNELS. In a TypeScript as const object literal, duplicate keys are a compile error (and oxlint's no-dupe-keys rule will reject it). More critically, GET_SUPPORTED_CHANNELS is completely absent from the object, so subscriptions.ts and the unit tests will both fail typecheck with:

Property 'GET_SUPPORTED_CHANNELS' does not exist on type …

Replace this line with the correct constant (use the actual live endpoint URL — the placeholder below follows the naming pattern):

Suggested change
UPDATE_TOPIC: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription`,
GET_SUPPORTED_CHANNELS: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription/GetSupportedChannelStatus`,

@claude

claude Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review findings

One new issue found this run:

notification.ts line 33 — The second UPDATE_TOPIC line is a copy-paste artifact from the previous fix. It creates a duplicate key in the SUBSCRIPTION_ENDPOINTS object (rejected by both TypeScript and oxlint) and leaves GET_SUPPORTED_CHANNELS entirely absent — causing typecheck to fail because subscriptions.ts and the unit tests both reference SUBSCRIPTION_ENDPOINTS.GET_SUPPORTED_CHANNELS. Replace the duplicate line with the correct GET_SUPPORTED_CHANNELS entry pointing at the live endpoint URL.

Comment on lines +31 to +33
// Intentional duplicate of GET_ALL: same URL, POST vs GET differentiates the operation.
UPDATE_TOPIC: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription`,
UPDATE_TOPIC: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The fix-up for the prior review comment accidentally duplicated UPDATE_TOPIC and dropped GET_SUPPORTED_CHANNELS at the same time. Two problems:

  1. UPDATE_TOPIC appears twice — the second entry is dead code (second value wins in JS, but they're identical so the runtime value happens to be correct; still a defect).
  2. GET_SUPPORTED_CHANNELS is missingsubscriptions.ts:129 references SUBSCRIPTION_ENDPOINTS.GET_SUPPORTED_CHANNELS, which no longer exists in this object. TypeScript should reject this with Property 'GET_SUPPORTED_CHANNELS' does not exist on type ….
Suggested change
// Intentional duplicate of GET_ALL: same URL, POST vs GET differentiates the operation.
UPDATE_TOPIC: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription`,
UPDATE_TOPIC: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription`,
GET_SUPPORTED_CHANNELS: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription/GetSupportedChannelStatus`,
// Intentional duplicate of GET_ALL: same URL, POST vs GET differentiates the operation.
UPDATE_TOPIC: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription`,

@claude

claude Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review findings

One new issue posted this run:

src/utils/constants/endpoints/notification.ts:31-33 - The fix-up commit that addressed the prior UPDATE_TOPIC comment accidentally introduced a duplicate key and dropped GET_SUPPORTED_CHANNELS. subscriptions.ts:129 references SUBSCRIPTION_ENDPOINTS.GET_SUPPORTED_CHANNELS, which no longer exists in the object. Suggestion posted inline.

Comment on lines +30 to +33
GET_PUBLISHERS: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription/GetPublishers`,
// Intentional duplicate of GET_ALL: same URL, POST vs GET differentiates the operation.
UPDATE_TOPIC: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription`,
UPDATE_TOPIC: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription`,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Two bugs were introduced while applying the previous review fix:

  1. GET_SUPPORTED_CHANNELS is missingSubscriptionService.getSupportedChannels() calls SUBSCRIPTION_ENDPOINTS.GET_SUPPORTED_CHANNELS, but that key is not defined in this object. TypeScript will reject this with TS2339. The endpoint URL is in the PR description: …/UserSubscription/GetSupportedChannelStatus.

  2. Duplicate UPDATE_TOPIC keyUPDATE_TOPIC is now declared twice (lines 32–33 are identical). In JavaScript/TypeScript only the last value survives; the first line is dead code.

Suggested change
GET_PUBLISHERS: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription/GetPublishers`,
// Intentional duplicate of GET_ALL: same URL, POST vs GET differentiates the operation.
UPDATE_TOPIC: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription`,
UPDATE_TOPIC: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription`,
GET_PUBLISHERS: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription/GetPublishers`,
GET_SUPPORTED_CHANNELS: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription/GetSupportedChannelStatus`,
// Intentional duplicate of GET_ALL: same URL, POST vs GET differentiates the operation.
UPDATE_TOPIC: `${SUBSCRIPTION_API_BASE}/api/v1/UserSubscription`,

@claude

claude Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Review findings

One issue found this run:

src/utils/constants/endpoints/notification.ts lines 30-33 (#500 (comment)) — Two bugs were introduced while applying the previous round fix: (1) GET_SUPPORTED_CHANNELS is missing from SUBSCRIPTION_ENDPOINTS but subscriptions.ts references it — TypeScript will reject this with TS2339. (2) UPDATE_TOPIC is declared twice; the first occurrence is dead code.

Every public method on Notifications and Subscriptions now takes the
tenant GUID as its first positional argument, sent via the
X-UIPATH-Internal-TenantId header. Callers no longer configure tenantId
on the SDK; the header is built per-call inline. Unit and integration
tests + ServiceModel JSDoc updated to match.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment on lines +20 to +23
* const unread = await notifications.getAll({ filter: 'isRead eq false' });
*
* const subscriptions = new Subscriptions(sdk);
* const { publishers } = await subscriptions.getAll();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The module-level @example is missing the required tenantId first argument on both calls. As-written the example won't compile — getAll and getAll both have tenantId: string as their first positional parameter.

Suggested change
* const unread = await notifications.getAll({ filter: 'isRead eq false' });
*
* const subscriptions = new Subscriptions(sdk);
* const { publishers } = await subscriptions.getAll();
* const notifications = new Notifications(sdk);
* const unread = await notifications.getAll('<tenantId>', { filter: 'isRead eq false' });
*
* const subscriptions = new Subscriptions(sdk);
* const { publishers } = await subscriptions.getAll('<tenantId>');

@claude

claude Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Review findings

One new issue found this run:

src/services/notification/index.ts:20-23 (#500 (comment)) — The module-level @example block omits the required tenantId first argument on both notifications.getAll() and subscriptions.getAll() calls. The example will not compile since tenantId: string is a required positional parameter on both methods. Suggestion posted inline.

@sarthak688

Copy link
Copy Markdown
Author

Closing in favor of the 7-PR stack #512#513#514#516#517#518#519, which splits this work into reviewable slices (foundation + 1 method per PR; subsequent PRs group similar methods).

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.

1 participant