@cap-js/notifications

中文文档
1.1.1发布于 2026/09/29Apache-2.0CommonJS构建来源已验证近 30 天下载 7314

CDS plugin providing support for business notifications in SAP Build WorkZone.

原始使用文档
文档目录43 节
  1. Table of Contents
  2. Setup
  3. Getting Started
  4. Quick start: Direct notification
  5. Recommended: Define notification types
  6. Running the Sample
  7. 1. Start the sample app
  8. 2. Trigger a notification
  9. 3. Customize the notification type
  10. 4. Connect to SAP Build Work Zone
  11. Define Notification Types
  12. Option A: CDS Annotations (recommended)
  13. Option B: JSON file
  14. Email delivery
  15. Send Notifications
  16. Pattern 1: Emit a CDS event (recommended)
  17. Pattern 2: Call notify() directly
  18. Batch notifications
  19. Entity Notifications
  20. Annotation properties
  21. Notification properties
  22. API Reference
  23. Simple Notification
  24. Named Notification Type
  25. Validation
  26. Annotation Reference
  27. Test-drive Locally
  28. Run in Production
  29. Notification Destination
  30. Notification Type Registration
  31. Integrate with SAP Build Work Zone
  32. Advanced Usage
  33. Custom Notification Types Path
  34. Custom Notification Type Prefix
  35. Custom Destination Name
  36. Authentication Identifier
  37. Default Channels
  38. Outbox Behavior
  39. Disabling the Plugin
  40. Low-level Notifications API
  41. Contributing
  42. Code of Conduct
  43. Licensing

REUSE status

Notifications Plugin

The @cap-js/notifications package is a CDS plugin that provides support for publishing business notifications in SAP Build Work Zone.

Table of Contents

Setup

Requirements: Node.js >= 20, @sap/cds >= 8.

To enable notifications, simply add this self-configuring plugin package to your project:

npm add @cap-js/notifications

Getting Started

After installing the plugin, you can send notifications in two ways:

Quick start: Direct notification

Send a simple notification using notify():

const alert = await cds.connect.to("notifications")

await alert.notify({
  recipients: ["[email protected]"],
  title: "Book Order Received",
  description: 'Your order for "Wuthering Heights" is being processed.'
})

Define a notification event in your service model with @notification:

using { CatalogService } from './cat-service';

extend service CatalogService with {
  @notification: {
    title: 'Book {{title}} Ordered',
    subtitle: '{{buyer}} ordered {{title}}'
  }
  event BookOrdered {
    title : String;
    buyer : String;
  }
}

Emit the event from your service handler:

this.on("submitOrder", async req => {
  // ... process order ...

  await this.emit("BookOrdered", {
    title: book.title,
    buyer: req.user.id,
    recipients: ["[email protected]"]
  })
})

The plugin intercepts the event and sends the notification automatically. During local development, notifications are printed to the console. No BTP connection required.

Running the Sample

This section uses the Bookshop sample included in this repository.

1. Start the sample app

cd tests/bookshop
npm install
cds watch

The server starts at http://localhost:4004. During local development, the plugin prints the notifications to the console thus no BTP account is yet needed.

2. Trigger a notification

The bookshop's submitOrder action reduces book stock and emits a BookOrderedNotify event. The plugin intercepts that event and sends a notification.

Open tests/bookshop/test/http/CatalogService.http in VS Code and click Send Request above the submitOrder block. This file has the server URL and credentials pre-configured.

In the server console you will see the notification printed to confirm the notification was successful.

3. Customize the notification type

Open tests/bookshop/srv/notifications.cds. This file defines the BookOrderedNotify event and all of its @notification annotations. Change the subtitle template to include the quantity:

// Before
subtitle: '{i18n>BOOK_ORDERED_SUBTITLE}',

// After
subtitle: '{{buyer}} ordered {{quantity}}x {{title}}',

Save the file and cds watch reloads automatically. Send the request again and the updated subtitle appears in the console output. From here, try adjusting the priority expression, adding a @description, or exploring the other annotations on the event.

