Compare commits

..

4 Commits

Author SHA1 Message Date
Christian Georgi
173eda2d72 Merge branch 'main' into mocha 2022-10-05 16:16:51 +02:00
Christian Georgi
a486b1ee19 Enforce parallel and recursive 2022-08-15 15:42:05 +02:00
Christian Georgi
8eb13d1e45 Increase timeout 2022-08-15 14:56:59 +02:00
Christian Georgi
defb62d232 Execute mocha tests as well 2022-08-15 14:55:17 +02:00
30 changed files with 109 additions and 396 deletions

View File

@@ -13,7 +13,6 @@
"globals": {
"SELECT": true,
"INSERT": true,
"UPSERT": true,
"UPDATE": true,
"DELETE": true,
"CREATE": true,

View File

@@ -1,5 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: This channel is CLOSED.
about: Use SAP community instead
url: https://answers.sap.com/tags/9f13aee1-834c-4105-8e43-ee442775e5ce

View File

@@ -0,0 +1,10 @@
---
name: This channel is CLOSED.
about: Use our community at https://answers.sap.com/tags/9f13aee1-834c-4105-8e43-ee442775e5ce
title: ''
labels: ''
assignees: ''
---
Please use our community on https://answers.sap.com/tags/9f13aee1-834c-4105-8e43-ee442775e5ce

View File

@@ -26,4 +26,5 @@ jobs:
node-version: ${{ matrix.node-version }}
- run: npm i -g npm@8
- run: npm ci
- run: npm test
- run: npm run test
- run: npm run test:mocha

View File

@@ -2,5 +2,5 @@ ID;title;descr;author_ID;stock;price;currency_code;genre_ID
201;Wuthering Heights;"Wuthering Heights, Emily Brontë's only novel, was published in 1847 under the pseudonym ""Ellis Bell"". It was written between October 1845 and June 1846. Wuthering Heights and Anne Brontë's Agnes Grey were accepted by publisher Thomas Newby before the success of their sister Charlotte's novel Jane Eyre. After Emily's death, Charlotte edited the manuscript of Wuthering Heights and arranged for the edited version to be published as a posthumous second edition in 1850.";101;12;11.11;GBP;11
207;Jane Eyre;"Jane Eyre /ɛər/ (originally published as Jane Eyre: An Autobiography) is a novel by English writer Charlotte Brontë, published under the pen name ""Currer Bell"", on 16 October 1847, by Smith, Elder & Co. of London. The first American edition was published the following year by Harper & Brothers of New York. Primarily a bildungsroman, Jane Eyre follows the experiences of its eponymous heroine, including her growth to adulthood and her love for Mr. Rochester, the brooding master of Thornfield Hall. The novel revolutionised prose fiction in that the focus on Jane's moral and spiritual development is told through an intimate, first-person narrative, where actions and events are coloured by a psychological intensity. The book contains elements of social criticism, with a strong sense of Christian morality at its core and is considered by many to be ahead of its time because of Jane's individualistic character and how the novel approaches the topics of class, sexuality, religion and feminism.";107;11;12.34;GBP;11
251;The Raven;"""The Raven"" is a narrative poem by American writer Edgar Allan Poe. First published in January 1845, the poem is often noted for its musicality, stylized language, and supernatural atmosphere. It tells of a talking raven's mysterious visit to a distraught lover, tracing the man's slow fall into madness. The lover, often identified as being a student, is lamenting the loss of his love, Lenore. Sitting on a bust of Pallas, the raven seems to further distress the protagonist with its constant repetition of the word ""Nevermore"". The poem makes use of folk, mythological, religious, and classical references.";150;333;13.13;USD;16
252;Eleonora;"""Eleonora"" is a short story by Edgar Allan Poe, first published in 1842 in Philadelphia in the literary annual The Gift. It is often regarded as somewhat autobiographical and has a relatively ""happy"" ending.";150;555;14;USD;15
252;Eleonora;"""Eleonora"" is a short story by Edgar Allan Poe, first published in 1842 in Philadelphia in the literary annual The Gift. It is often regarded as somewhat autobiographical and has a relatively ""happy"" ending.";150;555;14;USD;16
271;Catweazle;Catweazle is a British fantasy television series, starring Geoffrey Bayldon in the title role, and created by Richard Carpenter for London Weekend Television. The first series, produced and directed by Quentin Lawrence, was screened in the UK on ITV in 1970. The second series, directed by David Reid and David Lane, was shown in 1971. Each series had thirteen episodes, most but not all written by Carpenter, who also published two books based on the scripts.;170;22;150;JPY;13
1 ID title descr author_ID stock price currency_code genre_ID
2 201 Wuthering Heights Wuthering Heights, Emily Brontë's only novel, was published in 1847 under the pseudonym "Ellis Bell". It was written between October 1845 and June 1846. Wuthering Heights and Anne Brontë's Agnes Grey were accepted by publisher Thomas Newby before the success of their sister Charlotte's novel Jane Eyre. After Emily's death, Charlotte edited the manuscript of Wuthering Heights and arranged for the edited version to be published as a posthumous second edition in 1850. 101 12 11.11 GBP 11
3 207 Jane Eyre Jane Eyre /ɛər/ (originally published as Jane Eyre: An Autobiography) is a novel by English writer Charlotte Brontë, published under the pen name "Currer Bell", on 16 October 1847, by Smith, Elder & Co. of London. The first American edition was published the following year by Harper & Brothers of New York. Primarily a bildungsroman, Jane Eyre follows the experiences of its eponymous heroine, including her growth to adulthood and her love for Mr. Rochester, the brooding master of Thornfield Hall. The novel revolutionised prose fiction in that the focus on Jane's moral and spiritual development is told through an intimate, first-person narrative, where actions and events are coloured by a psychological intensity. The book contains elements of social criticism, with a strong sense of Christian morality at its core and is considered by many to be ahead of its time because of Jane's individualistic character and how the novel approaches the topics of class, sexuality, religion and feminism. 107 11 12.34 GBP 11
4 251 The Raven "The Raven" is a narrative poem by American writer Edgar Allan Poe. First published in January 1845, the poem is often noted for its musicality, stylized language, and supernatural atmosphere. It tells of a talking raven's mysterious visit to a distraught lover, tracing the man's slow fall into madness. The lover, often identified as being a student, is lamenting the loss of his love, Lenore. Sitting on a bust of Pallas, the raven seems to further distress the protagonist with its constant repetition of the word "Nevermore". The poem makes use of folk, mythological, religious, and classical references. 150 333 13.13 USD 16
5 252 Eleonora "Eleonora" is a short story by Edgar Allan Poe, first published in 1842 in Philadelphia in the literary annual The Gift. It is often regarded as somewhat autobiographical and has a relatively "happy" ending. 150 555 14 USD 15 16
6 271 Catweazle Catweazle is a British fantasy television series, starring Geoffrey Bayldon in the title role, and created by Richard Carpenter for London Weekend Television. The first series, produced and directed by Quentin Lawrence, was screened in the UK on ITV in 1970. The second series, directed by David Reid and David Lane, was shown in 1971. Each series had thirteen episodes, most but not all written by Carpenter, who also published two books based on the scripts. 170 22 150 JPY 13

View File

@@ -4,9 +4,15 @@
* currencies, if not obtained through @capire/common.
*/
module.exports = async ()=>{
module.exports = async (db)=>{
await UPSERT.into ('sap.common.Currencies') .columns (
const has_common = db.model.definitions['sap.common.Currencies'].elements.numcode
if (has_common) return
const already_filled = await db.exists('sap.common.Currencies',{code:'EUR'})
if (already_filled) return
await INSERT.into ('sap.common.Currencies') .columns (
'code','symbol','name'
) .rows (
[ 'EUR','€','Euro' ],

View File

@@ -26,8 +26,7 @@
"[production]": { "kind": "enterprise-messaging" }
},
"db": {
"kind": "sql",
"schema_evolution": "auto"
"kind": "sql"
}
},
"log": { "service": true }

View File

@@ -12,11 +12,7 @@ using { sap.capire.bookshop.Books } from '@capire/bookshop';
using { ReviewsService.Reviews } from '@capire/reviews';
extend Books with {
reviews : Composition of many Reviews on reviews.subject = $self.ID;
@Common.Label : '{i18n>Rating}'
rating : Decimal;
@Common.Label : '{i18n>NumberOfReviews}'
numberOfReviews : Integer;
}

View File

@@ -6,33 +6,16 @@ Author = Author
AuthorID = Author ID
Stock = Stock
Name = Name
Description = Description
Image = Image
AuthorName = Author's Name
DateOfBirth = Date of Birth
DateOfDeath = Date of Death
PlaceOfBirth = Place of Birth
PlaceOfDeath = Place of Death
Age = Age
Lifetime = Lifetime
Authors = Authors
Order = Order
Orders = Orders
OrderNo = Order Number
OrderItems = Order Items
Customer = Customer
Product = Product
ProductID = Product ID
ProductTitle = Product Title
UnitPrice = Unit Price
Quantity = Quantity
Price = Price
Currency = Currency
Date = Date
Rating = Rating
NumberOfReviews = Number of Reviews
Genre = Genre
Genres = Genres

View File

@@ -43,10 +43,5 @@ extend sap.capire.bookshop.Authors with {
virtual lifetime : String;
}
annotate AdminService.Authors with {
age @Common.Label : '{i18n>Age}';
lifetime @Common.Label : '{i18n>Lifetime}'
}
// Workaround for Fiori popup for asking user to enter a new UUID on Create
annotate AdminService.Authors with { ID @Core.Computed; }

View File

@@ -62,11 +62,6 @@ annotate AdminService.Books.texts with @(
}
);
annotate AdminService.Books.texts with {
ID @UI.Hidden;
ID_texts @UI.Hidden;
};
// Add Value Help for Locales
annotate AdminService.Books.texts {
locale @(

View File

@@ -52,6 +52,9 @@ annotate CatalogService.Books with @(UI : {
},
{Value : genre.name},
{Value : price},
{Value : currency.symbol},
{
Value : currency.symbol,
Label : ' '
},
]
}, );

View File

@@ -4,7 +4,6 @@
using { sap.capire.bookshop as my } from '@capire/bookstore';
using { sap.common } from '@capire/common';
using { sap.common.Currencies } from '@sap/cds/common';
////////////////////////////////////////////////////////////////////////////
//
@@ -26,7 +25,7 @@ annotate my.Books with @(
{ Value: genre.name },
{ Value: stock },
{ Value: price },
{ Value: currency.symbol },
{ Value: currency.symbol, Label: ' ' },
]
}
) {
@@ -38,10 +37,6 @@ annotate my.Books with @(
author @ValueList.entity : 'Authors';
};
annotate Currencies with {
symbol @Common.Label : '{i18n>Currency}';
}
////////////////////////////////////////////////////////////////////////////
//
// Books Details
@@ -65,8 +60,7 @@ annotate my.Books with {
author @title: '{i18n>Author}' @Common: { Text: author.name, TextArrangement: #TextOnly };
price @title: '{i18n>Price}' @Measures.ISOCurrency : currency_code;
stock @title: '{i18n>Stock}';
descr @title: '{i18n>Description}' @UI.MultiLineText;
image @title: '{i18n>Image}';
descr @UI.MultiLineText;
}
////////////////////////////////////////////////////////////////////////////
@@ -87,10 +81,6 @@ annotate my.Genres with @(
}
);
annotate my.Genres with {
ID @Common.Text : name @Common.TextArrangement : #TextOnly;
}
////////////////////////////////////////////////////////////////////////////
//
// Genre Details

View File

@@ -34,8 +34,7 @@
}
},
"db": {
"kind": "sql",
"schema_evolution": "auto"
"kind": "sql"
},
"db-ext": {
"[development]": {

View File

@@ -1,7 +1,3 @@
module.exports = class say {
hello(req) {
let {to} = req.data
if (to === 'me') to = require('os').userInfo().username
return `Hello ${to}!`
}
hello(req) { return `Hello ${req.data.to}!` }
}

View File

@@ -1,76 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title> cds.log </title>
<link rel="stylesheet" href="https://unpkg.com/primitive-ui/dist/css/main.css">
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
<style>
select { border-color: transparent; padding: 4px 12px; margin: 0px; }
button { padding: 2px 11px; margin: 0px 4px; font: 90% italic; }
</style>
</head>
<body class="small-container" , style="margin-top: 70px;">
<div id='app'>
<h1> Log Levels </h1>
<input type="text" placeholder="Search by ID or Log Level..." @input="fetch">
<table id='loggers'>
<thead>
<th> Module ID </th>
<th> Log Level </th>
</thead>
<tr v-for="each in list">
<td>{{ each.id }}</td>
<td><select v-bind:id="each.id" v-model="each.level" @change="set">
<option>SILENT</option>
<option>ERROR</option>
<option>WARN</option>
<option>INFO</option>
<option>DEBUG</option>
<option>TRACE</option>
</select>
</td>
</tr>
</table>
<h4>Log Format:</h4>
[ <button class="round-button" :class={'muted-button':!format.timestamp} @click="toggle_format" id="timestamp">Timestamp </button>
| <button class="round-button" :class={'muted-button':!format.level} @click="toggle_format" id="level">Log Level </button>
| <button class="round-button" :class={'muted-button':!format.tenant} @click="toggle_format" id="tenant">Tenant </button>
| <button class="round-button" :class={'muted-button':!format.reqid} @click="toggle_format" id="reqid">Request ID </button>
| <button class="round-button" :class={'muted-button':!format.id} @click="toggle_format" id="module">Logger ID </button>
] - <i>log message ...</i>
</div>
</body>
<script>
axios.defaults.headers['Content-Type'] = 'application/json'
axios.defaults.baseURL = '/log'
const loggers = Vue.createApp({ el: '#app',
data() {
return {
format: { timestamp:false, level:false, tenant:false, reqid:false, id:true, },
list: [],
}
},
methods: {
async fetch (eve) {
this.list = (await axios.get (`/Loggers${
eve && eve.target.value ? `?$search=${eve.target.value}` : ''
}`)).data
},
async set (eve) {
const { id, value:level } = eve.target
await axios.put (`/Logger/${id}`, {id,level})
},
async toggle_format (eve) {
this.format[eve.target.id] = !this.format[eve.target.id]
await axios.post (`/format`, this.format)
},
},
}).mount('#app')
loggers.fetch() // initially fill list of loggers
</script>
</html>

View File

@@ -1,22 +0,0 @@
{
"name": "@capire/loggers",
"version": "1.0.0",
"description": "Simple sample on how to dynamically set cds.log levels and formats.",
"files": [
"app",
"srv"
],
"dependencies": {
"@sap/cds": ">=5.9",
"express": "^4.17.1"
},
"scripts": {
"start": "cds run",
"watch": "cds watch"
},
"cds": {
"requires": {
"db": "sql"
}
}
}

View File

@@ -1,11 +0,0 @@
# Dynamically Set `cds.log` Levels and Formats
### Run
```sh
cds watch
```
### Test
Either using the UI through http://localhost:4004/loggers.html, or try the requests in `test/requests.http`

View File

@@ -1,3 +0,0 @@
service Sue {
entity Dummy { key ID: UUID; title: String; }
}

View File

@@ -1,20 +0,0 @@
@rest service LogService {
@readonly entity Loggers : Logger {};
entity Logger {
key id : String;
level : String;
}
action format (
timestamp : Boolean,
level : Boolean,
tenant : Boolean,
reqid : Boolean,
id : Boolean,
);
action debug (logger : String) returns Logger;
action reset (logger : String) returns Logger;
}

View File

@@ -1,56 +0,0 @@
const cds = require ('@sap/cds/lib')
const LOG = cds.log('cds.log')
module.exports = class LogService extends cds.Service {
init(){
this.on('GET','Loggers', (req)=>{
let loggers = Object.values(cds.log.loggers).map (_logger)
let {$search} = req._.req.query
if ($search) {
const re = RegExp($search,'i')
loggers = loggers.filter (l => re.test(l.id) || re.test(l.level))
}
return loggers.sort ((a,b) => a.id < b.id ? -1 : 1)
})
this.on('PUT','Logger', (req)=>{
const {id} = req.params[0] || req.data
if (!id) return req.reject('No logger id specified in request')
return _logger (cds.log (id, req.data))
})
this.on('debug', (req)=>{
const {logger:id} = req.params[0] || req.data
if (!id) return req.reject('No logger id specified in request')
return _logger (cds.log (id, {level:'debug'}))
})
this.on('reset', (req)=>{
const {logger:id} = req.params[0] || req.data
if (!id) return req.reject('No logger id specified in request')
return _logger (cds.log (id, {level:'info'}))
})
this.on('format', (req)=>{
const $ = req.data; LOG.info('format:',$)
// Set format for new loggers constructed subsequently
cds.log.format = (id, level, ...args) => {
const fmt = []
if ($.timestamp) fmt.push ('|', (new Date).toISOString())
if ($.level) fmt.push ('|', _levels[level].padEnd(5))
if ($.tenant) fmt.push ('|', cds.context && cds.context.tenant)
if ($.reqid) fmt.push ('|', cds.context && cds.context.id)
if ($.id) fmt.push ('|', id)
fmt[0] = '[', fmt.push ('] -', ...args)
return fmt
}
// Apply this format to all existing loggers
Object.values(cds.log.loggers).forEach (l => l.setFormat (cds.log.format))
})
}
}
const _logger = ({id,level}) => ({id, level:_levels[level] })
const _levels = [ 'SILENT', 'ERROR', 'WARN', 'INFO', 'DEBUG', 'TRACE' ]

View File

@@ -1,18 +0,0 @@
http://localhost:4004/loggers.html
@body: = Content-Type: application/json\n\n
###
GET http://localhost:4004/log/Loggers
###
PUT http://localhost:4004/log/Logger/sqlite
{{body:}} { "level": "debug" }
###
POST http://localhost:4004/log/debug(logger='sqlite')
###
POST http://localhost:4004/log/reset(logger='sqlite')
### Dummy request to see sqlite debug output
GET http://localhost:4004/sue/Dummy

View File

@@ -40,7 +40,7 @@ module.exports = srv => {
req.reject(404, 'Media not found for the ID')
return
}
const decodedMedia = Buffer.from(
const decodedMedia = new Buffer(
mediaObj.media.split(';base64,').pop(),
'base64'
)

View File

@@ -18,22 +18,22 @@ annotate OrdersService.Orders with @(
UI: {
SelectionFields: [ createdBy ],
LineItem: [
{Value: OrderNo, Label:'{i18n>OrderNo}'},
{Value: buyer, Label:'{i18n>Customer}'},
{Value: currency.symbol, Label:'{i18n>Currency}'},
{Value: createdAt, Label:'{i18n>Date}'},
{Value: OrderNo, Label:'OrderNo'},
{Value: buyer, Label:'Customer'},
{Value: currency.symbol, Label:'Currency'},
{Value: createdAt, Label:'Date'},
],
HeaderInfo: {
TypeName: '{i18n>Order}', TypeNamePlural: '{i18n>Orders}',
TypeName: 'Order', TypeNamePlural: 'Orders',
Title: {
Label: '{i18n>OrderNo}', //A label is possible but it is not considered on the ObjectPage yet
Label: 'Order number ', //A label is possible but it is not considered on the ObjectPage yet
Value: OrderNo
},
Description: {Value: createdBy}
},
Identification: [ //Is the main field group
{Value: createdBy, Label:'{i18n>Customer}'},
{Value: createdAt, Label:'{i18n>Date}'},
{Value: createdBy, Label:'Customer'},
{Value: createdAt, Label:'Date'},
{Value: OrderNo },
],
HeaderFacets: [
@@ -46,7 +46,7 @@ annotate OrdersService.Orders with @(
],
FieldGroup#Details: {
Data: [
{Value: currency.code, Label:'{i18n>Currency}'}
{Value: currency.code, Label:'Currency'}
]
},
FieldGroup#Created: {
@@ -65,7 +65,6 @@ annotate OrdersService.Orders with @(
) {
createdAt @UI.HiddenFilter:false;
createdBy @UI.HiddenFilter:false;
ID @UI.Hidden;
};
@@ -73,15 +72,15 @@ annotate OrdersService.Orders with @(
annotate OrdersService.Orders.Items with @(
UI: {
LineItem: [
{Value: product_ID, Label:'{i18n>ProductID}'},
{Value: title, Label:'{i18n>ProductTitle}'},
{Value: price, Label:'{i18n>UnitPrice}'},
{Value: quantity, Label:'{i18n>Quantity}'},
{Value: product_ID, Label:'Product ID'},
{Value: title, Label:'Product Title'},
{Value: price, Label:'Unit Price'},
{Value: quantity, Label:'Quantity'},
],
Identification: [ //Is the main field group
{Value: quantity, Label:'{i18n>Quantity}'},
{Value: title, Label:'{i18n>Product}'},
{Value: price, Label:'{i18n>UnitPrice}'},
{Value: quantity, Label:'Quantity'},
{Value: title, Label:'Product'},
{Value: price, Label:'Unit Price'},
],
Facets: [
{$Type: 'UI.ReferenceFacet', Label: '{i18n>OrderItems}', Target: '@UI.Identification'},
@@ -91,7 +90,4 @@ annotate OrdersService.Orders.Items with @(
quantity @(
Common.FieldControl: #Mandatory
);
ID @UI.Hidden;
up_ @UI.Hidden;
};

128
package-lock.json generated
View File

@@ -17,14 +17,13 @@
"./hello",
"./media",
"./orders",
"./loggers",
"./reviews"
],
"dependencies": {
"@sap/cds": ">=5.5.3"
},
"devDependencies": {
"axios": "^1",
"axios": "^0",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"chai-subset": "^1.6.0",
@@ -91,14 +90,6 @@
"typescript": "^4.3.5"
}
},
"loggers": {
"name": "@capire/loggers",
"version": "1.0.0",
"dependencies": {
"@sap/cds": ">=5.9",
"express": "^4.17.1"
}
},
"media": {
"name": "@capire/media",
"version": "1.0.0",
@@ -236,10 +227,6 @@
"resolved": "hello",
"link": true
},
"node_modules/@capire/loggers": {
"resolved": "loggers",
"link": true
},
"node_modules/@capire/media": {
"resolved": "media",
"link": true
@@ -346,24 +333,24 @@
}
},
"node_modules/@sap/cds": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/@sap/cds/-/cds-6.4.0.tgz",
"integrity": "sha512-Z19veNd0lf+W3Q97Xzxi7cJ50NsYx42wiiRs+44Xp7DArQuose4XkrN3iZ7DdX+FxcJSYojPnuDdN22QnZPZbA==",
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/@sap/cds/-/cds-6.1.3.tgz",
"integrity": "sha512-yvL9lPonVwUx9Md1eylAtpY0JrlSMyoxZXnCA2q9lNoVNudmjPMynO5CJBfAYEaThZSqd2yMJg/+xyKy/mn3wg==",
"dependencies": {
"@sap/cds-compiler": "^3.2.0",
"@sap/cds-compiler": "^3.0.0",
"@sap/cds-foss": "^4"
},
"bin": {
"cds": "bin/cds.js"
},
"engines": {
"node": ">=14.18.0"
"node": ">=14.15.0"
}
},
"node_modules/@sap/cds-compiler": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/@sap/cds-compiler/-/cds-compiler-3.3.2.tgz",
"integrity": "sha512-jOUEjSMBOVZXmWgx3/mu8H9BbvgP+HVyyKXbHHZWJlk0NMlk+FI/q4KagUaGWJFyRVBskdzF4zBD/QLlrhRnHA==",
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@sap/cds-compiler/-/cds-compiler-3.1.2.tgz",
"integrity": "sha512-csH3aEs4aPCzAtc75Jx/Ayym2A06JgAeaDUFLXI867/Vsp2F0g7MJxuCkNhpa+zVZsXcyB0Kxzzv4xU7zuJXsQ==",
"dependencies": {
"antlr4": "4.9.3"
},
@@ -623,14 +610,13 @@
"dev": true
},
"node_modules/axios": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz",
"integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==",
"version": "0.27.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
"dev": true,
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
"follow-redirects": "^1.14.9",
"form-data": "^4.0.0"
}
},
"node_modules/balanced-match": {
@@ -800,14 +786,14 @@
}
},
"node_modules/chai": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz",
"integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==",
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
"integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
"dev": true,
"dependencies": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.2",
"deep-eql": "^4.1.2",
"deep-eql": "^3.0.1",
"get-func-name": "^2.0.0",
"loupe": "^2.3.1",
"pathval": "^1.1.1",
@@ -989,15 +975,15 @@
}
},
"node_modules/deep-eql": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.2.tgz",
"integrity": "sha512-gT18+YW4CcW/DBNTwAmqTtkJh7f9qqScu2qFVlx7kCoeY9tlBu9cUcr7+I+Z/noG8INehS3xQgLpTtd/QUTn4w==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
"integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
"dev": true,
"dependencies": {
"type-detect": "^4.0.0"
},
"engines": {
"node": ">=6"
"node": ">=0.12"
}
},
"node_modules/delayed-stream": {
@@ -2340,12 +2326,6 @@
"node": ">= 0.10"
}
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"dev": true
},
"node_modules/qs": {
"version": "6.10.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
@@ -2631,9 +2611,9 @@
}
},
"node_modules/sqlite3": {
"version": "5.1.4",
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.4.tgz",
"integrity": "sha512-i0UlWAzPlzX3B5XP2cYuhWQJsTtlMD6obOa1PgeEQ4DHEXUuyJkgv50I3isqZAP5oFc2T8OFvakmDh2W6I+YpA==",
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.2.tgz",
"integrity": "sha512-D0Reg6pRWAFXFUnZKsszCI67tthFD8fGPewRddDCX6w4cYwz3MbvuwRICbL+YQjBAh9zbw+lJ/V9oC8nG5j6eg==",
"dev": true,
"hasInstallScript": true,
"dependencies": {
@@ -3114,13 +3094,6 @@
"typescript": "^4.3.5"
}
},
"@capire/loggers": {
"version": "file:loggers",
"requires": {
"@sap/cds": ">=5.9",
"express": "^4.17.1"
}
},
"@capire/media": {
"version": "file:media",
"requires": {
@@ -3220,18 +3193,18 @@
}
},
"@sap/cds": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/@sap/cds/-/cds-6.4.0.tgz",
"integrity": "sha512-Z19veNd0lf+W3Q97Xzxi7cJ50NsYx42wiiRs+44Xp7DArQuose4XkrN3iZ7DdX+FxcJSYojPnuDdN22QnZPZbA==",
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/@sap/cds/-/cds-6.1.3.tgz",
"integrity": "sha512-yvL9lPonVwUx9Md1eylAtpY0JrlSMyoxZXnCA2q9lNoVNudmjPMynO5CJBfAYEaThZSqd2yMJg/+xyKy/mn3wg==",
"requires": {
"@sap/cds-compiler": "^3.2.0",
"@sap/cds-compiler": "^3.0.0",
"@sap/cds-foss": "^4"
}
},
"@sap/cds-compiler": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/@sap/cds-compiler/-/cds-compiler-3.3.2.tgz",
"integrity": "sha512-jOUEjSMBOVZXmWgx3/mu8H9BbvgP+HVyyKXbHHZWJlk0NMlk+FI/q4KagUaGWJFyRVBskdzF4zBD/QLlrhRnHA==",
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@sap/cds-compiler/-/cds-compiler-3.1.2.tgz",
"integrity": "sha512-csH3aEs4aPCzAtc75Jx/Ayym2A06JgAeaDUFLXI867/Vsp2F0g7MJxuCkNhpa+zVZsXcyB0Kxzzv4xU7zuJXsQ==",
"requires": {
"antlr4": "4.9.3"
}
@@ -3444,14 +3417,13 @@
"dev": true
},
"axios": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz",
"integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==",
"version": "0.27.2",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz",
"integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==",
"dev": true,
"requires": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
"follow-redirects": "^1.14.9",
"form-data": "^4.0.0"
}
},
"balanced-match": {
@@ -3588,14 +3560,14 @@
}
},
"chai": {
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz",
"integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==",
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.3.6.tgz",
"integrity": "sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q==",
"dev": true,
"requires": {
"assertion-error": "^1.1.0",
"check-error": "^1.0.2",
"deep-eql": "^4.1.2",
"deep-eql": "^3.0.1",
"get-func-name": "^2.0.0",
"loupe": "^2.3.1",
"pathval": "^1.1.1",
@@ -3727,9 +3699,9 @@
}
},
"deep-eql": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.2.tgz",
"integrity": "sha512-gT18+YW4CcW/DBNTwAmqTtkJh7f9qqScu2qFVlx7kCoeY9tlBu9cUcr7+I+Z/noG8INehS3xQgLpTtd/QUTn4w==",
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
"integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
"dev": true,
"requires": {
"type-detect": "^4.0.0"
@@ -4756,12 +4728,6 @@
"ipaddr.js": "1.9.1"
}
},
"proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"dev": true
},
"qs": {
"version": "6.10.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.10.3.tgz",
@@ -4980,9 +4946,9 @@
}
},
"sqlite3": {
"version": "5.1.4",
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.4.tgz",
"integrity": "sha512-i0UlWAzPlzX3B5XP2cYuhWQJsTtlMD6obOa1PgeEQ4DHEXUuyJkgv50I3isqZAP5oFc2T8OFvakmDh2W6I+YpA==",
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.2.tgz",
"integrity": "sha512-D0Reg6pRWAFXFUnZKsszCI67tthFD8fGPewRddDCX6w4cYwz3MbvuwRICbL+YQjBAh9zbw+lJ/V9oC8nG5j6eg==",
"dev": true,
"requires": {
"@mapbox/node-pre-gyp": "^1.0.0",

View File

@@ -16,11 +16,10 @@
"./hello",
"./media",
"./orders",
"./loggers",
"./reviews"
],
"devDependencies": {
"axios": "^1",
"axios": "^0",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"chai-subset": "^1.6.0",
@@ -38,6 +37,7 @@
"jest": "npx jest",
"start": "cds watch fiori",
"test": "npm run jest -- --silent",
"test:mocha": "npx mocha --parallel --recursive --timeout 20000",
"test:hello": "cd hello && npm test"
},
"jest": {

View File

@@ -1,5 +1,5 @@
ID;subject;rating;reviewer;title;text
1223a37c-9dca-4c4c-a629-9dd93b947864;201;5;bob;Intriguing;Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
ae275d4f-1fb5-491b-ba6e-79b339e1edef;201;4;bob;Fascinating;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Id diam maecenas ultricies mi eget mauris pharetra et. Risus at ultrices mi tempus imperdiet nulla malesuada pellentesque. Pulvinar mattis nunc sed blandit libero. Facilisis magna etiam tempor orci eu. Nec sagittis aliquam malesuada bibendum arcu. Eu consequat ac felis donec. Ultricies tristique nulla aliquet enim tortor at auctor urna nunc. Tortor posuere ac ut consequat semper viverra nam libero. Amet nisl suscipit adipiscing bibendum est ultricies integer quis auctor. Scelerisque purus semper eget duis at tellus. Elementum tempus egestas sed sed risus pretium. Arcu dictum varius duis at. Amet luctus venenatis lectus magna fringilla urna. Eget velit aliquet sagittis id consectetur purus ut faucibus. Vitae auctor eu augue ut lectus. Fermentum iaculis eu non diam phasellus vestibulum.
3fffe4b7-d34f-4fd3-9aab-f609f41539cc;207;2;bob;What is this?;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Libero justo laoreet sit amet cursus sit amet dictum. Nunc faucibus a pellentesque sit. Dis parturient montes nascetur ridiculus mus mauris vitae ultricies. Enim nunc faucibus a pellentesque. Commodo quis imperdiet massa tincidunt nunc pulvinar sapien. Cras ornare arcu dui vivamus. Facilisi etiam dignissim diam quis enim lobortis. Et molestie ac feugiat sed. Urna neque viverra justo nec ultrices dui. Ullamcorper a lacus vestibulum sed arcu non. Volutpat ac tincidunt vitae semper quis. Dignissim sodales ut eu sem. Feugiat in fermentum posuere urna nec. At augue eget arcu dictum varius.
71c037b3-767d-4f5d-9e90-90b894a2043a;251;3;bob;It's dark...;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Suscipit tellus mauris a diam. Velit aliquet sagittis id consectetur purus ut. Viverra adipiscing at in tellus integer. Vitae elementum curabitur vitae nunc. Mattis ullamcorper velit sed ullamcorper morbi. Diam quis enim lobortis scelerisque. Auctor neque vitae tempus quam pellentesque nec nam aliquam. Semper auctor neque vitae tempus. Quis eleifend quam adipiscing vitae proin. Neque convallis a cras semper auctor neque vitae. Imperdiet massa tincidunt nunc pulvinar sapien et ligula. Sit amet consectetur adipiscing elit ut aliquam purus. Pretium quam vulputate dignissim suspendisse.
subject;rating;reviewer;title;text
201;5;bob;Intriguing;Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
201;4;bob;Fascinating;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Id diam maecenas ultricies mi eget mauris pharetra et. Risus at ultrices mi tempus imperdiet nulla malesuada pellentesque. Pulvinar mattis nunc sed blandit libero. Facilisis magna etiam tempor orci eu. Nec sagittis aliquam malesuada bibendum arcu. Eu consequat ac felis donec. Ultricies tristique nulla aliquet enim tortor at auctor urna nunc. Tortor posuere ac ut consequat semper viverra nam libero. Amet nisl suscipit adipiscing bibendum est ultricies integer quis auctor. Scelerisque purus semper eget duis at tellus. Elementum tempus egestas sed sed risus pretium. Arcu dictum varius duis at. Amet luctus venenatis lectus magna fringilla urna. Eget velit aliquet sagittis id consectetur purus ut faucibus. Vitae auctor eu augue ut lectus. Fermentum iaculis eu non diam phasellus vestibulum.
207;2;bob;What is this?;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Libero justo laoreet sit amet cursus sit amet dictum. Nunc faucibus a pellentesque sit. Dis parturient montes nascetur ridiculus mus mauris vitae ultricies. Enim nunc faucibus a pellentesque. Commodo quis imperdiet massa tincidunt nunc pulvinar sapien. Cras ornare arcu dui vivamus. Facilisi etiam dignissim diam quis enim lobortis. Et molestie ac feugiat sed. Urna neque viverra justo nec ultrices dui. Ullamcorper a lacus vestibulum sed arcu non. Volutpat ac tincidunt vitae semper quis. Dignissim sodales ut eu sem. Feugiat in fermentum posuere urna nec. At augue eget arcu dictum varius.
251;3;bob;It's dark...;Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Suscipit tellus mauris a diam. Velit aliquet sagittis id consectetur purus ut. Viverra adipiscing at in tellus integer. Vitae elementum curabitur vitae nunc. Mattis ullamcorper velit sed ullamcorper morbi. Diam quis enim lobortis scelerisque. Auctor neque vitae tempus quam pellentesque nec nam aliquam. Semper auctor neque vitae tempus. Quis eleifend quam adipiscing vitae proin. Neque convallis a cras semper auctor neque vitae. Imperdiet massa tincidunt nunc pulvinar sapien et ligula. Sit amet consectetur adipiscing elit ut aliquam purus. Pretium quam vulputate dignissim suspendisse.
1 ID subject rating reviewer title text
2 1223a37c-9dca-4c4c-a629-9dd93b947864 201 5 bob Intriguing Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.
3 ae275d4f-1fb5-491b-ba6e-79b339e1edef 201 4 bob Fascinating Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Id diam maecenas ultricies mi eget mauris pharetra et. Risus at ultrices mi tempus imperdiet nulla malesuada pellentesque. Pulvinar mattis nunc sed blandit libero. Facilisis magna etiam tempor orci eu. Nec sagittis aliquam malesuada bibendum arcu. Eu consequat ac felis donec. Ultricies tristique nulla aliquet enim tortor at auctor urna nunc. Tortor posuere ac ut consequat semper viverra nam libero. Amet nisl suscipit adipiscing bibendum est ultricies integer quis auctor. Scelerisque purus semper eget duis at tellus. Elementum tempus egestas sed sed risus pretium. Arcu dictum varius duis at. Amet luctus venenatis lectus magna fringilla urna. Eget velit aliquet sagittis id consectetur purus ut faucibus. Vitae auctor eu augue ut lectus. Fermentum iaculis eu non diam phasellus vestibulum.
4 3fffe4b7-d34f-4fd3-9aab-f609f41539cc 207 2 bob What is this? Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Libero justo laoreet sit amet cursus sit amet dictum. Nunc faucibus a pellentesque sit. Dis parturient montes nascetur ridiculus mus mauris vitae ultricies. Enim nunc faucibus a pellentesque. Commodo quis imperdiet massa tincidunt nunc pulvinar sapien. Cras ornare arcu dui vivamus. Facilisi etiam dignissim diam quis enim lobortis. Et molestie ac feugiat sed. Urna neque viverra justo nec ultrices dui. Ullamcorper a lacus vestibulum sed arcu non. Volutpat ac tincidunt vitae semper quis. Dignissim sodales ut eu sem. Feugiat in fermentum posuere urna nec. At augue eget arcu dictum varius.
5 71c037b3-767d-4f5d-9e90-90b894a2043a 251 3 bob It's dark... Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Suscipit tellus mauris a diam. Velit aliquet sagittis id consectetur purus ut. Viverra adipiscing at in tellus integer. Vitae elementum curabitur vitae nunc. Mattis ullamcorper velit sed ullamcorper morbi. Diam quis enim lobortis scelerisque. Auctor neque vitae tempus quam pellentesque nec nam aliquam. Semper auctor neque vitae tempus. Quis eleifend quam adipiscing vitae proin. Neque convallis a cras semper auctor neque vitae. Imperdiet massa tincidunt nunc pulvinar sapien et ligula. Sit amet consectetur adipiscing elit ut aliquam purus. Pretium quam vulputate dignissim suspendisse.

View File

@@ -1,10 +0,0 @@
{
"cds": {
"requires": {
"db": {
"kind": "sql",
"schema_evolution": "auto"
}
}
}
}

View File

@@ -17,10 +17,10 @@ describe('cap/samples - Bookshop APIs', () => {
"ID": 16,
"parent_ID": 10
}
const Romance = {
"name": "Romance",
const Fantasy = {
"name": "Fantasy",
"descr": null,
"ID": 15,
"ID": 13,
"parent_ID": 10
}
@@ -62,7 +62,7 @@ describe('cap/samples - Bookshop APIs', () => {
}}`
expect(data.value).to.eql([
{ ID: 251, title: 'The Raven', author: 'Edgar Allen Poe', genre:Mystery, currency:USD },
{ ID: 252, title: 'Eleonora', author: 'Edgar Allen Poe', genre:Romance, currency:USD },
{ ID: 252, title: 'Eleonora', author: 'Edgar Allen Poe', genre:Mystery, currency:USD },
])
})
@@ -128,11 +128,11 @@ describe('cap/samples - Bookshop APIs', () => {
it('serves user info', async () => {
{
const { data } = await GET (`/user/me`)
expect(data).to.containSubset({ id: 'alice', locale:'en' })
expect(data).to.containSubset({ id: 'alice', locale:'en', tenant: null })
}
{
const { data } = await GET (`/user/me`, {auth: { username: 'joe' }})
expect(data).to.containSubset({ id: 'joe', locale:'en' })
expect(data).to.containSubset({ id: 'joe', locale:'en', tenant: null })
}
})

View File

@@ -17,10 +17,10 @@ describe('cap/samples - Local NPM registry', () => {
const env = Object.assign(process.env, {PORT:'0'})
const res = await exec (resolve(cwd, '.registry/server.js'), {cwd, stdio: 'pipe', env})
registry = res.cp
axios = require('axios').create ({ baseURL: res.url, validateStatus: (status)=>status<500 })
axios = require('axios').default.create ({ baseURL: res.url, validateStatus: (status)=>status<500 })
})
after(done => { registry.once('exit',done); registry.kill() })
after(() => { registry.kill() })
for (const mod of ['bookshop', 'data-viewer', 'fiori','orders','reviews']) {
it(`should serve ${mod}`, async () => {