Skip to content

Port extensibility customization guide to XTravels and add CDS-Oyster documentation and reference - #2917

Draft
nkaputnik wants to merge 17 commits into
mainfrom
port-extensibility-guide-to-xtravels
Draft

nkaputnik wants to merge 17 commits into
mainfrom
port-extensibility-guide-to-xtravels

Conversation

@nkaputnik

@nkaputnik nkaputnik commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

Port Extensibility Guides to XTravels

Documentation

📚 Updates the extensibility documentation to use the XTravels sample throughout and adds new code extensibility guides for sandboxed business logic extensions. The model customization walkthrough now focuses on extending sap.capire.travels.Travels with x_priority and x_CostCenter, including local setup, tenant activation, test data guidance, and refreshed UI verification screenshots.

Changes

  • guides/extensibility/customization.md: Reworked the customization guide from Orders/bookshop examples to XTravels, including multi-repo workspace setup, MTX sidecar subscription flow, extension template layout, local reference wiring, model-only extension examples, local vs shipped data guidance, and XTravels-specific UI annotations.
  • guides/extensibility/business-logic.md: Added a new guide for pre-defined business logic extension points using @sap/cds-oyster, covering provider setup, tenant handler implementation, local/wasm testing, push flow, and best practices.
  • guides/extensibility/business-logic-advanced.md: Added advanced guidance for opening regular services to controlled code extensions, including CRUD handlers, after-READ enrichment, cross-record validation, pagination, and safety recommendations.
  • guides/extensibility/code-extension.md: Added a sandbox reference covering engines, configuration, handler file layout, sandbox API, event scope, query constraints, forbidden constructs, quarantine behavior, and troubleshooting.
  • guides/extensibility/_menu.md: Added navigation entries for the new business logic and code extension documentation pages.
  • guides/extensibility/assets/*: Replaced superseded Orders screenshots with new XTravels screenshots for the base Travels list, extension template README, Fiori preview, and deployed tenant UI.

Images and Links

XTravels Travels List
XTravels Extension README
XTravels Fiori Preview Extension
XTravels Deployed Extension

  • 🔄 Regenerate and Update Summary
PR Bot Information

Version: 1.31.64

  • Correlation ID: 264dc780-bcda-11f1-810b-d179ffdc6203
  • Event Trigger: issue_comment.edited

Port the extensibility customization guide from the Orders/bookshop
sample to XTravels: model-only extension (x_priority + x_CostCenter),
multi-repo workspace setup, local multitenancy, and tenant subscription.

Regenerate all four screenshots against a running XTravels tenant:
- base Travels list
- extension project readme
- Fiori preview with Priority and Cost Center columns
- deployed tenant UI with Priority and Cost Center columns

Remove the superseded Orders screenshots.

@hyperspace-pr-bot hyperspace-pr-bot Bot left a comment •

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.

(deleted)

nkaputnik and others added 10 commits September 23, 2026 15:55
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
- Add Preferred Project Layout, Ship a Pre-Filled Base Model, and Make It
  Browsable subsections so a cloned template runs with npm install + cds watch.
- Add Seed External & Federated Data (@capire/common, S4 customers, flights):
  explain the minified base model, trim sap.common-Currencies.csv to
  code;symbol;name;descr, and don't seed Languages/Regions (no target table).
- Split reference wiring into its own section (Provide Reference Logic for
  Local Runs); renumber Extension Guides/Deploy accordingly.
- Purge comments from JSON code blocks; use VitePress line-highlight instead.
- Regenerate xtravels-deployed-ext and xtravels-ext-readme screenshots.
Extract the @sap/cds-oyster code-extension sandbox reference material into
a dedicated Code Extension Reference page (code-extension.md), mirroring the
multitenancy index.md/mtxs.md how+reference split. business-logic.md and
business-logic-advanced.md keep their walkthroughs and best practices, with
moved blocks replaced by short orientation stubs linking into the reference.

Also applies a house-style pass across all three pages (pre-defined, -ize
spelling, bare ## Introduction headings, no & in headings) and adds the new
page to _menu.md.
…ox debugging

business-logic.md:
- Document the generated JSDoc handler stub and how it drives code completion
- Note the mocked sandbox is debuggable in-process (cds watch --debug)

business-logic-advanced.md:
- Reframe before-CREATE around the verified declarative-vs-handler boundary:
  @mandatory/@assert.range/@assert.notNull/@readonly work in extensions only on
  added, defaulted fields; provider fields and @Assert:(case ...) constraints are
  rejected at push. Keep only the cross-record checks (customer lookup, budget).
- Replace the hand-rolled TravelLog audit trio with a pointer to
  @cap-js/change-tracking and a single after-CREATE emit('TravelCreated') example
- Swap TravelLog for CustomerPolicies + a TravelCreated event in the opened surface

code-extension.md:
- Add a Debugging in the mocked sandbox section and a troubleshooting row
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>

@hyperspace-pr-bot hyperspace-pr-bot Bot left a comment •

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.

(deleted)

nkaputnik and others added 3 commits September 30, 2026 16:10
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>

@hyperspace-pr-bot hyperspace-pr-bot Bot left a comment •

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.

(deleted)

Co-authored-by: hyperspace-pr-bot[bot] <209611008+hyperspace-pr-bot[bot]@users.noreply.github.com>
@hyperspace-pr-bot

hyperspace-pr-bot Bot commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Control Panel

Hi, I'm an AI-powered Review Bot that helps you with summarizing and reviewing pull requests.
To interact with me, just use the following actions:

  • 📝 Summarize PR
  • 🔍 Review
  • 🗑️ Delete all bot comments and reviews

@hyperspace-pr-bot

Copy link
Copy Markdown
Contributor

Summary

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


Update Extensibility Guides for XTravels and Code Extensions

Documentation

📚 Ports the extensibility customization walkthrough from the Orders sample to XTravels and expands the extensibility documentation with new code-extension guidance.

Changes

  • guides/extensibility/customization.md: Reworked the customization guide around XTravels, including multi-repo workspace setup, local multitenancy, tenant subscription, extension project templates, test/reference data guidance, and a model-only extension using x_priority and x_CostCenter.
  • guides/extensibility/business-logic.md: Added a new guide for pre-defined business logic extension points using @sap/cds-oyster, covering provider setup, subscriber handlers, local testing, sandbox verification, and push flow.
  • guides/extensibility/business-logic-advanced.md: Added advanced guidance for safely opening regular services to CRUD handlers, after-READ enrichment, cross-record validation, events, pagination, and extension-supply-chain considerations.
  • guides/extensibility/code-extension.md: Added a reference page for the code-extension sandbox, including configuration, handler layout, sandbox API, event scope, query rules, forbidden constructs, debugging, quarantine behavior, and troubleshooting.
  • guides/extensibility/_menu.md: Added navigation entries for the new business logic and code extension reference guides.
  • guides/extensibility/assets/*: Replaced superseded Orders screenshots with regenerated XTravels screenshots for the base list, extension README, local Fiori preview, and deployed tenant UI.

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

Version: 1.31.64

  • Summary Prompt: Default Prompt
  • Correlation ID: 227659b0-bcda-11f1-9296-c3cac77d1d8d
  • File Content Strategy: Full file content
  • Output Template: Default Template
  • Event Trigger: issue_comment.edited
  • LLM: gpt-5.5

@hyperspace-pr-bot hyperspace-pr-bot Bot left a comment

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.

I found a few substantive documentation issues that could mislead readers about CAP handler transaction timing and one template layout mismatch around db/data. The rest of the PR reads as a coherent port to XTravels with clear structure and useful examples.

PR Bot Information

Version: 1.31.64

Comment thread guides/extensibility/business-logic-advanced.md Outdated
Comment thread guides/extensibility/business-logic-advanced.md Outdated
Comment thread guides/extensibility/business-logic-advanced.md Outdated
Comment thread guides/extensibility/customization.md
…layout

after handlers run inside the request transaction (pre-commit), not
post-commit: a reject rolls back both the write and the handler's own
changes. Verified via a purpose-built test in cds-oyster under both the
mocked and wasm engines. Also show db/data in the template layout, which
the walkthrough creates for the shipped code list.

@hyperspace-pr-bot hyperspace-pr-bot Bot left a comment

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.

I posted a few targeted comments where the new docs could mislead readers about supported handler events or local test setup. The earlier transaction-boundary and template-layout comments appear to have been addressed, so I did not repeat them.

PR Bot Information

Version: 1.31.64


## CRUD Event Handler Scope {#crud}

Beyond the action and event handlers used for [pre-defined extension points](business-logic), opening an entity enables **before** and **after** handlers on its CRUD events (Create, Read, Update, Delete, Upsert). The full event scope (signatures, transaction semantics, and the `req.data` / `req.subject` / `req.results` each handler sees) is in [Code Extension Reference › Event Scope](code-extension#events). The handler-file convention and sandbox API are unchanged from [Part 1](code-extension#files).

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.

Clarity: This sentence implies before-READ handlers are supported

The reference page only lists before handlers for Create, Update, Upsert, and Delete, while Read is only listed for after. Readers may create before-READ.js handlers that do not match the documented sandbox surface.

Consider splitting the before and after scopes explicitly.

Suggested change
Beyond the action and event handlers used for [pre-defined extension points](business-logic), opening an entity enables **before** and **after** handlers on its CRUD events (Create, Read, Update, Delete, Upsert). The full event scope (signatures, transaction semantics, and the `req.data` / `req.subject` / `req.results` each handler sees) is in [Code Extension Reference › Event Scope](code-extension#events). The handler-file convention and sandbox API are unchanged from [Part 1](code-extension#files).
Beyond the action and event handlers used for [pre-defined extension points](business-logic), opening an entity enables **before** handlers on Create, Update, Upsert, and Delete, plus **after** handlers on Read, Create, Update, Upsert, and Delete. The full event scope (signatures, transaction semantics, and the `req.data` / `req.subject` / `req.results` each handler sees) is in [Code Extension Reference › Event Scope](code-extension#events). The handler-file convention and sandbox API are unchanged from [Part 1](code-extension#files).

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 on lines +84 to +88
├─ on-<action>.js # unbound action or event
└─ <EntityName>/
├─ before-<CUD>.js # before a Create/Update/Delete
├─ after-READ.js # after a Read
└─ on-<action>.js # bound action or event

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.

Clarity: Handler layout omits supported CRUD events

The event table below includes before Upsert and after Create, Update, Delete, and Upsert, but this tree only documents before-<CUD>.js and after-READ.js. Readers may not know how to name supported files such as after-CREATE.js.

Consider making the file pattern match the documented event scope.

Suggested change
├─ on-<action>.js # unbound action or event
└─ <EntityName>/
├─ before-<CUD>.js # before a Create/Update/Delete
├─ after-READ.js # after a Read
└─ on-<action>.js # bound action or event
├─ on-<action>.js # unbound action or event
└─ <EntityName>/
├─ before-<CUD|UPSERT>.js # before a Create/Update/Delete/Upsert
├─ after-<CRUD|UPSERT>.js # after a Create/Read/Update/Delete/Upsert
└─ on-<action>.js # bound action or event

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

Because the mocked sandbox runs your handler **in-process**, you can debug it like ordinary code. Start with `cds watch --debug` (or `--inspect-brk` to break on the first line), then set breakpoints straight in your handler file to step through and inspect `req`, `req.data`, and `this.entities`. The production `wasm` sandbox runs isolated, so breakpoints don't bind there — see [Debugging in the mocked sandbox](code-extension#debugging) for the full story.

::: tip Reproduce provider wiring locally
`cds pull` delivers the base *model*, not the provider's handler code, so the `before(submitForReview)` call that triggers your handler isn't present in a standalone run. Re-provide just that wiring in a read-only _srv/server.js_, exactly as described for [reference logic](customization#reference-wiring). On a real tenant this wiring is already there.

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.

Clarity: The referenced local wiring does not trigger submitForReview

The customization#reference-wiring example is model-only and stubs existing UI actions; it does not reconnect to TravelExtensionService or register the before(submitForReview) call needed for this code-extension test. Readers following it exactly will still have a handler that never fires locally.

Consider telling readers to adapt the reference pattern with the provider wiring shown earlier.

Suggested change
`cds pull` delivers the base *model*, not the provider's handler code, so the `before(submitForReview)` call that triggers your handler isn't present in a standalone run. Re-provide just that wiring in a read-only _srv/server.js_, exactly as described for [reference logic](customization#reference-wiring). On a real tenant this wiring is already there.
`cds pull` delivers the base *model*, not the provider's handler code, so the `before(submitForReview)` call that triggers your handler isn't present in a standalone run. Add a local-only _srv/server.js_ that reconnects to `TravelExtensionService` and registers the same `before(submitForReview)` handler shown in [Call the Extension Point](#wire); use the [reference logic](customization#reference-wiring) section only as the pattern for local wiring. On a real tenant this wiring is already there.

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

cds add ext-handler --filter validateReview
```

This writes _srv/TravelExtensionService/on-validateReview.js_ with a leading `#` in its name, marking it an **inactive** stub. Remove the `#` to activate it.

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.

Clarity: The generated inactive filename is shown without the leading #

The sentence says the file has a leading #, but the path shown is the active filename. This can make readers look for or rename the wrong file.

Consider showing the inactive filename explicitly.

Suggested change
This writes _srv/TravelExtensionService/on-validateReview.js_ with a leading `#` in its name, marking it an **inactive** stub. Remove the `#` to activate it.
This writes _srv/TravelExtensionService/#on-validateReview.js_, marking it an **inactive** stub. Remove the `#` to activate it.

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

@nkaputnik nkaputnik changed the title Port extensibility customization guide to XTravels Port extensibility customization guide to XTravels and add CDS-Oyster documentation and reference Oct 1, 2026

This branch has not been deployed

No deployments
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