Compare commits

..

12 Commits

Author SHA1 Message Date
Daniel
835f450686 PoC for code sandboxing 2020-05-26 14:12:12 +02:00
Christian Georgi
0a552b4346 Try with other node 12 version 2020-05-14 21:50:30 +02:00
Christian Georgi
6367081e9d CI badge 2020-05-14 21:19:18 +02:00
Christian Georgi
3e73683d99 Rename job 2020-05-14 21:05:26 +02:00
Christian Georgi
2b345ca447 Remove call to build script 2020-05-14 21:05:26 +02:00
Christian Georgi
20593f2fa2 Workflow file for node.js 2020-05-14 20:46:17 +02:00
Vitaly Kozyura
ca45aa1cf7 Merge pull request #74 from SAP-samples/temporary-skip-test
Temporary disable test
2020-05-07 09:59:39 +02:00
Christian Georgi
e408836c2a Fix typo in bootstrap event 2020-05-06 18:33:16 +02:00
D051920
3000a9e2df Temporary disable test 2020-05-06 18:13:40 +02:00
Heiko Witteborg
b83236de2a Merge pull request #73 from SAP-samples/add-test-for-subselect
add test for subselect in query api as documented
2020-05-06 13:03:50 +02:00
d045778
46b3b8aaec add test for subselect in query api as documented 2020-05-06 11:52:30 +02:00
Iwona Hahn
59f5c82684 Cosmetics 2020-05-05 15:01:53 +02:00
15 changed files with 191 additions and 17 deletions

1
.env
View File

@@ -1,2 +1 @@
cds.features.snapi = y
cds.cdsc.beta.aspectCompositions = true

28
.github/workflows/node.js.yml vendored Normal file
View File

@@ -0,0 +1,28 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.x, 12.16.2]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
- run: npm install
- run: npm test

View File

