Compare commits
4 Commits
shared-db-
...
ord-servic
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ccd11062a | ||
|
|
20348e0776 | ||
|
|
6acd5338d9 | ||
|
|
413d4de745 |
@@ -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
|
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.
|
parties the right to use of access any SAP External Product, through API Calls.
|
||||||
|
|
||||||
Files: *.*
|
Files: *
|
||||||
Copyright: 2019-2025 SAP SE or an SAP affiliate company and cap-cloud-samples
|
Copyright: 2019-2020 SAP SE or an SAP affiliate company and cap-cloud-samples
|
||||||
License: Apache-2.0
|
License: Apache-2.0
|
||||||
|
|||||||
12
README.md
12
README.md
@@ -1,5 +1,3 @@
|
|||||||
|
|
||||||
|
|
||||||
# Welcome to cap/samples
|
# 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).
|
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).
|
||||||
@@ -9,12 +7,20 @@ Find here a collection of samples for the [SAP Cloud Application Programming Mod
|
|||||||

|

|
||||||
|
|
||||||

|

|
||||||
|
[](https://api.reuse.software/info/github.com/SAP-samples/cloud-cap-samples)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Preliminaries
|
### Preliminaries
|
||||||
|
|
||||||
Ensure you have the latest LTS version of Node.js, [`@sap/cds-dk`](https://www.npmjs.com/package/@sap/cds-dk) installed globally, `git` and your IDE ready (see [Initial Setup](https://cap.cloud.sap/docs/get-started/#setup))
|
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
|
### Download
|
||||||
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
../../bookshop/app/vue
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../orders/app/orders
|
|
||||||
2427
app/router/package-lock.json
generated
2427
app/router/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "approuter",
|
|
||||||
"dependencies": {
|
|
||||||
"@sap/approuter": "^19.0.0"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": "^20"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"start": "node node_modules/@sap/approuter/approuter.js"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../reviews/app/vue
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
{
|
|
||||||
"welcomeFile": "app/bookshop/index.html",
|
|
||||||
"routes": [
|
|
||||||
{
|
|
||||||
"source": "^/app/(.*)$",
|
|
||||||
"target": "$1",
|
|
||||||
"localDir": ".",
|
|
||||||
"cacheControl": "no-cache, no-store, must-revalidate"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"source": "^/appconfig/",
|
|
||||||
"localDir": ".",
|
|
||||||
"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
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"source": "^(.*)$",
|
|
||||||
"target": "$1",
|
|
||||||
"localDir": ".",
|
|
||||||
"cacheControl": "no-cache, no-store, must-revalidate"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
"@cap-js/sqlite": "*"
|
"@cap-js/sqlite": "*"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@cap-js/ord": "2",
|
||||||
"@sap/cds": ">=7",
|
"@sap/cds": ">=7",
|
||||||
"express": "^4.17.1"
|
"express": "^4.17.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -2,21 +2,14 @@
|
|||||||
"name": "@capire/bookstore",
|
"name": "@capire/bookstore",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cap-js/hana": "^1.7.0",
|
|
||||||
"@capire/bookshop": "*",
|
"@capire/bookshop": "*",
|
||||||
|
"@capire/reviews": "*",
|
||||||
|
"@capire/orders": "*",
|
||||||
"@capire/common": "*",
|
"@capire/common": "*",
|
||||||
"@capire/data-viewer": "*",
|
"@capire/data-viewer": "*",
|
||||||
"@capire/orders": "*",
|
|
||||||
"@capire/reviews": "*",
|
|
||||||
"@sap-cloud-sdk/http-client": "^3.26.4",
|
|
||||||
"@sap-cloud-sdk/resilience": "^3.26.4",
|
|
||||||
"@sap/cds": ">=5",
|
"@sap/cds": ">=5",
|
||||||
"@sap/xssec": "^4.4.0",
|
|
||||||
"express": "^4.17.1"
|
"express": "^4.17.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
|
||||||
"start": "cds-serve"
|
|
||||||
},
|
|
||||||
"cds": {
|
"cds": {
|
||||||
"requires": {
|
"requires": {
|
||||||
"ReviewsService": {
|
"ReviewsService": {
|
||||||
@@ -27,13 +20,15 @@
|
|||||||
"kind": "odata",
|
"kind": "odata",
|
||||||
"model": "@capire/orders"
|
"model": "@capire/orders"
|
||||||
},
|
},
|
||||||
"messaging": true,
|
"messaging": {
|
||||||
|
"[development]": { "kind": "file-based-messaging" },
|
||||||
|
"[hybrid]": { "kind": "enterprise-messaging-shared" },
|
||||||
|
"[production]": { "kind": "enterprise-messaging" }
|
||||||
|
},
|
||||||
"db": {
|
"db": {
|
||||||
"kind": "sql"
|
"kind": "sql"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"log": {
|
"log": { "service": true }
|
||||||
"service": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ module.exports = async()=>{ // called by server.js
|
|||||||
CatalogService.on ('OrderedBook', async (msg) => {
|
CatalogService.on ('OrderedBook', async (msg) => {
|
||||||
const { book, quantity, buyer } = msg.data
|
const { book, quantity, buyer } = msg.data
|
||||||
const { title, price } = await db.read (Books, book, b => { b.title, b.price })
|
const { title, price } = await db.read (Books, book, b => { b.title, b.price })
|
||||||
return OrdersService.create ('OrdersNoDraft').entries({
|
return OrdersService.create ('Orders').entries({
|
||||||
OrderNo: 'Order at '+ (new Date).toLocaleString(),
|
OrderNo: 'Order at '+ (new Date).toLocaleString(),
|
||||||
Items: [{ product:{ID:`${book}`}, title, price, quantity }],
|
Items: [{ product:{ID:`${book}`}, title, price, quantity }],
|
||||||
buyer, createdBy: buyer
|
buyer, createdBy: buyer
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ class DataService extends cds.ApplicationService { init(){
|
|||||||
query.SELECT.limit = req.query.SELECT.limit // forward $skip / $top
|
query.SELECT.limit = req.query.SELECT.limit // forward $skip / $top
|
||||||
|
|
||||||
const dataSource = findDataSource(dataSourceName, entityName)
|
const dataSource = findDataSource(dataSourceName, entityName)
|
||||||
let res = await dataSource.run(query)
|
const res = await dataSource.run(query)
|
||||||
if (!Array.isArray(res)) res = [res] // singleton result
|
|
||||||
return res.map((line) => {
|
return res.map((line) => {
|
||||||
const record = Object.entries(line).map(([column, data]) => ({ column, data }))
|
const record = Object.entries(line).map(([column, data]) => ({ column, data }))
|
||||||
return {
|
return {
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
{
|
|
||||||
"version": "1.1.0",
|
|
||||||
"options": {
|
|
||||||
"management": true,
|
|
||||||
"messagingrest": true,
|
|
||||||
"messaging": true
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"topicRules": {
|
|
||||||
"publishFilter": [
|
|
||||||
"*"
|
|
||||||
],
|
|
||||||
"subscribeFilter": [
|
|
||||||
"*"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"queueRules": {
|
|
||||||
"publishFilter": [
|
|
||||||
"*"
|
|
||||||
],
|
|
||||||
"subscribeFilter": [
|
|
||||||
"*"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"authorities": [
|
|
||||||
"$ACCEPT_GRANTED_AUTHORITIES"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
15
hello/README.md
Normal file
15
hello/README.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# 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)
|
||||||
12
hello/package.json
Normal file
12
hello/package.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
3
hello/srv/world.cds
Normal file
3
hello/srv/world.cds
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
service say {
|
||||||
|
function hello (to:String) returns String;
|
||||||
|
}
|
||||||
7
hello/srv/world.js
Normal file
7
hello/srv/world.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
module.exports = class say {
|
||||||
|
hello(req) {
|
||||||
|
let {to} = req.data
|
||||||
|
if (to === 'me') to = require('os').userInfo().username
|
||||||
|
return `Hello ${to}!`
|
||||||
|
}
|
||||||
|
}
|
||||||
7
hello/srv/world.ts
Normal file
7
hello/srv/world.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { Request } from "@sap/cds"
|
||||||
|
|
||||||
|
module.exports = class say {
|
||||||
|
hello(req: Request) {
|
||||||
|
return `Hello ${req.data.to} from a TypeScript file!`
|
||||||
|
}
|
||||||
|
}
|
||||||
5
hello/test/test.http
Normal file
5
hello/test/test.http
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
GET http://localhost:4004/odata/v4/say/hello
|
||||||
|
###
|
||||||
|
|
||||||
|
GET http://localhost:4004/odata/v4/say/hello(to='me')
|
||||||
|
###
|
||||||
13
media/db/data-model.cds
Normal file
13
media/db/data-model.cds
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
namespace sap.capire.media;
|
||||||
|
|
||||||
|
entity Media {
|
||||||
|
|
||||||
|
key id:Integer;
|
||||||
|
@Core.MediaType: mediaType
|
||||||
|
content : LargeBinary ;
|
||||||
|
|
||||||
|
@Core.IsMediaType: true
|
||||||
|
mediaType : String;
|
||||||
|
fileName : String;
|
||||||
|
applicationName:String;
|
||||||
|
}
|
||||||
2
media/index.cds
Normal file
2
media/index.cds
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
using from './db/data-model';
|
||||||
|
using from './srv/media-service';
|
||||||
19
media/package.json
Normal file
19
media/package.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "@capire/media",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"lokijs": "^1.5.6"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"db",
|
||||||
|
"srv",
|
||||||
|
"index.cds"
|
||||||
|
],
|
||||||
|
"cds": {
|
||||||
|
"requires": {
|
||||||
|
"db": {
|
||||||
|
"kind": "sql"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
9
media/srv/media-service.cds
Normal file
9
media/srv/media-service.cds
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
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 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
68
media/srv/media-service.js
Normal file
68
media/srv/media-service.js
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
media/test/Test.png
Normal file
BIN
media/test/Test.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
35
media/test/media.http
Normal file
35
media/test/media.http
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
### 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:
|
||||||
177
mta.yaml
177
mta.yaml
@@ -1,177 +0,0 @@
|
|||||||
_schema-version: 3.3.0
|
|
||||||
ID: capire.samples
|
|
||||||
version: 3.0.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: bookstore-srv
|
|
||||||
type: nodejs
|
|
||||||
path: bookstore/gen/srv
|
|
||||||
parameters:
|
|
||||||
instances: 1
|
|
||||||
buildpack: nodejs_buildpack
|
|
||||||
build-parameters:
|
|
||||||
builder: npm
|
|
||||||
properties:
|
|
||||||
cds_requires_ReviewsService_credentials: {"destination": "reviews-dest","path": "/reviews"}
|
|
||||||
cds_requires_OrdersService_credentials: {"destination": "orders-dest","path": "/odata/v4/orders"}
|
|
||||||
provides:
|
|
||||||
- name: bookstore-api # required by consumers of CAP services (e.g. approuter)
|
|
||||||
properties:
|
|
||||||
srv-url: ${default-url}
|
|
||||||
requires:
|
|
||||||
- name: samples-db
|
|
||||||
- name: samples-auth
|
|
||||||
- name: samples-messaging
|
|
||||||
- name: samples-destination
|
|
||||||
|
|
||||||
- name: orders-srv
|
|
||||||
type: nodejs
|
|
||||||
path: orders/gen/srv
|
|
||||||
parameters:
|
|
||||||
instances: 1
|
|
||||||
buildpack: nodejs_buildpack
|
|
||||||
build-parameters:
|
|
||||||
builder: npm
|
|
||||||
provides:
|
|
||||||
- name: orders-api # required by consumers of CAP services (e.g. approuter)
|
|
||||||
properties:
|
|
||||||
srv-url: ${default-url}
|
|
||||||
requires:
|
|
||||||
- name: samples-db
|
|
||||||
- name: samples-auth
|
|
||||||
- name: samples-messaging
|
|
||||||
- name: samples-destination
|
|
||||||
|
|
||||||
- name: reviews-srv
|
|
||||||
type: nodejs
|
|
||||||
path: reviews/gen/srv
|
|
||||||
parameters:
|
|
||||||
instances: 1
|
|
||||||
buildpack: nodejs_buildpack
|
|
||||||
build-parameters:
|
|
||||||
builder: npm
|
|
||||||
provides:
|
|
||||||
- name: reviews-api # required by consumers of CAP services (e.g. approuter)
|
|
||||||
properties:
|
|
||||||
srv-url: ${default-url}
|
|
||||||
requires:
|
|
||||||
- name: samples-db
|
|
||||||
- name: samples-auth
|
|
||||||
- name: samples-messaging
|
|
||||||
- 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: app/router
|
|
||||||
parameters:
|
|
||||||
keep-existing-routes: true
|
|
||||||
disk-quota: 256M
|
|
||||||
memory: 256M
|
|
||||||
requires:
|
|
||||||
- name: orders-api
|
|
||||||
group: destinations
|
|
||||||
properties:
|
|
||||||
name: orders-api
|
|
||||||
url: ~{srv-url}
|
|
||||||
forwardAuthToken: true
|
|
||||||
- name: reviews-api
|
|
||||||
group: destinations
|
|
||||||
properties:
|
|
||||||
name: reviews-api
|
|
||||||
url: ~{srv-url}
|
|
||||||
forwardAuthToken: true
|
|
||||||
- name: bookstore-api
|
|
||||||
group: destinations
|
|
||||||
properties:
|
|
||||||
name: bookstore-api
|
|
||||||
url: ~{srv-url}
|
|
||||||
forwardAuthToken: true
|
|
||||||
- name: samples-auth
|
|
||||||
- name: samples-destination
|
|
||||||
provides:
|
|
||||||
- name: app-api
|
|
||||||
properties:
|
|
||||||
app-protocol: ${protocol}
|
|
||||||
app-uri: ${default-uri}
|
|
||||||
|
|
||||||
- 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-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-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-destination
|
|
||||||
type: org.cloudfoundry.managed-service
|
|
||||||
parameters:
|
|
||||||
service: destination
|
|
||||||
service-plan: lite
|
|
||||||
1
ord/cds-plugin.js
Normal file
1
ord/cds-plugin.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// just a dummy tag file to be identified as a plugin
|
||||||
12
ord/package.json
Normal file
12
ord/package.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "@cap-js/ord",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"cds": {
|
||||||
|
"requires": {
|
||||||
|
"SAP ORD Service": {
|
||||||
|
"model": "@cap-js/ord/srv/ord-service",
|
||||||
|
"service": "OrdService"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
ord/srv/ord-service.cds
Normal file
12
ord/srv/ord-service.cds
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// @requires: 'ORDconsumer'
|
||||||
|
@rest @path:'/ord/v1'
|
||||||
|
service OrdService {
|
||||||
|
@readonly entity documents {
|
||||||
|
key id: String;
|
||||||
|
}
|
||||||
|
@readonly entity csn {
|
||||||
|
key id: String;
|
||||||
|
}
|
||||||
|
|
||||||
|
function api (service: String, format: String) returns {};
|
||||||
|
}
|
||||||
73
ord/srv/ord-service.mjs
Normal file
73
ord/srv/ord-service.mjs
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
import cds from '@sap/cds'
|
||||||
|
export class OrdService extends cds.ApplicationService {
|
||||||
|
init(){
|
||||||
|
|
||||||
|
this.on('READ','documents', req => {
|
||||||
|
let csn = cds.context?.model || cds.model
|
||||||
|
return { ord: csn }
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just an example to do something with id, if given.
|
||||||
|
* Try it out with URLs like that:
|
||||||
|
*
|
||||||
|
* - http://localhost:4004/ord/v1/documents
|
||||||
|
* - http://localhost:4004/ord/v1/documents/CatalogService
|
||||||
|
* - http://localhost:4004/ord/v1/documents/CatalogService.Books
|
||||||
|
* - http://localhost:4004/ord/v1/documents/CatalogService.Authors
|
||||||
|
*/
|
||||||
|
this.on('READ','csn', req => {
|
||||||
|
let csn = cds.context?.model || cds.model
|
||||||
|
let { id } = req.data
|
||||||
|
if (id) csn = csn.definitions[id] || 'not in model!'
|
||||||
|
return { id, csn }
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Just an example to serve arbitrary content with a function.
|
||||||
|
* Try it out with URLs like that:
|
||||||
|
*
|
||||||
|
* - http://localhost:4004/ord/v1/api?service=CatalogService
|
||||||
|
* - http://localhost:4004/ord/v1/api?service=CatalogService&format=edmx
|
||||||
|
* - http://localhost:4004/ord/v1/api?service=CatalogService&format=edmx-v2
|
||||||
|
* - http://localhost:4004/ord/v1/api?service=CatalogService&format=openapi
|
||||||
|
*/
|
||||||
|
this.on('api', req => {
|
||||||
|
let csn = cds.context?.model || cds.model
|
||||||
|
let { service, format = 'csn' } = req.data
|
||||||
|
let { res } = req.http
|
||||||
|
if (format === 'csn') {
|
||||||
|
if (!service) return res.send(csn)
|
||||||
|
service = csn.services[service]
|
||||||
|
return res.send({ definitions: [ service, ...service.entities ] .reduce ((all,e) => {
|
||||||
|
let d = all[e.name] = {...e}
|
||||||
|
delete d.projection // not part of the API
|
||||||
|
delete d.query // not part of the API
|
||||||
|
return all
|
||||||
|
},{})})
|
||||||
|
}
|
||||||
|
let api = cds.compile(csn).to[format]({service})
|
||||||
|
return res.send(api)
|
||||||
|
})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example how to register arbitrary express routes,
|
||||||
|
* and map them to our service's interface.
|
||||||
|
* Try it out with URLs like that:
|
||||||
|
*
|
||||||
|
* - http://localhost:4004/ord/v1/csn/CatalogService
|
||||||
|
* - http://localhost:4004/ord/v1/edmx/CatalogService
|
||||||
|
* - http://localhost:4004/ord/v1/openapi/CatalogService
|
||||||
|
* - http://localhost:4004/ord/v1/asyncapi/CatalogService
|
||||||
|
*
|
||||||
|
* NOTE: we add cds.middlewares.before to the route, which gives us all
|
||||||
|
* the context and auth handling, which is also available to CAP services.
|
||||||
|
*/
|
||||||
|
cds.app.get (`${this.path}/:api?/:service?`, cds.middlewares.before, req => {
|
||||||
|
const { api, service } = req.params
|
||||||
|
return this.api (service, api)
|
||||||
|
})
|
||||||
|
|
||||||
|
return super.init()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,18 +2,7 @@
|
|||||||
"name": "@capire/orders",
|
"name": "@capire/orders",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cap-js/hana": "^1.7.0",
|
|
||||||
"@capire/common": "*",
|
"@capire/common": "*",
|
||||||
"@sap/cds": ">=5",
|
"@sap/cds": ">=5"
|
||||||
"@sap/xssec": "^4.4.0"
|
|
||||||
},
|
|
||||||
"scripts": {
|
|
||||||
"start": "cds-serve"
|
|
||||||
},
|
|
||||||
"cds": {
|
|
||||||
"requires": {
|
|
||||||
"messaging": true,
|
|
||||||
"db": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,14 +2,4 @@ using { sap.capire.orders as my } from '../db/schema';
|
|||||||
|
|
||||||
service OrdersService {
|
service OrdersService {
|
||||||
entity Orders as projection on my.Orders;
|
entity Orders as projection on my.Orders;
|
||||||
|
|
||||||
event OrderChanged {
|
|
||||||
product: String;
|
|
||||||
deltaQuantity: Integer;
|
|
||||||
}
|
|
||||||
|
|
||||||
@odata.draft.bypass
|
|
||||||
@(requires: 'system-user')
|
|
||||||
entity OrdersNoDraft as projection on my.Orders;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
1237
package-lock.json
generated
1237
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
46
package.json
46
package.json
@@ -1,42 +1,46 @@
|
|||||||
{
|
{
|
||||||
"name": "@capire/samples",
|
"name": "@capire/samples",
|
||||||
"version": "3.0.0",
|
"version": "2.1.0",
|
||||||
"description": "A monorepo with several samples for CAP.",
|
"description": "A monorepo with several samples for CAP.",
|
||||||
"repository": "https://github.com/sap-samples/cloud-cap-samples.git",
|
"repository": "https://github.com/sap-samples/cloud-cap-samples.git",
|
||||||
"author": "daniel.hutzel@sap.com",
|
"author": "daniel.hutzel@sap.com",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sap/cds": ">=8",
|
"@sap/cds": ">=8"
|
||||||
"@cap-js/hana": "^1",
|
|
||||||
"@sap/xssec": "^4"
|
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"./bookshop",
|
"./bookshop",
|
||||||
"./bookstore",
|
"./bookstore",
|
||||||
"./common",
|
"./common",
|
||||||
|
"./data-viewer",
|
||||||
"./fiori",
|
"./fiori",
|
||||||
|
"./hello",
|
||||||
|
"./media",
|
||||||
|
"./ord",
|
||||||
"./orders",
|
"./orders",
|
||||||
"./reviews",
|
"./loggers",
|
||||||
"./etc/data-viewer",
|
"./reviews"
|
||||||
"./etc/loggers"
|
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cap-js/cds-test": "^0",
|
|
||||||
"@cap-js/cds-types": "^0",
|
"@cap-js/cds-types": "^0",
|
||||||
"@cap-js/sqlite": "^1",
|
"@cap-js/sqlite": "^1",
|
||||||
"@sap/cds-dk": "^8",
|
"axios": "^1",
|
||||||
|
"chai": "^4.3.4",
|
||||||
|
"chai-as-promised": "^7.1.1",
|
||||||
|
"chai-subset": "^1.6.0",
|
||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"semver": "^7"
|
"semver": "^7"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "mbt build -t gen --mtar mta.tar",
|
|
||||||
"deploy": "cf deploy gen/mta.tar",
|
|
||||||
"undeploy": "cf undeploy capire.samples --delete-services --delete-service-keys",
|
|
||||||
"bookshop": "cds watch bookshop",
|
"bookshop": "cds watch bookshop",
|
||||||
|
"start": "cds watch fiori",
|
||||||
"fiori": "cds watch fiori",
|
"fiori": "cds watch fiori",
|
||||||
|
"hello": "cds watch hello",
|
||||||
|
"media": "cds watch media",
|
||||||
"lint": "eslint",
|
"lint": "eslint",
|
||||||
"test": "npx jest --silent",
|
"test": "npx jest --silent",
|
||||||
"jest": "npx jest --silent",
|
"jest": "npx jest --silent",
|
||||||
"mocha": "CDS_TEST_SILENT=y npx mocha"
|
"mocha": "CDS_TEST_SILENT=y npx mocha",
|
||||||
|
"test:hello": "cd hello && npm test"
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"recursive": true,
|
"recursive": true,
|
||||||
@@ -44,19 +48,5 @@
|
|||||||
"timeout": 6666
|
"timeout": 6666
|
||||||
},
|
},
|
||||||
"license": "SEE LICENSE IN LICENSE",
|
"license": "SEE LICENSE IN LICENSE",
|
||||||
"private": true,
|
"private": true
|
||||||
"cds": {
|
|
||||||
"sql": {
|
|
||||||
"native_hana_associations": false
|
|
||||||
},
|
|
||||||
"requires": {
|
|
||||||
"[production]": {
|
|
||||||
"auth": "xsuaa"
|
|
||||||
},
|
|
||||||
"messaging": {
|
|
||||||
"kind": "enterprise-messaging"
|
|
||||||
},
|
|
||||||
"destinations": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
ID;subject;rating;reviewer;title;text
|
subject;rating;reviewer;title;text
|
||||||
1689144d-3b10-4849-bcbe-2408a13e161a;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;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.
|
||||||
1689144d-3b10-4849-bcbe-2408a13e161b;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.
|
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.
|
||||||
1689144d-3b10-4849-bcbe-2408a13e161c;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.
|
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.
|
||||||
1689144d-3b10-4849-bcbe-2408a13e161d;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.
|
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.
|
||||||
|
@@ -7,28 +7,17 @@
|
|||||||
"index.cds"
|
"index.cds"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@cap-js/hana": "^1.7.0",
|
|
||||||
"@sap/cds": ">=5",
|
"@sap/cds": ">=5",
|
||||||
"@sap/xssec": "^4.4.0",
|
|
||||||
"express": "^4.17.1"
|
"express": "^4.17.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
|
||||||
"start": "cds-serve"
|
|
||||||
},
|
|
||||||
"cds": {
|
"cds": {
|
||||||
"requires": {
|
"requires": {
|
||||||
"messaging": {
|
"messaging": {
|
||||||
"[development]": {
|
"[development]": { "kind": "file-based-messaging" },
|
||||||
"kind": "file-based-messaging"
|
"[hybrid]": { "kind": "enterprise-messaging-shared" },
|
||||||
|
"[production]": { "kind": "enterprise-messaging" }
|
||||||
},
|
},
|
||||||
"[hybrid]": {
|
"db": { "kind": "sql" }
|
||||||
"kind": "enterprise-messaging-shared"
|
|
||||||
},
|
|
||||||
"[production]": {
|
|
||||||
"kind": "enterprise-messaging"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"db": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
10
samples.md
10
samples.md
@@ -6,6 +6,12 @@ Each sub directory essentially is an individual npm package arranged in an [all-
|
|||||||

|

|
||||||
|
|
||||||
|
|
||||||
|
## [@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)
|
## [@capire/bookshop](bookshop)
|
||||||
|
|
||||||
- [Getting Started](https://cap.cloud.sap/docs/get-started/in-a-nutshell) with CAP, briefly introducing:
|
- [Getting Started](https://cap.cloud.sap/docs/get-started/in-a-nutshell) with CAP, briefly introducing:
|
||||||
@@ -54,10 +60,10 @@ Each sub directory essentially is an individual npm package arranged in an [all-
|
|||||||
- [@capire/reviews](reviews)
|
- [@capire/reviews](reviews)
|
||||||
- [@capire/orders](orders)
|
- [@capire/orders](orders)
|
||||||
- [@capire/common](common)
|
- [@capire/common](common)
|
||||||
- [@capire/data-viewer](etc/data-viewer)
|
- [@capire/data-viewer](data-viewer)
|
||||||
- [The Vue.js app](bookshop/app/vue) imported from `bookshop` is served as well
|
- [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](reviews/app/vue) imported from `reviews` is served as well
|
||||||
- [The Vue.js app](etc/data-viewer/app/data) imported from `data-viewer` is served as well
|
- [The Vue.js app](data-viewer/app/data) imported from `data-viewer` is served as well
|
||||||
- [The Fiori app](orders/app) imported from `orders` 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)
|
- [OpenAPI export + Swagger UI](https://cap.cloud.sap/docs/advanced/openapi)
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
using from '@capire/bookstore';
|
|
||||||
using from '@capire/reviews';
|
|
||||||
using from '@capire/orders';
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "shared-db",
|
|
||||||
"version": "1.0.0",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
|
||||||
},
|
|
||||||
"keywords": [],
|
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"description": "",
|
|
||||||
"cds": {
|
|
||||||
"sql": {
|
|
||||||
"native_hana_associations": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
22
test/hello-world.test.js
Normal file
22
test/hello-world.test.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
const cds = require('@sap/cds')
|
||||||
|
|
||||||
|
describe('cap/samples - Hello world!', () => {
|
||||||
|
|
||||||
|
const { GET, expect } = cds.test (__dirname+'/../hello')
|
||||||
|
|
||||||
|
it('should say hello with class impl', async () => {
|
||||||
|
const {data} = await GET `/odata/v4/say/hello(to='world')`
|
||||||
|
expect(data.value).to.eql('Hello world!')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should say hello with another impl', async () => {
|
||||||
|
await cds.serve('say').from(cds.model)
|
||||||
|
.at('/say-again').in(cds.app)
|
||||||
|
.with(srv => {
|
||||||
|
srv.on('hello', (req) => `Hello again ${req.data.to}!`)
|
||||||
|
})
|
||||||
|
const {data} = await GET `/say-again/hello(to='world')`
|
||||||
|
expect(data.value).to.eql('Hello again world!')
|
||||||
|
})
|
||||||
|
|
||||||
|
})
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"scopes": [
|
|
||||||
{
|
|
||||||
"name": "$XSAPPNAME.admin",
|
|
||||||
"description": "admin"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "$XSAPPNAME.emcallback",
|
|
||||||
"description": "Enterprise-Messaging Callback Access",
|
|
||||||
"grant-as-authority-to-apps": [
|
|
||||||
"$XSSERVICENAME(samples-messaging)"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "$XSAPPNAME.emmanagement",
|
|
||||||
"description": "Enterprise-Messaging Management Access"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"attributes": [],
|
|
||||||
"role-templates": [
|
|
||||||
{
|
|
||||||
"name": "admin",
|
|
||||||
"scope-references": [
|
|
||||||
"$XSAPPNAME.admin"
|
|
||||||
],
|
|
||||||
"description": "cap samples multi-service shared-db"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"authorities-inheritance": false,
|
|
||||||
"authorities": [
|
|
||||||
"$XSAPPNAME.emmanagement",
|
|
||||||
"$XSAPPNAME.mtcallback"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user