Skip to content

Support html files#130

Draft
eric-pSAP wants to merge 11 commits into
mainfrom
supportHTMLFiles
Draft

Support html files#130
eric-pSAP wants to merge 11 commits into
mainfrom
supportHTMLFiles

Conversation

@eric-pSAP
Copy link
Copy Markdown
Contributor

Should support using HTML files for email body for clarity

Copy link
Copy Markdown
Contributor

@hyperspace-insights hyperspace-insights Bot left a comment

Choose a reason for hiding this comment

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

Summary

The PR introduces a well-structured feature for defining notification types via CDS @notification annotations, HTML email file references, i18n resolution, and automatic type registration at startup. The implementation is thorough with good test coverage.

Two issues were flagged:

  1. lib/compile.jsresolveHtmlFile crash on missing $location: When a CDS event definition lacks a $location (e.g. programmatically constructed models), passing undefined as the location argument and then accessing location.file throws a TypeError. A null guard was suggested.

  2. lib/content-deployment.js – operator precedence with spread and ??: The expression ...readFile(filePath) ?? [] has ambiguous precedence intent; parentheses should be used to make the fallback apply correctly: ...(readFile(filePath) ?? []).

Additionally, there is a minor typo in README.md line 219: "iori notifications icon" should be "Fiori notifications icon" (capital 'F' dropped).

PR Bot Information

Version: 1.21.0

  • Correlation ID: a1fd8159-c276-4391-8e4e-0a856cca8015
  • Event Trigger: pull_request.opened
  • File Content Strategy: Full file content
  • LLM: anthropic--claude-4.6-sonnet

Comment thread lib/compile.js
Comment on lines +64 to +68
function resolveHtmlFile(value, location) {
if (typeof value !== 'string') return value
if (!value.startsWith('./') && !value.startsWith('../')) return value

const cdsFile = resolve(cds.root, location.file)
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.

Bug: resolveHtmlFile crashes with TypeError when location is undefined

If def.$location is absent (e.g. in programmatically constructed models or certain CDS compiler outputs), location will be undefined. When the annotation value starts with ./ or ../, the code reaches location.file and throws TypeError: Cannot read properties of undefined (reading 'file').

Should guard against a missing location before dereferencing it.

Suggested change
function resolveHtmlFile(value, location) {
if (typeof value !== 'string') return value
if (!value.startsWith('./') && !value.startsWith('../')) return value
const cdsFile = resolve(cds.root, location.file)
function resolveHtmlFile(value, location) {
if (typeof value !== 'string') return value
if (!value.startsWith('./') && !value.startsWith('../')) return value
if (!location?.file) {
LOG._warn && LOG.warn(`Cannot resolve relative HTML path '${value}': no source location available`)
return value
}
const cdsFile = resolve(cds.root, location.file)
const htmlPath = resolve(dirname(cdsFile), value)
if (!existsSync(htmlPath)) {
LOG._warn && LOG.warn(`HTML file not found: ${htmlPath}`)
return value
}
return readFileSync(htmlPath, 'utf8')
}

Double-check suggestion before committing. Edit this comment for amendments.


Please provide feedback on the review comment by checking the appropriate box:

  • 🌟 Awesome comment, a human might have missed that.
  • ✅ Helpful comment
  • 🤷 Neutral
  • ❌ This comment is not helpful

Comment thread lib/content-deployment.js

const notificationTypes = [
...notificationTypesFromModel(model),
...readFile(filePath) ?? []
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.

Bug: Operator precedence causes spread of null/undefined instead of empty array

The expression ...readFile(filePath) ?? [] is parsed as ...(readFile(filePath) ?? []) only if readFile never returns null/undefined — but if filePath is an empty string '', readFile logs a warning and returns [], so this is safe in practice. However, the ?? has lower precedence than the spread operator, so the actual parse is (...readFile(filePath)) ?? [], which means the nullish coalescing never applies as intended and a null/undefined return from readFile would cause a runtime error spreading null.

Should wrap the expression in parentheses to ensure correct evaluation order.

Suggested change
...readFile(filePath) ?? []
...(readFile(filePath) ?? [])

Double-check suggestion before committing. Edit this comment for amendments.


Please provide feedback on the review comment by checking the appropriate box:

  • 🌟 Awesome comment, a human might have missed that.
  • ✅ Helpful comment
  • 🤷 Neutral
  • ❌ This comment is not helpful

@hyperspace-insights
Copy link
Copy Markdown
Contributor

Summary

The following content is AI-generated and provides a summary of the pull request:


Feat: Define Notification Types via CDS Annotations and Add Email Support

New Features

This pull request introduces a powerful new way to define notification types directly within your CDS models using @notification annotations. This significantly improves developer experience by co-locating notification definitions with your service events.

Key Enhancements:

  • CDS Annotations for Notifications: Define notification types, templates, descriptions, and navigation targets by annotating events in your .cds files. The plugin automatically discovers and registers them.
  • Email Delivery Channel: Full support for email notifications has been added. You can now configure email subjects and bodies for your notification types.
  • HTML Email Templates: The email body can be specified using an external HTML file path (e.g., ./email-template.html), which will be read and embedded during compilation.
  • i18n Support: Internationalization is now supported in annotation string values and within external HTML templates using the {i18n>key} syntax.
  • Automatic Registration: Notification types defined via annotations or JSON are now automatically registered and synced with the notification service on application startup in hybrid/production environments, simplifying deployment.
  • DX Improvements: The plugin now automatically injects a recipients element into annotated notification events, reducing boilerplate code.

Changes

The documentation has been completely rewritten to reflect these new features, using a bookshop example to illustrate the new capabilities.

  • lib/compile.js: (New) Introduces the core logic for compiling @notification annotations from CDS models into the required JSON structure. It handles i18n resolution and the loading of external HTML files for email bodies.
  • cds-plugin.js: Hooks into the CDS loaded and served lifecycle events to automatically inject recipients into annotated events, compile types from the model, and trigger the registration process on startup.
  • lib/build.js: The build task now intelligently discovers annotated events, merges them with any existing notification-types.json definitions, and writes a consolidated file to the build output.
  • README.md: Overhauled the documentation to explain the new annotation-based workflow, email configuration, and automatic registration, with updated examples.
  • CHANGELOG.md: Updated to list the comprehensive set of new features and fixes included in this change.
  • lib/notificationTypes.js & lib/utils.js: Refactored for better error handling and code style.
  • tests/: Added an extensive new test suite, including a bookshop integration test and new unit tests for the annotation compilation logic (compile.test.js) and plugin hooks (plugin.test.js).

  • 🔄 Regenerate and Update Summary
  • ✏️ Insert as PR Description (deletes this comment)
  • 🗑️ Delete comment
PR Bot Information

Version: 1.21.0

  • LLM: gemini-2.5-pro
  • Output Template: Default Template
  • Correlation ID: a1fd8159-c276-4391-8e4e-0a856cca8015
  • File Content Strategy: Full file content
  • Summary Prompt: Default Prompt
  • Event Trigger: pull_request.opened

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