Compare commits
1 Commits
use-contex
...
deploy/mul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6906e68142 |
@@ -1,6 +1,11 @@
|
|||||||
{
|
{
|
||||||
"welcomeFile": "app/bookshop/index.html",
|
"welcomeFile": "app/bookshop/index.html",
|
||||||
"routes": [
|
"routes": [
|
||||||
|
{
|
||||||
|
"source": "^/-/cds/.*",
|
||||||
|
"destination": "mtx-api",
|
||||||
|
"authenticationType": "none"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"source": "^/app/(.*)$",
|
"source": "^/app/(.*)$",
|
||||||
"target": "$1",
|
"target": "$1",
|
||||||
|
|||||||
6
bookstore/app/routes.js
Normal file
6
bookstore/app/routes.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
// Add routes to UIs from imported packages
|
||||||
|
module.exports = (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')
|
||||||
|
}
|
||||||
@@ -11,7 +11,8 @@
|
|||||||
"@sap-cloud-sdk/resilience": "^4",
|
"@sap-cloud-sdk/resilience": "^4",
|
||||||
"@sap/cds": ">=5",
|
"@sap/cds": ">=5",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"@cap-js/hana": "^1"
|
"@cap-js/hana": "^1",
|
||||||
|
"@sap/cds-mtxs": "^2"
|
||||||
},
|
},
|
||||||
"cds": {
|
"cds": {
|
||||||
"requires": {
|
"requires": {
|
||||||
@@ -24,7 +25,10 @@
|
|||||||
"model": "@capire/orders"
|
"model": "@capire/orders"
|
||||||
},
|
},
|
||||||
"messaging": true,
|
"messaging": true,
|
||||||
"db": true
|
"db": true,
|
||||||
|
"multitenancy": true,
|
||||||
|
"auth": "xsuaa"
|
||||||
|
|
||||||
},
|
},
|
||||||
"log": { "service": true }
|
"log": { "service": true }
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
const cds = require ('@sap/cds')
|
const cds = require ('@sap/cds')
|
||||||
|
|
||||||
|
|
||||||
// Add routes to UIs from imported packages
|
// Add routes to UIs from imported packages
|
||||||
if (!cds.env.production) cds.once ('bootstrap', (app) => {
|
if (!cds.env.production) cds.once ('bootstrap', require('../app/routes'))
|
||||||
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...
|
// Mashing up bookshop services with required services...
|
||||||
cds.once ('served', async ()=>{
|
cds.once ('served', async ()=>{ // called by server.js
|
||||||
|
|
||||||
const CatalogService = await cds.connect.to ('CatalogService')
|
const CatalogService = await cds.connect.to ('CatalogService')
|
||||||
const ReviewsService = await cds.connect.to ('ReviewsService')
|
const ReviewsService = await cds.connect.to ('ReviewsService')
|
||||||
|
|||||||
@@ -106,7 +106,7 @@
|
|||||||
"name": "sap.fe.templates.ObjectPage",
|
"name": "sap.fe.templates.ObjectPage",
|
||||||
"options": {
|
"options": {
|
||||||
"settings" : {
|
"settings" : {
|
||||||
"contextPath" : "/Books",
|
"entitySet" : "Books",
|
||||||
"navigation" : {
|
"navigation" : {
|
||||||
"Authors" : {
|
"Authors" : {
|
||||||
"detail" : {
|
"detail" : {
|
||||||
@@ -123,7 +123,7 @@
|
|||||||
"name": "sap.fe.templates.ObjectPage",
|
"name": "sap.fe.templates.ObjectPage",
|
||||||
"options": {
|
"options": {
|
||||||
"settings" : {
|
"settings" : {
|
||||||
"contextPath" : "/Authors"
|
"entitySet" : "Authors"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,7 +99,7 @@
|
|||||||
"name": "sap.fe.templates.ListReport",
|
"name": "sap.fe.templates.ListReport",
|
||||||
"options": {
|
"options": {
|
||||||
"settings": {
|
"settings": {
|
||||||
"contextPath": "/Books",
|
"entitySet": "Books",
|
||||||
"initialLoad": true,
|
"initialLoad": true,
|
||||||
"navigation": {
|
"navigation": {
|
||||||
"Books": {
|
"Books": {
|
||||||
@@ -117,7 +117,7 @@
|
|||||||
"name": "sap.fe.templates.ObjectPage",
|
"name": "sap.fe.templates.ObjectPage",
|
||||||
"options": {
|
"options": {
|
||||||
"settings": {
|
"settings": {
|
||||||
"contextPath": "/Books"
|
"entitySet": "Books"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
32
fiori/server.js
Normal file
32
fiori/server.js
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
const cds = require('@sap/cds/lib')
|
||||||
|
if (cds.requires.db?.kind === 'sqlite') {
|
||||||
|
cds.on ('serving:AdminService', srv => srv.prepend(() => {
|
||||||
|
const {Genres} = srv.entities
|
||||||
|
// Register a simplistic handler for hierarchical queries
|
||||||
|
srv.on('READ', Genres, (req,next) => {
|
||||||
|
const q = req.query
|
||||||
|
// Expand query on a single row
|
||||||
|
if (q.SELECT.recurse?.where?.[0].ref[0] === 'Distance') {
|
||||||
|
q.SELECT.where[0] = 'parent_ID'
|
||||||
|
// Initial query
|
||||||
|
} else if (!q.SELECT.search && !is_count(q)) {
|
||||||
|
q.SELECT.where ??= [ 'parent_ID is null' ]
|
||||||
|
}
|
||||||
|
// Use scalar subselect for DrillState
|
||||||
|
q.SELECT.from.as = 'g'
|
||||||
|
q.SELECT.columns = q.SELECT.columns.map (c => {
|
||||||
|
if (c.ref == 'DrillState') return { xpr:[`
|
||||||
|
CASE WHEN ( SELECT count(1) from ${Genres} where parent_ID = g.ID ) > 0
|
||||||
|
THEN 'collapsed' ELSE 'leaf' END`
|
||||||
|
], as: 'DrillState' }
|
||||||
|
else return c
|
||||||
|
})
|
||||||
|
// Suppress error message: Feature "recurse" queries not supported.
|
||||||
|
delete q.SELECT.__proto__.recurse
|
||||||
|
delete q.SELECT.recurse
|
||||||
|
return next()
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
const is_count = q => q.SELECT.columns?.length === 1 && q.SELECT.columns[0].func === 'count'
|
||||||
79
mta.yaml
79
mta.yaml
@@ -9,7 +9,7 @@ build-parameters:
|
|||||||
- builder: custom
|
- builder: custom
|
||||||
commands:
|
commands:
|
||||||
- npm ci
|
- npm ci
|
||||||
- npx cds build shared-db --for hana --production
|
- npx cds build --production
|
||||||
- npx cds build orders --for nodejs --production --ws-pack
|
- npx cds build orders --for nodejs --production --ws-pack
|
||||||
- npx cds build reviews --for nodejs --production
|
- npx cds build reviews --for nodejs --production
|
||||||
- npx cds build bookstore --for nodejs --production --ws-pack
|
- npx cds build bookstore --for nodejs --production --ws-pack
|
||||||
@@ -78,14 +78,6 @@ modules:
|
|||||||
- name: samples-auth
|
- name: samples-auth
|
||||||
- name: samples-destination
|
- name: samples-destination
|
||||||
|
|
||||||
- name: samples-db-deployer
|
|
||||||
type: hdb
|
|
||||||
path: shared-db/gen/db
|
|
||||||
parameters:
|
|
||||||
buildpack: nodejs_buildpack
|
|
||||||
requires:
|
|
||||||
- name: samples-db
|
|
||||||
|
|
||||||
- name: samples
|
- name: samples
|
||||||
type: approuter.nodejs
|
type: approuter.nodejs
|
||||||
path: .deploy/app-router
|
path: .deploy/app-router
|
||||||
@@ -93,6 +85,8 @@ modules:
|
|||||||
keep-existing-routes: true
|
keep-existing-routes: true
|
||||||
disk-quota: 256M
|
disk-quota: 256M
|
||||||
memory: 256M
|
memory: 256M
|
||||||
|
properties:
|
||||||
|
TENANT_HOST_PATTERN: "^(.*)-${default-uri}"
|
||||||
requires:
|
requires:
|
||||||
- name: orders-api
|
- name: orders-api
|
||||||
group: destinations
|
group: destinations
|
||||||
@@ -112,7 +106,17 @@ modules:
|
|||||||
name: bookstore-api # must be used in xs-app.json as well
|
name: bookstore-api # must be used in xs-app.json as well
|
||||||
url: ~{srv-url}
|
url: ~{srv-url}
|
||||||
forwardAuthToken: true
|
forwardAuthToken: true
|
||||||
|
- name: mtx-api
|
||||||
|
group: destinations
|
||||||
|
properties:
|
||||||
|
name: mtx-api # must be used in xs-app.json as well
|
||||||
|
url: ~{mtx-url}
|
||||||
- name: samples-auth
|
- name: samples-auth
|
||||||
|
provides:
|
||||||
|
- name: app-api
|
||||||
|
properties:
|
||||||
|
app-protocol: ${protocol}
|
||||||
|
app-uri: ${default-uri}
|
||||||
|
|
||||||
- name: destination-content
|
- name: destination-content
|
||||||
type: com.sap.application.content
|
type: com.sap.application.content
|
||||||
@@ -145,6 +149,27 @@ modules:
|
|||||||
TokenServiceInstanceName: samples-auth
|
TokenServiceInstanceName: samples-auth
|
||||||
TokenServiceKeyName: xsuaa-service-key
|
TokenServiceKeyName: xsuaa-service-key
|
||||||
|
|
||||||
|
- name: samples-mtx
|
||||||
|
type: nodejs
|
||||||
|
path: gen/mtx/sidecar
|
||||||
|
build-parameters:
|
||||||
|
builder: npm
|
||||||
|
parameters:
|
||||||
|
instances: 1
|
||||||
|
memory: 256M
|
||||||
|
disk-quota: 512M
|
||||||
|
provides:
|
||||||
|
- name: mtx-api
|
||||||
|
properties:
|
||||||
|
mtx-url: ${default-url}
|
||||||
|
requires:
|
||||||
|
- name: samples-db
|
||||||
|
- name: samples-registry
|
||||||
|
- name: samples-auth
|
||||||
|
- name: app-api
|
||||||
|
properties:
|
||||||
|
SUBSCRIPTION_URL: ~{app-protocol}://\${tenant_subdomain}-~{app-uri}
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
- name: samples-messaging
|
- name: samples-messaging
|
||||||
type: org.cloudfoundry.managed-service
|
type: org.cloudfoundry.managed-service
|
||||||
@@ -156,23 +181,51 @@ resources:
|
|||||||
emname: bookstore-${org}-${space}
|
emname: bookstore-${org}-${space}
|
||||||
namespace: cap/samples/${space}
|
namespace: cap/samples/${space}
|
||||||
- name: samples-db
|
- name: samples-db
|
||||||
type: com.sap.xs.hdi-container
|
type: org.cloudfoundry.managed-service
|
||||||
parameters:
|
parameters:
|
||||||
service: hana
|
service: service-manager
|
||||||
service-plan: hdi-shared
|
service-plan: container
|
||||||
|
|
||||||
- name: samples-auth
|
- name: samples-auth
|
||||||
type: org.cloudfoundry.managed-service
|
type: org.cloudfoundry.managed-service
|
||||||
processed-after:
|
processed-after:
|
||||||
- samples-messaging
|
- samples-messaging
|
||||||
|
requires:
|
||||||
|
- name: app-api
|
||||||
parameters:
|
parameters:
|
||||||
service: xsuaa
|
service: xsuaa
|
||||||
service-plan: application
|
service-plan: application
|
||||||
path: ./xs-security.json
|
path: ./xs-security.json
|
||||||
config:
|
config:
|
||||||
xsappname: samples-${org}-${space}
|
xsappname: samples-${org}-${space}
|
||||||
tenant-mode: dedicated
|
tenant-mode: shared
|
||||||
|
oauth2-configuration:
|
||||||
|
redirect-uris:
|
||||||
|
- https://*-~{app-api/app-uri}/**
|
||||||
|
|
||||||
- name: samples-destination
|
- name: samples-destination
|
||||||
type: org.cloudfoundry.managed-service
|
type: org.cloudfoundry.managed-service
|
||||||
parameters:
|
parameters:
|
||||||
service: destination
|
service: destination
|
||||||
service-plan: lite
|
service-plan: lite
|
||||||
|
|
||||||
|
- name: samples-registry
|
||||||
|
type: org.cloudfoundry.managed-service
|
||||||
|
requires:
|
||||||
|
- name: mtx-api
|
||||||
|
parameters:
|
||||||
|
service: saas-registry
|
||||||
|
service-plan: application
|
||||||
|
config:
|
||||||
|
xsappname: samples-${org}-${space}
|
||||||
|
appName: samples-${org}-${space}
|
||||||
|
displayName: samples-shared-db
|
||||||
|
description: CAP Samples with shared-db and multitenancy
|
||||||
|
category: 'Samples shared-db'
|
||||||
|
appUrls:
|
||||||
|
getDependencies: ~{mtx-api/mtx-url}/-/cds/saas-provisioning/dependencies
|
||||||
|
onSubscription: ~{mtx-api/mtx-url}/-/cds/saas-provisioning/tenant/{tenantId}
|
||||||
|
onSubscriptionAsync: true
|
||||||
|
onUnSubscriptionAsync: true
|
||||||
|
onUpdateDependenciesAsync: true
|
||||||
|
callbackTimeoutMillis: 300000 # Increase if your deployments are taking longer than that
|
||||||
|
|||||||
19
mtx/sidecar/package.json
Normal file
19
mtx/sidecar/package.json
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "samples-mtx",
|
||||||
|
"dependencies": {
|
||||||
|
"@cap-js/hana": "^1",
|
||||||
|
"@sap/cds": "^8",
|
||||||
|
"@sap/cds-mtxs": "^2",
|
||||||
|
"@sap/xssec": "^4",
|
||||||
|
"express": "^4"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@cap-js/sqlite": "^1"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"start": "cds-serve"
|
||||||
|
},
|
||||||
|
"cds": {
|
||||||
|
"profile": "mtx-sidecar"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,12 +5,15 @@
|
|||||||
"@cap-js/hana": "^1",
|
"@cap-js/hana": "^1",
|
||||||
"@capire/common": "*",
|
"@capire/common": "*",
|
||||||
"@sap/cds": ">=5",
|
"@sap/cds": ">=5",
|
||||||
"@sap/xssec": "^4"
|
"@sap/xssec": "^4",
|
||||||
|
"@sap/cds-mtxs": "^2"
|
||||||
},
|
},
|
||||||
"cds": {
|
"cds": {
|
||||||
"requires": {
|
"requires": {
|
||||||
"messaging": true,
|
"messaging": true,
|
||||||
"db": true
|
"db": true,
|
||||||
|
"multitenancy": true,
|
||||||
|
"auth": "xsuaa"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
23
package.json
23
package.json
@@ -5,15 +5,8 @@
|
|||||||
"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",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"bookshop",
|
"./*",
|
||||||
"bookstore",
|
"./etc/*"
|
||||||
"common",
|
|
||||||
"fiori",
|
|
||||||
"orders",
|
|
||||||
"reviews",
|
|
||||||
"shared-db",
|
|
||||||
"etc/data-viewer",
|
|
||||||
"etc/loggers"
|
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cap-js/cds-test": "^0"
|
"@cap-js/cds-test": "^0"
|
||||||
@@ -40,5 +33,15 @@
|
|||||||
"timeout": 6666
|
"timeout": 6666
|
||||||
},
|
},
|
||||||
"license": "SEE LICENSE IN LICENSE",
|
"license": "SEE LICENSE IN LICENSE",
|
||||||
"private": true
|
"private": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@sap/cds-mtxs": "^2"
|
||||||
|
},
|
||||||
|
"cds": {
|
||||||
|
"profile": "with-mtx-sidecar",
|
||||||
|
"requires": {
|
||||||
|
"multitenancy": true,
|
||||||
|
"auth": "xsuaa"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -10,12 +10,15 @@
|
|||||||
"@cap-js/hana": "^1",
|
"@cap-js/hana": "^1",
|
||||||
"@sap/cds": ">=5",
|
"@sap/cds": ">=5",
|
||||||
"@sap/xssec": "^4.2.7",
|
"@sap/xssec": "^4.2.7",
|
||||||
"express": "^4.17.1"
|
"express": "^4.17.1",
|
||||||
|
"@sap/cds-mtxs": "^2"
|
||||||
},
|
},
|
||||||
"cds": {
|
"cds": {
|
||||||
"requires": {
|
"requires": {
|
||||||
"messaging": true,
|
"messaging": true,
|
||||||
"db": true
|
"db": true,
|
||||||
|
"multitenancy": true,
|
||||||
|
"auth": "xsuaa"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ module.exports = cds.service.impl (function(){
|
|||||||
|
|
||||||
// Get the CSN definition for Reviews from the db schema for sub-sequent queries
|
// Get the CSN definition for Reviews from the db schema for sub-sequent queries
|
||||||
// ( Note: we explicitly specify the namespace to support embedded reuse )
|
// ( Note: we explicitly specify the namespace to support embedded reuse )
|
||||||
const { Reviews, Likes } = this.entities
|
const { Reviews, Likes } = this.entities ('sap.capire.reviews')
|
||||||
|
|
||||||
this.before (['CREATE','UPDATE'], 'Reviews', req => {
|
this.before (['CREATE','UPDATE'], 'Reviews', req => {
|
||||||
if (!req.data.rating) req.data.rating = Math.round(Math.random()*4)+1
|
if (!req.data.rating) req.data.rating = Math.round(Math.random()*4)+1
|
||||||
|
|||||||
@@ -2,11 +2,6 @@
|
|||||||
"name": "@capire/shared-db",
|
"name": "@capire/shared-db",
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"description": "CAP Sample CDS model deployment for shared-db scenario",
|
"description": "CAP Sample CDS model deployment for shared-db scenario",
|
||||||
"dependencies": {
|
|
||||||
"@capire/bookstore": "*",
|
|
||||||
"@capire/orders": "*",
|
|
||||||
"@capire/reviews": "*"
|
|
||||||
},
|
|
||||||
"cds": {
|
"cds": {
|
||||||
"sql": {
|
"sql": {
|
||||||
"native_hana_associations": false
|
"native_hana_associations": false
|
||||||
|
|||||||
@@ -14,6 +14,13 @@
|
|||||||
{
|
{
|
||||||
"name": "$XSAPPNAME.emmanagement",
|
"name": "$XSAPPNAME.emmanagement",
|
||||||
"description": "Enterprise-Messaging Management Access"
|
"description": "Enterprise-Messaging Management Access"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "$XSAPPNAME.mtcallback",
|
||||||
|
"description": "Subscription via SaaS Registry",
|
||||||
|
"grant-as-authority-to-apps": [
|
||||||
|
"$XSAPPNAME(application,sap-provisioning,tenant-onboarding)"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"attributes": [],
|
"attributes": [],
|
||||||
|
|||||||
Reference in New Issue
Block a user