4. Connect to SAP Build Work Zone

To see the notification appear in the Work Zone, you need a BTP subaccount with SAP Build Work Zone and the SAP Alert Notification service configured.

  1. Follow the SAP Build Work Zone setup guide to subscribe to the service and configure the required SAP_Notifications destination in your subaccount.
  2. Bind your local environment to the destination service instance in CF using cds bind, then run cds watch --profile hybrid to connect to BTP destinations from your local machine.

On startup the plugin registers your notification types automatically. Submitting an order will now deliver a notification to the bell in Work Zone for the recipient.

[!Note] The bookshop sample uses in-app notifications by default. The Work Zone bell icon shows notifications for recipients identified by their SAP BTP Global User ID (UUID). To test email delivery as well, additional setup is required. For enabling, see email delivery and default email delivery. For required BTP configuration see the SMTP mail destination guide.

Define Notification Types

Notifications are based on notification types: templates that define how a notification looks, including titles, subtitles, and email content. These types can be defined in two ways, both of which can be used together and are merged at startup.

The recommended approach is to define the notification type directly in your service model by annotating events with @notification. The plugin discovers and registers them automatically during startup.

Define an event in your srv/ model:

using { CatalogService } from './cat-service';

extend service CatalogService with {

  @description: 'Sent when a book is ordered'
  @notification: {
    title        : 'Book {{title}} Ordered',
    publicTitle  : 'Book Ordered',
    subtitle     : '{{buyer}} ordered {{title}}',
    groupedTitle : 'Bookshop Updates'
  }
  @Common.SemanticObject: 'Books'
  @Common.SemanticObjectAction: 'display'
  event BookOrdered {
    title : String;
    buyer : String;
  }

}

Any event with at least one @notification annotation (the bare @notification flag or any @notification.* property) is picked up. The notification type key is derived from the event name. Namespace prefixes are stripped, my.bookshop.BookOrdered becomes BookOrdered.

[!Note] The plugin automatically injects a recipients element into every notification event at model-load time; you don't need to declare it yourself.

[!Important] The event must be contained within a service either by defining it directly inside a service or by using extend service / using to include it in an existing one.

[!Note] Annotations can also be placed in a separate file using the standard CDS annotate directive.

Common annotations:

@notification: {
  title        : 'Book {{title}} Ordered',
  publicTitle  : 'Book Ordered',
  subtitle     : '{{buyer}} ordered {{title}}',
  groupedTitle : 'Bookshop Updates', // Group header for multiple notifications
  email: {
    subject: 'Your order: {{title}}',
    html   : './email-template.html' // Path to HTML template or inline HTML
  },
  priority: #HIGH // Priority: LOW, NEUTRAL, MEDIUM, HIGH
}
event BookOrdered { ... }

For a complete list of supported annotations and their mappings, see Annotation Reference.

Delivery channels (Option A only)

Use @notification.channels to specify which channels a notification type is delivered through:

@notification: {
  title   : 'Book Ordered',
  channels: ['email']
}
event BookOrdered { ... }

The supported values are email (SAP Mail) and workzone (SAP Build Work Zone). If no channel is specified, the channel defaults to the value of cds.env.requires.notifications.channels, or workzone if nothing is set.

i18n support (Option A only)

The @notification annotation values support {i18n>key} syntax. Keys are automatically resolved against your project's i18n bundles at startup. Templates are generated for each locale where at least one translation differs from the default language.

@notification.title:    '{i18n>BOOK_ORDERED_TITLE}'
@notification.subtitle: '{i18n>BOOK_ORDERED_SUBTITLE}'
event BookOrdered { ... }

HTML email templates (Option A only)

The email.html annotation accepts either an inline HTML string or a path to an .html file relative to the .cds source file. The file is read at startup and i18n placeholders within it are resolved.

@notification: {
  email: {
    subject: 'Your order: {{title}}',
    html   : './book-ordered-email.html'
  }
}
event BookOrdered { ... }

