A learning-focused SAP Cloud Application Programming Model (CAP) sample built on the Star Wars universe. Every feature in this repo exists to demonstrate a real production pattern — not just to make it run.
Jump to a learning track: Beginner · Intermediate · Advanced
| Path | Purpose |
|---|---|
db/schema.cds |
Domain model – entities, types, associations |
db/hana/ db/sqlite/ db/postgres/ |
Profile-specific model extensions |
srv/*-service.cds |
Service definitions – projections, actions, functions |
srv/*-fiori.cds |
Fiori/UI5 annotations (kept separate from service contracts) |
srv/episode-service.cds |
Read-only StarWarsEpisode service (OData v4, GraphQL, REST) |
srv/episode-fiori.cds |
Fiori annotations for the Episodes list |
srv/services-auth.cds |
Centralized authorization – @requires / @restrict |
srv/*.js |
Service handlers – before / on / after hooks |
test/ |
Automated tests by layer (model, service, handler) |
docs/ |
Architecture, learning path, cheat sheet, pitfalls |
labs/ |
Hands-on exercises with guided steps |
app/ |
Fiori web apps (People, Media, Film, Show) + launchpad (launchpadPage.html) |
../scripts/scraper/ |
Wookieepedia scraper — rate-limited MediaWiki API crawler |
../scripts/data/raw/ |
Scraped JSON output loaded by convertData.js |
Client (Fiori / REST / GraphQL)
│
▼
┌─────────────────────────────────────┐
│ CAP Service Layer (srv/) │
│ ┌────────────┐ ┌───────────────┐ │
│ │ *-service │ │ *-fiori.cds │ │
│ │ .cds │ │ (UI annot.) │ │
│ └────────────┘ └───────────────┘ │
│ ┌─────────────────────────────┐ │
│ │ *.js handler lifecycle │ │
│ │ before → on → after │ │
│ └─────────────────────────────┘ │
└─────────────────────────────────────┘
│
▼
┌─────────────────────────────────────┐
│ Domain Model (db/) │
│ schema.cds + profile extensions │
└─────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────┐
│ Persistence (profile-selected at runtime) │
│ SQLite (dev) · SAP HANA (prod) · PG │
└───────────────────────────────────────────┘
See docs/cap-architecture.md for the full annotated diagram.
Goal: understand CDS modeling and how CAP exposes it automatically.
| # | Task | Where to look |
|---|---|---|
| 1 | Read db/schema.cds — find entities, types, associations |
db/schema.cds |
| 2 | Start the app (npm run sqlite) and browse /odata/v4/StarWarsPeople/People |
people-service.cds |
| 3 | Open Swagger UI at http://localhost:4004/api-docs |
server.js |
| 4 | Understand how @mandatory, @assert.range, @assert.format work |
db/schema.cds |
| 5 | Find the Episode entity and its parent Show — notice the Composition of many |
db/schema.cds |
| 6 | Complete Lab 01 (add a new entity) | labs/lab-01-model/ |
| 7 | Open the Fiori launchpad at http://localhost:4004/launchpadPage.html and explore all four apps |
app/ |
Goal: understand service handlers, events, and custom operations.
| # | Task | Where to look |
|---|---|---|
| 1 | Trace the full before → on → after handler lifecycle for People |
people-service.js |
| 2 | Call the rename bound action via HTTP |
people-service.cds |
| 3 | Call the countByGender unbound function |
people-service.cds |
| 4 | Understand how notifications + domain events are emitted | people-service.js |
| 5 | Compare StarWarsEpisode (read-only, no .js handler) with StarWarsPeople (full lifecycle) |
episode-service.cds |
| 6 | Complete Lab 03 (add your own hook) | labs/lab-03-handler/ |
Goal: master authorization, testing by layer, and multi-profile deployment.
| # | Task | Where to look |
|---|---|---|
| 1 | Study the role matrix (Viewer / Editor / Admin) |
services-auth.cds |
| 2 | Read handler-level tests and understand what each layer tests | test/handler.test.js |
| 3 | Compare SQLite vs HANA vs PG behavior | docs/profile-comparison.md |
| 4 | Work through common pitfalls | docs/pitfalls.md |
| 5 | Complete Lab 04 (add role-based auth) | labs/lab-04-auth/ |
# Install dependencies
npm install
# Start with SQLite (no external services needed)
npm run sqlite
# Run all tests
npm run test
# Regenerate scraped Star Wars data (cache-first — fast from committed cache files)
npm run scrape
# Load Star Wars data into SQLite
npm run load_sqliteBrowse to http://localhost:4004 to see the service index, Swagger UI, and Fiori preview.
| Profile | Command | Database | Use when |
|---|---|---|---|
sqlite |
npm run sqlite |
SQLite (file) | Local development, no external services |
hybrid |
npm run watch |
SAP HANA HDI | Integrated local dev with HANA |
pg |
npm run pg |
PostgreSQL | PostgreSQL-based environments |
production |
cds-serve |
SAP HANA HDI | BTP production deployment |
See docs/profile-comparison.md for a full comparison of what changes between profiles.
cds.requires.queue: true— enables the persistent outbox queue for reliable event delivery.cds.requires.middlewares: true— enables the full CAP middleware chain (CORS, authentication, etc.).- PostgreSQL credentials are intentionally not hardcoded; provide them via
.env(seecap/.env).
npm run test # full model + handler test suite
npm run test:profile # fast profile-scoping regression gate (use in CI)
npm run test:migration # data conversion / migration tests| Resource | Link |
|---|---|
| CAP Architecture (this repo) | docs/cap-architecture.md |
| Learning Path | docs/learning-path.md |
| CAP Cheat Sheet | docs/cap-cheat-sheet.md |
| Profile Comparison | docs/profile-comparison.md |
| Common Pitfalls | docs/pitfalls.md |
| Hands-on Labs | labs/README.md |
| Official CAP Docs | https://cap.cloud.sap/docs/ |
- Breaking change: legacy value-help helper endpoints were removed in favor of
*Valuesentities. Update using docs/value-help-migration.md.