@@ -2,6 +2,7 @@
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)
![](https://github.com/SAP-samples/cloud-cap-samples/workflows/CI/badge.svg)
### Preliminaries
@@ -39,19 +40,19 @@ After that open this link in your browser: [http://localhost:4004](http://localh
### Testing
Run the provided tests with [_jest_](http://jestjs.io) or [_mocha_](http://mochajs.org), e.g.:
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.
> While mocha is a bit smaller and faster, jest runs tests in parallel and isolation, which allows to run all tests.
## Get Support
Check out the cap docs at [https://cap.cloud.sap](https://cap.cloud.sap). <br>
Check out the documentation at [https://cap.cloud.sap](https://cap.cloud.sap). <br>
In case you find a bug or need support, please [open an issue in here](https://github.com/SAP-samples/cloud-cap-samples/issues/new).
## License
Copyright (c) 2019 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.
Copyright (c) 2020 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.

24
ext/.eslintrc Normal file
View File

@@ -0,0 +1,24 @@
{
"extends": "eslint:recommended",
"env": {
"node": true,
"es6": true,
"jest": true
},
"parserOptions": {
"ecmaVersion": 2017
},
"globals": {
"SELECT": true,
"INSERT": true,
"UPDATE": true,
"DELETE": true,
"CREATE": true,
"DROP": true,
"cds": true
},
"rules": {
"no-console": "off",
"require-atomic-updates": "off"
}
}

30
ext/.gitignore vendored Normal file
View File

@@ -0,0 +1,30 @@
# CAP ext
_out
*.db
connection.properties
default-*.json
gen/
node_modules/
package-lock.json
target/
# Web IDE, App Studio
.che/
.gen/
# MTA
*_mta_build_tmp
*.mtar
mta_archives/
# Other
.DS_Store
*.orig
*.log
*.iml
*.flattened-pom.xml
# IDEs
.vscode
.idea

6
ext/db/schema.cds Normal file
View File

@@ -0,0 +1,6 @@
using { sap.capire.bookshop.Books } from '@capire/bookshop';
extend Books with {
ISBN : String;
discount : Decimal @assert.range:[0,1];
}

19
ext/package.json Normal file
View File

@@ -0,0 +1,19 @@
{
"name": "ext",
"version": "1.0.0",
"description": "A simple CAP project.",
"repository": "<Add your repository here>",
"license": "UNLICENSED",
"private": true,
"dependencies": {
"@capire/bookshop": "../bookshop",
"@sap/cds": "^4",
"express": "^4"
},
"devDependencies": {
"sqlite3": "^4"
},
"scripts": {
"start": "npx cds run"
}
}

40
ext/server.js Normal file
View File

@@ -0,0 +1,40 @@
const cds = require ('@sap/cds')
const path = require ('path')
const fs = require ('fs')
const protected = {db:1,messaging:1,auth:1}
const { isfile } = cds.utils
cds.on('served', ()=>{
for (let each of cds.services) {
if (each.name in protected) continue
// search for local srv/<each>.js files and if exist
// activate them in a service extension sandbox
const impl = isfile (path.resolve('srv/'+each.name+'.js'))
if (impl) activate_sandboxed (each,impl)
}
})
function activate_sandboxed (srv,impl) {
console.log (`[cds] - extending ${srv.name} with sandboxed:`, {impl:path.relative(process.cwd(),impl)})
const src = fs.readFileSync (impl)
const sandbox = Object.keys(global).filter(name => name !== 'cds')
const fn = new Function (
'module','cds','global','process', ...sandbox,
src
)
// restricted sandboxed variant of 'module' and 'cds'
const module = {}
const cds = {
service: {
impl: fn=>fn
}
}
fn (module,cds,undefined,undefined, ...sandbox.map((()=>(undefined))))
if (typeof module.exports === 'function') try {
module.exports.call (srv,srv)
} catch (e) {
console.log (e)
}
}
module.exports = cds.server

10
ext/srv/AdminService.js Normal file
View File

@@ -0,0 +1,10 @@
module.exports = cds.service.impl(function(){
this.before(['CREATE','UPDATE'],'Books', req => { //> ....
const book = req.data
if (book.stock < 10 && book.discount > 0.5) {
req.error('Hey, da sind so wenig übrig, die wollen wir nicht zu billig verticken')
}
})
})

View File

@@ -0,0 +1,9 @@
console.log ('Böses Zeug', global, process, cds)
// process.exit()
// const fs = require('fs')
// cds.run('Böses Zeugs')
// SELECT.from ('Foo')
module.exports = cds.service.impl(function(){
this.after('READ','Books', each => each.title += ' (served through sandbox)')
})

View File

@@ -1,4 +1,4 @@
ID;amount;parent_ID;book_ID
58040e66-1dcd-4ffb-ab10-fdce32028b79;1;7e2f2640-6866-4dcf-8f4d-3027aa831cad;201
64e718c9-ff99-47f1-8ca3-950c850777d4;1;7e2f2640-6866-4dcf-8f4d-3027aa831cad;271
e9641166-e050-4261-bfee-d1e797e6cb7f;2;64e718c9-ff99-47f1-8ca3-950c850777d4;252
ID;amount;parent_ID;book_ID;netAmount
58040e66-1dcd-4ffb-ab10-fdce32028b79;1;7e2f2640-6866-4dcf-8f4d-3027aa831cad;201;11.11
64e718c9-ff99-47f1-8ca3-950c850777d4;1;7e2f2640-6866-4dcf-8f4d-3027aa831cad;271;15
e9641166-e050-4261-bfee-d1e797e6cb7f;2;64e718c9-ff99-47f1-8ca3-950c850777d4;252;28
1 ID amount parent_ID book_ID netAmount
2 58040e66-1dcd-4ffb-ab10-fdce32028b79 1 7e2f2640-6866-4dcf-8f4d-3027aa831cad 201 11.11
3 64e718c9-ff99-47f1-8ca3-950c850777d4 1 7e2f2640-6866-4dcf-8f4d-3027aa831cad 271 15
4 e9641166-e050-4261-bfee-d1e797e6cb7f 2 64e718c9-ff99-47f1-8ca3-950c850777d4 252 28

View File

@@ -4,10 +4,13 @@ namespace sap.capire.bookshop;
entity Orders : cuid, managed {
OrderNo : String @title:'Order Number'; //> readable key
Items : Composition of many {
key pos : Integer;
book : Association to Books;
amount : Integer;
};
Items : Composition of many OrderItems on Items.parent = $self;
currency : Currency;
}
entity OrderItems : cuid {
parent : Association to Orders;
book : Association to Books;
amount : Integer;
netAmount : Decimal(9,2);
}

View File

@@ -34,7 +34,7 @@ cds.once('served', async()=>{
// Other bootstrapping events you could hook in to...
/* eslint-disable no-unused-vars */
cds.on('boostrap',(app) => {/* ... */})
cds.on('bootstrap',(app) => {/* ... */})
cds.on('loaded', (model) => {/* ... */})
cds.on('connect', (srv) => {/* ... */})
cds.on('serving', (srv) => {/* ... */})

View File

@@ -359,6 +359,11 @@ describe('cds.ql → cqn', () => {
CQL`SELECT from Foo where x in (SELECT y from Bar)`
)
// using query api
expect(SELECT.from('Books').where(
`author.name in`, SELECT('name').from('Authors'))).to.eql(CQL`SELECT from Books where author.name in (SELECT name from Authors)`
)
// in classical semi joins
expect(
SELECT('x').from(Foo) .where ( `exists`,

View File

@@ -72,7 +72,7 @@ describe('Localized Data', () => {
])
})
it('supports @cds.localized:false', async ()=>{
xit('supports @cds.localized:false', async ()=>{
const { data } = await GET(`/browse/BooksSans?&$select=title,localized_title&$expand=currency&$filter=locale eq 'de' or locale eq null`, {
headers: { 'Accept-Language': 'de' },
})