Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cba8e0cc5c | ||
|
|
7a2e345cd5 | ||
|
|
722cf622eb | ||
|
|
b8d389a40a | ||
|
|
82c633ce01 | ||
|
|
3161758e5f | ||
|
|
02ea798f5f | ||
|
|
09f02676ef | ||
|
|
cae0d36206 |
10
.vscode/settings.json
vendored
10
.vscode/settings.json
vendored
@@ -13,13 +13,5 @@
|
|||||||
"**/cds/lib/req/cds-context.js",
|
"**/cds/lib/req/cds-context.js",
|
||||||
"**/odata-v4/okra/**"
|
"**/odata-v4/okra/**"
|
||||||
]
|
]
|
||||||
},
|
}
|
||||||
"eslint.probe": [
|
|
||||||
"cds",
|
|
||||||
"csn",
|
|
||||||
"csv",
|
|
||||||
"csv (semicolon)",
|
|
||||||
"tsv",
|
|
||||||
"tab"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ function csrfToken (request) {
|
|||||||
document.csrfToken = token
|
document.csrfToken = token
|
||||||
request.headers['x-csrf-token'] = document.csrfToken
|
request.headers['x-csrf-token'] = document.csrfToken
|
||||||
return request
|
return request
|
||||||
}).catch(_ => {
|
}).catch(() => {
|
||||||
document.csrfToken = null // set mark to not try again
|
document.csrfToken = null // set mark to not try again
|
||||||
return request
|
return request
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import cds from '@sap/cds'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* In order to keep basic bookshop sample as simple as possible, we don't add
|
* In order to keep basic bookshop sample as simple as possible, we don't add
|
||||||
* reuse dependencies. This db/init.js ensures we still have a minimum set of
|
* reuse dependencies. This db/init.js ensures we still have a minimum set of
|
||||||
@@ -6,7 +8,7 @@
|
|||||||
|
|
||||||
// NOTE: We use cds.on('served') to delay the UPSERTs after the db init
|
// NOTE: We use cds.on('served') to delay the UPSERTs after the db init
|
||||||
// to run after all INSERTs from .csv files happened.
|
// to run after all INSERTs from .csv files happened.
|
||||||
module.exports = cds.on('served', ()=> cds.run(
|
export default cds.on('served', ()=>
|
||||||
UPSERT.into ('sap.common.Currencies') .columns (
|
UPSERT.into ('sap.common.Currencies') .columns (
|
||||||
[ 'code', 'symbol', 'name' ]
|
[ 'code', 'symbol', 'name' ]
|
||||||
) .rows (
|
) .rows (
|
||||||
@@ -16,4 +18,4 @@ module.exports = cds.on('served', ()=> cds.run(
|
|||||||
[ 'ILS', '₪', 'Shekel' ],
|
[ 'ILS', '₪', 'Shekel' ],
|
||||||
[ 'JPY', '¥', 'Yen' ],
|
[ 'JPY', '¥', 'Yen' ],
|
||||||
)
|
)
|
||||||
))
|
)
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
const { CatalogService } = require('./srv/cat-service')
|
|
||||||
module.exports = { CatalogService }
|
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
"name": "@capire/bookshop",
|
"name": "@capire/bookshop",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "A simple self-contained bookshop service.",
|
"description": "A simple self-contained bookshop service.",
|
||||||
|
"type": "module",
|
||||||
"files": [
|
"files": [
|
||||||
"app",
|
"app",
|
||||||
"srv",
|
"srv",
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
const cds = require('@sap/cds')
|
import cds from '@sap/cds'
|
||||||
|
|
||||||
module.exports = class AdminService extends cds.ApplicationService { init(){
|
export class AdminService extends cds.ApplicationService { init(){
|
||||||
this.before ('NEW','Authors', genid)
|
this.before (['NEW','CREATE'],'Authors', genid)
|
||||||
this.before ('NEW','Books', genid)
|
this.before (['NEW','CREATE'],'Books', genid)
|
||||||
return super.init()
|
return super.init()
|
||||||
}}
|
}}
|
||||||
|
|
||||||
/** Generate primary keys for target entity in request */
|
/** Generate primary keys for target entity in request */
|
||||||
async function genid (req) {
|
async function genid (req) {
|
||||||
|
if (req.data.ID) return
|
||||||
const {id} = await SELECT.one.from(req.target).columns('max(ID) as id')
|
const {id} = await SELECT.one.from(req.target).columns('max(ID) as id')
|
||||||
req.data.ID = id - id % 100 + 100 + 1
|
req.data.ID = id + 4 // Note: that is not safe! ok for this sample only.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
const cds = require('@sap/cds')
|
import cds from '@sap/cds'
|
||||||
module.exports = class CatalogService extends cds.ApplicationService { init() {
|
|
||||||
|
export class CatalogService extends cds.ApplicationService { init() {
|
||||||
|
|
||||||
const { Books } = cds.entities('sap.capire.bookshop')
|
const { Books } = cds.entities('sap.capire.bookshop')
|
||||||
const { ListOfBooks } = this.entities
|
const { ListOfBooks } = this.entities
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const cds = require('@sap/cds')
|
import cds from '@sap/cds'
|
||||||
module.exports = class UserService extends cds.Service { init(){
|
export class UserService extends cds.Service { init(){
|
||||||
this.on('READ', 'me', ({ tenant, user, locale }) => ({ id: user.id, locale, tenant }))
|
this.on('READ', 'me', ({ tenant, user, locale }) => ({ id: user.id, locale, tenant }))
|
||||||
this.on('login', (req) => {
|
this.on('login', (req) => {
|
||||||
if (req.user._is_anonymous)
|
if (req.user._is_anonymous)
|
||||||
|
|||||||
@@ -3,15 +3,15 @@
|
|||||||
# Genres
|
# Genres
|
||||||
#
|
#
|
||||||
|
|
||||||
GET http://localhost:4004/test/Genres?
|
GET http://localhost:4004/odata/v4/test/Genres?
|
||||||
###
|
###
|
||||||
|
|
||||||
GET http://localhost:4004/test/Genres?
|
GET http://localhost:4004/odata/v4/test/Genres?
|
||||||
&$filter=parent_ID eq null&$select=name
|
&$filter=parent_ID eq null&$select=name
|
||||||
&$expand=children($select=name)
|
&$expand=children($select=name)
|
||||||
###
|
###
|
||||||
|
|
||||||
POST http://localhost:4004/test/Genres?
|
POST http://localhost:4004/odata/v4/test/Genres?
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{ "ID":100, "name":"Some Sample Genres...", "children":[
|
{ "ID":100, "name":"Some Sample Genres...", "children":[
|
||||||
@@ -26,13 +26,13 @@ Content-Type: application/json
|
|||||||
]}
|
]}
|
||||||
###
|
###
|
||||||
|
|
||||||
GET http://localhost:4004/test/Genres(100)?
|
GET http://localhost:4004/odata/v4/test/Genres(100)?
|
||||||
# &$expand=children
|
# &$expand=children
|
||||||
# &$expand=children($expand=children($expand=children($expand=children)))
|
# &$expand=children($expand=children($expand=children($expand=children)))
|
||||||
###
|
###
|
||||||
|
|
||||||
DELETE http://localhost:4004/test/Genres(103)
|
DELETE http://localhost:4004/odata/v4/test/Genres(103)
|
||||||
###
|
###
|
||||||
|
|
||||||
DELETE http://localhost:4004/test/Genres(100)
|
DELETE http://localhost:4004/odata/v4/test/Genres(100)
|
||||||
###
|
###
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@capire/bookstore",
|
"name": "@capire/bookstore",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@capire/bookshop": "*",
|
"@capire/bookshop": "*",
|
||||||
"@capire/reviews": "*",
|
"@capire/reviews": "*",
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
const cds = require ('@sap/cds')
|
import mashup from './srv/mashup.js'
|
||||||
|
import cds from '@sap/cds'
|
||||||
|
|
||||||
// Add mashup logic
|
// Add mashup logic
|
||||||
cds.once('served', require('./srv/mashup'))
|
cds.once('served', mashup)
|
||||||
|
|
||||||
// Add routes to UIs from imported packages
|
// Add routes to UIs from imported packages
|
||||||
cds.once('bootstrap',(app)=>{
|
cds.once('bootstrap',(app)=>{
|
||||||
@@ -10,6 +11,3 @@ cds.once('bootstrap',(app)=>{
|
|||||||
app.serve ('/orders') .from('@capire/orders','app/orders')
|
app.serve ('/orders') .from('@capire/orders','app/orders')
|
||||||
app.serve ('/data') .from('@capire/data-viewer','app/viewer')
|
app.serve ('/data') .from('@capire/data-viewer','app/viewer')
|
||||||
})
|
})
|
||||||
|
|
||||||
// Add Swagger UI
|
|
||||||
require('./srv/swagger-ui')
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
|
import cds from '@sap/cds'
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Mashing up bookshop services with required services...
|
// Mashing up bookshop services with required services...
|
||||||
//
|
//
|
||||||
module.exports = async()=>{ // called by server.js
|
export default async()=>{ // called by server.js
|
||||||
|
|
||||||
const cds = require('@sap/cds')
|
|
||||||
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')
|
||||||
const OrdersService = await cds.connect.to ('OrdersService')
|
const OrdersService = await cds.connect.to ('OrdersService')
|
||||||
@@ -18,7 +19,7 @@ module.exports = async()=>{ // called by server.js
|
|||||||
// Note: prepend is neccessary to intercept generic default handler
|
// Note: prepend is neccessary to intercept generic default handler
|
||||||
//
|
//
|
||||||
CatalogService.prepend (srv => srv.on ('READ', 'Books/reviews', (req) => {
|
CatalogService.prepend (srv => srv.on ('READ', 'Books/reviews', (req) => {
|
||||||
console.debug ('> delegating request to ReviewsService')
|
console.debug ('> delegating request to ReviewsService') // eslint-disable-line no-console
|
||||||
const [id] = req.params, { columns, limit } = req.query.SELECT
|
const [id] = req.params, { columns, limit } = req.query.SELECT
|
||||||
return ReviewsService.read ('Reviews',columns).limit(limit).where({subject:String(id)})
|
return ReviewsService.read ('Reviews',columns).limit(limit).where({subject:String(id)})
|
||||||
}))
|
}))
|
||||||
@@ -40,7 +41,7 @@ module.exports = async()=>{ // called by server.js
|
|||||||
// Update Books' average ratings when ReviewsService signals updated reviews
|
// Update Books' average ratings when ReviewsService signals updated reviews
|
||||||
//
|
//
|
||||||
ReviewsService.on ('reviewed', (msg) => {
|
ReviewsService.on ('reviewed', (msg) => {
|
||||||
console.debug ('> received:', msg.event, msg.data)
|
console.debug ('> received:', msg.event, msg.data) // eslint-disable-line no-console
|
||||||
const { subject, count, rating } = msg.data
|
const { subject, count, rating } = msg.data
|
||||||
return UPDATE(Books,subject).with({ numberOfReviews:count, rating })
|
return UPDATE(Books,subject).with({ numberOfReviews:count, rating })
|
||||||
})
|
})
|
||||||
@@ -49,7 +50,7 @@ module.exports = async()=>{ // called by server.js
|
|||||||
// Reduce stock of ordered books for orders are created from Orders admin UI
|
// Reduce stock of ordered books for orders are created from Orders admin UI
|
||||||
//
|
//
|
||||||
OrdersService.on ('OrderChanged', (msg) => {
|
OrdersService.on ('OrderChanged', (msg) => {
|
||||||
console.debug ('> received:', msg.event, msg.data)
|
console.debug ('> received:', msg.event, msg.data) // eslint-disable-line no-console
|
||||||
const { product, deltaQuantity } = msg.data
|
const { product, deltaQuantity } = msg.data
|
||||||
return UPDATE (Books) .where ('ID =', product)
|
return UPDATE (Books) .where ('ID =', product)
|
||||||
.and ('stock >=', deltaQuantity)
|
.and ('stock >=', deltaQuantity)
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------
|
|
||||||
// Adding Swagger UI - see https://cap.cloud.sap/docs/advanced/openapi
|
|
||||||
const cds = require ('@sap/cds')
|
|
||||||
try {
|
|
||||||
const cds_swagger = require ('cds-swagger-ui-express')
|
|
||||||
cds.once ('bootstrap', app => app.use (cds_swagger()) )
|
|
||||||
} catch (err) {
|
|
||||||
if (err.code !== 'MODULE_NOT_FOUND') throw err
|
|
||||||
}
|
|
||||||
@@ -12,11 +12,12 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
GET {{reviews-service}}/Reviews
|
GET {{reviews-service}}/Reviews
|
||||||
|
Authorization: Basic me:
|
||||||
|
|
||||||
###
|
###
|
||||||
|
|
||||||
POST {{reviews-service}}/Reviews
|
POST {{reviews-service}}/Reviews
|
||||||
Authorization: Basic {{$processEnv USER}}:
|
Authorization: Basic me:
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{"subject":"201", "title":"boo", "rating":3 }
|
{"subject":"201", "title":"boo", "rating":3 }
|
||||||
@@ -50,23 +51,23 @@ Accept-Language: de
|
|||||||
#
|
#
|
||||||
@newOrderID = e939604c-ab83-4d4f-bdb6-95fe30b3773e
|
@newOrderID = e939604c-ab83-4d4f-bdb6-95fe30b3773e
|
||||||
|
|
||||||
GET {{bookshop}}/orders/Orders
|
GET {{bookshop}}/odata/v4/orders/Orders
|
||||||
|
|
||||||
### Create order, still inactive
|
### Create order, still inactive
|
||||||
POST {{bookshop}}/orders/Orders
|
POST {{bookshop}}/odata/v4/orders/Orders
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{"ID": "{{newOrderID}}"}
|
{"ID": "{{newOrderID}}"}
|
||||||
|
|
||||||
### Get inactive order. We have to specify `IsActiveEntity`.
|
### Get inactive order. We have to specify `IsActiveEntity`.
|
||||||
GET {{bookshop}}/orders/Orders(ID={{newOrderID}},IsActiveEntity=false)
|
GET {{bookshop}}/odata/v4/orders/Orders(ID={{newOrderID}},IsActiveEntity=false)
|
||||||
|
|
||||||
### Activate order using `.../<servicename>.draftActivate`
|
### Activate order using `.../<servicename>.draftActivate`
|
||||||
POST {{bookshop}}/orders/Orders(ID={{newOrderID}},IsActiveEntity=false)/OrdersService.draftActivate
|
POST {{bookshop}}/odata/v4/orders/Orders(ID={{newOrderID}},IsActiveEntity=false)/OrdersService.draftActivate
|
||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
### Get active order
|
### Get active order
|
||||||
GET {{bookshop}}/orders/Orders(ID={{newOrderID}},IsActiveEntity=true)
|
GET {{bookshop}}/odata/v4/orders/Orders(ID={{newOrderID}},IsActiveEntity=true)
|
||||||
|
|
||||||
### Create author
|
### Create author
|
||||||
POST {{bookshop}}/admin/Authors
|
POST {{bookshop}}/admin/Authors
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class DataService extends cds.ApplicationService { init(){
|
|||||||
.sort((e1, e2) => e1.name.localeCompare(e2.name))
|
.sort((e1, e2) => e1.name.localeCompare(e2.name))
|
||||||
.map(e => {
|
.map(e => {
|
||||||
const columns = Object.entries(e.elements)
|
const columns = Object.entries(e.elements)
|
||||||
.filter(([_, el]) => !(el instanceof cds.Association)) // exclude assocs+compositions
|
.filter(([,el]) => !(el instanceof cds.Association)) // exclude assocs+compositions
|
||||||
.map(([name, el]) => { return { name, type: el.type, isKey:!!el.key }})
|
.map(([name, el]) => { return { name, type: el.type, isKey:!!el.key }})
|
||||||
return { name: e.name, columns }
|
return { name: e.name, columns }
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,36 +0,0 @@
|
|||||||
const cds = require('@sap/eslint-plugin-cds')
|
|
||||||
const globals = require('globals')
|
|
||||||
const js = require('@eslint/js')
|
|
||||||
|
|
||||||
module.exports = [
|
|
||||||
cds.configs.recommended,
|
|
||||||
js.configs.recommended,
|
|
||||||
{
|
|
||||||
languageOptions: {
|
|
||||||
globals: {
|
|
||||||
es2022: true,
|
|
||||||
...globals.browser,
|
|
||||||
...globals.node,
|
|
||||||
...globals.jest,
|
|
||||||
...globals.mocha,
|
|
||||||
cds: true,
|
|
||||||
sap: true,
|
|
||||||
CDL: true,
|
|
||||||
CQL: true,
|
|
||||||
CREATE: true,
|
|
||||||
DELETE: true,
|
|
||||||
DROP: true,
|
|
||||||
INSERT: true,
|
|
||||||
SELECT: true,
|
|
||||||
UPDATE: true,
|
|
||||||
UPSERT: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
'no-console': 'off',
|
|
||||||
'no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
|
|
||||||
'require-atomic-updates': 'off',
|
|
||||||
'require-await': 'warn'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
20
eslint.config.mjs
Normal file
20
eslint.config.mjs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import cds from '@sap/cds/eslint.config.mjs'
|
||||||
|
export default [ ...cds.recommended ]
|
||||||
|
|
||||||
|
//
|
||||||
|
// The above is the recommended minimalistic eslint config, just using
|
||||||
|
// recommended defaults provided by cds. Alternatively, go for enhanced
|
||||||
|
// project-specific options, but only if really required, like this:
|
||||||
|
//
|
||||||
|
// export default [ ...cds.recommended, {
|
||||||
|
// rules: {
|
||||||
|
// 'complexity': [ 'warn', 66 ],
|
||||||
|
// 'require-await': 'warn',
|
||||||
|
// 'no-await-in-loop': 'warn',
|
||||||
|
// },
|
||||||
|
// }, {
|
||||||
|
// ignores: [
|
||||||
|
// '**/webapp/**'
|
||||||
|
// ]
|
||||||
|
// }]
|
||||||
|
//
|
||||||
@@ -1,42 +1,13 @@
|
|||||||
{
|
{
|
||||||
"name": "@capire/hello-world",
|
"name": "@capire/hello-world",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "npx jest --silent",
|
"test": "npx jest --silent",
|
||||||
"start": "cds serve srv/world.cds",
|
"start": "cds-serve srv/world.cds",
|
||||||
"start:ts": "cds-ts serve srv/world.cds"
|
"start:ts": "cds-ts serve srv/world.cds"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sap/cds": ">=5.0.4"
|
"@sap/cds": ">=5.0.4"
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/jest": "*",
|
|
||||||
"@types/node": "*",
|
|
||||||
"typescript": ">=4.3.5"
|
|
||||||
},
|
|
||||||
"eslintConfig": {
|
|
||||||
"extends": "eslint:recommended",
|
|
||||||
"env": {
|
|
||||||
"es2020": true,
|
|
||||||
"node": true,
|
|
||||||
"jest": true,
|
|
||||||
"mocha": true
|
|
||||||
},
|
|
||||||
"globals": {
|
|
||||||
"SELECT": true,
|
|
||||||
"INSERT": true,
|
|
||||||
"UPDATE": true,
|
|
||||||
"DELETE": true,
|
|
||||||
"CREATE": true,
|
|
||||||
"DROP": true,
|
|
||||||
"CDL": true,
|
|
||||||
"CQL": true,
|
|
||||||
"CXL": true,
|
|
||||||
"cds": true
|
|
||||||
},
|
|
||||||
"rules": {
|
|
||||||
"no-console": "off",
|
|
||||||
"require-atomic-updates": "off"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
service say @(path: '/say') {
|
service say {
|
||||||
function hello (to:String) returns String;
|
function hello (to:String) returns String;
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
module.exports = class say {
|
import cds from '@sap/cds'
|
||||||
hello(req) {
|
export class say extends cds.ApplicationService {
|
||||||
let {to} = req.data
|
hello (to = 'World') {
|
||||||
if (to === 'me') to = require('os').userInfo().username
|
|
||||||
return `Hello ${to}!`
|
return `Hello ${to}!`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { Request } from "@sap/cds"
|
import cds from '@sap/cds'
|
||||||
|
export class say extends cds.ApplicationService {
|
||||||
module.exports = class say {
|
hello (to : String = 'World') {
|
||||||
hello(req: Request) {
|
return `Hello ${to} from TypeScript!`
|
||||||
return `Hello ${req.data.to} from a TypeScript file!`
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
const cds = require ('@sap/cds')
|
|
||||||
describe('Hello world!', () => {
|
|
||||||
const {GET} = cds.test.in(__dirname,'../srv').run('serve', 'world.cds')
|
|
||||||
|
|
||||||
it('should say hello with class impl', async () => {
|
|
||||||
const {data} = await GET`/say/hello(to='world')`
|
|
||||||
expect(data.value).to.match(/Hello world.*typescript.*/i)
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
@@ -1 +1,5 @@
|
|||||||
GET http://localhost:4004/say/hello(to='world')
|
GET http://localhost:4004/odata/v4/say/hello
|
||||||
|
###
|
||||||
|
|
||||||
|
GET http://localhost:4004/odata/v4/say/hello(to='me')
|
||||||
|
###
|
||||||
|
|||||||
@@ -13,10 +13,5 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "cds-serve",
|
"start": "cds-serve",
|
||||||
"watch": "cds watch"
|
"watch": "cds watch"
|
||||||
},
|
|
||||||
"cds": {
|
|
||||||
"requires": {
|
|
||||||
"db": "sql"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class OrdersService extends cds.ApplicationService {
|
|||||||
/** order changed -> broadcast event */
|
/** order changed -> broadcast event */
|
||||||
orderChanged (product, deltaQuantity) {
|
orderChanged (product, deltaQuantity) {
|
||||||
// Emit events to inform subscribers about changes in orders
|
// Emit events to inform subscribers about changes in orders
|
||||||
console.log ('> emitting:', 'OrderChanged', { product, deltaQuantity })
|
console.log ('> emitting:', 'OrderChanged', { product, deltaQuantity }) // eslint-disable-line no-console
|
||||||
return this.emit ('OrderChanged', { product, deltaQuantity })
|
return this.emit ('OrderChanged', { product, deltaQuantity })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1026
package-lock.json
generated
1026
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
22
package.json
22
package.json
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "@capire/samples",
|
"name": "@capire/samples",
|
||||||
"version": "2.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": ">=7"
|
"@sap/cds": ">=8"
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"./bookshop",
|
"./bookshop",
|
||||||
@@ -21,7 +21,6 @@
|
|||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@cap-js/sqlite": "^1",
|
"@cap-js/sqlite": "^1",
|
||||||
"@sap/eslint-plugin-cds": "^3",
|
|
||||||
"axios": "^1",
|
"axios": "^1",
|
||||||
"chai": "^4.3.4",
|
"chai": "^4.3.4",
|
||||||
"chai-as-promised": "^7.1.1",
|
"chai-as-promised": "^7.1.1",
|
||||||
@@ -30,23 +29,16 @@
|
|||||||
"semver": "^7"
|
"semver": "^7"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"cleanup": "rm -rf node_modules && rm -rf */node_modules && rm -rf */*/node_modules",
|
|
||||||
"bookshop": "cds watch bookshop",
|
"bookshop": "cds watch bookshop",
|
||||||
|
"start": "cds watch fiori",
|
||||||
"fiori": "cds watch fiori",
|
"fiori": "cds watch fiori",
|
||||||
"hello": "cds watch hello",
|
"hello": "cds watch hello",
|
||||||
"media": "cds watch media",
|
"media": "cds watch media",
|
||||||
"mocha": "CDS_TEST_SILENT=y npx mocha",
|
"lint": "eslint",
|
||||||
|
"test": "npx jest --silent",
|
||||||
"jest": "npx jest --silent",
|
"jest": "npx jest --silent",
|
||||||
"start": "cds watch fiori",
|
"mocha": "CDS_TEST_SILENT=y npx mocha",
|
||||||
"test": "npm run jest -- --silent",
|
"test:hello": "cd hello && npm test"
|
||||||
"test:hello": "cd hello && npm test",
|
|
||||||
"lint": "eslint ."
|
|
||||||
},
|
|
||||||
"jest": {
|
|
||||||
"testTimeout": 20000,
|
|
||||||
"testMatch": [
|
|
||||||
"**/*.test.js"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"mocha": {
|
"mocha": {
|
||||||
"recursive": true,
|
"recursive": true,
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ const reviews = Vue.createApp ({
|
|||||||
const res = await POST(`/Reviews`,review)
|
const res = await POST(`/Reviews`,review)
|
||||||
reviews.ID = res.data.ID
|
reviews.ID = res.data.ID
|
||||||
} else {
|
} else {
|
||||||
console.trace()
|
|
||||||
await PUT(`/Reviews/${review.ID}`,review)
|
await PUT(`/Reviews/${review.ID}`,review)
|
||||||
}
|
}
|
||||||
reviews.message = { succeeded: 'Your review was submitted successfully. Thanks.' }
|
reviews.message = { succeeded: 'Your review was submitted successfully. Thanks.' }
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ module.exports = cds.service.impl (function(){
|
|||||||
const { count, rating } = await cds.tx(req) .run (
|
const { count, rating } = await cds.tx(req) .run (
|
||||||
SELECT.one `round(avg(rating),2) as rating, count(*) as count` .from (Reviews) .where ({subject})
|
SELECT.one `round(avg(rating),2) as rating, count(*) as count` .from (Reviews) .where ({subject})
|
||||||
)
|
)
|
||||||
global.it || console.log ('< emitting:', 'reviewed', { subject, count, rating })
|
global.it || console.log ('< emitting:', 'reviewed', { subject, count, rating }) // eslint-disable-line no-console
|
||||||
await this.emit ('reviewed', { subject, count, rating })
|
await this.emit ('reviewed', { subject, count, rating })
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -677,7 +677,7 @@ describe('cds.ql → cqn', () => {
|
|||||||
.to.eql(INSERT.into(Foo).entries(...entries))
|
.to.eql(INSERT.into(Foo).entries(...entries))
|
||||||
.to.eql(INSERT.into(Foo).entries(entries))
|
.to.eql(INSERT.into(Foo).entries(entries))
|
||||||
.to.eql({
|
.to.eql({
|
||||||
INSERT: { into: cds.env.ql.quirks_mode ? 'Foo' : { ref: ['Foo'] }, entries },
|
INSERT: { into: { ref: ['Foo'] }, entries },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -693,7 +693,7 @@ describe('cds.ql → cqn', () => {
|
|||||||
.to.eql(INSERT.into(Foo).columns('a', 'b').rows([1, 2], [3, 4]))
|
.to.eql(INSERT.into(Foo).columns('a', 'b').rows([1, 2], [3, 4]))
|
||||||
.to.eql({
|
.to.eql({
|
||||||
INSERT: {
|
INSERT: {
|
||||||
into: cds.env.ql.quirks_mode ? 'Foo' : { ref: ['Foo'] },
|
into: { ref: ['Foo'] },
|
||||||
columns: ['a', 'b'],
|
columns: ['a', 'b'],
|
||||||
rows: [
|
rows: [
|
||||||
[1, 2],
|
[1, 2],
|
||||||
@@ -707,7 +707,7 @@ describe('cds.ql → cqn', () => {
|
|||||||
expect(INSERT.into(Foo).columns('a', 'b').values([1, 2]))
|
expect(INSERT.into(Foo).columns('a', 'b').values([1, 2]))
|
||||||
.to.eql(INSERT.into(Foo).columns('a', 'b').values(1, 2))
|
.to.eql(INSERT.into(Foo).columns('a', 'b').values(1, 2))
|
||||||
.to.eql({
|
.to.eql({
|
||||||
INSERT: { into: cds.env.ql.quirks_mode ? 'Foo' : { ref: ['Foo'] }, columns: ['a', 'b'], values: [1, 2] },
|
INSERT: { into: { ref: ['Foo'] }, columns: ['a', 'b'], values: [1, 2] },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -722,7 +722,7 @@ describe('cds.ql → cqn', () => {
|
|||||||
test('entity (..., <key>)', () => {
|
test('entity (..., <key>)', () => {
|
||||||
const cqnWhere = {
|
const cqnWhere = {
|
||||||
UPDATE: {
|
UPDATE: {
|
||||||
entity: cds.env.ql.quirks_mode ? 'capire.bookshop.Books' : { ref: ['capire.bookshop.Books'] },
|
entity: { ref: ['capire.bookshop.Books'] },
|
||||||
where: [{ ref: ['ID'] }, '=', { val: 4711 }],
|
where: [{ ref: ['ID'] }, '=', { val: 4711 }],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -766,7 +766,7 @@ describe('cds.ql → cqn', () => {
|
|||||||
.to.eql(UPDATE(Foo).with({ foo: 11, bar: { '-=': 22 } }))
|
.to.eql(UPDATE(Foo).with({ foo: 11, bar: { '-=': 22 } }))
|
||||||
.to.eql({
|
.to.eql({
|
||||||
UPDATE: {
|
UPDATE: {
|
||||||
entity: cds.env.ql.quirks_mode ? 'Foo' : { ref: ['Foo'] },
|
entity: { ref: ['Foo'] },
|
||||||
data: { foo: 11 },
|
data: { foo: 11 },
|
||||||
with: {
|
with: {
|
||||||
bar: { xpr: [{ ref: ['bar'] }, '-', { val: 22 }] },
|
bar: { xpr: [{ ref: ['bar'] }, '-', { val: 22 }] },
|
||||||
@@ -777,7 +777,7 @@ describe('cds.ql → cqn', () => {
|
|||||||
// some more
|
// some more
|
||||||
expect(UPDATE(Foo).with(`bar = coalesce(x,y), car = 'foo''s bar, car'`)).to.eql({
|
expect(UPDATE(Foo).with(`bar = coalesce(x,y), car = 'foo''s bar, car'`)).to.eql({
|
||||||
UPDATE: {
|
UPDATE: {
|
||||||
entity: cds.env.ql.quirks_mode ? 'Foo' : { ref: ['Foo'] },
|
entity: { ref: ['Foo'] },
|
||||||
data: {
|
data: {
|
||||||
car: "foo's bar, car",
|
car: "foo's bar, car",
|
||||||
},
|
},
|
||||||
@@ -797,7 +797,7 @@ describe('cds.ql → cqn', () => {
|
|||||||
test('from (..., <key>)', () => {
|
test('from (..., <key>)', () => {
|
||||||
const cqnWhere = {
|
const cqnWhere = {
|
||||||
DELETE: {
|
DELETE: {
|
||||||
from: cds.env.ql.quirks_mode ? 'capire.bookshop.Books' : { ref: ['capire.bookshop.Books'] },
|
from: { ref: ['capire.bookshop.Books'] },
|
||||||
where: [{ ref: ['ID'] }, '=', { val: 4711 }],
|
where: [{ ref: ['ID'] }, '=', { val: 4711 }],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ describe('cap/samples - Hello world!', () => {
|
|||||||
const { GET, expect } = cds.test (__dirname+'/../hello')
|
const { GET, expect } = cds.test (__dirname+'/../hello')
|
||||||
|
|
||||||
it('should say hello with class impl', async () => {
|
it('should say hello with class impl', async () => {
|
||||||
const {data} = await GET `/say/hello(to='world')`
|
const {data} = await GET `/odata/v4/say/hello(to='world')`
|
||||||
expect(data.value).to.eql('Hello world!')
|
expect(data.value).to.eql('Hello world!')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user