Priority (Option A only)

Notifications can be assigned different priority levels: LOW, NEUTRAL (default), MEDIUM, or HIGH. These priorities affect how notifications are displayed and sorted in SAP Build Work Zone.

Priorities can be set statically using # enum values, or dynamically using CDS Expression Language (CXL) with conditions evaluated at runtime.

Static priority:

@notification.priority: #HIGH
event BookOrdered { ... }

Dynamic priority:

Priority can be computed at runtime from event data using CDS ternary expressions evaluated against the database:

@notification.priority: (quantity > 5 ? #HIGH : #LOW)
event BookOrdered {
  quantity : Integer;
  title    : String;
}

Complex expressions using CDS functions are also supported:

@notification.priority: (days_between(orderDate, deliveryDate) > 7 ? #HIGH : #LOW)
event LateDelivery {
  orderDate    : Date;
  deliveryDate : Date;
}

Dynamic priority requires the event to be emitted via this.emit(...) so the plugin can intercept and evaluate it.

Build integration

Running cds build processes all @notification annotated events and generates a merged notification-types.json to the build output, combining types from CDS annotations with any types from the JSON file.

Option B: JSON file

An alternative approach is to define notification types statically in srv/notification-types.json or custom path (see Custom Notification Types Path):

[
  {
    "NotificationTypeKey": "BookOrdered",
    "NotificationTypeVersion": "1",
    "Templates": [
      {
        "Language": "en",
        "TemplatePublic": "Book Ordered",
        "TemplateSensitive": "Book '{{title}}' Ordered",
        "TemplateGrouped": "Bookshop Updates",
        "TemplateLanguage": "mustache",
        "Subtitle": "{{buyer}} ordered {{title}}."
      }
    ]
  }
]

[!Note] i18n resolution, HTML file paths, and priority annotations (@notification.priority) are only available when using CDS annotations (Option A). The JSON file format uses pre-resolved strings.

Email delivery

Email delivery can be configured for notification types in both approaches. It requires the SAP Alert Notification Service with the business-notifications plan and a configured SMTP mail destination.

[!Warning] The business-notifications plan validates all of your notification types at registration time, not only the ones with email. This means every notification type in your app, even purely in-app ones, must have TemplatePublic (mapped from publicTitle) and TemplateGrouped (mapped from groupedTitle) set, or startup registration will fail.

Via CDS annotations:

@notification: {
  title        : 'Book {{title}} Ordered',
  publicTitle  : 'Book Ordered',
  subtitle     : '{{buyer}} ordered {{title}}',
  groupedTitle : 'Bookshop Updates',
  email: {
    subject: 'Your order: {{title}}',
    html   : './book-ordered-email.html'
  },
  channels: ['email']
}
event BookOrdered { ... }

Via JSON:

{
  "NotificationTypeKey": "BookOrdered",
  "Templates": [
    {
      "Language": "en",
      "TemplatePublic": "Book Ordered",
      "TemplateSensitive": "Book '{{title}}' Ordered",
      "TemplateGrouped": "Bookshop Updates",
      "TemplateLanguage": "mustache",
      "EmailSubject": "Your order: {{title}}",
      "EmailHtml": "<p>Thanks for ordering <b>{{title}}</b>!</p>"
    }
  ],
  "DeliveryChannels": [{ "Type": "MAIL", "Enabled": true, "DefaultPreference": true, "EditablePreference": true }]
}

Note: Enabled, DefaultPreference, and EditablePreference are required ANS fields. Use the values as shown above without changing them.

Send Notifications

There are two patterns for sending notifications.

If you defined your notification type as a CDS event with a @notification annotation, the plugin hooks into your service automatically. Simply emit the event from your service handler.

this.on("submitOrder", async req => {
  const book = await SELECT.one.from("Books").where({ ID: req.data.book })

  await this.emit("BookOrdered", {
    title: book.title,
    buyer: req.user.id,
    recipients: ["[email protected]"]
  })
})

The plugin registers an event handler which forwards the notification to ANS. You can still register your own event handlers if you need to process the event yourself. The plugin's handler runs alongside them.

Pattern 2: Call notify() directly

You can also connect to the notification service and call notify() directly. This works with or without pre-defined notification types.

Simple notification (no pre-defined type needed):

const alert = await cds.connect.to("notifications")

await alert.notify({
  recipients: [...readers()],
  priority: "HIGH",
  title: "New book arrived!",
  description: "Book 'Wuthering Heights' has been added to the catalog."
})

[!Note] The simple API supports only recipients, priority, title, and description. For advanced properties use a named notification type or the low-level API.

Named notification type:

await alert.notify("BookOrdered", {
  recipients: [buyer.id],
  data: {
    title: book.title,
    buyer: buyer.name
  }
})

Batch notifications

It is possible to pass an array to notify() to send multiple notifications in a single call. This triggers only one outbox event, reducing the number of transactions when notifying many recipients. If some items fail, the successful ones are still delivered. Failures are logged as warnings, and the call only throws if all items fail.

alert.notify("BookOrdered", [
  { recipients: [buyer1.id], data: { title: book.title, buyer: buyer1.name } },
  { recipients: [buyer2.id], data: { title: book.title, buyer: buyer2.name } }
])

[!Warning] Batch sending is only available via notify([...]). CDS event emission dispatches one event per call.

Alternatively, the default notification template can be used:

await alert.notify([
  { type: "BookOrdered", recipients: [buyer1.id], data: { title: book1.title, buyer: buyer1.name } },
  { type: "BookOrdered", recipients: [buyer2.id], data: { title: book2.title, buyer: buyer2.name } }
])

Entity Notifications

Entity notifications let you declaratively fire notifications when entity data is read or changed, without writing any handler code. Add a @notifications annotation directly to a CDS entity, each entry in the array defines one notification:

service CatalogService {
  @notifications: [{
    type      : 'BookOrdered',
    on        : ['READ'],
    recipients: ($self.createdBy),
    where     : ($self.stock < 5),
    priority  : #High
  }]
  entity Books as projection on my.Books;
}

Annotation properties

PropertyRequiredDescription
typeyesThe name for this notification type (e.g. 'BookOrdered'). The plugin registers it automatically.
onyesArray of CDS events to listen on: 'READ', 'CREATE', 'UPDATE'
recipientsyesField reference (e.g. $self.createdBy) or literal recipient identifier
wherenoFilter expression: only entities matching this condition fire a notification
priorityno#Low, #Neutral, #Medium, or #High
parametersnoExplicit mapping of notification template placeholders to entity fields

Notification properties

By default, all entity fields are passed to the notification template. Use parameters to map only specific fields instead:

@notifications: [{
  type      : 'BookOrdered',
  on        : ['READ'],
  recipients: ($self.createdBy),
  parameters: { bookTitle: $self.title, bookId: $self.ID }
}]
entity Books as projection on my.Books;

This produces a notification with only the bookTitle and bookId properties set, matching the placeholders in the notification type template.

API Reference

Simple Notification

For notify({ recipients, title, ... }), no pre-defined notification type is needed. The plugin uses a built-in Default template.

ParameterRequiredDescription
recipientsyesArray of recipient identifiers: email addresses or SAP BTP Global User IDs (UUIDs)
titleyesNotification title string
prioritynoLOW, NEUTRAL (default), MEDIUM, or HIGH
descriptionnoSubtitle text

Named Notification Type

For notify('TypeKey', payload) or notify({ type: 'TypeKey', ... }), a notification using a pre-defined notification type is sent.

ParameterRequiredDescription
recipientsyesArray of recipient identifiers: email addresses or SAP BTP Global User IDs (UUIDs)
typeyesNotification type key (e.g. 'BookOrdered')
datanoKey-value pairs used to fill mustache placeholders in the type template
prioritynoLOW, NEUTRAL (default), MEDIUM, or HIGH

Note: Recipients can be email addresses (e.g. [email protected]) or SAP BTP Global User IDs (UUID format, e.g. a1b2c3d4-...). In auto mode (default), the plugin detects the format per recipient and uses the correct key automatically. See Authentication Identifier for details.

Validation

  • Property values must not exceed 255 characters. Longer values cause the notification to be rejected.
  • TargetParameters values longer than 250 characters are silently dropped.
  • Event element names must not exceed 128 characters. Violations are caught at cds build time.

Annotation Reference

Complete mapping of CDS annotations to notification fields:

AnnotationANS FieldDescription
@descriptionDescriptionNotification type description
@notification.titleTemplateSensitiveMain notification title (supports placeholders)
@notification.publicTitleTemplatePublicPublic fallback title
@notification.subtitleSubtitleSubtitle text
@notification.groupedTitleTemplateGroupedGroup header for multiple notifications
@notification.email.subjectEmailSubjectEmail subject line
@notification.email.htmlEmailHtmlInline HTML or path to .html file
@Common.SemanticObjectNavigationTargetObjectNavigation target object
@Common.SemanticObjectActionNavigationTargetActionNavigation action
@notification.priorityPriorityLOW, NEUTRAL, MEDIUM, or HIGH

Test-drive Locally

During local development, notifications are mocked and printed to the console. No external service is required.

Notify to console

Run in Production

Notification Destination

As a prerequisite, configure a destination named SAP_Notifications in your BTP subaccount. The plugin uses this destination by default to connect to the notification service in hybrid and production environments.

Notification Type Registration

Notification types are automatically registered and kept in sync with the notification service each time the application starts. Any additions, changes, or removals to your notification types, whether from CDS annotations or the JSON file, are applied on the next startup. No manual cds build or content deployment step is required.

Integrate with SAP Build Work Zone

Once the application is deployed and integrated with SAP Build Work Zone, notifications appear under the Fiori notifications icon.

Sample Application Demo

Advanced Usage

Custom Notification Types Path

The plugin reads srv/notification-types.json as the default JSON types file. To use a different path:

"cds": {
  "requires": {
    "notifications": {
      "types": "srv/my-notification-types.json"
    }
  }
}

Custom Notification Type Prefix

To make notification type keys unique per application, the plugin prefixes them with the application name from package.json by default. To use a custom prefix:

"cds": {
  "requires": {
    "notifications": {
      "prefix": "my-custom-prefix"
    }
  }
}

Custom Destination Name

To override the default SAP_Notifications destination name:

"cds": {
  "requires": {
    "notifications": {
      "destination": "MY_CUSTOM_DESTINATION"
    }
  }
}

Authentication Identifier

cds.env.requires.notifications.authenticationIdentifier controls which recipient key is used when publishing notifications.

  • auto (default): the recipient key is chosen per recipient. Values in UUID format are treated as SAP BTP Global User IDs and published with GlobalUserId; everything else is published with RecipientId. A warning is logged if a value is neither a UUID nor an email address. This allows mixing UUIDs and email addresses in the same recipients array without any configuration.
  • UserUUID: always use GlobalUserId. Use this when the Work Zone authentication identifier is set to User ID.
  • RecipientId: always use RecipientId. Use this when recipients are identified by email or login name.

[!NOTE] For email notifications sent with a User ID, a destination to the Identity Directory Service (IDS) must be configured for the email address lookup.

For Work Zone authentication identifier configuration, see Work Zone Subaccount Settings.

Default Channels

By default, all notification types use the workzone channel. To change the default for all types that don't have a channels annotation, set channels in your configuration:

"cds": {
  "requires": {
    "notifications": {
      "channels": ["email"]
    }
  }
}

Multiple channels are also supported:

"notifications": {
  "channels": ["email", "workzone"]
}

Per-event channels annotations always take precedence over this global default.

Outbox Behavior

By default, the notification service uses an outbox (outbox: true): notify() resolves as soon as the message is queued, not when it has been sent to ANS. This means the HTTP response from ANS is not returned. To send synchronously and receive the HTTP response:

"cds": {
  "requires": {
    "notifications": {
      "outbox": false
    }
  }
}

Disabling the Plugin

To disable the plugin without removing it, set enabled: false:

"cds": {
  "requires": {
    "notifications": {
      "enabled": false
    }
  }
}

This prevents the plugin from registering its hooks which results into no automatic this.emit() interception, no notification type registration, and no build task. Direct calls to cds.connect.to('notifications').notify() are not affected by this flag.

Low-level Notifications API

For full control, pass the complete notification object directly as described in the ANS API documentation.

With individual parameters

alert.notify({
  recipients: [...readers()],
  type: "BookOrdered",
  priority: "NEUTRAL",
  data: {
    title: book.title,
    buyer: buyer.name
  },
  OriginId: "Example Origin Id",
  NotificationTypeVersion: "1",
  ProviderId: "/SAMPLEPROVIDER",
  ActorId: "BACKENDACTORID",
  ActorDisplayText: "ActorName",
  ActorImageURL: "https://some-url",
  NotificationTypeTimestamp: "2022-03-15T09:58:42.807Z",
  TargetParameters: [{ Key: "string", Value: "string" }] //tell Work Zone which record to open when the user clicks on the notification
})

Passing the full notification object

alert.notify({
  NotificationTypeKey: "BookOrdered",
  NotificationTypeVersion: "1",
  Priority: "NEUTRAL",
  Properties: [
    { Key: "title", IsSensitive: false, Language: "en", Value: "Wuthering Heights", Type: "String" },
    { Key: "buyer", IsSensitive: false, Language: "en", Value: "[email protected]", Type: "String" }
  ],
  Recipients: [{ RecipientId: "[email protected]" }, { RecipientId: "[email protected]" }]
})

Contributing

This project is open to feature requests/suggestions, bug reports etc. via GitHub issues. Contribution and feedback are encouraged and always welcome. For more information about how to contribute, the project structure, as well as additional contribution information, see our Contribution Guidelines.

Code of Conduct

We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone. By participating in this project, you agree to abide by its Code of Conduct at all times.

Licensing

Copyright 2026 SAP SE or an SAP affiliate company and contributors. Please see our LICENSE for copyright and license information. Detailed information including third-party components and their licensing/copyright information is available via the REUSE tool.

版本与发布记录

@cap-js/notifications 共发布 11 个版本,首次发布于 2023/10/30;过去 12 个月发布了 4 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
1.1.1latest2026/09/291 个月前
1.1.02026/09/042 个月前
1.0.02026/08/073 个月前
0.3.02026/01/099 个月前
0.2.52025/06/051.4 年前
0.2.42025/05/291.4 年前

关于 @cap-js/notifications 的常见问题

@cap-js/notifications 是什么?

CDS plugin providing support for business notifications in SAP Build WorkZone.

如何安装 @cap-js/notifications?

在项目目录运行 npm install @cap-js/notifications,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@sap/cds(>=8.0)、@sap/cds-dk(>=8.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@cap-js/notifications 支持 TypeScript 吗?

该包的 package.json 没有声明类型入口。需要类型提示时,可以在 npm 上查找社区维护的 @types/cap-js__notifications 是否存在。

@cap-js/notifications 支持 ESM 还是 CommonJS?

以 CommonJS 形式发布,可以直接 require();在 ES Module 项目中也可以用 import 引入(Node.js 会把 module.exports 作为默认导出)。

@cap-js/notifications 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=20.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@cap-js/notifications 可以商用吗?

@cap-js/notifications 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@cap-js/notifications 的下载量有多少?

根据 npm 官方下载统计,@cap-js/notifications 在 2026/10/09 – 2026/11/07 这 30 天内被下载 7,314 次,日均约 244 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@cap-js/notifications 还在维护吗?

最新版本 1.1.1 发布于 2026/09/29(1 个月前);至今共发布 11 个版本,其中过去 12 个月发布了 4 个;首次发布于 2023/10/30。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。