Skip to content

Commit 27cbc39

Browse files
sarthak688claudeclaude[bot]
committed
feat(notifications): add Notifications service foundation + getAll
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-Authored-By: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
1 parent 2aa68d2 commit 27cbc39

20 files changed

Lines changed: 713 additions & 1 deletion

File tree

package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,16 @@
205205
"types": "./dist/governance/index.d.ts",
206206
"default": "./dist/governance/index.cjs"
207207
}
208+
},
209+
"./notifications": {
210+
"import": {
211+
"types": "./dist/notifications/index.d.ts",
212+
"default": "./dist/notifications/index.mjs"
213+
},
214+
"require": {
215+
"types": "./dist/notifications/index.d.ts",
216+
"default": "./dist/notifications/index.cjs"
217+
}
208218
}
209219
},
210220
"files": [

rollup.config.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,11 @@ const serviceEntries = [
223223
name: 'governance',
224224
input: 'src/services/governance/index.ts',
225225
output: 'governance/index'
226+
},
227+
{
228+
name: 'notifications',
229+
input: 'src/services/notification/index.ts',
230+
output: 'notifications/index'
226231
}
227232
];
228233

src/models/notification/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/**
2+
* Notification models barrel export.
3+
*/
4+
5+
export * from './notifications.types';
6+
export * from './notifications.models';
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/**
2+
* Internal-only types for the Notification service.
3+
*
4+
* NOT exported from the public barrel (`src/models/notification/index.ts`).
5+
*/
6+
7+
import type { NotificationGetResponse } from './notifications.types';
8+
9+
/**
10+
* Raw notification entry shape as returned by `/odata/v1/NotificationEntry` — includes
11+
* the internal/transport-layer fields the SDK drops before returning to consumers.
12+
*/
13+
export interface RawNotificationEntry extends NotificationGetResponse {
14+
entityOrgName?: string | null;
15+
entityTenantName?: string | null;
16+
serviceRegistryName?: string | null;
17+
messageTemplateKey?: string | null;
18+
messageVersion?: number;
19+
publicationId?: string;
20+
correlationId?: string | null;
21+
partitionKey?: string;
22+
}
23+
24+
/**
25+
* Fields stripped from each {@link RawNotificationEntry} before it is returned to the
26+
* SDK consumer as a {@link NotificationGetResponse}.
27+
*/
28+
export const INTERNAL_NOTIFICATION_FIELDS: ReadonlyArray<keyof RawNotificationEntry> = [
29+
'entityOrgName',
30+
'entityTenantName',
31+
'serviceRegistryName',
32+
'messageTemplateKey',
33+
'messageVersion',
34+
'publicationId',
35+
'correlationId',
36+
'partitionKey',
37+
];
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/**
2+
* Notification service model — public response shapes and the ServiceModel interface
3+
* that drives generated API documentation.
4+
*/
5+
6+
import type {
7+
HasPaginationOptions,
8+
NonPaginatedResponse,
9+
PaginatedResponse,
10+
} from '../../utils/pagination/types';
11+
12+
import type {
13+
NotificationGetAllOptions,
14+
NotificationGetResponse,
15+
} from './notifications.types';
16+
17+
/**
18+
* Public surface of the Notifications service. JSDoc on this interface drives
19+
* the generated API reference documentation.
20+
*
21+
* Every method takes the tenant GUID as the first argument — the notification
22+
* API identifies the acting tenant via the `X-UIPATH-Internal-TenantId` header
23+
* and the SDK forwards `tenantId` into that header on each call.
24+
*/
25+
export interface NotificationServiceModel {
26+
/**
27+
* Lists notifications from the current user's inbox.
28+
*
29+
* Returns the full list when no pagination params are provided, or a paginated cursor result
30+
* when any of `pageSize`/`cursor`/`jumpToPage` is supplied. Supports OData `filter` and
31+
* `orderby` query options.
32+
*
33+
* @param tenantId - Tenant GUID (sent via `X-UIPATH-Internal-TenantId`)
34+
* @param options - Optional OData query and pagination options
35+
* @returns Array of notifications, or a paginated result when pagination params are supplied
36+
* {@link NotificationGetResponse}
37+
*
38+
* @example Basic usage
39+
* ```typescript
40+
* import { Notifications } from '@uipath/uipath-typescript/notifications';
41+
*
42+
* const notifications = new Notifications(sdk);
43+
* const all = await notifications.getAll('<tenantId>');
44+
* ```
45+
*
46+
* @example Filter unread, most recent first
47+
* ```typescript
48+
* const unread = await notifications.getAll('<tenantId>', {
49+
* filter: 'isRead eq false',
50+
* orderby: 'publishedOn desc',
51+
* });
52+
* ```
53+
*
54+
* @example First page with pagination
55+
* ```typescript
56+
* const page1 = await notifications.getAll('<tenantId>', { pageSize: 20 });
57+
* if (page1.hasNextPage) {
58+
* const page2 = await notifications.getAll('<tenantId>', { cursor: page1.nextCursor });
59+
* }
60+
* ```
61+
* @internal
62+
*/
63+
getAll<T extends NotificationGetAllOptions = NotificationGetAllOptions>(
64+
tenantId: string,
65+
options?: T
66+
): Promise<
67+
T extends HasPaginationOptions<T>
68+
? PaginatedResponse<NotificationGetResponse>
69+
: NonPaginatedResponse<NotificationGetResponse>
70+
>;
71+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/**
2+
* Notification inbox types — raw API shapes and request/response options.
3+
*/
4+
5+
import type { RequestOptions } from '../common/types';
6+
import type { PaginationOptions } from '../../utils/pagination/types';
7+
8+
/**
9+
* Priority level assigned to a notification by the publisher.
10+
*/
11+
export enum NotificationPriority {
12+
Low = 'Low',
13+
Medium = 'Medium',
14+
High = 'High',
15+
Critical = 'Critical',
16+
}
17+
18+
/**
19+
* Severity classification of a notification topic.
20+
*/
21+
export enum NotificationCategory {
22+
/** Informational — no action required. */
23+
Info = 'Info',
24+
/** Successful operation completed. */
25+
Success = 'Success',
26+
/** Warning — degraded behaviour or non-fatal issue. */
27+
Warn = 'Warn',
28+
/** Error — operation failed but the system continues. */
29+
Error = 'Error',
30+
/** Fatal — unrecoverable failure. */
31+
Fatal = 'Fatal',
32+
}
33+
34+
/**
35+
* Notification entry as returned by `GET /odata/v1/NotificationEntry`.
36+
*
37+
* Field selection: many internal/transport-layer fields (`partitionKey`, `correlationId`,
38+
* `publicationId`, `messageVersion`, `messageTemplateKey`, `serviceRegistryName`,
39+
* `entityOrgName`, `entityTenantName`) are returned by the API but dropped from the SDK
40+
* because they have no use for an application developer.
41+
*/
42+
export interface NotificationGetResponse {
43+
/** Notification GUID. */
44+
id: string;
45+
/** Resolved notification message text. */
46+
message: string | null;
47+
/** Whether the user has read this notification. */
48+
isRead: boolean;
49+
/** Name of the publisher (e.g. `Orchestrator`, `Actions`). */
50+
publisherName: string;
51+
/** Publisher GUID. */
52+
publisherId: string;
53+
/** Human-readable topic name. */
54+
topicName: string;
55+
/** Stable topic identifier (e.g. `Process.JobExecution.Faulted`). */
56+
topicKeyName: string;
57+
/** Topic GUID. */
58+
topicId: string;
59+
/** GUID of the user this notification belongs to (returned uppercase by the API). */
60+
userId: string;
61+
/** Email of the user. Often `null`. */
62+
userEmail: string | null;
63+
/** Tenant GUID this notification belongs to. Often `null` for org-scoped notifications. */
64+
tenantId: string | null;
65+
/** Notification priority. */
66+
priority: NotificationPriority;
67+
/** Notification severity category. */
68+
category: NotificationCategory;
69+
/** JSON string of template parameters — parse with `JSON.parse()`. May be `null`. */
70+
messageParam: string | null;
71+
/** URL to navigate to when the notification is clicked. */
72+
redirectionUrl: string | null;
73+
/** Unix epoch **seconds** when the notification was published. */
74+
publishedOn: number;
75+
}
76+
77+
/**
78+
* Options for `Notifications.getAll()`.
79+
*
80+
* Supports OData query options (`filter`, `orderby`) and SDK cursor pagination.
81+
*
82+
* Notes:
83+
* - `$select` and `$expand` are not exposed because the API returns 500 on `$select`
84+
* and there are no expandable relationships on this endpoint.
85+
*/
86+
export type NotificationGetAllOptions = Omit<RequestOptions, 'expand' | 'select'> & PaginationOptions;

src/services/notification/index.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* Notification Service Module
3+
*
4+
* Provides access to the UiPath Notification platform from the perspective of an
5+
* authenticated user (UserContext):
6+
* - `Notifications` — list operations on the user's inbox (further operations land in
7+
* follow-up PRs)
8+
*
9+
* Publishing (sending) notifications is a first-party service action and is NOT part of this module.
10+
*
11+
* @example
12+
* ```typescript
13+
* import { UiPath } from '@uipath/uipath-typescript/core';
14+
* import { Notifications } from '@uipath/uipath-typescript/notifications';
15+
*
16+
* const sdk = new UiPath(config);
17+
* await sdk.initialize();
18+
*
19+
* const notifications = new Notifications(sdk);
20+
* const unread = await notifications.getAll('<tenantId>', { filter: 'isRead eq false' });
21+
* ```
22+
*
23+
* @module
24+
*/
25+
26+
export { NotificationService as Notifications } from './notifications';
27+
28+
// Models (types, enums, response shapes)
29+
export * from '../../models/notification';
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* NotificationService — manages the current user's notification inbox.
3+
*/
4+
5+
import { track } from '../../core/telemetry';
6+
import { BaseService } from '../base';
7+
8+
import type {
9+
NotificationGetAllOptions,
10+
NotificationGetResponse,
11+
} from '../../models/notification/notifications.types';
12+
import type {
13+
NotificationServiceModel,
14+
} from '../../models/notification/notifications.models';
15+
import {
16+
INTERNAL_NOTIFICATION_FIELDS,
17+
type RawNotificationEntry,
18+
} from '../../models/notification/notifications.internal-types';
19+
20+
import { ODATA_OFFSET_PARAMS, ODATA_PAGINATION } from '../../utils/constants/common';
21+
import { NOTIFICATION_ENDPOINTS } from '../../utils/constants/endpoints';
22+
import { TENANT_ID } from '../../utils/constants/headers';
23+
import { createHeaders } from '../../utils/http/headers';
24+
import {
25+
HasPaginationOptions,
26+
NonPaginatedResponse,
27+
PaginatedResponse,
28+
} from '../../utils/pagination/types';
29+
import { PaginationHelpers } from '../../utils/pagination/helpers';
30+
import { PaginationType } from '../../utils/pagination/internal-types';
31+
32+
/**
33+
* Service for interacting with the UiPath Notification inbox.
34+
*
35+
* Provides list operations against the current user's notifications (the
36+
* `/odata/v1/NotificationEntry` API). Further inbox operations (mark-read,
37+
* delete) land in follow-up PRs.
38+
*
39+
* Every public method takes the acting tenant GUID as the first argument — the
40+
* notification API identifies the tenant via the `X-UIPATH-Internal-TenantId`
41+
* header and the SDK forwards `tenantId` into that header on each call.
42+
*/
43+
export class NotificationService extends BaseService implements NotificationServiceModel {
44+
/**
45+
* Lists notifications from the current user's inbox.
46+
*
47+
* Returns the full list when no pagination params are provided, or a paginated cursor result
48+
* when any of `pageSize`/`cursor`/`jumpToPage` is supplied. Supports OData `filter` and
49+
* `orderby` query options.
50+
*
51+
* @param tenantId - Tenant GUID (sent via `X-UIPATH-Internal-TenantId`)
52+
* @param options - Optional OData query and pagination options
53+
* @returns Array of notifications, or a paginated result when pagination params are supplied
54+
* {@link NotificationGetResponse}
55+
*
56+
* @example Basic usage
57+
* ```typescript
58+
* import { Notifications } from '@uipath/uipath-typescript/notifications';
59+
*
60+
* const notifications = new Notifications(sdk);
61+
* const all = await notifications.getAll('<tenantId>');
62+
* ```
63+
*
64+
* @example Filter unread, most recent first
65+
* ```typescript
66+
* const unread = await notifications.getAll('<tenantId>', {
67+
* filter: 'isRead eq false',
68+
* orderby: 'publishedOn desc',
69+
* });
70+
* ```
71+
*
72+
* @example First page with pagination
73+
* ```typescript
74+
* const page1 = await notifications.getAll('<tenantId>', { pageSize: 20 });
75+
* if (page1.hasNextPage) {
76+
* const page2 = await notifications.getAll('<tenantId>', { cursor: page1.nextCursor });
77+
* }
78+
* ```
79+
* @internal
80+
*/
81+
@track('Notifications.GetAll')
82+
async getAll<T extends NotificationGetAllOptions = NotificationGetAllOptions>(
83+
tenantId: string,
84+
options?: T
85+
): Promise<
86+
T extends HasPaginationOptions<T>
87+
? PaginatedResponse<NotificationGetResponse>
88+
: NonPaginatedResponse<NotificationGetResponse>
89+
> {
90+
return PaginationHelpers.getAll({
91+
serviceAccess: this.createPaginationServiceAccess(),
92+
getEndpoint: () => NOTIFICATION_ENDPOINTS.GET_ALL,
93+
headers: createHeaders({ [TENANT_ID]: tenantId }),
94+
transformFn: stripInternalNotificationFields,
95+
pagination: {
96+
paginationType: PaginationType.OFFSET,
97+
itemsField: ODATA_PAGINATION.ITEMS_FIELD,
98+
totalCountField: ODATA_PAGINATION.TOTAL_COUNT_FIELD,
99+
paginationParams: {
100+
pageSizeParam: ODATA_OFFSET_PARAMS.PAGE_SIZE_PARAM,
101+
offsetParam: ODATA_OFFSET_PARAMS.OFFSET_PARAM,
102+
countParam: ODATA_OFFSET_PARAMS.COUNT_PARAM,
103+
},
104+
},
105+
}, options) as Promise<
106+
T extends HasPaginationOptions<T>
107+
? PaginatedResponse<NotificationGetResponse>
108+
: NonPaginatedResponse<NotificationGetResponse>
109+
>;
110+
}
111+
}
112+
113+
/**
114+
* Drops internal/transport-layer fields from a raw notification entry before
115+
* returning it to the SDK consumer. Exported as module-level for testability.
116+
*
117+
* @internal
118+
*/
119+
export function stripInternalNotificationFields(item: RawNotificationEntry): NotificationGetResponse {
120+
const result: RawNotificationEntry = { ...item };
121+
for (const field of INTERNAL_NOTIFICATION_FIELDS) {
122+
delete result[field];
123+
}
124+
return result;
125+
}

0 commit comments

Comments
 (0)