Compare commits

...

9 Commits
v7 ... esm

Author SHA1 Message Date
Daniel Hutzel
cba8e0cc5c Using ES Modules 2024-07-16 15:29:45 +02:00
Daniel Hutzel
7a2e345cd5 fix bookshop requests.http 2024-07-16 15:29:08 +02:00
Daniel Hutzel
722cf622eb Simplify hello world sample 2024-07-16 15:28:27 +02:00
Daniel Hutzel
b8d389a40a Update genres.http 2024-07-15 18:30:12 +02:00
Daniel Hutzel
82c633ce01 Post TechEd cosmetics (#619)
* Post TechEd cosmetics

* Update package-lock.json
2024-07-15 14:45:03 +02:00
Daniel Hutzel
3161758e5f chore: reducing 3rd dependencies (#722)
* chore: reducing 3rd dependencies

* Update package.json

Co-authored-by: Bob den Os <108393871+BobdenOs@users.noreply.github.com>

* Keep using jest by default

---------

Co-authored-by: Bob den Os <108393871+BobdenOs@users.noreply.github.com>
2024-07-15 14:37:58 +02:00
Daniel Hutzel
02ea798f5f Streamlined eslint usage for eslint9 w/ cds8 (#719)
* Streamlined eslint usage

* import from @sap/cds instead of @sap/cds/lib

* Using @sap/cds/eslint.js

* eslint.config.mjs aktualisieren

* Adjusted eslint usage for eslint9 with cds8
2024-07-15 14:27:03 +02:00
Daniel Hutzel
09f02676ef Quirks mode is gone w/ cds8 (#729)
* Quirks mode is gone w/ cds8

* Update test/cds.ql.test.js

* Updated package-lock.json
2024-07-15 14:16:10 +02:00
Daniel Hutzel
cae0d36206 Fixed id generation for non-draft requests 2024-07-11 11:35:40 +02:00
31 changed files with 3313 additions and 3584 deletions

10
.vscode/settings.json vendored
View File

@@ -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"
]
} }

View File

@@ -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
}) })

View File

@@ -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' ],
) )
)) )

View File

@@ -1,2 +0,0 @@
const { CatalogService } = require('./srv/cat-service')
module.exports = { CatalogService }

View File

@@ -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",

View File

@@ -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.
} }

View File

@@ -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

View File

@@ -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)

View File

@@ -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)
### ###

View File

@@ -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": "*",

View File

@@ -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')

View File

@@ -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)

View File

@@ -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
}

View File

@@ -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

View File

@@ -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 }
}) })

View File

@@ -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
View 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/**'
// ]
// }]
//

View File

@@ -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"
}
} }
} }

View File

@@ -1,3 +1,3 @@
service say @(path: '/say') { service say {
function hello (to:String) returns String; function hello (to:String) returns String;
} }

View File

@@ -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}!`
} }
} }

View File

@@ -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!`
} }
} }

View 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)
})
})

View File

@@ -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')
###

View File

@@ -13,10 +13,5 @@
"scripts": { "scripts": {
"start": "cds-serve", "start": "cds-serve",
"watch": "cds watch" "watch": "cds watch"
},
"cds": {
"requires": {
"db": "sql"
}
} }
} }

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -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,

View File

@@ -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.' }

View File

@@ -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 })
}) })

View File

@@ -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 }],
}, },
} }

View File

@@ -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!')
}) })