{"id":16163462,"url":"https://github.com/gregorwolf/bookshop-demo","last_synced_at":"2025-04-13T05:24:39.416Z","repository":{"id":38029616,"uuid":"197668993","full_name":"gregorwolf/bookshop-demo","owner":"gregorwolf","description":"Simple CDS bookshop","archived":false,"fork":false,"pushed_at":"2025-04-10T11:14:25.000Z","size":9687,"stargazers_count":118,"open_issues_count":12,"forks_count":77,"subscribers_count":8,"default_branch":"main","last_synced_at":"2025-04-10T12:49:21.811Z","etag":null,"topics":["cap","cloud-foundry","nodejs","sample","sap-btp","sap-cap"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gregorwolf.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["gregorwolf"],"patreon":null,"open_collective":null,"ko_fi":"gregorwolf","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2019-07-18T23:22:05.000Z","updated_at":"2025-04-10T11:14:29.000Z","dependencies_parsed_at":"2023-10-02T06:42:33.141Z","dependency_job_id":"a694f479-b261-4553-ab13-f49d7f60d3ce","html_url":"https://github.com/gregorwolf/bookshop-demo","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregorwolf%2Fbookshop-demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregorwolf%2Fbookshop-demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregorwolf%2Fbookshop-demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gregorwolf%2Fbookshop-demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gregorwolf","download_url":"https://codeload.github.com/gregorwolf/bookshop-demo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248666971,"owners_count":21142352,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cap","cloud-foundry","nodejs","sample","sap-btp","sap-cap"],"created_at":"2024-10-10T02:35:46.076Z","updated_at":"2025-04-13T05:24:39.381Z","avatar_url":"https://github.com/gregorwolf.png","language":"TypeScript","funding_links":["https://github.com/sponsors/gregorwolf","https://ko-fi.com/gregorwolf"],"categories":[],"sub_categories":[],"readme":"# Bookshop Sample App\n\nSample application showcasing different services serving the same set of data entities from a sqlite database.\nThe services match different use cases visualized in corresponding Fiori apps.\n\n## Develop in VS Code devcontainer\n\nThe easiest way to get started with devlopment of this project is inside a Docker Devcontainer. See [this blog post](https://github.com/htammen/cap-vscode-dev-container#so-what-do-i-have-to-do) for details.  \nIf you don't have Docker installed **you can of course develop within you local OS**. But in that case you have to install all your tools and vs extensions on your own.\n\n## Preliminaries\n\n- get [_Node.js_](https://nodejs.org/en/) v16 or higher\n- get [_sqlite_](https://www.sqlite.org/download.html) (Windows only; pre-installed on Mac/Linux)\n- As SAP has deprecated their own NPM registry please remove the setting in your npm config with the following command\n\n```sh\nnpm config rm @sap:registry\n```\n\n## Setup\n\nCopy \u0026 paste this to your command line:\n\n```sh\ngit clone https://github.com/gregorwolf/bookshop-demo.git\ncd bookshop-demo\nnpm install\nnpm run setup\n```\n\n## Run local\n\nIf you want to try also the external service calls, then you need to create a `default-env.json` file in the project root folder and add the following content:\n\n```json\n{\n  \"destinations\": [\n    {\n      \"name\": \"ES5\",\n      \"url\": \"https://sapes5.sapdevcenter.com\",\n      \"username\": \"\u003cyour-ES5-username\u003e\",\n      \"password\": \"\u003cyour-ES5-password\u003e\"\n    },\n    {\n      \"name\": \"ERP\",\n      \"url\": \"https://saperp.example.com\",\n      \"username\": \"\u003cyour-ERP-username\u003e\",\n      \"password\": \"\u003cyour-ERP-password\u003e\"\n    }\n  ]\n}\n```\n\n```sh\nnpm run build\nnpm start\n```\n\nIf you want to test the used SAP Business Technology Platform - Cloud Foundry services you need also to add the VCAP\\*SERVICES variable to `default-env.json`. I.e.:\n\n```json\n{\n  \"VCAP_SERVICES\": {}\n}\n```\n\n## Run local with SAP HANA Cloud (Hybrid Testing)\n\nBefore you can run the following commands you need to connect to the BTP Cloud Foundry environment using:\n\n```\ncf login -a \u003cCF-API-Endpoint\u003e -o \u003cCF-Organization\u003e -s \u003cCF-Space\u003e --sso\n```\n\nThen you can create or update an existing HDI using:\n\n```\nnpm run deploy:hana\n```\n\nThis should write the needed information to `.cdsrc-private.json`. When you have deployed the application already to BTP Cloud Foundry you can run:\n\n```\ncds bind -2 bookshop-demo-db-service --for hybrid\n```\n\nto reuse the existing HDI container. Then you can use:\n\n```\nnpm run test:hana\n```\n\nto start the test or you run\n\n```\nnpm run start:hana\n```\n\nto start the app with SAP HANA Cloud as the database.\n\n## Test\n\nOpen these links in your browser:\n\n- \u003chttp://localhost:4004/webapp/fiori.html\u003e \u0026ndash; Fiori Launchpad sandbox\n\n## Late-Cut Microservices\n\nThe services:\n\n- JobService\n- JobExecutionService\n\nshow a concrete example of the [Late-Cut Microservices](https://cap.cloud.sap/docs/guides/providing-services#late-cut-microservices).\n\nTo get the two instances talk to each other you need to add the following entries in `default-env.json`:\n\n```json\n{\n  \"destinations\": [\n    {\n      \"existing\": \"entries\"\n    },\n    {\n      \"name\": \"job-service\",\n      \"url\": \"http://localhost:4004\",\n      \"username\": \"job\",\n      \"password\": \"Secret1\"\n    },\n    {\n      \"name\": \"job-execution-service\",\n      \"url\": \"http://localhost:4005\",\n      \"username\": \"job-execution\",\n      \"password\": \"Secret2\"\n    }\n  ]\n}\n```\n\n### Run local with sqlite\n\nTo run this example locally you can run:\n\n```\nrun-s \"deploy:sqlite:instance:**\"\n```\n\nto deploy two separate sqlite databases. You can start the two instances\n\n```\nnpm run watchboth\n```\n\n### Run hybrid with SAP HANA Cloud\n\nFirst you need to create the HDI Containers using:\n\n```\nrun-s \"deploy:hana:instance:**\"\n```\n\nDue to the issue reported at [cds deploy does not support --profile](https://answers.sap.com/questions/13754675/cds-deploy-does-not-support-profile.html) the resulting configuration isn't written to the profiles defined with --profile. So you need to add this entries manually to your `.cdsrc-private.json`:\n\n```json\n{\n  \"requires\": {\n    \"[hybrid-instance1]\": {\n      \"db\": {\n        \"binding\": {\n          \"type\": \"cf\",\n          \"apiEndpoint\": \"\u003cCF-API-Endpoint\u003e\",\n          \"org\": \"\u003cCF-Organization\u003e\",\n          \"space\": \"\u003cCF-Space\u003e\",\n          \"instance\": \"bookshop-demo-db-instance1\",\n          \"key\": \"bookshop-demo-db-instance1-key\",\n          \"resolved\": false\n        },\n        \"kind\": \"hana\",\n        \"vcap\": {\n          \"name\": \"db\"\n        }\n      }\n    },\n    \"[hybrid-instance2]\": {\n      \"db\": {\n        \"binding\": {\n          \"type\": \"cf\",\n          \"apiEndpoint\": \"\u003cCF-API-Endpoint\u003e\",\n          \"org\": \"\u003cCF-Organization\u003e\",\n          \"space\": \"\u003cCF-Space\u003e\",\n          \"instance\": \"bookshop-demo-db-instance2\",\n          \"key\": \"bookshop-demo-db-instance2-key\",\n          \"resolved\": false\n        },\n        \"kind\": \"hana\",\n        \"vcap\": {\n          \"name\": \"db\"\n        }\n      }\n    },\n```\n\nThen you can start with:\n\n```\nnpm run start:hybridboth\n```\n\n### Testing\n\nUse the REST Client scripts in `tests/job.http`.\n\n### Adding XSUAA Authentication\n\n```sh\ncf create-service xsuaa broker bookshop-demo-uaa -c xs-security.json\ncf create-service-key bookshop-demo-uaa bookshop-demo-uaa-key\ncf create-service xsuaa broker bookshop-demo-instance2-uaa -c xs-security-instance2.json\ncf create-service-key bookshop-demo-instance2-uaa bookshop-demo-instance2-uaa-key\n```\n\n```\ncds bind -2 bookshop-demo-uaa\ncds bind -2 bookshop-demo-instance2-uaa\n```\n\n## Manual steps needed for Service Broker\n\n### Generate Broker Credentials\n\n1. Navigate into folder `/broker`\n2. Run command `npm i` in terminal\n3. Run command `npm run init` in terminal\n4. Store the generated credentials in a safe place\n\n### Create `.mtaext` file\n\n1. Copy file `cf-service-broker-template.mtaext` to `cf-service-broker-private.mtaext`\n2. Copy the hashed broker credentials from your safe place into the `cf-service-broker-private.mtaext` file\n\n### Register broker\n\nBuild and deploy the MTAR as described in the next step. After the deployment you can register the broker with:\n\n```sh\ncf create-service-broker bookshop-demo-broker broker-user \u003cplain-broker-password\u003e \u003cbroker-url\u003e --space-scoped\n```\n\n- The `broker-url` can be read from e.g. the SAP BTP cockpit by navigating to the broker application in the space where it was deployed.\n\n## Deploy to SAP Cloud Platform - Cloud Foundry Environment\n\nWe're using the mbt build to create a mtar that can be deployed to the SAP CP Cloud Foundry. The cf commandline must be installed and you have to be logged on to the space you want to deploy to. The build ist started with:\n\n```\nnpm run build:cf\n```\n\nthen you can deploy with:\n\n```\nnpm run deploy:cf\n```\n\nIf you need to redirect destinations according to your configuration you can achieve this by setting the environment variable `CDS_CONFIG` to this value:\n\n```JSON\n{\n  \"requires\": {\n    \"GWSAMPLE_BASIC\": {\n      \"credentials\": {\n        \"destination\": \"S4HANA\"\n      }\n    },\n    \"API_CV_ATTACHMENT_SRV\": {\n      \"credentials\": {\n        \"destination\": \"S4HANA\"\n      }\n    }\n  }\n}\n```\n\n## Deploy to SAP HANA XSA on Premise\n\nWe're using the mbt build to create a mtar that can be deployed to the SAP HANA. The xs commandline must be installed and you have to be logged on to the space you want to deploy to. The build ist started with:\n\n```\nnpm run build:xsa\n```\n\nthen you can deploy with:\n\n```\nnpm run deploy:xsa\n```\n\n## Allow embedding as an iFrame\n\nManuel Seeger described the needed steps in [Can't authenticate against HTML-Mashup embedded SCP application in C4C](https://answers.sap.com/questions/13014707/cant-authenticate-against-html-mashup-embedded-scp.html). Here are the concrete steps for this application:\n\n```sh\ncf create-service xsuaa apiaccess bookshop-access\ncf create-service-key bookshop-access bookshop-access-sk\ncf service-key bookshop-access bookshop-access-sk\n```\n\nStore the returned values as Key-Value Pairs in tests/.env. I.e.:\n\n```\napiurl=\"https://api.authentication.us10.hana.ondemand.com\"\n```\n\nAlso add a variable for appurl which represents the app you want to enable to be embedded in an iFrame. Then run the REST Client Script tests/configure-xsuaa.http.\n\n## Allow API Access\n\n[Carlos Roggan](https://people.sap.com/carlos.roggan) provides a great description in his SAP Community blog post: [How to call protected app from external app as external user with scope](https://blogs.sap.com/2020/06/02/how-to-call-protected-app-from-external-app-as-external-user-with-scope/). For the moment we will not use a separate client app but a REST client script. Follow the next steps to get it working for this project. You have to create and display a service key for the client xsuaa instance:\n\n```sh\ncf create-service-key xsuaaforclient xsuaaforclient-sk\ncf service-key xsuaaforclient xsuaaforclient-sk\n```\n\nStore the returned values as Key-Value Pairs for clientid, clientsecret, url in tests/.env. as:\n\n```\nclientid=\"sb-xsappforclientapp!dsjdfs\"\nclientsecret=\"NbFeh8ibk2zQ=\"\nurl=\"https://\u003cyour-trial-account\u003etrial.authentication.eu10.hana.ondemand.com\"\nsrvurl=\"https://\u003cyour-trial-account\u003etrial-dev-bookshop-demo-srv.cfapps.us10.hana.ondemand.com\"\n```\n\nThen open the REST Client script `tests/api-access.http` in VS Code and run the script with the comment `Get Access Token (Cloud Foundry)`. It should return a valid access\\*token. Now execute the requests `Read Orders` and `Read Books`. You should see a valid result.\n\n## Authentication and Authorization\n\nThe services of this application use authentication and authorization to\nrestrict usage of the functions.  \nThe scopes of the app are defined in `xs-security.json`.\nThey are used in the services files `srv/cat-service.cds` and `srv/admin-service.cds`.\n\n_Please have a look at these files for the restrictions cause they can change due to the POC character of this project_\n\n### Authentication and Authorization in local environment\n\nIf you run the application in a local environment the users you can use are\ndefined in the field `.cdsrc`.  \nCurrently in this file the following users are defined\n\n_Please have a look at this file to see the current users and roles cause they can change due to the POC character of this project_\n\n| Username    | Scopes                       |\n| ----------- | ---------------------------- |\n| requester   | admin                        |\n| booksadmin  | booksadmin                   |\n| admin       | admin, roleadmin, booksadmin |\n| littleadmin | admin                        |\n| bob         | authenticated-user, openid   |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgregorwolf%2Fbookshop-demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgregorwolf%2Fbookshop-demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgregorwolf%2Fbookshop-demo/lists"}