diff --git a/demo/server.js b/demo/server.js deleted file mode 100644 index 0717b6e9..00000000 --- a/demo/server.js +++ /dev/null @@ -1,11 +0,0 @@ -const express = require('express') -const cds = require('@sap/cds') - -cds.once('bootstrap',(app)=>{ - const {dirname} = require('path') - // serving the vue.js app imported from @capire/bookshop - const vue_app = dirname (require.resolve('@capire/bookshop/app/vue/index.html')) - app.use ('/vue', express.static(vue_app)) -}) - -module.exports = cds.server diff --git a/demo/srv/service.js b/demo/srv/service.js deleted file mode 100644 index e69de29b..00000000 diff --git a/demo/srv/services.cds b/demo/srv/services.cds deleted file mode 100644 index 90b2cb55..00000000 --- a/demo/srv/services.cds +++ /dev/null @@ -1,17 +0,0 @@ -using { sap.capire, sap.capire.bookshop.Books } from '@capire/bookshop'; -using { API_BUSINESS_PARTNER as external } from './external/API_BUSINESS_PARTNER.csn'; - -extend Books with { - supplier : Association to Suppliers; -} - -extend service CatalogService with { - entity MySuppliers as projection on Suppliers; -} - -@cds.persistence:{table,skip:false} -entity Suppliers as projection on external.A_BusinessPartner { - BusinessPartner as ID, - LastName, - AcademicTitle -} diff --git a/demo/.cdsrc.json b/done/.cdsrc.json similarity index 100% rename from demo/.cdsrc.json rename to done/.cdsrc.json diff --git a/demo/.eslintrc b/done/.eslintrc similarity index 100% rename from demo/.eslintrc rename to done/.eslintrc diff --git a/demo/.gitignore b/done/.gitignore similarity index 100% rename from demo/.gitignore rename to done/.gitignore diff --git a/demo/.vscode/extensions.json b/done/.vscode/extensions.json similarity index 100% rename from demo/.vscode/extensions.json rename to done/.vscode/extensions.json diff --git a/demo/.vscode/launch.json b/done/.vscode/launch.json similarity index 100% rename from demo/.vscode/launch.json rename to done/.vscode/launch.json diff --git a/demo/.vscode/settings.json b/done/.vscode/settings.json similarity index 100% rename from demo/.vscode/settings.json rename to done/.vscode/settings.json diff --git a/demo/.vscode/tasks.json b/done/.vscode/tasks.json similarity index 100% rename from demo/.vscode/tasks.json rename to done/.vscode/tasks.json diff --git a/demo/README.md b/done/README.md similarity index 100% rename from demo/README.md rename to done/README.md diff --git a/demo/app/vue/index.html b/done/app/vue/index.html similarity index 100% rename from demo/app/vue/index.html rename to done/app/vue/index.html diff --git a/demo/package.json b/done/package.json similarity index 84% rename from demo/package.json rename to done/package.json index a6059a32..2039df49 100644 --- a/demo/package.json +++ b/done/package.json @@ -7,6 +7,9 @@ "private": true, "dependencies": { "@capire/bookshop": "^1.0.0", + "@capire/common": "^1.0.0", + "@capire/orders": "^1.0.0", + "@capire/reviews": "^1.0.0", "@sap/cds": "^4", "express": "^4" }, @@ -24,4 +27,4 @@ } } } -} \ No newline at end of file +} diff --git a/done/server.js b/done/server.js new file mode 100644 index 00000000..d3e2d01a --- /dev/null +++ b/done/server.js @@ -0,0 +1,67 @@ +const cds = require('@sap/cds') +module.exports = cds.server + + +cds.once('bootstrap',(app)=>{ + app.use('/vue',_from('@capire/bookshop/app/vue')) +}) + + + +cds.once('served', async ()=>{ + + // Connect to services we want to mashup below... + const S4bupa = await cds.connect.to('API_BUSINESS_PARTNER') //> external S4 service + const admin = await cds.connect.to('AdminService') //> local domain service + const db = await cds.connect.to('db') //> our primary database + + // Reflect CDS definition of the Suppliers entity + const Suppliers = S4bupa.entities + + // admin.prepend (()=>{ + + // Delegate Value Help reads for Suppliers to S4 backend + admin.on ('READ', 'Suppliers', req => { + console.log ('>> delegating to S4 service...') + return S4bupa.read(Suppliers) .where (req.query.where) + }) + + + // Replicate Supplier data when Books are edited + admin.on (['CREATE','UPDATE'], 'Books', async req => { + const { supplier } = req.data + if (supplier) { + let cached = await db.read (Suppliers, supplier) + if (!cached) await replicate (supplier,'initial') + } + }) + + // }) + + // Subscribe to changes in the S4 origin of Suppliers data + S4bupa.on ('BusinessPartner/Changed', async msg => { + const ID = msg.businessPartner.KEYS + const cached = await db.read (Suppliers, sup => sup.ID) .where ({ ID }) + for (let each of cached) replicate (each, 'update') + }) + + // Helper function to replicate Suppliers data + async function replicate (ID,_initial) { + let data = await S4bupa.read (Suppliers, ID) + if (_initial) return db.insert (data) .into (Suppliers) + else return db.update (Suppliers,ID) .with (data) + } + +}) + + + + + + + +// ----------------------------------------------------------------------- +// Helper for serving static content from npm-installed packages +const {static} = require('express') +const {dirname} = require('path') +const _from = target => static (dirname (require.resolve(`${target}/index.html`))) diff --git a/demo/srv/external/API_BUSINESS_PARTNER.csn b/done/srv/external/API_BUSINESS_PARTNER.csn similarity index 100% rename from demo/srv/external/API_BUSINESS_PARTNER.csn rename to done/srv/external/API_BUSINESS_PARTNER.csn diff --git a/demo/srv/external/API_BUSINESS_PARTNER.edmx b/done/srv/external/API_BUSINESS_PARTNER.edmx similarity index 100% rename from demo/srv/external/API_BUSINESS_PARTNER.edmx rename to done/srv/external/API_BUSINESS_PARTNER.edmx diff --git a/done/srv/external/data/API_BUSINESS_PARTNER-Suppliers.csv b/done/srv/external/data/API_BUSINESS_PARTNER-Suppliers.csv new file mode 100644 index 00000000..ac0c0746 --- /dev/null +++ b/done/srv/external/data/API_BUSINESS_PARTNER-Suppliers.csv @@ -0,0 +1,5 @@ +ID;name;city +ACME;A Company Making Everything;Massachusetts +B4U;Books for You;Philadelphia +S&C;Shakespeare & Co.;Paris +WSL;Waterstones;London diff --git a/done/srv/services.cds b/done/srv/services.cds new file mode 100644 index 00000000..03ea01cb --- /dev/null +++ b/done/srv/services.cds @@ -0,0 +1,55 @@ +/* + Optionally add projections to external entities, to capture what + you actually want to use from there. + */ + +using { API_BUSINESS_PARTNER as S4 } from './external/API_BUSINESS_PARTNER.csn'; +extend service S4 with { + entity Suppliers as projection on S4.A_BusinessPartner { + key BusinessPartner as ID, + BusinessPartnerFullName as name, + to_BusinessPartnerAddress.CityName as city + } +} + + +/* + You can mashup entities from external services, or projections + thereof, with your project's own entities + */ +using { sap.capire.bookshop.Books } from '@capire/bookshop'; +extend Books with { + supplier : Association to S4.Suppliers; +} + + +/* + You can also expose external entities through your own services + For this to work, you need to delegate the respective calls + addressed to your services into calls to the external service. + */ +extend service AdminService with { + entity Suppliers as projection on S4.Suppliers; +} + +/* + Optionally add a local persistence to keep replicas of external + entities to have data in fast access locally; much like a cache. + */ +annotate S4.Suppliers with @cds.persistence:{table,skip:false}; + +/** + Having locally cached replicas also allows us to display supplier + data in lists of books, which otherwise would generate unwanted + traffic on S4 backends. + */ +extend projection CatalogService.ListOfBooks with { + supplier +} + +/* + The following using directives activate imported reuse packages. + */ +using from '@capire/common'; +using from '@capire/orders'; +using from '@capire/reviews';