Compare commits

...

100 Commits

Author SHA1 Message Date
Dr. David A. Kunz
55c0190653 . 2025-07-10 12:04:45 +02:00
Dr. David A. Kunz
5716dece3f cosmetics 2025-07-10 12:04:07 +02:00
Olena
ef892b58e7 Merge branch 'main' into hierarch-draft-crud 2025-07-08 14:25:01 +02:00
dependabot[bot]
dcb0c0394a Bump the production-dependencies group across 1 directory with 2 updates (#845)
Bumps the production-dependencies group with 2 updates in the / directory: [@cap-js/hana](https://cap.cloud.sap/) and @sap/xssec.


Updates `@cap-js/hana` from 1.8.1 to 2.1.1

Updates `@sap/xssec` from 4.6.0 to 4.8.0

---
updated-dependencies:
- dependency-name: "@cap-js/hana"
  dependency-version: 2.1.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: production-dependencies
- dependency-name: "@sap/xssec"
  dependency-version: 4.8.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-08 09:53:54 +02:00
dependabot[bot]
c7d869ef62 Bump the development-dependencies group across 1 directory with 2 updates (#842)
Bumps the development-dependencies group with 2 updates in the / directory: [@cap-js/cds-test](https://github.com/cap-js/cds-test) and [@cap-js/sqlite](https://github.com/cap-js/cds-dbs).


Updates `@cap-js/cds-test` from 0.3.0 to 0.4.0
- [Release notes](https://github.com/cap-js/cds-test/releases)
- [Changelog](https://github.com/cap-js/cds-test/blob/main/CHANGELOG.md)
- [Commits](https://github.com/cap-js/cds-test/compare/v0.3.0...v0.4.0)

Updates `@cap-js/sqlite` from 1.10.0 to 2.0.1
- [Release notes](https://github.com/cap-js/cds-dbs/releases)
- [Changelog](https://github.com/cap-js/cds-dbs/blob/hana-v2.0.1/release-please-config.json)
- [Commits](https://github.com/cap-js/cds-dbs/compare/sqlite-v1.10.0...hana-v2.0.1)

---
updated-dependencies:
- dependency-name: "@cap-js/cds-test"
  dependency-version: 0.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
- dependency-name: "@cap-js/sqlite"
  dependency-version: 2.0.1
  dependency-type: direct:development
  update-type: version-update:semver-major
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-08 09:51:38 +02:00
Christian Georgi
991b672e53 chore(dependabot): ignore express 5 2025-07-08 09:49:20 +02:00
Christian Georgi
a7b4a23163 Remove Node 18 2025-07-08 09:45:19 +02:00
D070615
c175575840 rm node 18.x from workflow 2025-07-07 17:13:12 +02:00
D070615
c6cc70a062 fix redirect 2025-07-07 15:37:02 +02:00
D070615
7c33813102 redirect to fix test 2025-07-04 13:40:25 +02:00
D070615
ef9a891445 fix tests 2025-07-04 13:37:49 +02:00
Dr. David A. Kunz
8230757540 . 2025-07-03 13:14:07 +02:00
Dr. David A. Kunz
fe53798330 package-lock 2025-07-03 13:12:25 +02:00
D070615
3ca79efcfb add object page and manage genres 2025-07-03 11:20:18 +02:00
Olena
9c1d5280af Merge branch 'main' into hierarch-draft-crud 2025-07-03 10:33:00 +02:00
Olena
9b80311472 Merge pull request #840 from SAP-samples/hierarch-object-page
Fiori: Tree View Object Page
2025-07-02 16:15:26 +02:00
Heiko Witteborg
36d58664c9 Merge pull request #841 from SAP-samples/bookshop-tests
Fix: adjust IDs and size of Genre objects for testing
2025-07-02 11:34:12 +02:00
Dr. David A. Kunz
34f75b52c8 add children as composition 2025-06-26 13:36:03 +02:00
Eric Peairs
f8252207a0 Fix: adjust IDs and size of Genre objects for testing
Changed ID values of Genre objects to UUIDs and decreased depth of the POSTed Genre object to match the maximum depth of DELETE
2025-06-24 14:51:25 +02:00
D070615
aeb8bca9ac object page first version 2025-06-18 15:41:46 +02:00
Daniel Hutzel
600afb704a Fiori Tree Views towards GA (#839)
* Fiori Tree Views towards GA

* Also automate addition of Aggregation.RecursiveHierarchy

* Cleanup models for Genres Tree View

* Implementing @hierarchy shortcut

* .

* Formatting

* Using verbose config
2025-06-05 15:39:50 +02:00
Dr. David A. Kunz
044f513e16 . 2025-05-28 13:08:54 +02:00
Dr. David A. Kunz
6b15dbdd2e draft crud 2025-05-28 13:08:52 +02:00
Johannes Vogel
6fa2aaee34 fiori: rm unused hierarchy elements (#838) 2025-05-15 15:43:21 +02:00
Daniel Hutzel
987611b009 cosmetics 2025-05-14 14:09:13 +02:00
Daniel Hutzel
ce1da7fce9 cleanup deps in nested tests' package.jsons 2025-05-08 10:28:48 +02:00
Daniel Hutzel
395587b1bf fix: update SAP UI5 resource URLs to use the latest domain 2025-05-07 10:29:17 +02:00
Johannes Vogel
bab7827000 chore(deps): allow newer cap-js versions (#835) 2025-04-29 14:48:22 +02:00
Daniel Hutzel
efc2f3632f Moved app/routes back into srv/server, as cds build ignores the former 2025-04-28 06:55:35 +02:00
Daniel Hutzel
61ceb4a63a Removed TreeView fake handlers for SQLite 2025-04-28 06:07:40 +02:00
Daniel Hutzel
226ab2539e Using specific list of npm workspaces 2025-04-24 14:38:11 +02:00
Daniel Hutzel
56a9796329 . 2025-04-24 05:33:59 +02:00
Johannes Vogt
ece1962052 Merge pull request #834 from SAP-samples/shared-db-deps
add shared-db dependencies
2025-04-23 10:47:41 +02:00
Johannes Vogt
f90c43150a add shared-db dependencies 2025-04-23 09:42:50 +02:00
Johannes Vogel
7d170eed73 chore: use newest cloud sdk version (#829)
* chore: use newest cloud sdk version

* ci: use npm i instead of npm ci

* revert to npm ci

* update package-lock
2025-04-15 13:11:56 +00:00
Johannes Vogel
2b11b8b7e6 chore: prep for service restrictions by default (#828)
* chore: prep for service restrictions by default

* Revert "chore: prep for service restrictions by default"

This reverts commit 703cf79e11.

* disable auth checks

* without before hook

* early as possible

* rm line
2025-04-15 15:02:35 +02:00
Daniel Hutzel
b888a65381 Prepare for cds9 2025-04-14 18:13:27 +02:00
Johannes Vogel
75eec39a46 chore: reintroduce package-lock.json (#830) 2025-04-14 15:52:39 +02:00
Daniel Hutzel
339c87c55a Add node:test script to package.json for running Node.js tests 2025-04-02 19:14:49 +02:00
Daniel Hutzel
c81fd6e31e . 2025-04-02 19:09:48 +02:00
Daniel Hutzel
5263dbbb38 . 2025-04-02 19:04:43 +02:00
Daniel Hutzel
a79e07deed Add package-lock.json to .gitignore 2025-04-02 18:48:46 +02:00
Daniel Hutzel
62070bb851 rm package-lock.json 2025-04-02 18:48:06 +02:00
Olena
1ff53edf85 Fiori Tree Views (#816)
* add read only tree table and value help
* rm tree table in catalogservice
* Update cat-service.cds
* i18n and object page
* hana workaround, local messaging and rm virtual
* move hierarchy to fiori
* Update admin-service.cds

* Update common.cds

* fix after moving to fiori

* fix UI filter

* file-based-messaging in hybrid

* review fixes

* Update services.cds

* make bookshop Books fiori.draft.enabled

* add simplest handler for sqlite

* adapt test and link in csvs

* .

* Reverting to human-readable UUIDs :)

* Less obstrusive workaround

* typo

* Update fiori/app/common.cds

* Update fiori/app/common.cds

* Workaround for stupid GUID check in Fiori client

* ...

* Simplified mock support for recursive hierarchies in SQLite :)

* missing comma

* Rudimentary tree support for Genres on SQLite

* ?.

* fixed copy error

* using subselect to determine leafs

* Revert "using subselect to determine leafs"

This reverts commit f01ddaea1f.

* Using scalar subselect for DrillState

* .

---------

Co-authored-by: D070615 <olena.timrova@sap.com>
Co-authored-by: D045778 <johannes.vogel@sap.com>
Co-authored-by: Daniel Hutzel <daniel.hutzel@sap.com>
2025-04-02 13:00:32 +02:00
Vladislav Leonkev
cc1e8ffd54 deploy: rename shared-db model file (#826) 2025-04-01 13:48:34 +02:00
Vladislav Leonkev
38decb41dc Vue UIs: unstable unpkg - use jsdelivr (#825) 2025-03-31 17:23:57 +02:00
Daniel Hutzel
9451e3ff67 Eliminate usages of obsolete cds.tx(req) 2025-03-31 12:15:59 +02:00
Johannes Vogel
335d6bb53b skip expectation for next release (#824) 2025-03-31 10:08:14 +02:00
Vladislav Leonkev
31fbad4442 move UI sym-links to resources (#823) 2025-03-28 18:00:39 +01:00
Daniel Hutzel
4232ab1d3a chore: moving app-router to .deploy folder (#822)
* chore: moving app-router and mta.yaml to .deploy folder?

* reverted mta.yaml in .deploy

* chore: update package-lock.json

* Added guide about Micro Services with CAP

* updated package-lock.json

* Leaving mta.yaml in root

* .

* .

* .

* Remove Micro Services with CAP documentation
2025-03-28 11:46:19 +01:00
Daniel Hutzel
81557d5ad7 . 2025-03-28 10:50:02 +01:00
Daniel Hutzel
1c8b71fe1c Update readme.md 2025-03-27 09:29:27 +01:00
Daniel Hutzel
396fd050ef Update readme.md 2025-03-27 09:28:15 +01:00
Daniel Hutzel
9b5aa61a1f Update readme.md 2025-03-27 09:26:22 +01:00
Daniel Hutzel
f21fbae587 readme.md aktualisieren 2025-03-27 08:09:13 +01:00
Daniel Hutzel
919b811235 readme.md aktualisieren 2025-03-27 08:06:08 +01:00
Daniel Hutzel
4de60d6115 readme.md aktualisieren 2025-03-27 08:05:26 +01:00
Johannes Vogt
f0527e142f Merge pull request #821 from SAP-samples/fix-orders-app
Fix xs-app.json routes
2025-03-26 15:32:17 +01:00
Johannes Vogt
f65c71e930 Merge branch 'main' into fix-orders-app 2025-03-26 15:31:44 +01:00
Daniel Hutzel
45995bcfc5 chore: update package.json to include all files in etc directory 2025-03-26 12:10:26 +01:00
Daniel Hutzel
ef6c76f2d1 chore: rm @eslint/js and add scripts for jest and mocha 2025-03-26 12:09:37 +01:00
Johannes Vogt
62e9043119 move app symlinks to resources folder 2025-03-26 11:41:46 +01:00
Johannes Vogt
bfa20d0b49 make manage-orders app relative 2025-03-26 11:17:58 +01:00
Vladislav Leonkev
bfa1c174f1 deploy: skip local UI routes in production (#818) 2025-03-26 09:18:55 +00:00
Daniel Hutzel
fdb613a023 Update readme.md 2025-03-26 10:18:08 +01:00
Daniel Hutzel
4070c98f52 . 2025-03-26 10:00:20 +01:00
Daniel Hutzel
8f036f9bee . 2025-03-26 09:58:46 +01:00
Daniel Hutzel
7cb886b7e2 . 2025-03-26 09:58:19 +01:00
Daniel Hutzel
5bf70eb589 . 2025-03-26 09:57:56 +01:00
Daniel Hutzel
e55856d259 . 2025-03-26 09:38:33 +01:00
Daniel Hutzel
e983dbe56f . 2025-03-26 09:38:10 +01:00
Daniel Hutzel
6b5bbe8626 Add Jest command line configuration to VSCode settings 2025-03-26 09:13:01 +01:00
Daniel Hutzel
05fe6c4c17 Add start script to launch bookshop with cds watch --open 2025-03-26 09:12:38 +01:00
Daniel Hutzel
ebb2c2d064 Bump @sap/approuter version to ^20.0.0 in package.json (#819) 2025-03-26 07:54:52 +00:00
Daniel Hutzel
87c13e9654 Update README.md 2025-03-26 07:42:49 +01:00
Daniel Hutzel
59a3a639c4 Update README.md 2025-03-26 07:40:10 +01:00
Daniel Hutzel
817be8854a Update README.md 2025-03-26 07:38:05 +01:00
Daniel Hutzel
29382a18e9 Update README.md 2025-03-26 07:12:10 +01:00
Daniel Hutzel
6512367a2c Update README.md (#820) 2025-03-26 07:11:33 +01:00
Daniel Hutzel
0af0192818 . 2025-03-26 06:51:58 +01:00
Daniel Hutzel
23922c7f99 . 2025-03-26 06:51:01 +01:00
Daniel Hutzel
ef91e5e526 . 2025-03-26 00:51:01 +01:00
Daniel Hutzel
8ab5430a14 data-viewer as plugin 2025-03-26 00:49:59 +01:00
Christian Georgi
6c0520d83f Cleanup removed features 2025-03-21 09:56:44 +01:00
Christian Georgi
04eeab9217 Remove code tours from readme
They are not used...
2025-03-21 09:54:59 +01:00
Daniel Hutzel
7b92463394 Spring cleaning, part 2 (#813)
* Remove OData v2 show case: Genres TreeView
* Refactored bookstore and fiori services: consolidate routing and remove deprecated files
* Add Jest configuration file with silent mode enabled
* Refactor test files: streamline imports and remove redundant code
* Change price field type to Price for better clarity and precision
* Example for separation of concerns: access-control.cds
2025-03-21 09:48:11 +01:00
Vladislav Leonkev
737e766d53 Deploy on BTP (#793)
minimal changes required to deploy the CAP samples in _shared db_ mode:
- db: all bookshop, orders, reviews CDS models into one db instance (_shared-db_)
- services: bookstore, orders, reviews
- approuter with UI symlinks:
  - Vue: bookshop, reviews
  - Fiori: orders
 - authentification: xsuaa
 - messaging: Event Mesh
 - destinations: orders, reviews
- cds:
  - projection OrdersNoDraft for backend direct access
  - event OrderChanged
- deployment: mta.yml
2025-03-20 09:36:16 +01:00
dependabot[bot]
ac4154eef3 Bump @sap/cds from 8.8.1 to 8.8.2 in the production-dependencies group (#814)
Bumps the production-dependencies group with 1 update: [@sap/cds](https://cap.cloud.sap/).


Updates `@sap/cds` from 8.8.1 to 8.8.2

---
updated-dependencies:
- dependency-name: "@sap/cds"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-18 16:58:51 +01:00
Daniel Schlachter
49a4dfc988 Simplify setup instructions (#807)
- link directly to the initial setup section in capire, instead of the getting started guide with a different sample.
- remove installation section here, as it's a duplicate to the capire section

---------

Co-authored-by: Christian Georgi <chgeo@users.noreply.github.com>
2025-03-12 11:02:08 +01:00
Christian Georgi
af3e905866 Use cds-test package (#812)
Replacing chai et al.
2025-03-12 10:51:49 +01:00
Daniel Hutzel
aee2f35327 Update README.md (#811) 2025-03-12 10:44:00 +01:00
Daniel Hutzel
bbaaefae5b Spring Cleaning → removing obsolete stuff, and moved non-app things to ./etc (#810)
* Remove obsolete stuff, and moved non-app things to ./etc
* remove test
* Update package-lock

---------

Co-authored-by: Christian Georgi <christian.georgi@sap.com>
2025-03-12 10:37:47 +01:00
Christian Georgi
c1dbe94c64 Handle singleton results in data viewer 2025-03-12 10:23:46 +01:00
dependabot[bot]
5e161d1564 Bump the production-dependencies group across 1 directory with 2 updates (#808)
Bumps the production-dependencies group with 2 updates in the / directory: [@sap/cds](https://cap.cloud.sap/) and [@cap-js-community/odata-v2-adapter](https://github.com/cap-js-community/odata-v2-adapter).


Updates `@sap/cds` from 8.6.1 to 8.8.1

Updates `@cap-js-community/odata-v2-adapter` from 1.14.0 to 1.14.2
- [Release notes](https://github.com/cap-js-community/odata-v2-adapter/releases)
- [Changelog](https://github.com/cap-js-community/odata-v2-adapter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/cap-js-community/odata-v2-adapter/compare/v1.14.0...v1.14.2)

---
updated-dependencies:
- dependency-name: "@sap/cds"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: "@cap-js-community/odata-v2-adapter"
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-11 14:13:40 +00:00
dependabot[bot]
7536a30313 Bump the development-dependencies group across 1 directory with 4 updates (#809)
Bumps the development-dependencies group with 4 updates in the / directory: [@cap-js/sqlite](https://github.com/cap-js/cds-dbs), [axios](https://github.com/axios/axios), [eslint](https://github.com/eslint/eslint) and [semver](https://github.com/npm/node-semver).


Updates `@cap-js/sqlite` from 1.7.8 to 1.9.0
- [Release notes](https://github.com/cap-js/cds-dbs/releases)
- [Changelog](https://github.com/cap-js/cds-dbs/blob/main/release-please-config.json)
- [Commits](https://github.com/cap-js/cds-dbs/compare/sqlite-v1.7.8...sqlite-v1.9.0)

Updates `axios` from 1.7.9 to 1.8.2
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.9...v1.8.2)

Updates `eslint` from 9.19.0 to 9.22.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.19.0...v9.22.0)

Updates `semver` from 7.6.3 to 7.7.1
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v7.6.3...v7.7.1)

---
updated-dependencies:
- dependency-name: "@cap-js/sqlite"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
- dependency-name: semver
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-03-11 15:11:44 +01:00
Ajinkya Patil
14ac3efaa1 Update dep5 2025-02-25 20:09:17 +01:00
Ajinkya Patil
9c476eb348 Adding the reuse badge 2025-02-25 20:08:49 +01:00
Daniel Hutzel
23bea0f629 cosmetics 2025-01-31 14:42:40 +01:00
dependabot[bot]
8c6ba30673 Bump the production-dependencies group across 1 directory with 3 updates (#790)
Bumps the production-dependencies group with 3 updates in the / directory: [@sap/cds](https://cap.cloud.sap/), [express](https://github.com/expressjs/express) and [@cap-js-community/odata-v2-adapter](https://github.com/cap-js-community/odata-v2-adapter).


Updates `@sap/cds` from 8.5.0 to 8.6.1

Updates `express` from 4.21.1 to 4.21.2
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/4.21.2/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.21.1...4.21.2)

Updates `@cap-js-community/odata-v2-adapter` from 1.13.8 to 1.14.0
- [Release notes](https://github.com/cap-js-community/odata-v2-adapter/releases)
- [Changelog](https://github.com/cap-js-community/odata-v2-adapter/blob/main/CHANGELOG.md)
- [Commits](https://github.com/cap-js-community/odata-v2-adapter/compare/v1.13.8...v1.14.0)

---
updated-dependencies:
- dependency-name: "@sap/cds"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
- dependency-name: express
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: production-dependencies
- dependency-name: "@cap-js-community/odata-v2-adapter"
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: production-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 13:27:56 +00:00
dependabot[bot]
06956b1077 Bump the development-dependencies group across 1 directory with 4 updates (#794)
Bumps the development-dependencies group with 4 updates in the / directory: [@cap-js/cds-types](https://github.com/cap-js/cds-types), [@cap-js/sqlite](https://github.com/cap-js/cds-dbs), [axios](https://github.com/axios/axios) and [eslint](https://github.com/eslint/eslint).


Updates `@cap-js/cds-types` from 0.8.0 to 0.9.0
- [Release notes](https://github.com/cap-js/cds-types/releases)
- [Changelog](https://github.com/cap-js/cds-types/blob/main/CHANGELOG.md)
- [Commits](https://github.com/cap-js/cds-types/compare/v0.8.0...v0.9.0)

Updates `@cap-js/sqlite` from 1.7.7 to 1.7.8
- [Release notes](https://github.com/cap-js/cds-dbs/releases)
- [Changelog](https://github.com/cap-js/cds-dbs/blob/main/release-please-config.json)
- [Commits](https://github.com/cap-js/cds-dbs/compare/sqlite-v1.7.7...sqlite-v1.7.8)

Updates `axios` from 1.7.8 to 1.7.9
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.7.8...v1.7.9)

Updates `eslint` from 9.16.0 to 9.19.0
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/main/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v9.16.0...v9.19.0)

---
updated-dependencies:
- dependency-name: "@cap-js/cds-types"
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
- dependency-name: "@cap-js/sqlite"
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: development-dependencies
- dependency-name: eslint
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: development-dependencies
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-01-27 14:26:02 +01:00
112 changed files with 6014 additions and 4332 deletions

2425
.deploy/app-router/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,9 @@
{
"name": "approuter",
"dependencies": {
"@sap/approuter": "^20.0.0"
},
"scripts": {
"start": "node node_modules/@sap/approuter/approuter.js"
}
}

View File

@@ -0,0 +1 @@
../../../bookshop/app/vue

View File

@@ -0,0 +1 @@
../../../orders/app/orders

View File

@@ -0,0 +1 @@
../../../reviews/app/vue

View File

@@ -0,0 +1,41 @@
{
"welcomeFile": "app/bookshop/index.html",
"routes": [
{
"source": "^/app/(.*)$",
"target": "$1",
"localDir": "resources",
"cacheControl": "no-cache, no-store, must-revalidate"
},
{
"source": "^/admin/(.*)$",
"target": "/admin/$1",
"destination": "bookstore-api",
"csrfProtection": true
},
{
"source": "^/browse/(.*)$",
"target": "/browse/$1",
"destination": "bookstore-api",
"csrfProtection": true
},
{
"source": "^/user/(.*)$",
"target": "/user/$1",
"destination": "bookstore-api",
"csrfProtection": true
},
{
"source": "^/odata/v4/orders/(.*)$",
"target": "/odata/v4/orders/$1",
"destination": "orders-api",
"csrfProtection": true
},
{
"source": "^/reviews/(.*)$",
"target": "/reviews/$1",
"destination": "reviews-api",
"csrfProtection": true
}
]
}

View File

@@ -18,3 +18,6 @@ updates:
- dependency-name: "chai-as-promised"
# chai-as-promised 8 doesn't work atm w/ cds.test, TODO fix that in cds.test
versions: ["8.x"]
- dependency-name: "express"
# express 5 not supported atm
versions: ["5.x"]

View File

@@ -15,7 +15,7 @@ jobs:
strategy:
matrix:
node-version: [22.x, 20.x, 18.x]
node-version: [22.x, 20.x]
steps:
- uses: actions/checkout@v4

3
.npmrc
View File

@@ -1,3 +0,0 @@
# Ensure we always use public packages, i.e. avoid using local registries from ~/.npmrc
@sap:registry=https://registry.npmjs.org/
registry=https://registry.npmjs.org/

View File

@@ -24,6 +24,6 @@ Disclaimer: The code in this project may include calls to APIs (“API Calls”)
you any rights to use or access any SAP External Product, or provide any third
parties the right to use of access any SAP External Product, through API Calls.
Files: *
Copyright: 2019-2020 SAP SE or an SAP affiliate company and cap-cloud-samples
Files: *.*
Copyright: 2019-2025 SAP SE or an SAP affiliate company and cap-cloud-samples
License: Apache-2.0

View File

@@ -1,117 +0,0 @@
{
"$schema": "https://aka.ms/codetour-schema",
"title": "Database Functions",
"steps": [
{
"title": "Introduction",
"description": "### Database Functions in CDS Models\n\nIn this tour, you'll learn how to add database-specific functions to CDS models in your application."
},
{
"file": "bookshop/db/schema.cds",
"description": "#### Basic Schema\n\nWe want to add two fields to the `Authors` entity, one for the author's age and one for the span of years that she or he lived.\n\nThese two fields can be computed out of the existing `dateOfBirth` and `dateOfDeath` fields.",
"selection": {
"start": {
"line": 19,
"character": 1
},
"end": {
"line": 21,
"character": 1
}
},
"title": "Base fields in Author"
},
{
"file": "bookshop/srv/admin-service.cds",
"description": "This is how the `Authors` entity gets exposed in an OData or REST service.\n\nIn the next step, you'll see how we extend this projection.",
"selection": {
"start": {
"line": 4,
"character": 1
},
"end": {
"line": 5,
"character": 1
}
},
"title": "Authors service"
},
{
"file": "fiori/db/sqlite/index.cds",
"description": "#### SQLite Implementation\n\nHere's the first implementation for SQLite. It computes the two fields `age` and `lifetime` through SQLite's [strftime](https://sqlite.org/lang_datefunc.html) function.\n\nThrough the [`extend projection`](https://cap.cloud.sap/docs/cds/cdl#extend-view) clause you can add additional fields to projection entities. These are deployed as database views, which is why we can integrate the database functions in the first place.\n",
"selection": {
"start": {
"line": 7,
"character": 1
},
"end": {
"line": 11,
"character": 1
}
},
"title": "SQLite implementation"
},
{
"file": "fiori/db/hana/index.cds",
"description": "#### SAP HANA Implementation\n\nThis is the second implementation for SAP HANA. It computes the same two fields `age` and `lifetime` through the [YEARS_BETWEEN](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/7c0d2c161ea34def86de3f5eadd6a0af.html) and [YEAR](https://help.sap.com/viewer/7c78579ce9b14a669c1f3295b0d8ca16/Cloud/en-US/20f5fac6751910148dabd3c6821f907d.html) functions of SAP HANA.\n\n#### File Layout and Code Structure\n\nNote the path of the `.cds` file we are in: it's in a subfolder of `db`, so that it's _not_ automatically picked up when we start the application. The same is true for the SQLite implementation: it's in a separate `db/sqlite/` folder as well. In the next step, you'll see how these files are loaded.\n\nAlso, we choose to implement all of that as an extension of the original bookshop here in the _fiori_ package. See the first [CAP Samples] code tour for more details on the different packages of this repository.",
"selection": {
"start": {
"line": 7,
"character": 1
},
"end": {
"line": 11,
"character": 1
}
},
"title": "SAP HANA implementation"
},
{
"file": "fiori/package.json",
"description": "#### Configuration\n\nThe `cds.requires` section in `package.json` is a place to configure which of the `db/sqlite` and `db/hana` folders are used for which database.\n\nWe use [Node.js profiles](https://cap.cloud.sap/docs/node.js/cds-env#profiles) to separate the configuration.\nIn the `development` profile, you can see that `db/sqlite` is set as the model, while the `db/hana` folder is configured in the `production` profile. `db-ext` is a pseudo datasource, its name doesn't matter.\n\nSee [`cds.resolve`](https://cap.cloud.sap/docs/node.js/cds-compile#cds-resolve) to learn more about how models are found.",
"selection": {
"start": {
"line": 41,
"character": 1
},
"end": {
"line": 48,
"character": 1
}
},
"title": "Configuration"
},
{
"file": "fiori/package.json",
"description": "#### Run with SQLite\n\nTo run with `development` and an in-memory SQLite database, you don't need to do anything special, because it's activated by default. Just run:\n\n>> cds watch fiori\n\nThen open [http://localhost:4004/admin/Authors](http://localhost:4004/admin/Authors) to see the two new fields.\n",
"line": 43,
"title": "Run with SQLite"
},
{
"file": "fiori/package.json",
"description": "#### Deploy the CDS Model to SAP HANA\n\nTo 'activate' SAP HANA through the `production` profile, you can use the global `--production` flag:\n\n>> cd fiori; cds deploy --to hana --production\n\n[Learn more about SAP HANA deployment](https://cap.cloud.sap/docs/guides/databases#get-hana)\n\n#### Run the Application\n\n>> cd fiori; cds watch --production\n\nThe service on [http://localhost:4004/admin/Authors](http://localhost:4004/admin/Authors) is the same as before, but this time the `Authors` entity is backed by a database view with an SAP HANA function.\n\n#### More\n\nIf you don't see data, you can add some in the next step.",
"line": 46,
"title": "Run with SAP HANA"
},
{
"file": "fiori/test/requests.http",
"description": "### Add More Data\n\nOptionally you can add some `Authors` data by clicking on the _Send Request_ link (provided by the [REST client](https://marketplace.visualstudio.com/items?itemName=humao.rest-client) extension).",
"line": 72,
"selection": {
"start": {
"line": 67,
"character": 1
},
"end": {
"line": 73,
"character": 1
}
},
"title": "Add Data"
},
{
"title": "Wrap-up",
"description": "### Summary\n\nThat's it! You have seen: \n- How to integrate database-specific functions in a CDS model.\n- How to switch between the two implementations for SQLite and SAP HANA."
}
]
}

View File

@@ -1,139 +0,0 @@
{
"$schema": "https://aka.ms/codetour-schema",
"title": "CAP Samples",
"steps": [
{
"title": "Welcome",
"file": "README.md",
"description": "### Welcome to CAP Samples!\n\nThis tour leads you through a collection of samples for the [SAP Cloud Application Programming Model (CAP)](https://cap.cloud.sap).\nYou will learn which features of the programming model are demonstrated in which sample.\n\nLet's start!",
"line": 2,
"selection": {
"start": {
"line": 1,
"character": 1
},
"end": {
"line": 3,
"character": 108
}
}
},
{
"file": "hello/srv/world.cds",
"description": "### Hello World!\n\nThis is a simplistic [Hello World](https://cap.cloud.sap/docs/get-started/hello-world) service using [CDS](https://cap.cloud.sap/docs/cds/) and [cds.services](https://cap.cloud.sap/docs/node.js/api#services-api).",
"line": 2,
"selection": {
"start": {
"line": 1,
"character": 1
},
"end": {
"line": 4,
"character": 1
}
},
"title": "Hello World!"
},
{
"file": "bookshop/db/schema.cds",
"description": "### A Bookshop!\n\nIntroduces:\n- [Project Setup](https://cap.cloud.sap/docs/get-started/) and [Layouts](https://cap.cloud.sap/docs/get-started/projects)\n- [Domain Modeling](https://cap.cloud.sap/docs/guides/domain-models)\n- [Defining Services](https://cap.cloud.sap/docs/guides/providing-services)\n- [Generic Providers](https://cap.cloud.sap/docs/guides/generic-providers)\n- [Adding Custom Logic](https://cap.cloud.sap/docs/guides/service-impl)\n- [Using Databases](https://cap.cloud.sap/docs/guides/databases)\n",
"line": 1,
"selection": {
"start": {
"line": 1,
"character": 1
},
"end": {
"line": 32,
"character": 1
}
},
"title": "Bookshop"
},
{
"file": "common/index.cds",
"description": "### Extend and Reuse\n\nShowcases how to extend [@sap/cds/common](https://cap.cloud.sap/docs/cds/common) thereby covering:\n- Building [extension packages](https://cap.cloud.sap/docs/guides/domain-models#aspects-extensibility)\n- Providing [reuse packages](https://cap.cloud.sap/docs/get-started/projects#sharing-and-reusing-content)\n- [Verticalization](https://cap.cloud.sap/docs/cds/common#adapting-to-your-needs)\n- Using [Aspects](https://cap.cloud.sap/docs/cds/cdl#aspects)\n- Used in the [fiori app sample](#fiori)\n",
"line": 1,
"selection": {
"start": {
"line": 1,
"character": 1
},
"end": {
"line": 46,
"character": 1
}
},
"title": "Common"
},
{
"file": "orders/db/schema.cds",
"description": "### Orders - Compositions and Serving Documents\n\nA standalone orders management service, demonstrating:\n- Using [Compositions](https://cap.cloud.sap/docs/cds/cdl#compositions) in [Domain Models](https://cap.cloud.sap/docs/guides/domain-models), along with\n- [Serving deeply nested documents](https://cap.cloud.sap/docs/guides/generic-providers#serving-structured-data)\n",
"line": 1,
"selection": {
"start": {
"line": 1,
"character": 1
},
"end": {
"line": 27,
"character": 1
}
},
"title": "Orders"
},
{
"file": "reviews/db/schema.cds",
"description": "### Reviews - More Modularity\n\nShows how to implement a modular service to manage product reviews, including:\n- Consuming other services synchronously and asynchronously\n- Serving requests synchronously\n- Emitting events asynchronously\n- Grow as you go, with:\n- Mocking app services\n- Running service meshes\n- Late-cut Micro Services\n- As well as managed data, input validations, and authorization\n",
"line": 1,
"selection": {
"start": {
"line": 1,
"character": 1
},
"end": {
"line": 39,
"character": 1
}
},
"title": "Reviews"
},
{
"title": "Bookstore",
"description": "### Bookstore - Reuse and UI\n\n- A [composite app, reusing and combining](https://cap.cloud.sap/docs/guides/reuse-and-compose) these packages:\n - [@capire/bookshop](bookshop)\n - [@capire/reviews](reviews)\n - [@capire/orders](orders)\n - [@capire/common](common)\n- [The Vue.js app](bookshop/app/vue) imported from bookshop is served as well\n- [The Vue.js app](reviews/app/vue) imported from reviews is served as well\n- [The Fiori app](orders/app) imported from orders is served as well\n- [OpenAPI export + Swagger UI](https://cap.cloud.sap/docs/advanced/openapi)"
},
{
"file": "fiori/app/services.cds",
"description": "### Annotations for SAP Fiori Elements\n\nAdds an SAP Fiori elements application to bookstore, thereby introducing:\n- OData Annotations in `.cds` files\n- Support for Fiori Draft\n- Support for Value Helps\n- Serving SAP Fiori apps locally\n\nSee the [Serving Fiori UIs](https://cap.cloud.sap/docs/advanced/fiori) documentation for more information.",
"line": 1,
"selection": {
"start": {
"line": 1,
"character": 1
},
"end": {
"line": 13,
"character": 1
}
},
"title": "Fiori"
},
{
"file": "package.json",
"description": "### All-in-one Monorepo\n\nEach sample sub directory essentially is a standard npm package, some with standard npm dependencies to other samples. The root folder's [package.json](package.json) has local links to the sub folders, such that an `npm install` populates a local `node_modules` folder acts like a local npm registry to the individual sample packages.\n",
"selection": {
"start": {
"line": 8,
"character": 1
},
"end": {
"line": 16,
"character": 1
}
},
"title": "Packages"
}
],
"isPrimary": true,
"description": "Overview of CAP Samples for Node.js"
}

View File

@@ -9,8 +9,6 @@
"dbaeumer.vscode-eslint",
"mechatroner.rainbow-csv",
"humao.rest-client",
"sdras.night-owl",
"vsls-contrib.codetour"
],
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
"unwantedRecommendations": [

10
.vscode/settings.json vendored
View File

@@ -1,9 +1,8 @@
{
"files.exclude": {
".reuse/**": true,
"**/.gitignore": true,
"**/.vscode": true,
"LICENSES/**": true
"**/node_modules": true,
"LICENSES": true,
".reuse": true
},
"debug.javascript.terminalOptions": {
"skipFiles": [
@@ -13,5 +12,6 @@
"**/cds/lib/req/cds-context.js",
"**/odata-v4/okra/**"
]
}
},
"jest.jestCommandLine": "npx jest"
}

View File

@@ -1,75 +0,0 @@
# Welcome to cap/samples
Find here a collection of samples for the [SAP Cloud Application Programming Model](https://cap.cloud.sap) organized in a simplistic [monorepo setup](samples.md#all-in-one-monorepo).
[See **Overview** of contained samples](samples.md):
![](etc/samples.drawio.svg)
![](https://github.com/SAP-samples/cloud-cap-samples/workflows/CI/badge.svg)
[![REUSE status](https://api.reuse.software/badge/github.com/SAP-samples/cloud-cap-samples)](https://api.reuse.software/info/github.com/SAP-samples/cloud-cap-samples)
### Preliminaries
1. Ensure you have the latest LTS version of Node.js installed (see [Getting Started](https://cap.cloud.sap/docs/get-started/jumpstart))
2. Install [**@sap/cds-dk**](https://cap.cloud.sap/docs/get-started/) globally:
```sh
npm i -g @sap/cds-dk
```
3. _Optional:_ [Use Visual Studio Code](https://cap.cloud.sap/docs/get-started/tools#vscode)
### Download
If you've [Git](https://git-scm.com/downloads) installed, clone this repo as shown below, otherwise [download as ZIP file](archive/main.zip).
```sh
git clone https://github.com/sap-samples/cloud-cap-samples samples
cd samples
```
### Setup
In the samples folder run:
```sh
npm ci
```
### Run
With that you're ready to run the samples, for example:
```sh
cds watch bookshop
```
After that open this link in your browser: [http://localhost:4004](http://localhost:4004)
When asked to log in, type `alice` as user and leave the password field blank, which is the [default user](https://cap.cloud.sap/docs/node.js/authentication#mocked).
### Testing
Run the provided tests with [_jest_](http://jestjs.io) or [_mocha_](http://mochajs.org), for example:
```sh
npx jest
```
> While mocha is a bit smaller and faster, jest runs tests in parallel and isolation, which allows to run all tests.
## Code Tours
Take one of the [guided tours](.tours) in VS Code through our CAP samples and learn which CAP features are showcased by the different parts of the repository. Just install the [CodeTour extension](https://marketplace.visualstudio.com/items?itemName=vsls-contrib.codetour) for VS Code. We'll add more code tours in the future. Stay tuned!
## Get Support
Check out the documentation at [https://cap.cloud.sap](https://cap.cloud.sap). <br>
In case you've a question, find a bug, or otherwise need support, use our [community](https://answers.sap.com/tags/9f13aee1-834c-4105-8e43-ee442775e5ce) to get more visibility.
## License
Copyright (c) 2022 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, version 2.0 except as noted otherwise in the [LICENSE](LICENSE) file.

View File

@@ -3,7 +3,7 @@
<head>
<title> Capire Books </title>
<link rel="stylesheet" href="https://unpkg.com/primitive-ui/dist/css/main.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/primitive-ui/dist/css/main.css">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
<style>

View File

@@ -1,6 +1,6 @@
ID,title,descr,author_ID,stock,price,currency_code,genre_ID
201,Wuthering Heights,"Wuthering Heights, Emily Brontë's only novel, was published in 1847 under the pseudonym ""Ellis Bell"". It was written between October 1845 and June 1846. Wuthering Heights and Anne Brontë's Agnes Grey were accepted by publisher Thomas Newby before the success of their sister Charlotte's novel Jane Eyre. After Emily's death, Charlotte edited the manuscript of Wuthering Heights and arranged for the edited version to be published as a posthumous second edition in 1850.",101,12,11.11,GBP,11
207,Jane Eyre,"Jane Eyre /ɛər/ (originally published as Jane Eyre: An Autobiography) is a novel by English writer Charlotte Brontë, published under the pen name ""Currer Bell"", on 16 October 1847, by Smith, Elder & Co. of London. The first American edition was published the following year by Harper & Brothers of New York. Primarily a bildungsroman, Jane Eyre follows the experiences of its eponymous heroine, including her growth to adulthood and her love for Mr. Rochester, the brooding master of Thornfield Hall. The novel revolutionised prose fiction in that the focus on Jane's moral and spiritual development is told through an intimate, first-person narrative, where actions and events are coloured by a psychological intensity. The book contains elements of social criticism, with a strong sense of Christian morality at its core and is considered by many to be ahead of its time because of Jane's individualistic character and how the novel approaches the topics of class, sexuality, religion and feminism.",107,11,12.34,GBP,11
251,The Raven,"""The Raven"" is a narrative poem by American writer Edgar Allan Poe. First published in January 1845, the poem is often noted for its musicality, stylized language, and supernatural atmosphere. It tells of a talking raven's mysterious visit to a distraught lover, tracing the man's slow fall into madness. The lover, often identified as being a student, is lamenting the loss of his love, Lenore. Sitting on a bust of Pallas, the raven seems to further distress the protagonist with its constant repetition of the word ""Nevermore"". The poem makes use of folk, mythological, religious, and classical references.",150,333,13.13,USD,16
252,Eleonora,"""Eleonora"" is a short story by Edgar Allan Poe, first published in 1842 in Philadelphia in the literary annual The Gift. It is often regarded as somewhat autobiographical and has a relatively ""happy"" ending.",150,555,14,USD,15
271,Catweazle,"Catweazle is a British fantasy television series, starring Geoffrey Bayldon in the title role, and created by Richard Carpenter for London Weekend Television. The first series, produced and directed by Quentin Lawrence, was screened in the UK on ITV in 1970. The second series, directed by David Reid and David Lane, was shown in 1971. Each series had thirteen episodes, most but not all written by Carpenter, who also published two books based on the scripts.",170,22,150,JPY,13
201,Wuthering Heights,"Wuthering Heights, Emily Brontë's only novel, was published in 1847 under the pseudonym ""Ellis Bell"". It was written between October 1845 and June 1846. Wuthering Heights and Anne Brontë's Agnes Grey were accepted by publisher Thomas Newby before the success of their sister Charlotte's novel Jane Eyre. After Emily's death, Charlotte edited the manuscript of Wuthering Heights and arranged for the edited version to be published as a posthumous second edition in 1850.",101,12,11.11,GBP,11aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
207,Jane Eyre,"Jane Eyre /ɛər/ (originally published as Jane Eyre: An Autobiography) is a novel by English writer Charlotte Brontë, published under the pen name ""Currer Bell"", on 16 October 1847, by Smith, Elder & Co. of London. The first American edition was published the following year by Harper & Brothers of New York. Primarily a bildungsroman, Jane Eyre follows the experiences of its eponymous heroine, including her growth to adulthood and her love for Mr. Rochester, the brooding master of Thornfield Hall. The novel revolutionised prose fiction in that the focus on Jane's moral and spiritual development is told through an intimate, first-person narrative, where actions and events are coloured by a psychological intensity. The book contains elements of social criticism, with a strong sense of Christian morality at its core and is considered by many to be ahead of its time because of Jane's individualistic character and how the novel approaches the topics of class, sexuality, religion and feminism.",107,11,12.34,GBP,11aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
251,The Raven,"""The Raven"" is a narrative poem by American writer Edgar Allan Poe. First published in January 1845, the poem is often noted for its musicality, stylized language, and supernatural atmosphere. It tells of a talking raven's mysterious visit to a distraught lover, tracing the man's slow fall into madness. The lover, often identified as being a student, is lamenting the loss of his love, Lenore. Sitting on a bust of Pallas, the raven seems to further distress the protagonist with its constant repetition of the word ""Nevermore"". The poem makes use of folk, mythological, religious, and classical references.",150,333,13.13,USD,16aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
252,Eleonora,"""Eleonora"" is a short story by Edgar Allan Poe, first published in 1842 in Philadelphia in the literary annual The Gift. It is often regarded as somewhat autobiographical and has a relatively ""happy"" ending.",150,555,14,USD,15aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
271,Catweazle,"Catweazle is a British fantasy television series, starring Geoffrey Bayldon in the title role, and created by Richard Carpenter for London Weekend Television. The first series, produced and directed by Quentin Lawrence, was screened in the UK on ITV in 1970. The second series, directed by David Reid and David Lane, was shown in 1971. Each series had thirteen episodes, most but not all written by Carpenter, who also published two books based on the scripts.",170,22,150,JPY,13aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
1 ID title descr author_ID stock price currency_code genre_ID
2 201 Wuthering Heights Wuthering Heights, Emily Brontë's only novel, was published in 1847 under the pseudonym "Ellis Bell". It was written between October 1845 and June 1846. Wuthering Heights and Anne Brontë's Agnes Grey were accepted by publisher Thomas Newby before the success of their sister Charlotte's novel Jane Eyre. After Emily's death, Charlotte edited the manuscript of Wuthering Heights and arranged for the edited version to be published as a posthumous second edition in 1850. 101 12 11.11 GBP 11 11aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
3 207 Jane Eyre Jane Eyre /ɛər/ (originally published as Jane Eyre: An Autobiography) is a novel by English writer Charlotte Brontë, published under the pen name "Currer Bell", on 16 October 1847, by Smith, Elder & Co. of London. The first American edition was published the following year by Harper & Brothers of New York. Primarily a bildungsroman, Jane Eyre follows the experiences of its eponymous heroine, including her growth to adulthood and her love for Mr. Rochester, the brooding master of Thornfield Hall. The novel revolutionised prose fiction in that the focus on Jane's moral and spiritual development is told through an intimate, first-person narrative, where actions and events are coloured by a psychological intensity. The book contains elements of social criticism, with a strong sense of Christian morality at its core and is considered by many to be ahead of its time because of Jane's individualistic character and how the novel approaches the topics of class, sexuality, religion and feminism. 107 11 12.34 GBP 11 11aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
4 251 The Raven "The Raven" is a narrative poem by American writer Edgar Allan Poe. First published in January 1845, the poem is often noted for its musicality, stylized language, and supernatural atmosphere. It tells of a talking raven's mysterious visit to a distraught lover, tracing the man's slow fall into madness. The lover, often identified as being a student, is lamenting the loss of his love, Lenore. Sitting on a bust of Pallas, the raven seems to further distress the protagonist with its constant repetition of the word "Nevermore". The poem makes use of folk, mythological, religious, and classical references. 150 333 13.13 USD 16 16aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
5 252 Eleonora "Eleonora" is a short story by Edgar Allan Poe, first published in 1842 in Philadelphia in the literary annual The Gift. It is often regarded as somewhat autobiographical and has a relatively "happy" ending. 150 555 14 USD 15 15aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa
6 271 Catweazle Catweazle is a British fantasy television series, starring Geoffrey Bayldon in the title role, and created by Richard Carpenter for London Weekend Television. The first series, produced and directed by Quentin Lawrence, was screened in the UK on ITV in 1970. The second series, directed by David Reid and David Lane, was shown in 1971. Each series had thirteen episodes, most but not all written by Carpenter, who also published two books based on the scripts. 170 22 150 JPY 13 13aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa

View File

@@ -1,5 +1,5 @@
ID,locale,title,descr
201,de,Sturmhöhe,"Sturmhöhe (Originaltitel: Wuthering Heights) ist der einzige Roman der englischen Schriftstellerin Emily Brontë (18181848). Der 1847 unter dem Pseudonym Ellis Bell veröffentlichte Roman wurde vom viktorianischen Publikum weitgehend abgelehnt, heute gilt er als ein Klassiker der britischen Romanliteratur des 19. Jahrhunderts."
201,fr,Les Hauts de Hurlevent,"Les Hauts de Hurlevent (titre original : Wuthering Heights), parfois orthographié Les Hauts de Hurle-Vent, est l'unique roman d'Emily Brontë, publié pour la première fois en 1847 sous le pseudonyme dEllis Bell. Loin d'être un récit moralisateur, Emily Brontë achève néanmoins le roman dans une atmosphère sereine, suggérant le triomphe de la paix et du Bien sur la vengeance et le Mal."
207,de,Jane Eyre,"Jane Eyre. Eine Autobiographie (Originaltitel: Jane Eyre. An Autobiography), erstmals erschienen im Jahr 1847 unter dem Pseudonym Currer Bell, ist der erste veröffentlichte Roman der britischen Autorin Charlotte Brontë und ein Klassiker der viktorianischen Romanliteratur des 19. Jahrhunderts. Der Roman erzählt in Form einer Ich-Erzählung die Lebensgeschichte von Jane Eyre (ausgesprochen /ˌdʒeɪn ˈɛə/), die nach einer schweren Kindheit eine Stelle als Gouvernante annimmt und sich in ihren Arbeitgeber verliebt, jedoch immer wieder um ihre Freiheit und Selbstbestimmung kämpfen muss. Als klein, dünn, blass, stets schlicht dunkel gekleidet und mit strengem Mittelscheitel beschrieben, gilt die Heldin des Romans Jane Eyre nicht zuletzt aufgrund der Kino- und Fernsehversionen der melodramatischen Romanvorlage als die bekannteste englische Gouvernante der Literaturgeschichte"
252,de,Eleonora,"“Eleonora” ist eine Erzählung von Edgar Allan Poe. Sie wurde 1841 erstveröffentlicht. In ihr geht es um das Paradox der Treue in der Treulosigkeit."
ID_texts,ID,locale,title,descr
d2a65a27-9f2a-480f-bc38-84ee8ec5c13e,201,de,Sturmhöhe,"Sturmhöhe (Originaltitel: Wuthering Heights) ist der einzige Roman der englischen Schriftstellerin Emily Brontë (18181848). Der 1847 unter dem Pseudonym Ellis Bell veröffentlichte Roman wurde vom viktorianischen Publikum weitgehend abgelehnt, heute gilt er als ein Klassiker der britischen Romanliteratur des 19. Jahrhunderts."
8c42c706-a979-41cf-9ffe-91e6cf1383a0,201,fr,Les Hauts de Hurlevent,"Les Hauts de Hurlevent (titre original : Wuthering Heights), parfois orthographié Les Hauts de Hurle-Vent, est l'unique roman d'Emily Brontë, publié pour la première fois en 1847 sous le pseudonyme dEllis Bell. Loin d'être un récit moralisateur, Emily Brontë achève néanmoins le roman dans une atmosphère sereine, suggérant le triomphe de la paix et du Bien sur la vengeance et le Mal."
9e1c4c81-dc90-4600-85b1-e9dd4bf12ce0,207,de,Jane Eyre,"Jane Eyre. Eine Autobiographie (Originaltitel: Jane Eyre. An Autobiography), erstmals erschienen im Jahr 1847 unter dem Pseudonym Currer Bell, ist der erste veröffentlichte Roman der britischen Autorin Charlotte Brontë und ein Klassiker der viktorianischen Romanliteratur des 19. Jahrhunderts. Der Roman erzählt in Form einer Ich-Erzählung die Lebensgeschichte von Jane Eyre (ausgesprochen /ˌdʒeɪn ˈɛə/), die nach einer schweren Kindheit eine Stelle als Gouvernante annimmt und sich in ihren Arbeitgeber verliebt, jedoch immer wieder um ihre Freiheit und Selbstbestimmung kämpfen muss. Als klein, dünn, blass, stets schlicht dunkel gekleidet und mit strengem Mittelscheitel beschrieben, gilt die Heldin des Romans Jane Eyre nicht zuletzt aufgrund der Kino- und Fernsehversionen der melodramatischen Romanvorlage als die bekannteste englische Gouvernante der Literaturgeschichte"
9be0524b-4cb9-4fc1-9dc2-d65b1c13cf53,252,de,Eleonora,"“Eleonora” ist eine Erzählung von Edgar Allan Poe. Sie wurde 1841 erstveröffentlicht. In ihr geht es um das Paradox der Treue in der Treulosigkeit."
1 ID_texts ID locale title descr
2 d2a65a27-9f2a-480f-bc38-84ee8ec5c13e 201 de Sturmhöhe Sturmhöhe (Originaltitel: Wuthering Heights) ist der einzige Roman der englischen Schriftstellerin Emily Brontë (1818–1848). Der 1847 unter dem Pseudonym Ellis Bell veröffentlichte Roman wurde vom viktorianischen Publikum weitgehend abgelehnt, heute gilt er als ein Klassiker der britischen Romanliteratur des 19. Jahrhunderts.
3 8c42c706-a979-41cf-9ffe-91e6cf1383a0 201 fr Les Hauts de Hurlevent Les Hauts de Hurlevent (titre original : Wuthering Heights), parfois orthographié Les Hauts de Hurle-Vent, est l'unique roman d'Emily Brontë, publié pour la première fois en 1847 sous le pseudonyme d’Ellis Bell. Loin d'être un récit moralisateur, Emily Brontë achève néanmoins le roman dans une atmosphère sereine, suggérant le triomphe de la paix et du Bien sur la vengeance et le Mal.
4 9e1c4c81-dc90-4600-85b1-e9dd4bf12ce0 207 de Jane Eyre Jane Eyre. Eine Autobiographie (Originaltitel: Jane Eyre. An Autobiography), erstmals erschienen im Jahr 1847 unter dem Pseudonym Currer Bell, ist der erste veröffentlichte Roman der britischen Autorin Charlotte Brontë und ein Klassiker der viktorianischen Romanliteratur des 19. Jahrhunderts. Der Roman erzählt in Form einer Ich-Erzählung die Lebensgeschichte von Jane Eyre (ausgesprochen /ˌdʒeɪn ˈɛə/), die nach einer schweren Kindheit eine Stelle als Gouvernante annimmt und sich in ihren Arbeitgeber verliebt, jedoch immer wieder um ihre Freiheit und Selbstbestimmung kämpfen muss. Als klein, dünn, blass, stets schlicht dunkel gekleidet und mit strengem Mittelscheitel beschrieben, gilt die Heldin des Romans Jane Eyre nicht zuletzt aufgrund der Kino- und Fernsehversionen der melodramatischen Romanvorlage als die bekannteste englische Gouvernante der Literaturgeschichte
5 9be0524b-4cb9-4fc1-9dc2-d65b1c13cf53 252 de Eleonora “Eleonora” ist eine Erzählung von Edgar Allan Poe. Sie wurde 1841 erstveröffentlicht. In ihr geht es um das Paradox der Treue in der Treulosigkeit.

View File

@@ -0,0 +1,64 @@
ID;parent_ID;name;page;book_ID
f846b0b9-01d4-4f6d-82a4-d79204f62514;;Foreword;3;207
f846b0b9-01d4-4f6d-82a4-d79204f62515;;Chapter 1;4;207
f846b0b9-01d4-4f6d-82a4-d79204f62516;f846b0b9-01d4-4f6d-82a4-d79204f62515;Section 1.1;5;207
f846b0b9-01d4-4f6d-82a4-d79204f62517;f846b0b9-01d4-4f6d-82a4-d79204f62515;Section 1.2;28;207
f846b0b9-01d4-4f6d-82a4-d79204f62518;f846b0b9-01d4-4f6d-82a4-d79204f62517;Subsection 1.2.1;30;207
f846b0b9-01d4-4f6d-82a4-d79204f62519;f846b0b9-01d4-4f6d-82a4-d79204f62517;Subsection 1.2.2;33;207
f846b0b9-01d4-4f6d-82a4-d79204f62520;f846b0b9-01d4-4f6d-82a4-d79204f62515;Section 1.3;36;207
f846b0b9-01d4-4f6d-82a4-d79204f62521;;Chapter 2;54;207
f846b0b9-01d4-4f6d-82a4-d79204f62522;f846b0b9-01d4-4f6d-82a4-d79204f62521;Section 2.1;56;207
f846b0b9-01d4-4f6d-82a4-d79204f62523;f846b0b9-01d4-4f6d-82a4-d79204f62521;Section 2.2;58;207
f846b0b9-01d4-4f6d-82a4-d79204f62524;;Conclusion;63;207
f846b0b9-01d4-4f6d-82a4-d79204f62525;;Endnotes;65;207
f846b0b9-01d4-4f6d-82a4-d79204f62526;;Copyright notice;2;251
f846b0b9-01d4-4f6d-82a4-d79204f62527;;Chapter 1;3;251
f846b0b9-01d4-4f6d-82a4-d79204f62528;f846b0b9-01d4-4f6d-82a4-d79204f62527;Section 1.1;5;251
f846b0b9-01d4-4f6d-82a4-d79204f62529;f846b0b9-01d4-4f6d-82a4-d79204f62527;Section 1.2;13;251
f846b0b9-01d4-4f6d-82a4-d79204f62530;;Chapter 2;20;251
f846b0b9-01d4-4f6d-82a4-d79204f62531;f846b0b9-01d4-4f6d-82a4-d79204f62530;Section 2.1;21;251
f846b0b9-01d4-4f6d-82a4-d79204f62532;f846b0b9-01d4-4f6d-82a4-d79204f62530;Section 2.2;25;251
f846b0b9-01d4-4f6d-82a4-d79204f62533;f846b0b9-01d4-4f6d-82a4-d79204f62530;Section 2.3;27;251
f846b0b9-01d4-4f6d-82a4-d79204f62534;;Chapter 3;30;251
f846b0b9-01d4-4f6d-82a4-d79204f62535;;Endnotes;41;251
f846b0b9-01d4-4f6d-82a4-d79204f62551;;Acknowledgements;1;271
f846b0b9-01d4-4f6d-82a4-d79204f62552;;The Flight;2;271
f846b0b9-01d4-4f6d-82a4-d79204f62553;;Hexwood Farm;8;271
f846b0b9-01d4-4f6d-82a4-d79204f62554;f846b0b9-01d4-4f6d-82a4-d79204f62553;Castle Saburac;13;271
f846b0b9-01d4-4f6d-82a4-d79204f62555;f846b0b9-01d4-4f6d-82a4-d79204f62553;The Curse of Rapkyn;27;271
f846b0b9-01d4-4f6d-82a4-d79204f62556;f846b0b9-01d4-4f6d-82a4-d79204f62553;The Mannikin;35;271
f846b0b9-01d4-4f6d-82a4-d79204f62557;;The Eye of Time;44;271
f846b0b9-01d4-4f6d-82a4-d79204f62558;;The Enchanting;59;271
f846b0b9-01d4-4f6d-82a4-d79204f62559;f846b0b9-01d4-4f6d-82a4-d79204f62558;The Telling Bone;73;271
f846b0b9-01d4-4f6d-82a4-d79204f62560;f846b0b9-01d4-4f6d-82a4-d79204f62558;The Power of Adamcos;86;271
f846b0b9-01d4-4f6d-82a4-d79204f62561;f846b0b9-01d4-4f6d-82a4-d79204f62558;The House of the Sorcerer;98;271
f846b0b9-01d4-4f6d-82a4-d79204f62562;;The Changeling;105;271
f846b0b9-01d4-4f6d-82a4-d79204f62563;f846b0b9-01d4-4f6d-82a4-d79204f62562;The Flying Broomsticks;118;271
f846b0b9-01d4-4f6d-82a4-d79204f62564;f846b0b9-01d4-4f6d-82a4-d79204f62563;The Fish Out of Water;126;271
f846b0b9-01d4-4f6d-82a4-d79204f62565;;The Final Magic;138;271
f846b0b9-01d4-4f6d-82a4-d79204f62566;;Copyright;159;271
f846b0b9-01d4-4f6d-82a4-d79204f62567;;Editor's Note;1;201
f846b0b9-01d4-4f6d-82a4-d79204f62568;;Chapter I;2;201
f846b0b9-01d4-4f6d-82a4-d79204f62569;;Chapter II;31;201
f846b0b9-01d4-4f6d-82a4-d79204f62570;f846b0b9-01d4-4f6d-82a4-d79204f62569;Section II.I;47;201
f846b0b9-01d4-4f6d-82a4-d79204f62571;f846b0b9-01d4-4f6d-82a4-d79204f62569;Section II.II;62;201
f846b0b9-01d4-4f6d-82a4-d79204f62572;f846b0b9-01d4-4f6d-82a4-d79204f62569;Section II.III;75;201
f846b0b9-01d4-4f6d-82a4-d79204f62573;f846b0b9-01d4-4f6d-82a4-d79204f62569;Section II.IV;87;201
f846b0b9-01d4-4f6d-82a4-d79204f62574;;Chapter III;105;201
f846b0b9-01d4-4f6d-82a4-d79204f62575;f846b0b9-01d4-4f6d-82a4-d79204f62574;Section III.I;128;201
f846b0b9-01d4-4f6d-82a4-d79204f62576;f846b0b9-01d4-4f6d-82a4-d79204f62575;Subsection III.I.I;156;201
f846b0b9-01d4-4f6d-82a4-d79204f62577;f846b0b9-01d4-4f6d-82a4-d79204f62575;Subsection III.I.II;173;201
f846b0b9-01d4-4f6d-82a4-d79204f62578;f846b0b9-01d4-4f6d-82a4-d79204f62574;Section III.II;185;201
f846b0b9-01d4-4f6d-82a4-d79204f62579;;Chapter IV;203;201
f846b0b9-01d4-4f6d-82a4-d79204f62580;;Acknowledgments;250;201
f846b0b9-01d4-4f6d-82a4-d79204f62582;;Foreword;1;252
f846b0b9-01d4-4f6d-82a4-d79204f62583;;Chapter 1;3;252
f846b0b9-01d4-4f6d-82a4-d79204f62584;f846b0b9-01d4-4f6d-82a4-d79204f62583;Section 1.1;5;252
f846b0b9-01d4-4f6d-82a4-d79204f62585;f846b0b9-01d4-4f6d-82a4-d79204f62583;Section 1.2;8;252
f846b0b9-01d4-4f6d-82a4-d79204f62586;;Chapter 2;10;252
f846b0b9-01d4-4f6d-82a4-d79204f62587;f846b0b9-01d4-4f6d-82a4-d79204f62586;Section 2.1;12;252
f846b0b9-01d4-4f6d-82a4-d79204f62588;f846b0b9-01d4-4f6d-82a4-d79204f62587;Subsection 2.1.1;14;252
f846b0b9-01d4-4f6d-82a4-d79204f62589;f846b0b9-01d4-4f6d-82a4-d79204f62587;Subsection 2.1.2;16;252
f846b0b9-01d4-4f6d-82a4-d79204f62590;f846b0b9-01d4-4f6d-82a4-d79204f62586;Section 2.2;18;252
f846b0b9-01d4-4f6d-82a4-d79204f62591;f846b0b9-01d4-4f6d-82a4-d79204f62590;Subsection 2.2.1;21;252
f846b0b9-01d4-4f6d-82a4-d79204f62592;;Endnotes;25;252
1 ID parent_ID name page book_ID
2 f846b0b9-01d4-4f6d-82a4-d79204f62514 Foreword 3 207
3 f846b0b9-01d4-4f6d-82a4-d79204f62515 Chapter 1 4 207
4 f846b0b9-01d4-4f6d-82a4-d79204f62516 f846b0b9-01d4-4f6d-82a4-d79204f62515 Section 1.1 5 207
5 f846b0b9-01d4-4f6d-82a4-d79204f62517 f846b0b9-01d4-4f6d-82a4-d79204f62515 Section 1.2 28 207
6 f846b0b9-01d4-4f6d-82a4-d79204f62518 f846b0b9-01d4-4f6d-82a4-d79204f62517 Subsection 1.2.1 30 207
7 f846b0b9-01d4-4f6d-82a4-d79204f62519 f846b0b9-01d4-4f6d-82a4-d79204f62517 Subsection 1.2.2 33 207
8 f846b0b9-01d4-4f6d-82a4-d79204f62520 f846b0b9-01d4-4f6d-82a4-d79204f62515 Section 1.3 36 207
9 f846b0b9-01d4-4f6d-82a4-d79204f62521 Chapter 2 54 207
10 f846b0b9-01d4-4f6d-82a4-d79204f62522 f846b0b9-01d4-4f6d-82a4-d79204f62521 Section 2.1 56 207
11 f846b0b9-01d4-4f6d-82a4-d79204f62523 f846b0b9-01d4-4f6d-82a4-d79204f62521 Section 2.2 58 207
12 f846b0b9-01d4-4f6d-82a4-d79204f62524 Conclusion 63 207
13 f846b0b9-01d4-4f6d-82a4-d79204f62525 Endnotes 65 207
14 f846b0b9-01d4-4f6d-82a4-d79204f62526 Copyright notice 2 251
15 f846b0b9-01d4-4f6d-82a4-d79204f62527 Chapter 1 3 251
16 f846b0b9-01d4-4f6d-82a4-d79204f62528 f846b0b9-01d4-4f6d-82a4-d79204f62527 Section 1.1 5 251
17 f846b0b9-01d4-4f6d-82a4-d79204f62529 f846b0b9-01d4-4f6d-82a4-d79204f62527 Section 1.2 13 251
18 f846b0b9-01d4-4f6d-82a4-d79204f62530 Chapter 2 20 251
19 f846b0b9-01d4-4f6d-82a4-d79204f62531 f846b0b9-01d4-4f6d-82a4-d79204f62530 Section 2.1 21 251
20 f846b0b9-01d4-4f6d-82a4-d79204f62532 f846b0b9-01d4-4f6d-82a4-d79204f62530 Section 2.2 25 251
21 f846b0b9-01d4-4f6d-82a4-d79204f62533 f846b0b9-01d4-4f6d-82a4-d79204f62530 Section 2.3 27 251
22 f846b0b9-01d4-4f6d-82a4-d79204f62534 Chapter 3 30 251
23 f846b0b9-01d4-4f6d-82a4-d79204f62535 Endnotes 41 251
24 f846b0b9-01d4-4f6d-82a4-d79204f62551 Acknowledgements 1 271
25 f846b0b9-01d4-4f6d-82a4-d79204f62552 The Flight 2 271
26 f846b0b9-01d4-4f6d-82a4-d79204f62553 Hexwood Farm 8 271
27 f846b0b9-01d4-4f6d-82a4-d79204f62554 f846b0b9-01d4-4f6d-82a4-d79204f62553 Castle Saburac 13 271
28 f846b0b9-01d4-4f6d-82a4-d79204f62555 f846b0b9-01d4-4f6d-82a4-d79204f62553 The Curse of Rapkyn 27 271
29 f846b0b9-01d4-4f6d-82a4-d79204f62556 f846b0b9-01d4-4f6d-82a4-d79204f62553 The Mannikin 35 271
30 f846b0b9-01d4-4f6d-82a4-d79204f62557 The Eye of Time 44 271
31 f846b0b9-01d4-4f6d-82a4-d79204f62558 The Enchanting 59 271
32 f846b0b9-01d4-4f6d-82a4-d79204f62559 f846b0b9-01d4-4f6d-82a4-d79204f62558 The Telling Bone 73 271
33 f846b0b9-01d4-4f6d-82a4-d79204f62560 f846b0b9-01d4-4f6d-82a4-d79204f62558 The Power of Adamcos 86 271
34 f846b0b9-01d4-4f6d-82a4-d79204f62561 f846b0b9-01d4-4f6d-82a4-d79204f62558 The House of the Sorcerer 98 271
35 f846b0b9-01d4-4f6d-82a4-d79204f62562 The Changeling 105 271
36 f846b0b9-01d4-4f6d-82a4-d79204f62563 f846b0b9-01d4-4f6d-82a4-d79204f62562 The Flying Broomsticks 118 271
37 f846b0b9-01d4-4f6d-82a4-d79204f62564 f846b0b9-01d4-4f6d-82a4-d79204f62563 The Fish Out of Water 126 271
38 f846b0b9-01d4-4f6d-82a4-d79204f62565 The Final Magic 138 271
39 f846b0b9-01d4-4f6d-82a4-d79204f62566 Copyright 159 271
40 f846b0b9-01d4-4f6d-82a4-d79204f62567 Editor's Note 1 201
41 f846b0b9-01d4-4f6d-82a4-d79204f62568 Chapter I 2 201
42 f846b0b9-01d4-4f6d-82a4-d79204f62569 Chapter II 31 201
43 f846b0b9-01d4-4f6d-82a4-d79204f62570 f846b0b9-01d4-4f6d-82a4-d79204f62569 Section II.I 47 201
44 f846b0b9-01d4-4f6d-82a4-d79204f62571 f846b0b9-01d4-4f6d-82a4-d79204f62569 Section II.II 62 201
45 f846b0b9-01d4-4f6d-82a4-d79204f62572 f846b0b9-01d4-4f6d-82a4-d79204f62569 Section II.III 75 201
46 f846b0b9-01d4-4f6d-82a4-d79204f62573 f846b0b9-01d4-4f6d-82a4-d79204f62569 Section II.IV 87 201
47 f846b0b9-01d4-4f6d-82a4-d79204f62574 Chapter III 105 201
48 f846b0b9-01d4-4f6d-82a4-d79204f62575 f846b0b9-01d4-4f6d-82a4-d79204f62574 Section III.I 128 201
49 f846b0b9-01d4-4f6d-82a4-d79204f62576 f846b0b9-01d4-4f6d-82a4-d79204f62575 Subsection III.I.I 156 201
50 f846b0b9-01d4-4f6d-82a4-d79204f62577 f846b0b9-01d4-4f6d-82a4-d79204f62575 Subsection III.I.II 173 201
51 f846b0b9-01d4-4f6d-82a4-d79204f62578 f846b0b9-01d4-4f6d-82a4-d79204f62574 Section III.II 185 201
52 f846b0b9-01d4-4f6d-82a4-d79204f62579 Chapter IV 203 201
53 f846b0b9-01d4-4f6d-82a4-d79204f62580 Acknowledgments 250 201
54 f846b0b9-01d4-4f6d-82a4-d79204f62582 Foreword 1 252
55 f846b0b9-01d4-4f6d-82a4-d79204f62583 Chapter 1 3 252
56 f846b0b9-01d4-4f6d-82a4-d79204f62584 f846b0b9-01d4-4f6d-82a4-d79204f62583 Section 1.1 5 252
57 f846b0b9-01d4-4f6d-82a4-d79204f62585 f846b0b9-01d4-4f6d-82a4-d79204f62583 Section 1.2 8 252
58 f846b0b9-01d4-4f6d-82a4-d79204f62586 Chapter 2 10 252
59 f846b0b9-01d4-4f6d-82a4-d79204f62587 f846b0b9-01d4-4f6d-82a4-d79204f62586 Section 2.1 12 252
60 f846b0b9-01d4-4f6d-82a4-d79204f62588 f846b0b9-01d4-4f6d-82a4-d79204f62587 Subsection 2.1.1 14 252
61 f846b0b9-01d4-4f6d-82a4-d79204f62589 f846b0b9-01d4-4f6d-82a4-d79204f62587 Subsection 2.1.2 16 252
62 f846b0b9-01d4-4f6d-82a4-d79204f62590 f846b0b9-01d4-4f6d-82a4-d79204f62586 Section 2.2 18 252
63 f846b0b9-01d4-4f6d-82a4-d79204f62591 f846b0b9-01d4-4f6d-82a4-d79204f62590 Subsection 2.2.1 21 252
64 f846b0b9-01d4-4f6d-82a4-d79204f62592 Endnotes 25 252

View File

@@ -1,16 +1,43 @@
ID,parent_ID,name
10,,Fiction
11,10,Drama
12,10,Poetry
13,10,Fantasy
14,10,Science Fiction
15,10,Romance
16,10,Mystery
17,10,Thriller
18,10,Dystopia
19,10,Fairy Tale
20,,Non-Fiction
21,20,Biography
22,21,Autobiography
23,20,Essay
24,20,Speech
10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,,Fiction
11aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Drama
12aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Poetry
13aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Fantasy
131aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,13aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Fairy Tale
132aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,13aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Epic Fantasy
133aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,13aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,High Fantasy
134aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,13aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Gothic
14aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Science Fiction
141aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,14aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Utopian and Dystopian
1411aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,141aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Utopian
1412aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,141aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Dystopian
14121aaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,1412aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Cyberpunk
141211aa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,14121aaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Steampunk
142aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,14aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Space Opera
143aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,14aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Time Travel
144aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,14aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Tech Noir
15aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Romance
151aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,15aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Contemporary Romance
152aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,15aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Historical Romance
153aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,15aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Romantic Suspense
16aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Mystery
161aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,16aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Crime
1611aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,161aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Thriller
16111aaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,1611aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Police Procedural
16112aaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,1611aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Legal Thriller
16113aaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,1611aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Medical Thriller
16114aaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,1611aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Spy Thriller
1612aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,161aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Detective
1613aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,161aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Suspense
162aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,16aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Noir
1621aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,162aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Nordic Noir
1622aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,162aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Tart Noir
163aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,16aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Cozy Mystery
17aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Adventure
18aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Short Story
19aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Graphic Novel
20aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,,Non-Fiction
21aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,20aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Biography
22aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,21aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Autobiography
23aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,20aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Essay
24aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,20aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa,Speech
1 ID parent_ID name
2 10 10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Fiction
3 11 11aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 10 10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Drama
4 12 12aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 10 10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Poetry
5 13 13aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 10 10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Fantasy
6 14 131aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 10 13aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Science Fiction Fairy Tale
7 15 132aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 10 13aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Romance Epic Fantasy
8 16 133aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 10 13aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Mystery High Fantasy
9 17 134aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 10 13aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Thriller Gothic
10 18 14aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 10 10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Dystopia Science Fiction
11 19 141aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 10 14aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Fairy Tale Utopian and Dystopian
12 20 1411aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 141aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Non-Fiction Utopian
13 21 1412aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 20 141aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Biography Dystopian
14 22 14121aaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 21 1412aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Autobiography Cyberpunk
15 23 141211aa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 20 14121aaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Essay Steampunk
16 24 142aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 20 14aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Speech Space Opera
17 143aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 14aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Time Travel
18 144aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 14aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Tech Noir
19 15aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Romance
20 151aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 15aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Contemporary Romance
21 152aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 15aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Historical Romance
22 153aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 15aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Romantic Suspense
23 16aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Mystery
24 161aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 16aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Crime
25 1611aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 161aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Thriller
26 16111aaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 1611aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Police Procedural
27 16112aaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 1611aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Legal Thriller
28 16113aaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 1611aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Medical Thriller
29 16114aaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 1611aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Spy Thriller
30 1612aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 161aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Detective
31 1613aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 161aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Suspense
32 162aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 16aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Noir
33 1621aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 162aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Nordic Noir
34 1622aaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 162aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Tart Noir
35 163aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 16aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Cozy Mystery
36 17aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Adventure
37 18aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Short Story
38 19aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 10aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Graphic Novel
39 20aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Non-Fiction
40 21aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 20aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Biography
41 22aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 21aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Autobiography
42 23aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 20aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Essay
43 24aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa 20aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa Speech

View File

@@ -8,9 +8,10 @@ entity Books : managed {
author : Association to Authors @mandatory;
genre : Association to Genres;
stock : Integer;
price : Decimal;
price : Price;
currency : Currency;
image : LargeBinary @Core.MediaType: 'image/png';
contents : Composition of many Contents on contents.book = $self;
}
entity Authors : managed {
@@ -25,7 +26,24 @@ entity Authors : managed {
/** Hierarchically organized Code List for Genres */
entity Genres : sap.common.CodeList {
key ID : Integer;
key ID : UUID;
parent : Association to Genres;
children : Composition of many Genres on children.parent = $self;
}
/** Hierarchically organized entity for Contents */
entity Contents {
key ID : UUID;
name : String;
page : Integer;
parent : Association to Contents;
children : Composition of many Contents on children.parent = $self;
book : Association to Books;
}
type Price : Decimal(9,2);
// ------------------------------------------------------------------
// temporary workaround for reuse in fiori sample and hana deployment
annotate Books with @fiori.draft.enabled;

View File

@@ -6,11 +6,10 @@
"app",
"srv",
"db",
"index.cds",
"index.js"
"index.cds"
],
"devDependencies": {
"@cap-js/sqlite": "*"
"@cap-js/sqlite": ">=1"
},
"dependencies": {
"@sap/cds": ">=7",

View File

@@ -0,0 +1,2 @@
using { AdminService } from './admin-service';
annotate AdminService with @requires:'admin';

View File

@@ -1,5 +1,7 @@
using { sap.capire.bookshop as my } from '../db/schema';
service AdminService @(requires:'admin', path:'/admin') {
entity Books as projection on my.Books;
service AdminService @(path:'/admin') {
entity Authors as projection on my.Authors;
entity Books as projection on my.Books;
entity Genres as projection on my.Genres;
entity Contents as projection on my.Contents;
}

View File

@@ -3,14 +3,14 @@ service CatalogService @(path:'/browse') {
/** For displaying lists of Books */
@readonly entity ListOfBooks as projection on Books
excluding { descr };
excluding { descr, contents };
/** For display in details pages */
@readonly entity Books as projection on my.Books { *,
author.name as author
} excluding { createdBy, modifiedBy };
} excluding { createdBy, modifiedBy, contents };
@requires: 'authenticated-user'
action submitOrder ( book: Books:ID, quantity: Integer ) returns { stock: Integer };
event OrderedBook : { book: Books:ID; quantity: Integer; buyer: String };
}
}

View File

@@ -14,25 +14,24 @@ GET http://localhost:4004/odata/v4/test/Genres?
POST http://localhost:4004/odata/v4/test/Genres?
Content-Type: application/json
{ "ID":100, "name":"Some Sample Genres...", "children":[
{ "ID":101, "name":"Cat", "children":[
{ "ID":102, "name":"Kitty", "children":[
{ "ID":103, "name":"Kitty Cat", "children":[
{ "ID":104, "name":"Aristocat" } ]},
{ "ID":105, "name":"Kitty Bat" } ]},
{ "ID":106, "name":"Catwoman", "children":[
{ "ID":107, "name":"Catalina" } ]} ]},
{ "ID":108, "name":"Catweazle" }
{ "ID":"100aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "name":"Some Sample Genres...", "children":[
{ "ID":"101aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "name":"Cat", "children":[
{ "ID":"102aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "name":"Kitty", "children":[
{ "ID":"103aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "name":"Aristocat" },
{ "ID":"104aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "name":"Kitty Bat" } ]},
{ "ID":"105aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "name":"Catwoman", "children":[
{ "ID":"106aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "name":"Catalina" } ]} ]},
{ "ID":"107aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", "name":"Catweazle" }
]}
###
GET http://localhost:4004/odata/v4/test/Genres(100)?
# &$expand=children
# &$expand=children($expand=children($expand=children($expand=children)))
GET http://localhost:4004/odata/v4/test/Genres(100aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa)?
&$expand=children
&$expand=children($expand=children($expand=children($expand=children)))
###
DELETE http://localhost:4004/odata/v4/test/Genres(103)
DELETE http://localhost:4004/odata/v4/test/Genres(103aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa)
###
DELETE http://localhost:4004/odata/v4/test/Genres(100)
DELETE http://localhost:4004/odata/v4/test/Genres(100aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa)
###

View File

@@ -40,8 +40,7 @@ Authorization: Basic alice:
{
"ID": 112,
"name": "Shakespeeeeere",
"age": 22
"name": "Shakespeeeeere"
}
@@ -56,7 +55,7 @@ Authorization: Basic alice:
"title": "Poems : Pocket Poets",
"descr": "The Everyman's Library Pocket Poets hardcover series is popular for its compact size and reasonable price which does not compromise content. Poems: Bronte contains poems that demonstrate a sensibility elemental in its force with an imaginative discipline and flexibility of the highest order. Also included are an Editor's Note and an index of first lines.",
"author": { "ID": 101 },
"genre": { "ID": 12 },
"genre": { "ID": "12aaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" },
"stock": 5,
"price": "12.05",
"currency": { "code": "USD" }

1
bookstore/cds-plugin.js Normal file
View File

@@ -0,0 +1 @@
require('./srv/server')

View File

@@ -7,8 +7,11 @@
"@capire/orders": "*",
"@capire/common": "*",
"@capire/data-viewer": "*",
"@sap-cloud-sdk/http-client": "^4",
"@sap-cloud-sdk/resilience": "^4",
"@sap/cds": ">=5",
"express": "^4.17.1"
"express": "^4.17.1",
"@cap-js/hana": ">=1"
},
"cds": {
"requires": {
@@ -20,15 +23,12 @@
"kind": "odata",
"model": "@capire/orders"
},
"messaging": {
"[development]": { "kind": "file-based-messaging" },
"[hybrid]": { "kind": "enterprise-messaging-shared" },
"[production]": { "kind": "enterprise-messaging" }
},
"db": {
"kind": "sql"
}
"messaging": true,
"db": true
},
"log": { "service": true }
},
"scripts": {
"start": "cds-serve"
}
}
}

View File

@@ -1,20 +0,0 @@
const cds = require ('@sap/cds')
// Add mashup logic
cds.once('served', require('./srv/mashup'))
// Add routes to UIs from imported packages
cds.once('bootstrap',(app)=>{
try {
app.serve ('/bookshop') .from ('@capire/bookshop','app/vue')
app.serve ('/reviews') .from ('@capire/reviews','app/vue')
app.serve ('/orders') .from('@capire/orders','app/orders')
app.serve ('/data') .from('@capire/data-viewer','app/viewer')
} catch (err) {
if (err.code === 'MODULE_NOT_FOUND') throw new Error('Run "npm ci" to install the required dependencies', { cause: err })
throw err
}
})
// Add Swagger UI
require('./srv/swagger-ui')

View File

@@ -1,10 +1,17 @@
////////////////////////////////////////////////////////////////////////////
//
// Mashing up bookshop services with required services...
//
module.exports = async()=>{ // called by server.js
const cds = require ('@sap/cds')
// Add routes to UIs from imported packages
if (!cds.env.production) cds.once ('bootstrap', (app) => {
app.serve ('/bookshop') .from ('@capire/bookshop','app/vue')
app.serve ('/reviews') .from ('@capire/reviews','app/vue')
app.serve ('/orders') .from('@capire/orders','app/orders')
})
// Mashing up bookshop services with required services...
cds.once ('served', async ()=>{
const cds = require('@sap/cds')
const CatalogService = await cds.connect.to ('CatalogService')
const ReviewsService = await cds.connect.to ('ReviewsService')
const OrdersService = await cds.connect.to ('OrdersService')
@@ -28,8 +35,8 @@ module.exports = async()=>{ // called by server.js
//
CatalogService.on ('OrderedBook', async (msg) => {
const { book, quantity, buyer } = msg.data
const { title, price } = await db.tx(msg).read (Books, book, b => { b.title, b.price })
return OrdersService.tx(msg).create ('Orders').entries({
const { title, price } = await db.read (Books, book, b => { b.title, b.price })
return OrdersService.create ('OrdersNoDraft').entries({
OrderNo: 'Order at '+ (new Date).toLocaleString(),
Items: [{ product:{ID:`${book}`}, title, price, quantity }],
buyer, createdBy: buyer
@@ -55,4 +62,4 @@ module.exports = async()=>{ // called by server.js
.and ('stock >=', deltaQuantity)
.set ('stock -=', deltaQuantity)
})
}
})

View File

@@ -1,10 +0,0 @@
// -----------------------------------------------------------------------
// Adding Swagger UI - see https://cap.cloud.sap/docs/advanced/openapi
const cds = require ('@sap/cds')
try {
const cds_swagger = require ('cds-swagger-ui-express')
cds.once ('bootstrap', app => app.use (cds_swagger()) )
} catch (err) {
if (err.code !== 'MODULE_NOT_FOUND') throw err
}

13
common/currencies.cds Normal file
View File

@@ -0,0 +1,13 @@
using { sap } from '@sap/cds/common';
extend sap.common.Currencies with {
// Currencies.code = ISO 4217 alphabetic three-letter code
// with the first two letters being equal to ISO 3166 alphabetic country codes
// See also:
// [1] https://www.iso.org/iso-4217-currency-codes.html
// [2] https://www.currency-iso.org/en/home/tables/table-a1.html
// [3] https://www.ibm.com/support/knowledgecenter/en/SSZLC2_7.0.0/com.ibm.commerce.payments.developer.doc/refs/rpylerl2mst97.htm
numcode : Integer;
exponent : Integer; //> e.g. 2 --> 1 Dollar = 10^2 Cent
minor : String; //> e.g. 'Cent'
}

View File

@@ -1,45 +1,2 @@
using { sap } from '@sap/cds/common';
extend sap.common.Currencies with {
// Currencies.code = ISO 4217 alphabetic three-letter code
// with the first two letters being equal to ISO 3166 alphabetic country codes
// See also:
// [1] https://www.iso.org/iso-4217-currency-codes.html
// [2] https://www.currency-iso.org/en/home/tables/table-a1.html
// [3] https://www.ibm.com/support/knowledgecenter/en/SSZLC2_7.0.0/com.ibm.commerce.payments.developer.doc/refs/rpylerl2mst97.htm
numcode : Integer;
exponent : Integer; //> e.g. 2 --> 1 Dollar = 10^2 Cent
minor : String; //> e.g. 'Cent'
}
/**
* The Code Lists below are designed as optional extensions to
* the base schema. Switch them on by adding an Association to
* one of the code list entities in your models or by:
* annotate sap.common.Countries with @cds.persistence.skip:false;
*/
context sap.common.countries {
extend sap.common.Countries {
regions : Composition of many Regions on regions._parent = $self.code;
}
entity Regions : sap.common.CodeList {
key code : String(5); // ISO 3166-2 alpha5 codes, e.g. DE-BW
children : Composition of many Regions on children._parent = $self.code;
cities : Composition of many Cities on cities.region = $self;
_parent : String(11);
}
entity Cities : sap.common.CodeList {
key code : String(11);
region : Association to Regions;
districts : Composition of many Districts on districts.city = $self;
}
entity Districts : sap.common.CodeList {
key code : String(11);
city : Association to Cities;
}
}
using from './currencies';
using from './regions';

22
common/regions.cds Normal file
View File

@@ -0,0 +1,22 @@
using { sap.common } from '@sap/cds/common';
namespace sap.common.countries;
extend common.Countries {
regions : Composition of many Regions on regions._parent = $self.code;
}
entity Regions : common.CodeList {
key code : String(5); // ISO 3166-2 alpha5 codes, e.g. DE-BW
children : Composition of many Regions on children._parent = $self.code;
cities : Composition of many Cities on cities.region = $self;
_parent : String(11);
}
entity Cities : common.CodeList {
key code : String(11);
region : Association to Regions;
districts : Composition of many Districts on districts.city = $self;
}
entity Districts : common.CodeList {
key code : String(11);
city : Association to Cities;
}

View File

@@ -0,0 +1,4 @@
const cds = require("@sap/cds")
cds.on ('served', ()=> {
cds.app.serve ('/data') .from ('@capire/data-viewer','app/viewer')
})

View File

@@ -34,7 +34,8 @@ class DataService extends cds.ApplicationService { init(){
query.SELECT.limit = req.query.SELECT.limit // forward $skip / $top
const dataSource = findDataSource(dataSourceName, entityName)
const res = await dataSource.run(query)
let res = await dataSource.run(query)
if (!Array.isArray(res)) res = [res] // singleton result
return res.map((line) => {
const record = Object.entries(line).map(([column, data]) => ({ column, data }))
return {

BIN
etc/index-html.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 KiB

29
event-mesh.json Normal file
View File

@@ -0,0 +1,29 @@
{
"version": "1.1.0",
"options": {
"management": true,
"messagingrest": true,
"messaging": true
},
"rules": {
"topicRules": {
"publishFilter": [
"*"
],
"subscribeFilter": [
"*"
]
},
"queueRules": {
"publishFilter": [
"*"
],
"subscribeFilter": [
"*"
]
}
},
"authorities": [
"$ACCEPT_GRANTED_AUTHORITIES"
]
}

1
fiori/.env Normal file
View File

@@ -0,0 +1 @@
cds.requires.[hybrid].messaging.kind=file-based-messaging

View File

@@ -1,7 +1,7 @@
Age = Age
Lifetime = Lifetime
SubGenres = Sub Genres
SubGenres = Subgenre
NumCode = Numeric Code
MinorUnit = Minor Unit

View File

@@ -1,6 +1,11 @@
using { AdminService } from '@capire/bookstore';
using from '../common'; // to help UI linter get the complete annotations
annotate sap.capire.bookshop.Genres with @fiori.draft.enabled;
annotate AdminService.Genres with @odata.draft.enabled;
annotate AdminService.Genres with @odata.draft.bypass;
////////////////////////////////////////////////////////////////////////////
//
// Books Object Page
@@ -9,10 +14,11 @@ using from '../common'; // to help UI linter get the complete annotations
annotate AdminService.Books with @(
UI: {
Facets: [
{$Type: 'UI.ReferenceFacet', Label: '{i18n>General}', Target: '@UI.FieldGroup#General'},
{$Type: 'UI.ReferenceFacet', Label: '{i18n>Translations}', Target: 'texts/@UI.LineItem'},
{$Type: 'UI.ReferenceFacet', Label: '{i18n>Details}', Target: '@UI.FieldGroup#Details'},
{$Type: 'UI.ReferenceFacet', Label: '{i18n>Admin}', Target: '@UI.FieldGroup#Admin'},
{$Type: 'UI.ReferenceFacet', Label: '{i18n>General}', Target: '@UI.FieldGroup#General'},
{$Type: 'UI.ReferenceFacet', Label: '{i18n>Translations}', Target: 'texts/@UI.LineItem'},
{$Type: 'UI.ReferenceFacet', Label: '{i18n>Details}', Target: '@UI.FieldGroup#Details'},
{$Type: 'UI.ReferenceFacet', Label: '{i18n>Admin}', Target: '@UI.FieldGroup#Admin'},
{$Type: 'UI.ReferenceFacet', Label: '{i18n>Contents}', Target: 'contents/@UI.PresentationVariant'}
],
FieldGroup#General: {
Data: [
@@ -40,6 +46,34 @@ annotate AdminService.Books with @(
}
);
////////////////////////////////////////////////////////////////////////////
//
// Value Help for Tree Table
//
annotate AdminService.Books with {
genre @(Common: {
Label : 'Genre',
ValueList: {
CollectionPath : 'Genres',
Parameters : [
{
$Type : 'Common.ValueListParameterDisplayOnly',
ValueListProperty: 'name',
},
{
$Type : 'Common.ValueListParameterInOut',
LocalDataProperty: genre_ID,
ValueListProperty: 'ID',
}
],
}
});
}
// Hide ID because of the ValueHelp
annotate AdminService.Genres with {
ID @UI.Hidden;
};
////////////////////////////////////////////////////////////
@@ -82,5 +116,4 @@ extend service AdminService {
// Workaround for Fiori popup for asking user to enter a new UUID on Create
annotate AdminService.Books with { ID @Core.Computed; }
// Show Genre as drop down, not a dialog
annotate AdminService.Books with { genre @Common.ValueListWithFixedValues; }
using from './tree-view';

View File

@@ -0,0 +1,42 @@
using { AdminService } from '@capire/bookstore';
////////////////////////////////////////////////////////////////////////////
//
// Contents Tree Table Annotations
//
// Tell Fiori about the structure of the hierarchy
annotate AdminService.Contents with @Aggregation.RecursiveHierarchy #ContentsHierarchy : {
ParentNavigationProperty : parent, // navigates to a node's parent
NodeProperty : ID, // identifies a node, usually the key
};
// Fiori expects the following to be defined explicitly, even though they're always the same
extend AdminService.Contents with @(
// The columns expected by Fiori to be present in hierarchy entities
Hierarchy.RecursiveHierarchy #ContentsHierarchy : {
LimitedDescendantCount : LimitedDescendantCount,
DistanceFromRoot : DistanceFromRoot,
DrillState : DrillState,
LimitedRank : LimitedRank
},
// Disallow filtering on these properties from Fiori UIs
Capabilities.FilterRestrictions.NonFilterableProperties: [
'LimitedDescendantCount',
'DistanceFromRoot',
'DrillState',
'LimitedRank'
],
// Disallow sorting on these properties from Fiori UIs
Capabilities.SortRestrictions.NonSortableProperties : [
'LimitedDescendantCount',
'DistanceFromRoot',
'DrillState',
'LimitedRank'
],
) columns { // Ensure we can query these fields from database
null as LimitedDescendantCount : Int16,
null as DistanceFromRoot : Int16,
null as DrillState : String,
null as LimitedRank : Int16,
};

View File

@@ -79,6 +79,11 @@
"pattern": "Books({key}/author({key2}):?query:",
"name": "AuthorsDetails",
"target": "AuthorsDetails"
},
{
"pattern": "Books({key})/contents({key2}):?query:",
"name": "ContentsDetails",
"target": "ContentsDetails"
}
],
"targets": {
@@ -112,11 +117,34 @@
"detail" : {
"route" : "AuthorsDetails"
}
},
"contents": {
"detail": {
"route": "ContentsDetails"
}
}
},
"controlConfiguration": {
"contents/@com.sap.vocabularies.UI.v1.LineItem": {
"tableSettings": {
"hierarchyQualifier": "ContentsHierarchy",
"type": "TreeTable"
}
}
}
}
}
},
"ContentsDetails": {
"type": "Component",
"id": "ContentsDetails",
"name": "sap.fe.templates.ObjectPage",
"options": {
"settings": {
"contextPath": "/Books/contents"
}
}
},
"AuthorsDetails": {
"type": "Component",
"id": "AuthorsDetailsList",

View File

@@ -3,7 +3,6 @@
"LaunchPage": {
"adapter": {
"config": {
"catalogs": [],
"groups": [
{
"id": "Bookshop",
@@ -19,14 +18,6 @@
"title": "Browse Books",
"targetURL": "#Books-display"
}
},
{
"id": "BrowseGenres",
"tileType": "sap.ushell.ui.tile.StaticTile",
"properties": {
"title": "Browse Genres (OData v2)",
"targetURL": "#Genres-display"
}
}
]
},
@@ -44,6 +35,14 @@
"title": "Manage Books",
"targetURL": "#Books-manage"
}
},
{
"id": "ManageGenres",
"tileType": "sap.ushell.ui.tile.StaticTile",
"properties": {
"title": "Manage Genres",
"targetURL": "#Genres-manage"
}
},
{
"id": "ManageAuthors",
@@ -115,10 +114,10 @@
"url": "/admin-authors/webapp"
}
},
"BrowseGenres": {
"ManageGenres": {
"semanticObject": "Genres",
"action": "display",
"title": "Browse Genres",
"action": "manage",
"title": "Manage Genres",
"signature": {
"parameters": {
"Genre.ID": {

View File

@@ -4,7 +4,6 @@
using { sap.capire.bookshop as my } from '@capire/bookstore';
using { sap.common } from '@capire/common';
using { sap.common.Currencies } from '@sap/cds/common';
////////////////////////////////////////////////////////////////////////////
//
@@ -38,7 +37,7 @@ annotate my.Books with @(
author @ValueList.entity : 'Authors';
};
annotate Currencies with {
annotate common.Currencies with {
symbol @Common.Label : '{i18n>Currency}';
}
@@ -69,55 +68,53 @@ annotate my.Books with {
image @title: '{i18n>Image}';
}
////////////////////////////////////////////////////////////////////////////
//
// Genres List
//
annotate my.Genres with @(
Common.SemanticKey : [name],
UI : {
SelectionFields : [name],
LineItem : [
{ Value: name },
{
Value : parent.name,
Label: 'Main Genre'
},
],
}
annotate my.Contents with @(
cds.search: {name}
);
annotate my.Genres with {
ID @Common.Text : name @Common.TextArrangement : #TextOnly;
}
////////////////////////////////////////////////////////////////////////////
//
// Genre Details
// Contents List
//
annotate my.Genres with @(UI : {
Identification : [{ Value: name}],
HeaderInfo : {
TypeName : '{i18n>Genre}',
TypeNamePlural : '{i18n>Genres}',
Title : { Value: name },
Description : { Value: ID }
},
Facets : [{
$Type : 'UI.ReferenceFacet',
Label : '{i18n>SubGenres}',
Target : 'children/@UI.LineItem'
}, ],
});
////////////////////////////////////////////////////////////////////////////
//
// Genres Elements
//
annotate my.Genres with {
ID @title: '{i18n>ID}';
name @title: '{i18n>Genre}';
}
annotate my.Contents with @UI: {
PresentationVariant : {
$Type : 'UI.PresentationVariantType',
RequestAtLeast: [name],
Visualizations: ['@UI.LineItem'],
},
LineItem : [{
$Type: 'UI.DataField',
Value: name,
Label : '{i18n>Name}'
},
{
$Type: 'UI.DataField',
Value: page,
Label : '{i18n>Page}'
}],
HeaderInfo : {
$Type : 'UI.HeaderInfoType',
TypeName : '{i18n>ContentsLevel}',
TypeNamePlural: '{i18n>ContentsLevels}',
Title : {
$Type: 'UI.DataField',
Value: name,
}
},
FieldGroup : {
$Type: 'UI.FieldGroupType',
Data : [{
$Type: 'UI.DataField',
Value: page,
Label : '{i18n>PageNumber}'
}],
},
Facets : [{
$Type : 'UI.ReferenceFacet',
Target: '@UI.FieldGroup',
Label : '{i18n>Informations}',
}],
};
////////////////////////////////////////////////////////////////////////////
//

View File

@@ -1,8 +1,32 @@
using { sap.capire.bookshop } from '../../db/common';
using { sap.capire.bookshop.Genres } from '@capire/bookstore';
annotate bookshop.GenreHierarchy {
ID @sap.hierarchy.node.for;
parent @sap.hierarchy.parent.node.for;
hierarchyLevel @sap.hierarchy.level.for;
drillState @sap.hierarchy.drill.state.for;
annotate Genres with @cds.search: {name};
annotate Genres with {
name @title: '{i18n>Genre}';
}
// Lists
annotate Genres with @(
Common.SemanticKey : [name],
UI.SelectionFields : [name],
UI.LineItem : [
{ Value: name, Label: '{i18n>Name}' },
],
);
// Details
annotate Genres with @(UI : {
Identification : [{ Value: name }],
HeaderInfo : {
TypeName : '{i18n>Genre}',
TypeNamePlural : '{i18n>Genres}',
Title : { Value: name },
Description : { Value: ID }
}
});
// Tree Views
// annotate AdminService.Genres with @hierarchy; // upcomming simplification
using from './tree-view';
using from './value-help';

View File

@@ -0,0 +1,42 @@
using { AdminService } from '@capire/bookstore';
////////////////////////////////////////////////////////////////////////////
//
// Genres Tree View
//
// Tell Fiori about the structure of the hierarchy
annotate AdminService.Genres with @Aggregation.RecursiveHierarchy #GenresHierarchy : {
ParentNavigationProperty : parent, // navigates to a node's parent
NodeProperty : ID, // identifies a node, usually the key
};
// Fiori expects the following to be defined explicitly, even though they're always the same
extend AdminService.Genres with @(
// The columns expected by Fiori to be present in hierarchy entities
Hierarchy.RecursiveHierarchy #GenresHierarchy : {
LimitedDescendantCount : LimitedDescendantCount,
DistanceFromRoot : DistanceFromRoot,
DrillState : DrillState,
LimitedRank : LimitedRank
},
// Disallow filtering on these properties from Fiori UIs
Capabilities.FilterRestrictions.NonFilterableProperties: [
'LimitedDescendantCount',
'DistanceFromRoot',
'DrillState',
'LimitedRank'
],
// Disallow sorting on these properties from Fiori UIs
Capabilities.SortRestrictions.NonSortableProperties : [
'LimitedDescendantCount',
'DistanceFromRoot',
'DrillState',
'LimitedRank'
],
) columns { // Ensure we can query these fields from database
null as LimitedDescendantCount : Int16,
null as DistanceFromRoot : Int16,
null as DrillState : String,
null as LimitedRank : Int16,
};

View File

@@ -0,0 +1,6 @@
// Value help with Tree View
using from '../admin-books/fiori-service';
annotate AdminService.Books:genre with @Common.ValueList.PresentationVariantQualifier: 'VH';
annotate AdminService.Genres with @UI.PresentationVariant #VH: {
RecursiveHierarchyQualifier : 'GenresHierarchy',
};

View File

@@ -1,7 +1,3 @@
sap.ui.define(["sap/suite/ui/generic/template/lib/AppComponent"], (AppComponent) =>
AppComponent.extend("genres.Component", {
metadata: {
manifest: "json",
},
})
);
sap.ui.define(["sap/fe/core/AppComponent"], ac => ac.extend("genres.Component", {
metadata:{ manifest:'json' }
}))

View File

@@ -1,4 +1,4 @@
#XTIT
appTitle=Genres
appTitle=Manage Genres
#XTXT
appDescription=Browse Genres
appDescription=Genres as Tree View

View File

@@ -0,0 +1,2 @@
appTitle=Zeige Genres
appDescription=Genres als Baumansicht

View File

@@ -1,155 +1,124 @@
{
"_version": "1.8.0",
"sap.app": {
"id": "genres",
"type": "application",
"i18n": "i18n/i18n.properties",
"applicationVersion": {
"version": "1.0.0"
},
"title": "Browse Genres Hierarchy (OData v2)",
"description": "{{appDescription}}",
"tags": {
"keywords": []
},
"crossNavigation": {
"inbounds": {
"appShow": {
"title": "{{appTitle}}",
"semanticObject": "GenreHierarchy",
"action": "display",
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
},
"icon": "sap-icon://settings",
"size": "1x1"
}
},
"outbounds": {}
},
"ach": "",
"resources": "resources.json",
"dataSources": {
"main": {
"uri": "/odata/v2/browse",
"type": "OData",
"settings": {
"annotations": ["localAnnotations"],
"localUri": "localService/metadata.xml"
}
},
"localAnnotations": {
"type": "ODataAnnotation",
"uri": "annotations/localAnnotations.xml",
"settings": {
"localUri": "annotations/localAnnotations.xml"
}
}
},
"offline": false,
"sourceTemplate": {
"id": "ui5template.smartTemplate",
"version": "1.40.12"
}
},
"sap.ui": {
"technology": "UI5",
"icons": {
"icon": "",
"favIcon": "",
"phone": "",
"phone@2": "",
"tablet": "",
"tablet@2": ""
},
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
},
"supportedThemes": ["sap_hcb", "sap_belize", "sap_belize_deep", "sap_fiori_3"]
},
"sap.ui5": {
"resources": {
"js": [],
"css": []
},
"dependencies": {
"minUI5Version": "1.65.6",
"libs": {},
"components": {}
},
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"uri": "i18n/i18n.properties"
},
"@i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"uri": "i18n/i18n.properties"
},
"json": {
"type": "sap.ui.model.json.JSONModel"
},
"i18n|sap.suite.ui.generic.template.ListReport|Genres": {
"type": "sap.ui.model.resource.ResourceModel",
"uri": "i18n/ListReport/Genres/i18n.properties"
},
"": {
"dataSource": "main",
"preload": true,
"settings": {
"useBatch": true,
"defaultBindingMode": "TwoWay",
"defaultCountMode": "Inline",
"refreshAfterChange": true,
"metadataUrlParams": {
"sap-value-list": "none"
}
}
}
},
"contentDensities": {
"compact": true,
"cozy": true
}
},
"sap.ui.generic.app": {
"_version": "1.3.0",
"settings": {
"forceGlobalRefresh": false,
"useColumnLayoutForSmartForm": false,
"showBasicSearch": false
},
"pages": {
"ListReport|Genres": {
"entitySet": "GenreHierarchy",
"component": {
"name": "sap.suite.ui.generic.template.ListReport",
"list": true,
"settings": {
"condensedTableLayout": true,
"smartVariantManagement": true,
"tableType": "TreeTable",
"enableTableFilterInPageVariant": true,
"dataLoadSettings": {
"loadDataOnAppLaunch": "always"
}
}
}
}
}
},
"sap.fiori": {
"registrationIds": [],
"archeType": "transactional"
},
"sap.platform.hcp": {
"uri": ""
},
"sap.platform.cf": {
"oAuthScopes": []
}
}
"_version": "1.8.0",
"sap.app": {
"id": "genres",
"type": "application",
"title": "{{appTitle}}",
"description": "{{appDescription}}",
"applicationVersion": {
"version": "1.0.0"
},
"dataSources": {
"AdminService": {
"uri": "admin/",
"type": "OData",
"settings": {
"odataVersion": "4.0"
}
}
},
"crossNavigation": {
"inbounds": {
"Genres-manage": {
"signature": {
"parameters": {},
"additionalParameters": "allowed"
},
"semanticObject": "Genres",
"action": "manage"
}
}
}
},
"sap.ui5": {
"dependencies": {
"minUI5Version": "1.122.0",
"libs": {
"sap.fe.templates": {}
}
},
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"uri": "i18n/i18n.properties"
},
"": {
"dataSource": "AdminService",
"settings": {
"synchronizationMode": "None",
"operationMode": "Server",
"autoExpandSelect": true,
"earlyRequests": true,
"groupProperties": {
"default": {
"submit": "Auto"
}
}
}
}
},
"routing": {
"routes": [
{
"pattern": ":?query:",
"name": "GenresList",
"target": "GenresList"
},
{
"pattern": "Genres({key}):?query:",
"name": "GenresDetails",
"target": "GenresDetails"
}
],
"targets": {
"GenresList": {
"type": "Component",
"id": "GenresList",
"name": "sap.fe.templates.ListReport",
"options": {
"settings": {
"contextPath": "/Genres",
"navigation": {
"Genres": {
"detail": {
"route": "GenresDetails"
}
}
},
"controlConfiguration": {
"@com.sap.vocabularies.UI.v1.LineItem": {
"tableSettings": {
"hierarchyQualifier": "GenresHierarchy",
"type": "TreeTable"
}
}
}
}
}
},
"GenresDetails": {
"type": "Component",
"id": "GenresDetails",
"name": "sap.fe.templates.ObjectPage",
"options": {
"settings": {
"contextPath": "/Genres"
}
}
}
}
},
"contentDensities": {
"compact": true,
"cozy": true
}
},
"sap.ui": {
"technology": "UI5",
"fullWidth": false
},
"sap.fiori": {
"registrationIds": [],
"archeType": "transactional"
}
}

View File

@@ -6,5 +6,6 @@ using from './admin-authors/fiori-service';
using from './admin-books/fiori-service';
using from './browse/fiori-service';
using from './genres/fiori-service';
using from './common';
using from '@capire/bookstore/srv/mashup';

View File

@@ -1,14 +0,0 @@
namespace sap.capire.bookshop;
using { sap.capire.bookshop } from '@capire/bookstore/srv/mashup';
entity GenreHierarchy : bookshop.Genres {
hierarchyLevel : Integer default 0;
drillState : String default 'leaf';
parent : Association to GenreHierarchy;
children : Composition of many GenreHierarchy on children.parent = $self;
}
extend service CatalogService with {
@readonly entity GenreHierarchy as projection on bookshop.GenreHierarchy;
}

View File

@@ -1,16 +0,0 @@
ID;parent_ID;name;hierarchyLevel;drillState
10;;Fiction;0;expanded
11;10;Drama;1;leaf
12;10;Poetry;1;leaf
13;10;Fantasy;1;leaf
14;10;Science Fiction;1;leaf
15;10;Romance;1;leaf
16;10;Mystery;1;leaf
17;10;Thriller;1;leaf
18;10;Dystopia;1;leaf
20;;Non-Fiction;0;expanded
19;10;Fairy Tale;1;leaf
21;20;Biography;1;expanded
22;21;Autobiography;2;leaf
23;20;Essay;1;leaf
24;20;Speech;1;leaf
1 ID parent_ID name hierarchyLevel drillState
2 10 Fiction 0 expanded
3 11 10 Drama 1 leaf
4 12 10 Poetry 1 leaf
5 13 10 Fantasy 1 leaf
6 14 10 Science Fiction 1 leaf
7 15 10 Romance 1 leaf
8 16 10 Mystery 1 leaf
9 17 10 Thriller 1 leaf
10 18 10 Dystopia 1 leaf
11 20 Non-Fiction 0 expanded
12 19 10 Fairy Tale 1 leaf
13 21 20 Biography 1 expanded
14 22 21 Autobiography 2 leaf
15 23 20 Essay 1 leaf
16 24 20 Speech 1 leaf

View File

@@ -4,11 +4,10 @@
"dependencies": {
"@capire/bookstore": "*",
"@sap/cds": ">=5",
"@cap-js-community/odata-v2-adapter": "^1",
"express": "^4.17.1"
},
"devDependencies": {
"@cap-js/sqlite": "^1"
"@cap-js/sqlite": ">=1"
},
"scripts": {
"start": "cds-serve",
@@ -24,20 +23,8 @@
"kind": "odata",
"model": "@capire/orders"
},
"messaging": {
"[production]": {
"kind": "enterprise-messaging"
},
"[development]": {
"kind": "file-based-messaging"
},
"[hybrid]": {
"kind": "enterprise-messaging-shared"
}
},
"db": {
"kind": "sql"
},
"messaging": true,
"db": true,
"db-ext": {
"[development]": {
"model": "db/sqlite"
@@ -46,9 +33,6 @@
"model": "db/hana"
}
}
},
"hana": {
"deploy-format": "hdbtable"
}
},
"sapux": [

50
fiori/server.js Normal file
View File

@@ -0,0 +1,50 @@
const cds = require('@sap/cds/lib')
// PoC for simplified Fiori Tree Views
cds.on('compile.for.runtime', csn => {
for (let each of cds.linked(csn).definitions) {
if (each.is_entity && each._service && each['@hierarchy']) _hierarchy (each)
}
})
const _hierarchy = entity => {
// Add annotations explaining the hierarchy structure to Fiori
const Qualifier = entity.name.slice (entity._service.name.length+1) + 'Hierarchy'
const parent = _parent4(entity)
entity[`@Aggregation.RecursiveHierarchy#${Qualifier}.ParentNavigationProperty`] ??= {'=': parent.name }
entity[`@Aggregation.RecursiveHierarchy#${Qualifier}.NodeProperty`] ??= {'=': parent.keys[0].ref[0] }
// Add expected hierarchy elements to the entity
const columns = entity.projection.columns ??= ['*']
const elements = entity.elements
for (let e of Hierarchy.elements) {
entity[`@Hierarchy.RecursiveHierarchy#${Qualifier}.${e.name}`] = {'=': e.name }
if (e.name in elements) continue
const { name, value, ...rest } = e
elements[e.name] = Object.defineProperty ({ __proto__:e, ...rest }, 'parent', { value: entity })
columns.push ({ ...value, as: name, cast: { type: e.type } })
}
// Disable filter and sort for hierarchy elements
entity['@Capabilities.FilterRestrictions.NonFilterableProperties'] =
entity['@Capabilities.SortRestrictions.NonSortableProperties'] =
Object.keys (Hierarchy.elements)
}
const _parent4 = entity => {
const parent = entity['@hierarchy.parent'] || entity['@hierarchy.via']
if (parent) return entity.elements [parent['=']||parent]
else for (let e of entity.elements) // use first recursive uplink association
if (e.is2one && e._target === entity) return e
}
const { Hierarchy } = cds.linked `aspect Hierarchy {
LimitedDescendantCount : Int16 = null;
DistanceFromRoot : Int16 = null;
DrillState : String = null;
LimitedRank : Int16 = null;
}`.definitions

View File

@@ -1,15 +0,0 @@
# Hello World Getting Started Sample
## Next Steps
- To run the JavaScript implementation, open a new terminal and run `cds watch`.
- To run the TypeScript implementation, open a new terminal and run `cds-ts watch`.
Then call the service at: http://localhost:4004/say/hello(to='world')
## Learn More
Learn more about:
- [Hello World!](https://cap.cloud.sap/docs/get-started/hello-world)
- [Using TypeScript](https://cap.cloud.sap/docs/node.js/typescript)

View File

@@ -1,12 +0,0 @@
{
"name": "@capire/hello-world",
"version": "1.0.0",
"scripts": {
"test": "npx jest --silent",
"start": "cds-serve srv/world.cds",
"start:ts": "cds-ts serve srv/world.cds"
},
"dependencies": {
"@sap/cds": ">=5.0.4"
}
}

View File

@@ -1,3 +0,0 @@
service say {
function hello (to:String) returns String;
}

View File

@@ -1,7 +0,0 @@
module.exports = class say {
hello(req) {
let {to} = req.data
if (to === 'me') to = require('os').userInfo().username
return `Hello ${to}!`
}
}

View File

@@ -1,7 +0,0 @@
import { Request } from "@sap/cds"
module.exports = class say {
hello(req: Request) {
return `Hello ${req.data.to} from a TypeScript file!`
}
}

View File

@@ -1,5 +0,0 @@
GET http://localhost:4004/odata/v4/say/hello
###
GET http://localhost:4004/odata/v4/say/hello(to='me')
###

3
jest.config.mjs Normal file
View File

@@ -0,0 +1,3 @@
export default {
silent: true
}

View File

@@ -1,13 +0,0 @@
namespace sap.capire.media;
entity Media {
key id:Integer;
@Core.MediaType: mediaType
content : LargeBinary ;
@Core.IsMediaType: true
mediaType : String;
fileName : String;
applicationName:String;
}

View File

@@ -1,2 +0,0 @@
using from './db/data-model';
using from './srv/media-service';

View File

@@ -1,19 +0,0 @@
{
"name": "@capire/media",
"version": "1.0.0",
"dependencies": {
"lokijs": "^1.5.6"
},
"files": [
"db",
"srv",
"index.cds"
],
"cds": {
"requires": {
"db": {
"kind": "sql"
}
}
}
}

View File

@@ -1,9 +0,0 @@
using { sap.capire.media as db } from '../db/data-model';
namespace sap.capire.media;
@path: '/media-server'
service MediaServer {
entity Media as projection on db.Media ;
}

View File

@@ -1,68 +0,0 @@
const loki = require('lokijs')
const db = new loki('DB')
const mediaDB = db.addCollection('Media')
const { Readable, PassThrough } = require('stream')
module.exports = srv => {
srv.before('CREATE', 'Media', req => {
const obj = mediaDB.insert({ media: '' })
req.data.id = obj.$loki
})
srv.on('UPDATE', 'Media', (req, next) => {
const url = req.path
if (url.includes('content')) {
const id = req.data.id
const obj = mediaDB.get(id)
if (!obj) {
req.reject(404, 'No record found for the ID')
return
}
const stream = new PassThrough()
const chunks = []
stream.on('data', chunk => {
chunks.push(chunk)
})
stream.on('end', () => {
obj.media = Buffer.concat(chunks).toString('base64')
mediaDB.update(obj)
})
req.data.content.pipe(stream)
} else return next()
})
srv.on('READ', 'Media', (req, next) => {
const url = req.path
if (url.includes('content')) {
const id = req.data.id
const mediaObj = mediaDB.get(id)
if (!mediaObj) {
req.reject(404, 'Media not found for the ID')
return
}
const decodedMedia = Buffer.from(
mediaObj.media.split(';base64,').pop(),
'base64'
)
return _formatResult(decodedMedia)
} else return next() //> delegate to next/default handlers
})
srv.on('DELETE', 'Media', (req, next) => {
const id = req.data.id
mediaDB
.chain()
.find({ $loki: id })
.remove()
return next() //> delegate to next/default handlers
})
function _formatResult (decodedMedia) {
const readable = new Readable()
const result = new Array()
readable.push(decodedMedia)
readable.push(null)
result.push({ value: readable })
return result
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -1,35 +0,0 @@
### Requires REST Client for VS Code
### https://marketplace.visualstudio.com/items?itemName=humao.rest-client
###
@protocol = http
@host = localhost
@port = 4004
### Read Pictures
GET {{protocol}}://{{host}}:{{port}}/media-server/Media
Authorization: Basic admin:
### Create Picture with mediatype
POST {{protocol}}://{{host}}:{{port}}/media-server/Media
Authorization: Basic admin:
Accept: application/json
Content-Type: application/json
{
"id": 1,
"mediaType": "image/png"
}
### Upload Binary PNG
PUT {{protocol}}://{{host}}:{{port}}/media-server/Media(1)/content
Authorization: Basic admin:
Content-Type: image/png
< ./Test.png
### Read Binary
GET {{protocol}}://{{host}}:{{port}}/media-server/Media(1)/content
Authorization: Basic admin:
### Delete Image
DELETE {{protocol}}://{{host}}:{{port}}/media-server/Media(1)
Authorization: Basic admin:

178
mta.yaml Normal file
View File

@@ -0,0 +1,178 @@
_schema-version: 3.3.0
ID: capire.samples
version: 2.1.0
description: "A monorepo with several samples for CAP."
parameters:
enable-parallel-deployments: true
build-parameters:
before-all:
- builder: custom
commands:
- npm ci
- npx cds build shared-db --for hana --production
- npx cds build orders --for nodejs --production --ws-pack
- npx cds build reviews --for nodejs --production
- npx cds build bookstore --for nodejs --production --ws-pack
modules:
- name: orders-srv
type: nodejs
path: orders/gen/srv
parameters:
buildpack: nodejs_buildpack
readiness-health-check-type: http
readiness-health-check-http-endpoint: /health
disk-quota: 256M
memory: 256M
build-parameters:
builder: npm
provides:
- name: orders-api
properties:
srv-url: ${default-url}
requires:
- name: samples-messaging
- name: samples-db
- name: samples-auth
- name: reviews-srv
type: nodejs
path: reviews/gen/srv
parameters:
buildpack: nodejs_buildpack
readiness-health-check-type: http
readiness-health-check-http-endpoint: /health
disk-quota: 256M
memory: 256M
build-parameters:
builder: npm
provides:
- name: reviews-api
properties:
srv-url: ${default-url}
requires:
- name: samples-messaging
- name: samples-db
- name: samples-auth
- name: bookstore-srv
type: nodejs
path: bookstore/gen/srv
parameters:
buildpack: nodejs_buildpack
readiness-health-check-type: http
readiness-health-check-http-endpoint: /health
disk-quota: 256M
memory: 256M
properties:
cds_requires_ReviewsService_credentials: {"destination": "reviews-dest","path": "/reviews"}
cds_requires_OrdersService_credentials: {"destination": "orders-dest","path": "/odata/v4/orders"}
build-parameters:
builder: npm
provides:
- name: bookstore-api
properties:
srv-url: ${default-url}
requires:
- name: samples-messaging
- name: samples-db
- name: samples-auth
- name: samples-destination
- name: samples-db-deployer
type: hdb
path: shared-db/gen/db
parameters:
buildpack: nodejs_buildpack
requires:
- name: samples-db
- name: samples
type: approuter.nodejs
path: .deploy/app-router
parameters:
keep-existing-routes: true
disk-quota: 256M
memory: 256M
requires:
- name: orders-api
group: destinations
properties:
name: orders-api # must be used in xs-app.json as well
url: ~{srv-url}
forwardAuthToken: true
- name: reviews-api
group: destinations
properties:
name: reviews-api # must be used in xs-app.json as well
url: ~{srv-url}
forwardAuthToken: true
- name: bookstore-api
group: destinations
properties:
name: bookstore-api # must be used in xs-app.json as well
url: ~{srv-url}
forwardAuthToken: true
- name: samples-auth
- name: destination-content
type: com.sap.application.content
requires:
- name: orders-api
- name: reviews-api
- name: bookstore-api
- name: samples-auth
parameters:
service-key:
name: xsuaa-service-key
- name: samples-destination
parameters:
content-target: true
build-parameters:
no-source: true
parameters:
content:
instance:
existing_destinations_policy: update
destinations:
- Name: orders-dest
URL: ~{orders-api/srv-url}
Authentication: OAuth2ClientCredentials
TokenServiceInstanceName: samples-auth
TokenServiceKeyName: xsuaa-service-key
- Name: reviews-dest
URL: ~{reviews-api/srv-url}
Authentication: OAuth2ClientCredentials
TokenServiceInstanceName: samples-auth
TokenServiceKeyName: xsuaa-service-key
resources:
- name: samples-messaging
type: org.cloudfoundry.managed-service
parameters:
service: enterprise-messaging
service-plan: default
path: ./event-mesh.json
config:
emname: bookstore-${org}-${space}
namespace: cap/samples/${space}
- name: samples-db
type: com.sap.xs.hdi-container
parameters:
service: hana
service-plan: hdi-shared
- name: samples-auth
type: org.cloudfoundry.managed-service
processed-after:
- samples-messaging
parameters:
service: xsuaa
service-plan: application
path: ./xs-security.json
config:
xsappname: samples-${org}-${space}
tenant-mode: dedicated
- name: samples-destination
type: org.cloudfoundry.managed-service
parameters:
service: destination
service-plan: lite

View File

@@ -1,2 +1 @@
cds.requires.messaging.kind = file-based-messaging
PORT = 4006

View File

@@ -16,15 +16,15 @@
description: "CAP Sample App",
additionalInformation: "SAPUI5.Component=orders",
applicationType : "URL",
url: "/orders/webapp",
url: "webapp",
navigationMode: "embedded"
}
}
};
</script>
<script id="sap-ushell-bootstrap" src="https://sapui5.hana.ondemand.com/test-resources/sap/ushell/bootstrap/sandbox.js"></script>
<script id="sap-ui-bootstrap" src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
<script id="sap-ushell-bootstrap" src="https://ui5.sap.com/test-resources/sap/ushell/bootstrap/sandbox.js"></script>
<script id="sap-ui-bootstrap" src="https://ui5.sap.com/resources/sap-ui-core.js"
data-sap-ui-libs="sap.m, sap.ushell, sap.collaboration, sap.ui.layout"
data-sap-ui-compatVersion="edge"
data-sap-ui-theme="sap_horizon"

View File

@@ -2,7 +2,18 @@
"name": "@capire/orders",
"version": "1.0.0",
"dependencies": {
"@cap-js/hana": ">=1",
"@capire/common": "*",
"@sap/cds": ">=5"
"@sap/cds": ">=5",
"@sap/xssec": "^4"
},
"cds": {
"requires": {
"messaging": true,
"db": true
}
},
"scripts": {
"start": "cds-serve"
}
}
}

View File

@@ -2,4 +2,14 @@ using { sap.capire.orders as my } from '../db/schema';
service OrdersService {
entity Orders as projection on my.Orders;
@odata.draft.bypass
@(requires: 'system-user')
entity OrdersNoDraft as projection on my.Orders;
event OrderChanged {
product: String;
deltaQuantity: Integer;
}
}

View File

@@ -8,18 +8,14 @@ class OrdersService extends cds.ApplicationService {
this.before ('UPDATE', 'Orders', async function(req) {
const { ID, Items } = req.data
if (Items) for (let { product_ID, quantity } of Items) {
const { quantity:before } = await cds.tx(req).run (
SELECT.one.from (OrderItems, oi => oi.quantity) .where ({up__ID:ID, product_ID})
)
const { quantity:before } = await SELECT.one.from (OrderItems, oi => oi.quantity) .where ({up__ID:ID, product_ID})
if (quantity != before) await this.orderChanged (product_ID, quantity-before)
}
})
this.before ('DELETE', 'Orders', async function(req) {
const { ID } = req.data
const Items = await cds.tx(req).run (
SELECT.from (OrderItems, oi => { oi.product_ID, oi.quantity }) .where ({up__ID:ID})
)
const Items = await SELECT.from (OrderItems, oi => { oi.product_ID, oi.quantity }) .where ({up__ID:ID})
if (Items) await Promise.all (Items.map(it => this.orderChanged (it.product_ID, -it.quantity)))
})

5578
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,51 +1,44 @@
{
"name": "@capire/samples",
"version": "2.1.0",
"description": "A monorepo with several samples for CAP.",
"repository": "https://github.com/sap-samples/cloud-cap-samples.git",
"author": "daniel.hutzel@sap.com",
"dependencies": {
"@sap/cds": ">=8"
},
"workspaces": [
"./bookshop",
"./bookstore",
"./common",
"./data-viewer",
"./fiori",
"./hello",
"./media",
"./orders",
"./loggers",
"./reviews"
],
"devDependencies": {
"@cap-js/cds-types": "^0",
"@cap-js/sqlite": "^1",
"axios": "^1",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"chai-subset": "^1.6.0",
"eslint": "^9",
"semver": "^7"
},
"scripts": {
"bookshop": "cds watch bookshop",
"start": "cds watch fiori",
"fiori": "cds watch fiori",
"hello": "cds watch hello",
"media": "cds watch media",
"lint": "eslint",
"test": "npx jest --silent",
"jest": "npx jest --silent",
"mocha": "CDS_TEST_SILENT=y npx mocha",
"test:hello": "cd hello && npm test"
},
"mocha": {
"recursive": true,
"parallel": true,
"timeout": 6666
},
"license": "SEE LICENSE IN LICENSE",
"private": true
}
"name": "@capire/samples",
"version": "3.0.0",
"description": "A monorepo with several samples for CAP.",
"repository": "https://github.com/sap-samples/cloud-cap-samples.git",
"author": "daniel.hutzel@sap.com",
"workspaces": [
"bookshop",
"bookstore",
"common",
"fiori",
"orders",
"reviews",
"shared-db",
"etc/data-viewer",
"etc/loggers"
],
"devDependencies": {
"@cap-js/cds-test": "^0"
},
"scripts": {
"start": "cds watch bookshop --open http://localhost:4004",
"bookstore": "cds watch bookstore",
"bookshop": "cds watch bookshop",
"fiori": "cds watch fiori",
"orders": "cds watch orders",
"reviews": "cds watch reviews",
"lint": "npx eslint",
"test": "chest test",
"jest": "npx jest",
"mocha": "npx mocha",
"node:test": "node --test",
"build": "mbt build -t gen --mtar mta.tar",
"deploy": "cf deploy gen/mta.tar",
"undeploy": "cf undeploy capire.samples --delete-services --delete-service-keys"
},
"mocha": {
"recursive": true,
"parallel": true,
"timeout": 6666
},
"license": "SEE LICENSE IN LICENSE",
"private": true
}

57
readme.md Normal file
View File

@@ -0,0 +1,57 @@
# Welcome to cap/samples
Find here a collection of samples for the [SAP Cloud Application Programming Model](https://cap.cloud.sap) organized in a simplistic [monorepo setup](samples.md#all-in-one-monorepo).
![](https://github.com/SAP-samples/cloud-cap-samples/workflows/CI/badge.svg)
## Get Started
Assumed you did your [initial setup of CAP Node.js](https://cap.cloud.sap/docs/get-started/#setup), simply copy & paste these lines to a terminal for a jumpstart:
```sh
git clone -q https://github.com/sap-samples/cloud-cap-samples cap/samples
cd cap/samples
npm install
npm test
npm start
```
After download and setup this starts the bookshop server and opens a browser window on _http://localhost:4004_ looking like that:
<p align="center">
<img width=480 src="etc/index-html.png" alt="bookshop showing up in browser" />
</p>
Click on the *[/vue](http:/localhost:4004/vue)* link at the top to display the bookshop app (when asked to log in, type `alice` as user and leave the password field blank).
## Grow as you go...
After the jumpstart, have a look into the enclosed sub folders/projects, which are:
- [bookshop](bookshop) a simplistic [primer app](https://cap.cloud.sap/docs/get-started/in-a-nutshell)
- [reviews](reviews) - a generic reuse service
- [orders](orders) - a generic reuse service
- [common](common) - a reuse content package
- [bookstore](bookstore) - a composite app of the above
- [fiori](fiori) - Fiori elements UIs for the bookstore
- [etc/*](etc) - Plugins adding cross-cutting concerns
- [test](test) - Tests for all the above
> _see also [samples.md](samples.md)_
<p align="center">
<img width=480 src="etc/samples.drawio.svg">
</p>
## Get Help
- Visit the [*capire* docs](https://cap.cloud.sap) to learn about CAP, ...
- especially [*Getting Started in a Nutshell*](https://cap.cloud.sap/docs/get-started/in-a-nutshell).
- Visit our [*SAP Community*](https://answers.sap.com/tags/9f13aee1-834c-4105-8e43-ee442775e5ce) to ask questions.
## License
Copyright (c) 2022 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, version 2.0 except as noted otherwise in the _[LICENSE](LICENSE)_ file.

View File

@@ -69,3 +69,25 @@ const reviews = Vue.createApp ({
// initially fill list of my reviews
reviews.fetch()
axios.interceptors.request.use(csrfToken)
function csrfToken (request) {
if (request.method === 'head' || request.method === 'get') return request
if ('csrfToken' in document) {
request.headers['x-csrf-token'] = document.csrfToken
return request
}
return fetchToken().then(token => {
document.csrfToken = token
request.headers['x-csrf-token'] = document.csrfToken
return request
}).catch(() => {
document.csrfToken = null // set mark to not try again
return request
})
function fetchToken() {
return axios.get('/', { headers: { 'x-csrf-token': 'fetch' } })
.then(res => res.headers['x-csrf-token'])
}
}

View File

@@ -3,7 +3,7 @@
<head>
<title> Capire Reviews </title>
<link rel="stylesheet" href="https://unpkg.com/primitive-ui/dist/css/main.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/primitive-ui/dist/css/main.css">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
<style>

View File

@@ -1,5 +1,5 @@
subject;rating;reviewer;title;text
201;5;bob;Intriguing;Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
201;4;bob;Fascinating;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Id diam maecenas ultricies mi eget mauris pharetra et. Risus at ultrices mi tempus imperdiet nulla malesuada pellentesque. Pulvinar mattis nunc sed blandit libero. Facilisis magna etiam tempor orci eu. Nec sagittis aliquam malesuada bibendum arcu. Eu consequat ac felis donec. Ultricies tristique nulla aliquet enim tortor at auctor urna nunc. Tortor posuere ac ut consequat semper viverra nam libero. Amet nisl suscipit adipiscing bibendum est ultricies integer quis auctor. Scelerisque purus semper eget duis at tellus. Elementum tempus egestas sed sed risus pretium. Arcu dictum varius duis at. Amet luctus venenatis lectus magna fringilla urna. Eget velit aliquet sagittis id consectetur purus ut faucibus. Vitae auctor eu augue ut lectus. Fermentum iaculis eu non diam phasellus vestibulum.
207;2;bob;What is this?;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Libero justo laoreet sit amet cursus sit amet dictum. Nunc faucibus a pellentesque sit. Dis parturient montes nascetur ridiculus mus mauris vitae ultricies. Enim nunc faucibus a pellentesque. Commodo quis imperdiet massa tincidunt nunc pulvinar sapien. Cras ornare arcu dui vivamus. Facilisi etiam dignissim diam quis enim lobortis. Et molestie ac feugiat sed. Urna neque viverra justo nec ultrices dui. Ullamcorper a lacus vestibulum sed arcu non. Volutpat ac tincidunt vitae semper quis. Dignissim sodales ut eu sem. Feugiat in fermentum posuere urna nec. At augue eget arcu dictum varius.
251;3;bob;It's dark...;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Suscipit tellus mauris a diam. Velit aliquet sagittis id consectetur purus ut. Viverra adipiscing at in tellus integer. Vitae elementum curabitur vitae nunc. Mattis ullamcorper velit sed ullamcorper morbi. Diam quis enim lobortis scelerisque. Auctor neque vitae tempus quam pellentesque nec nam aliquam. Semper auctor neque vitae tempus. Quis eleifend quam adipiscing vitae proin. Neque convallis a cras semper auctor neque vitae. Imperdiet massa tincidunt nunc pulvinar sapien et ligula. Sit amet consectetur adipiscing elit ut aliquam purus. Pretium quam vulputate dignissim suspendisse.
ID;subject;rating;reviewer;title;text
1689144d-3b10-4849-bcbe-2408a13e161d;201;5;bob;Intriguing;Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
539ab728-3068-450f-a617-ed5af9e9dbb7;201;4;bob;Fascinating;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Id diam maecenas ultricies mi eget mauris pharetra et. Risus at ultrices mi tempus imperdiet nulla malesuada pellentesque. Pulvinar mattis nunc sed blandit libero. Facilisis magna etiam tempor orci eu. Nec sagittis aliquam malesuada bibendum arcu. Eu consequat ac felis donec. Ultricies tristique nulla aliquet enim tortor at auctor urna nunc. Tortor posuere ac ut consequat semper viverra nam libero. Amet nisl suscipit adipiscing bibendum est ultricies integer quis auctor. Scelerisque purus semper eget duis at tellus. Elementum tempus egestas sed sed risus pretium. Arcu dictum varius duis at. Amet luctus venenatis lectus magna fringilla urna. Eget velit aliquet sagittis id consectetur purus ut faucibus. Vitae auctor eu augue ut lectus. Fermentum iaculis eu non diam phasellus vestibulum.
cd9bfd8d-eab4-40ee-9b46-770302533009;207;2;bob;What is this?;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Libero justo laoreet sit amet cursus sit amet dictum. Nunc faucibus a pellentesque sit. Dis parturient montes nascetur ridiculus mus mauris vitae ultricies. Enim nunc faucibus a pellentesque. Commodo quis imperdiet massa tincidunt nunc pulvinar sapien. Cras ornare arcu dui vivamus. Facilisi etiam dignissim diam quis enim lobortis. Et molestie ac feugiat sed. Urna neque viverra justo nec ultrices dui. Ullamcorper a lacus vestibulum sed arcu non. Volutpat ac tincidunt vitae semper quis. Dignissim sodales ut eu sem. Feugiat in fermentum posuere urna nec. At augue eget arcu dictum varius.
f2896a44-637f-4198-a428-c0966d10b7ce;251;3;bob;It's dark...;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Suscipit tellus mauris a diam. Velit aliquet sagittis id consectetur purus ut. Viverra adipiscing at in tellus integer. Vitae elementum curabitur vitae nunc. Mattis ullamcorper velit sed ullamcorper morbi. Diam quis enim lobortis scelerisque. Auctor neque vitae tempus quam pellentesque nec nam aliquam. Semper auctor neque vitae tempus. Quis eleifend quam adipiscing vitae proin. Neque convallis a cras semper auctor neque vitae. Imperdiet massa tincidunt nunc pulvinar sapien et ligula. Sit amet consectetur adipiscing elit ut aliquam purus. Pretium quam vulputate dignissim suspendisse.
1 ID subject rating reviewer title text
2 1689144d-3b10-4849-bcbe-2408a13e161d 201 5 bob Intriguing Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
3 539ab728-3068-450f-a617-ed5af9e9dbb7 201 4 bob Fascinating Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Id diam maecenas ultricies mi eget mauris pharetra et. Risus at ultrices mi tempus imperdiet nulla malesuada pellentesque. Pulvinar mattis nunc sed blandit libero. Facilisis magna etiam tempor orci eu. Nec sagittis aliquam malesuada bibendum arcu. Eu consequat ac felis donec. Ultricies tristique nulla aliquet enim tortor at auctor urna nunc. Tortor posuere ac ut consequat semper viverra nam libero. Amet nisl suscipit adipiscing bibendum est ultricies integer quis auctor. Scelerisque purus semper eget duis at tellus. Elementum tempus egestas sed sed risus pretium. Arcu dictum varius duis at. Amet luctus venenatis lectus magna fringilla urna. Eget velit aliquet sagittis id consectetur purus ut faucibus. Vitae auctor eu augue ut lectus. Fermentum iaculis eu non diam phasellus vestibulum.
4 cd9bfd8d-eab4-40ee-9b46-770302533009 207 2 bob What is this? Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Libero justo laoreet sit amet cursus sit amet dictum. Nunc faucibus a pellentesque sit. Dis parturient montes nascetur ridiculus mus mauris vitae ultricies. Enim nunc faucibus a pellentesque. Commodo quis imperdiet massa tincidunt nunc pulvinar sapien. Cras ornare arcu dui vivamus. Facilisi etiam dignissim diam quis enim lobortis. Et molestie ac feugiat sed. Urna neque viverra justo nec ultrices dui. Ullamcorper a lacus vestibulum sed arcu non. Volutpat ac tincidunt vitae semper quis. Dignissim sodales ut eu sem. Feugiat in fermentum posuere urna nec. At augue eget arcu dictum varius.
5 f2896a44-637f-4198-a428-c0966d10b7ce 251 3 bob It's dark... Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Suscipit tellus mauris a diam. Velit aliquet sagittis id consectetur purus ut. Viverra adipiscing at in tellus integer. Vitae elementum curabitur vitae nunc. Mattis ullamcorper velit sed ullamcorper morbi. Diam quis enim lobortis scelerisque. Auctor neque vitae tempus quam pellentesque nec nam aliquam. Semper auctor neque vitae tempus. Quis eleifend quam adipiscing vitae proin. Neque convallis a cras semper auctor neque vitae. Imperdiet massa tincidunt nunc pulvinar sapien et ligula. Sit amet consectetur adipiscing elit ut aliquam purus. Pretium quam vulputate dignissim suspendisse.

View File

@@ -7,17 +7,18 @@
"index.cds"
],
"dependencies": {
"@cap-js/hana": ">=1",
"@sap/cds": ">=5",
"@sap/xssec": "^4.2.7",
"express": "^4.17.1"
},
"cds": {
"requires": {
"messaging": {
"[development]": { "kind": "file-based-messaging" },
"[hybrid]": { "kind": "enterprise-messaging-shared" },
"[production]": { "kind": "enterprise-messaging" }
},
"db": { "kind": "sql" }
"messaging": true,
"db": true
}
},
"scripts": {
"start": "cds-serve"
}
}
}

View File

@@ -3,7 +3,7 @@ module.exports = cds.service.impl (function(){
// Get the CSN definition for Reviews from the db schema for sub-sequent queries
// ( Note: we explicitly specify the namespace to support embedded reuse )
const { Reviews, Likes } = this.entities ('sap.capire.reviews')
const { Reviews, Likes } = this.entities
this.before (['CREATE','UPDATE'], 'Reviews', req => {
if (!req.data.rating) req.data.rating = Math.round(Math.random()*4)+1
@@ -12,9 +12,7 @@ module.exports = cds.service.impl (function(){
// Emit an event to inform subscribers about new avg ratings for reviewed subjects
this.after (['CREATE','UPDATE','DELETE'], 'Reviews', async function(_,req) {
const {subject} = req.data
const { count, rating } = await cds.tx(req) .run (
SELECT.one `round(avg(rating),2) as rating, count(*) as count` .from (Reviews) .where ({subject})
)
const { count, rating } = await SELECT.one `round(avg(rating),2) as rating, count(*) as count` .from (Reviews) .where ({subject})
global.it || console.log ('< emitting:', 'reviewed', { subject, count, rating }) // eslint-disable-line no-console
await this.emit ('reviewed', { subject, count, rating })
})
@@ -23,8 +21,7 @@ module.exports = cds.service.impl (function(){
this.on ('like', (req) => {
if (!req.user) return req.reject(400, 'You must be identified to like a review')
const {review} = req.data, {user} = req
const tx = cds.tx(req)
return tx.run ([
return cds.run ([
INSERT.into (Likes) .entries ({review_ID: review, user: user.id}),
UPDATE (Reviews) .set({liked: {'+=': 1}}) .where({ID:review})
]).catch(() => req.reject(400, 'You already liked that review'))
@@ -34,9 +31,8 @@ module.exports = cds.service.impl (function(){
this.on ('unlike', async (req) => {
if (!req.user) return req.reject(400, 'You must be identified to remove a former like of yours')
const {review} = req.data, {user} = req
const tx = cds.tx(req)
const affectedRows = await tx.run (DELETE.from (Likes) .where ({review_ID: review,user: user.id}))
if (affectedRows === 1) return tx.run (UPDATE (Reviews) .set ({liked: {'-=': 1}}) .where ({ID:review}))
const affectedRows = await DELETE.from (Likes) .where ({review_ID: review,user: user.id})
if (affectedRows === 1) return UPDATE (Reviews) .set ({liked: {'-=': 1}}) .where ({ID:review})
})
})

View File

@@ -6,12 +6,6 @@ Each sub directory essentially is an individual npm package arranged in an [all-
![](etc/samples.drawio.svg)
## [@capire/hello-world](hello)
- A simplistic [Hello World](https://cap.cloud.sap/docs/get-started/hello-world) service using [CDS](https://cap.cloud.sap/docs/cds/) and [cds.services](https://cap.cloud.sap/docs/node.js/api#services-api).
- [Typescript support](https://cap.cloud.sap/docs/node.js/typescript)
## [@capire/bookshop](bookshop)
- [Getting Started](https://cap.cloud.sap/docs/get-started/in-a-nutshell) with CAP, briefly introducing:
@@ -60,13 +54,11 @@ Each sub directory essentially is an individual npm package arranged in an [all-
- [@capire/reviews](reviews)
- [@capire/orders](orders)
- [@capire/common](common)
- [@capire/data-viewer](data-viewer)
- [@capire/data-viewer](etc/data-viewer)
- [The Vue.js app](bookshop/app/vue) imported from `bookshop` is served as well
- [The Vue.js app](reviews/app/vue) imported from `reviews` is served as well
- [The Vue.js app](data-viewer/app/data) imported from `data-viewer` is served as well
- [The Vue.js app](etc/data-viewer/app/data) imported from `data-viewer` is served as well
- [The Fiori app](orders/app) imported from `orders` is served as well
- [OpenAPI export + Swagger UI](https://cap.cloud.sap/docs/advanced/openapi)
## [@capire/fiori](fiori)
@@ -76,10 +68,6 @@ Each sub directory essentially is an individual npm package arranged in an [all-
- Support for Fiori Draft
- Support for Value Helps
- Serving SAP Fiori apps locally
- Fiori Elements V2
- OData V2 using CDS OData V2 Adapter Proxy
- List Report (type `TreeTable`)
- `@sap.hierarchy` annotations
See the [Serving Fiori UIs](https://cap.cloud.sap/docs/advanced/fiori) documentation for more information.

3
shared-db/db/schema.cds Normal file
View File

@@ -0,0 +1,3 @@
using from '@capire/bookstore';
using from '@capire/reviews';
using from '@capire/orders';

Some files were not shown because too many files have changed in this diff Show More