Compare commits

...

51 Commits

Author SHA1 Message Date
Daniel
df1224860a . 2023-03-02 17:16:06 +01:00
Daniel
f8db8c87eb mtx usage sample 2023-03-01 22:32:35 +01:00
dependabot[bot]
50b13f60ce Bump @sap/cds from 6.5.0 to 6.6.0
Bumps [@sap/cds](https://cap.cloud.sap/) from 6.5.0 to 6.6.0.

---
updated-dependencies:
- dependency-name: "@sap/cds"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-01 16:05:58 +01:00
dependabot[bot]
f889c27338 Bump @sap/eslint-plugin-cds from 2.6.1 to 2.6.3
Bumps [@sap/eslint-plugin-cds](https://cap.cloud.sap/) from 2.6.1 to 2.6.3.

---
updated-dependencies:
- dependency-name: "@sap/eslint-plugin-cds"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-28 11:56:46 +01:00
dependabot[bot]
624c6c5c72 Bump axios from 1.3.3 to 1.3.4
Bumps [axios](https://github.com/axios/axios) from 1.3.3 to 1.3.4.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.3.3...v1.3.4)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-28 11:52:58 +01:00
Mara Kiefer
12fd91ca4f Use eslint probe, not validate in VS Code settings
- Parsing error as see in issue https://github.tools.sap/cap/issues/issues/13123
- Related to [VS Code ESLint settings options](https://github.com/microsoft/vscode-eslint/blob/main/README.md#settings-options)
- Should use `eslint.probe` instead of `eslint.validate`

eslint.probe - an array for language identifiers for which the ESLint extension should be activated and should try to validate the file. If validation fails for probed languages the extension says silent. Defaults to ["javascript", "javascriptreact", "typescript", "typescriptreact", "html", "vue", "markdown"].

eslint.validate - an array of language identifiers specifying the files for which validation is to be enforced. This is an old legacy setting and should in normal cases not be necessary anymore. Defaults to ["javascript", "javascriptreact"].
2023-02-28 11:49:01 +01:00
Daniel
535981dc7e Fixing cds lint issues 2023-02-22 13:39:05 +01:00
Daniel
d15d0535d9 Updated package-lock.json -> fixed vulnerability 2023-02-17 17:39:23 +01:00
dependabot[bot]
430d3a46c4 Bump axios from 1.3.1 to 1.3.2
Bumps [axios](https://github.com/axios/axios) from 1.3.1 to 1.3.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.3.1...v1.3.2)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-06 17:55:15 +01:00
dependabot[bot]
308e6b932a Bump http-cache-semantics from 4.1.0 to 4.1.1
Bumps [http-cache-semantics](https://github.com/kornelski/http-cache-semantics) from 4.1.0 to 4.1.1.
- [Release notes](https://github.com/kornelski/http-cache-semantics/releases)
- [Commits](https://github.com/kornelski/http-cache-semantics/commits)

---
updated-dependencies:
- dependency-name: http-cache-semantics
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-02 13:38:42 +01:00
dependabot[bot]
703d45fab0 Bump axios from 1.3.0 to 1.3.1
Bumps [axios](https://github.com/axios/axios) from 1.3.0 to 1.3.1.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.3.0...v1.3.1)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-02 13:29:01 +01:00
dependabot[bot]
63c21c5a96 Bump axios from 1.2.6 to 1.3.0
Bumps [axios](https://github.com/axios/axios) from 1.2.6 to 1.3.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.2.6...v1.3.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-01 13:22:51 +01:00
dependabot[bot]
e0c6b16b15 Bump axios from 1.2.4 to 1.2.6
Bumps [axios](https://github.com/axios/axios) from 1.2.4 to 1.2.6.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.2.4...v1.2.6)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-30 17:16:47 +01:00
dependabot[bot]
0771fc06e6 Bump @sap/cds from 6.4.0 to 6.5.0
Bumps [@sap/cds](https://cap.cloud.sap/) from 6.4.0 to 6.5.0.

---
updated-dependencies:
- dependency-name: "@sap/cds"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-30 17:14:23 +01:00
dependabot[bot]
dc90cad8f4 Bump axios from 1.2.3 to 1.2.4
Bumps [axios](https://github.com/axios/axios) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.2.3...v1.2.4)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-25 13:34:30 +01:00
Christian Georgi
f731a95bd1 Fix indentation 2023-01-18 14:57:15 +01:00
dependabot[bot]
2cd092be10 Bump axios from 1.2.2 to 1.2.3
Bumps [axios](https://github.com/axios/axios) from 1.2.2 to 1.2.3.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/1.2.2...v1.2.3)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-18 13:19:55 +01:00
Daniel Hutzel
a1c2f32408 Cleanup (#440)
* Cleanup

* minor cleanups
2023-01-13 09:08:20 +01:00
dependabot[bot]
8a6a42f109 Bump axios from 1.2.1 to 1.2.2
Bumps [axios](https://github.com/axios/axios) from 1.2.1 to 1.2.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.2.1...1.2.2)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-09 11:11:29 +01:00
Daniel
28cfceeaf0 Avoid dangling IO resources 2022-12-20 13:30:17 +01:00
dependabot[bot]
879546829a Bump @sap/cds from 6.3.2 to 6.4.0
Bumps [@sap/cds](https://cap.cloud.sap/) from 6.3.2 to 6.4.0.

---
updated-dependencies:
- dependency-name: "@sap/cds"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-16 13:10:09 +01:00
dependabot[bot]
b7e435d611 Bump sqlite3 from 5.1.3 to 5.1.4
Bumps [sqlite3](https://github.com/TryGhost/node-sqlite3) from 5.1.3 to 5.1.4.
- [Release notes](https://github.com/TryGhost/node-sqlite3/releases)
- [Commits](https://github.com/TryGhost/node-sqlite3/compare/v5.1.3...v5.1.4)

---
updated-dependencies:
- dependency-name: sqlite3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-13 17:06:51 +01:00
dependabot[bot]
4f5f075697 Bump sqlite3 from 5.1.2 to 5.1.3
Bumps [sqlite3](https://github.com/TryGhost/node-sqlite3) from 5.1.2 to 5.1.3.
- [Release notes](https://github.com/TryGhost/node-sqlite3/releases)
- [Commits](https://github.com/TryGhost/node-sqlite3/compare/v5.1.2...v5.1.3)

---
updated-dependencies:
- dependency-name: sqlite3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-12 14:33:59 +01:00
dependabot[bot]
710c83aa1c Bump axios from 1.2.0 to 1.2.1
Bumps [axios](https://github.com/axios/axios) from 1.2.0 to 1.2.1.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.2.0...v1.2.1)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-06 13:39:02 +01:00
dependabot[bot]
e9fbba9f46 Bump axios from 1.1.3 to 1.2.0
Bumps [axios](https://github.com/axios/axios) from 1.1.3 to 1.2.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.1.3...v1.2.0)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-05 13:41:22 +01:00
dependabot[bot]
0d96447d4b Bump @sap/cds from 6.3.1 to 6.3.2
Bumps [@sap/cds](https://cap.cloud.sap/) from 6.3.1 to 6.3.2.

---
updated-dependencies:
- dependency-name: "@sap/cds"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-05 13:39:50 +01:00
Daniel
ed1510d173 sorting loggers 2022-11-30 17:37:51 +01:00
Daniel
d07b20a689 Added loggers sample 2022-11-28 17:54:32 +01:00
dependabot[bot]
e6584c4c15 Bump chai from 4.3.6 to 4.3.7
Bumps [chai](https://github.com/chaijs/chai) from 4.3.6 to 4.3.7.
- [Release notes](https://github.com/chaijs/chai/releases)
- [Changelog](https://github.com/chaijs/chai/blob/4.x.x/History.md)
- [Commits](https://github.com/chaijs/chai/compare/v4.3.6...v4.3.7)

---
updated-dependencies:
- dependency-name: chai
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-09 16:17:30 +01:00
dependabot[bot]
2a6fca177b Bump axios from 1.1.2 to 1.1.3
Bumps [axios](https://github.com/axios/axios) from 1.1.2 to 1.1.3.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v1.1.2...v1.1.3)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-08 14:43:24 +01:00
Pierre Fritsch
d9058f9b51 Manage Orders: Switch to translatable texts (#424)
Co-authored-by: Christian Georgi <chgeo@users.noreply.github.com>
2022-11-08 14:38:41 +01:00
Pierre Fritsch
affd1718ef Fiori app *Manage Orders*: Hide technical UUID's (#423)
* Hide Order ID
* Hide Order Item ID

Co-authored-by: Christian Georgi <chgeo@users.noreply.github.com>
2022-11-08 13:33:25 +00:00
Pierre Fritsch
5ff72c3f02 Hide ID and ID_Texts for Books.texts (#422)
Co-authored-by: Christian Georgi <chgeo@users.noreply.github.com>
2022-11-08 13:30:28 +00:00
Pierre Fritsch
666001d564 Filter criteria: Display the Genre name (#421)
Co-authored-by: Christian Georgi <chgeo@users.noreply.github.com>
2022-11-08 13:28:36 +00:00
Pierre Fritsch
e4214b0e40 Fiori app *Browse Books*: Add missing column labels (#420)
* Add labels for `rating` and `numberOfReviews`
* Add label for `currency.symbol`
* Add label for `descr`
* Add label for `image`

Co-authored-by: Christian Georgi <chgeo@users.noreply.github.com>
2022-11-08 13:26:48 +00:00
Pierre Fritsch
ad76c699c9 Add column labels for age and lifetime (#419)
Co-authored-by: Christian Georgi <chgeo@users.noreply.github.com>
2022-11-08 13:23:44 +00:00
dependabot[bot]
0ad8baefc7 Bump @sap/cds from 6.2.2 to 6.3.1
Bumps [@sap/cds](https://cap.cloud.sap/) from 6.2.2 to 6.3.1.

---
updated-dependencies:
- dependency-name: "@sap/cds"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-11-08 14:21:28 +01:00
Daniel
3f7b43346f Buffer() is deprecated 2022-11-06 18:03:38 +01:00
Christian Georgi
6981841d86 Delete question--feedback-or-bug-.md 2022-10-24 09:54:48 +02:00
Christian Georgi
18c29d8b67 Create config.yml 2022-10-24 09:54:18 +02:00
Daniel
02fc1a89a1 Fixed expected tenants in odata.test.js 2022-10-19 13:00:20 +02:00
dependabot[bot]
94b74d76ad Bump @sap/cds from 6.2.1 to 6.2.2 (#413)
Bumps [@sap/cds](https://cap.cloud.sap/) from 6.2.1 to 6.2.2.

---
updated-dependencies:
- dependency-name: "@sap/cds"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-14 15:41:17 +02:00
Daniel
b0b4412c7a Fixed genre for Eleonora 2022-10-12 14:59:10 +02:00
dependabot[bot]
70cfa82a35 Bump axios from 0.27.2 to 1.1.2 (#410)
Bumps [axios](https://github.com/axios/axios) from 0.27.2 to 1.1.2.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.27.2...v1.1.2)

---
updated-dependencies:
- dependency-name: axios
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-10 14:03:08 +00:00
dependabot[bot]
d17d74f1ec Bump @sap/cds from 6.1.3 to 6.2.1 (#411)
Bumps [@sap/cds](https://cap.cloud.sap/) from 6.1.3 to 6.2.1.

---
updated-dependencies:
- dependency-name: "@sap/cds"
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-10 15:52:35 +02:00
dependabot[bot]
9fbf7c69c9 Bump semver from 7.3.7 to 7.3.8 (#408)
Bumps [semver](https://github.com/npm/node-semver) from 7.3.7 to 7.3.8.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v7.3.7...v7.3.8)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-05 16:15:26 +02:00
Daniel
f54a8cecb7 Revert "Extensibility Walkthrough in capire (#405)"
This reverts commit 608e16090c.
2022-10-04 12:12:30 +02:00
Daniel Hutzel
608e16090c Extensibility Walkthrough in capire (#405)
* Extension project template

* SalesRegion ->  x_SalesRegion

* enhanced order repo

* updated package-lock.json
2022-10-04 12:05:57 +02:00
Daniel Hutzel
bd0f514026 Updated workspace setup (#406) 2022-10-04 11:59:22 +02:00
Daniel
ee2fdd0989 cosmetics 2022-10-04 11:48:01 +02:00
dependabot[bot]
92f7489def Bump sqlite3 from 5.1.1 to 5.1.2 (#404)
Bumps [sqlite3](https://github.com/TryGhost/node-sqlite3) from 5.1.1 to 5.1.2.
- [Release notes](https://github.com/TryGhost/node-sqlite3/releases)
- [Commits](https://github.com/TryGhost/node-sqlite3/compare/v5.1.1...v5.1.2)

---
updated-dependencies:
- dependency-name: sqlite3
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-10-04 10:36:43 +02:00
41 changed files with 1755 additions and 2864 deletions

View File

@@ -1,28 +1,31 @@
{
"extends": [
"eslint:recommended",
"plugin:@sap/cds/recommended"
],
"env": {
"browser": true,
"es2022": true,
"node": true,
"jest": true,
"mocha": true
},
"globals": {
"SELECT": true,
"INSERT": true,
"UPDATE": true,
"DELETE": true,
"CREATE": true,
"DROP": true,
"cds": true
},
"rules": {
"no-console": "off",
"require-atomic-updates": "off",
"extends": [
"plugin:@sap/cds/recommended",
"eslint:recommended"
],
"env": {
"browser": true,
"es2022": true,
"node": true,
"jest": true,
"mocha": true
},
"globals": {
"SELECT": true,
"INSERT": true,
"UPSERT": true,
"UPDATE": true,
"DELETE": true,
"CREATE": true,
"DROP": true,
"CDL": true,
"CQL": true,
"cds": true
},
"rules": {
"no-console": "off",
"require-atomic-updates": "off",
"require-await":"warn",
"no-unused-vars": ["warn", { "argsIgnorePattern": "_" }]
}
}
}

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
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

@@ -1,10 +0,0 @@
---
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

@@ -1 +0,0 @@
*.tgz

View File

@@ -1,81 +0,0 @@
const { exec } = require ('child_process')
const isWin = process.platform === 'win32'
const express = require ('express')
const fs = require ('fs')
const app = express()
const { PORT=4444 } = process.env
const [,,port=PORT,scope='@capire'] = process.argv
const cwd = __dirname
// clean up on start (exit handler might not complete on Windows)
exec(isWin ? 'del *.tgz' : 'rm *.tgz', {cwd})
app.use('/-/:tarball', (req,res,next) => {
console.debug ('GET', req.params)
try {
const { tarball } = req.params
const pkgFull = tarball.substring(0, tarball.lastIndexOf('-'))
const [, pkg ] = /^\w+-(.+)/.exec(pkgFull)
fs.lstat(tarball,(err => {
if (err) console.debug (`npm pack ../${pkg}`)
if (err) exec(`npm pack ../${pkg}`,{cwd},next)
else next()
}))
} catch (e) {
console.error(e)
res.sendStatus(500)
}
})
app.use('/-', express.static(__dirname))
app.get('/*', (req,res)=>{
const urlRegex = /^\/(@[\w-]+)\/(.+)/
const url = decodeURIComponent(req.url)
console.debug ('GET',url)
try {
if (!urlRegex.test(url)) return res.sendStatus(404)
const [, scpe, pkg ] = urlRegex.exec(url)
const package = require (`${scpe}/${pkg}/package.json`)
const tarball = `${scpe.slice(1)}-${pkg}-${package.version}.tgz`
// https://github.com/npm/registry/blob/master/docs/responses/package-metadata.md
res.json({
"name": package.name,
"dist-tags": {
"latest": package.version
},
"versions": {
[package.version]: {
"name": package.name,
"version": package.version,
"dist": {
"tarball": `${server.url}/-/${tarball}`
},
}
},
})
} catch (e) {
if (e.code === 'MODULE_NOT_FOUND') return res.sendStatus(404)
console.error(e); throw e
}
})
const server = app.listen(port, ()=>{
const url = server.url = `http://localhost:${server.address().port}`
console.log (`npm set ${scope}:registry=${url}`)
exec(`npm set ${scope}:registry=${url}`)
console.log (`${scope} registry listening on ${url}`)
})
const _exit = ()=>{
server.close()
exec(`npm conf rm "${scope}:registry"`, ()=> { process.exit() })
}
process.on ('SIGTERM',_exit)
process.on ('SIGHUP',_exit)
process.on ('SIGINT',_exit)
process.on ('SIGUSR2',_exit)

20
.vscode/launch.json vendored
View File

@@ -13,7 +13,7 @@
"<node_internals>/**",
"**/node_modules/**",
"**/cds/lib/lazy.js",
"**/cds/lib/req/cls.js",
"**/cds/lib/req/cds-context.js",
"**/odata-v4/okra/**"
]
},
@@ -26,10 +26,24 @@
"<node_internals>/**",
"**/node_modules/**",
"**/cds/lib/lazy.js",
"**/cds/lib/req/cls.js",
"**/cds/lib/req/cds-context.js",
"**/odata-v4/okra/**"
]
}
},
{
"name": "Debug Mocha Tests",
"type": "node",
"request": "attach",
"port": 9229,
"continueOnAttach": true,
"skipFiles": [
"<node_internals>/**",
"**/node_modules/**",
"**/cds/lib/lazy.js",
"**/cds/lib/req/cds-context.js",
"**/odata-v4/okra/**",
]
},
],
"inputs": [
{

View File

@@ -10,12 +10,13 @@
"<node_internals>/**",
"**/node_modules/**",
"**/cds/lib/lazy.js",
"**/cds/lib/req/cls.js",
"**/cds/lib/req/cds-context.js",
"**/odata-v4/okra/**"
]
},
"mochaExplorer.debuggerConfig": "Debug Mocha Tests",
"mochaExplorer.parallel": true,
"eslint.validate": [
"eslint.probe": [
"cds",
"csn",
"csv",

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;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
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 16 15
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,21 +4,21 @@
* currencies, if not obtained through @capire/common.
*/
module.exports = async (db)=>{
module.exports = async (tx)=>{
const has_common = db.model.definitions['sap.common.Currencies'].elements.numcode
const has_common = tx.model.definitions['sap.common.Currencies']?.elements.numcode
if (has_common) return
const already_filled = await db.exists('sap.common.Currencies',{code:'EUR'})
const already_filled = await tx.exists('sap.common.Currencies',{code:'EUR'})
if (already_filled) return
await INSERT.into ('sap.common.Currencies') .columns (
'code','symbol','name'
await tx.run (INSERT.into ('sap.common.Currencies') .columns (
[ 'code', 'symbol', 'name' ]
) .rows (
[ 'EUR','€','Euro' ],
[ 'USD','$','US Dollar' ],
[ 'GBP','£','British Pound' ],
[ 'ILS','₪','Shekel' ],
[ 'JPY','¥','Yen' ],
)
[ 'EUR', '€', 'Euro' ],
[ 'USD', '$', 'US Dollar' ],
[ 'GBP', '£', 'British Pound' ],
[ 'ILS', '₪', 'Shekel' ],
[ 'JPY', '¥', 'Yen' ],
))
}

View File

@@ -0,0 +1,11 @@
{
"name": "mtx-sidecar", "version": "0.0.0",
"dependencies": {
"@sap/cds-mtxs": "^1",
"@sap/cds": "^6",
"express": "^4"
},
"cds": {
"profile": "mtx-sidecar"
}
}

View File

@@ -20,8 +20,10 @@
"watch": "cds watch"
},
"cds": {
"profile": "with-mtx-sidecar",
"requires": {
"db": "sql"
"multitenancy": true,
"db": { "kind": "sql" }
}
}
}

View File

@@ -12,7 +12,11 @@ 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,16 +6,33 @@ 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,5 +43,10 @@ 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,6 +62,11 @@ 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

@@ -33,7 +33,7 @@ annotate CatalogService.Books with @(UI : {
////////////////////////////////////////////////////////////////////////////
//
// Books Object Page
// Books List Page
//
annotate CatalogService.Books with @(UI : {
SelectionFields : [
@@ -52,9 +52,6 @@ annotate CatalogService.Books with @(UI : {
},
{Value : genre.name},
{Value : price},
{
Value : currency.symbol,
Label : ' '
},
{Value : currency.symbol},
]
}, );

View File

@@ -4,57 +4,53 @@
using { sap.capire.bookshop as my } from '@capire/bookstore';
using { sap.common } from '@capire/common';
using { sap.common.Currencies } from '@sap/cds/common';
////////////////////////////////////////////////////////////////////////////
//
// Books Lists
//
annotate my.Books with @(
Common.SemanticKey : [ID],
UI : {
Identification : [{Value : title}],
SelectionFields : [
ID,
author_ID,
price,
currency_code
],
LineItem : [
{
Value : ID,
Label : '{i18n>Title}'
},
{
Value : author.ID,
Label : '{i18n>Author}'
},
{Value : genre.name},
{Value : stock},
{Value : price},
{
Value : currency.symbol,
Label : ' '
},
]
}
Common.SemanticKey : [ID],
UI : {
Identification : [{ Value: title }],
SelectionFields : [
ID,
author_ID,
price,
currency_code
],
LineItem : [
{ Value: ID, Label: '{i18n>Title}' },
{ Value: author.ID, Label: '{i18n>Author}' },
{ Value: genre.name },
{ Value: stock },
{ Value: price },
{ Value: currency.symbol },
]
}
) {
ID @Common: {
SemanticObject : 'Books',
Text: title,
TextArrangement : #TextOnly
};
author @ValueList.entity : 'Authors';
ID @Common: {
SemanticObject : 'Books',
Text: title,
TextArrangement : #TextOnly
};
author @ValueList.entity : 'Authors';
};
annotate Currencies with {
symbol @Common.Label : '{i18n>Currency}';
}
////////////////////////////////////////////////////////////////////////////
//
// Books Details
//
annotate my.Books with @(UI : {HeaderInfo : {
TypeName : '{i18n>Book}',
TypeNamePlural : '{i18n>Books}',
Title : {Value : title},
Description : {Value : author.name}
TypeName : '{i18n>Book}',
TypeNamePlural : '{i18n>Books}',
Title : { Value: title },
Description : { Value: author.name }
}, });
@@ -63,19 +59,14 @@ annotate my.Books with @(UI : {HeaderInfo : {
// Books Elements
//
annotate my.Books with {
ID @title : '{i18n>ID}';
title @title : '{i18n>Title}';
genre @title : '{i18n>Genre}' @Common : {
Text : genre.name,
TextArrangement : #TextOnly
};
author @title : '{i18n>Author}' @Common : {
Text : author.name,
TextArrangement : #TextOnly
};
price @title : '{i18n>Price}' @Measures.ISOCurrency : currency_code;
stock @title : '{i18n>Stock}';
descr @UI.MultiLineText;
ID @title: '{i18n>ID}';
title @title: '{i18n>Title}';
genre @title: '{i18n>Genre}' @Common: { Text: genre.name, TextArrangement: #TextOnly };
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}';
}
////////////////////////////////////////////////////////////////////////////
@@ -83,36 +74,40 @@ annotate my.Books with {
// Genres List
//
annotate my.Genres with @(
Common.SemanticKey : [name],
UI : {
SelectionFields : [name],
LineItem : [
{Value : name},
{
Value : parent.name,
Label : 'Main Genre'
},
],
}
Common.SemanticKey : [name],
UI : {
SelectionFields : [name],
LineItem : [
{ Value: name },
{
Value : parent.name,
Label: 'Main Genre'
},
],
}
);
annotate my.Genres with {
ID @Common.Text : name @Common.TextArrangement : #TextOnly;
}
////////////////////////////////////////////////////////////////////////////
//
// Genre Details
//
annotate my.Genres with @(UI : {
Identification : [{Value : name}],
HeaderInfo : {
TypeName : '{i18n>Genre}',
TypeNamePlural : '{i18n>Genres}',
Title : {Value : name},
Description : {Value : ID}
},
Facets : [{
$Type : 'UI.ReferenceFacet',
Label : '{i18n>SubGenres}',
Target : 'children/@UI.LineItem'
}, ],
Identification : [{ Value: name}],
HeaderInfo : {
TypeName : '{i18n>Genre}',
TypeNamePlural : '{i18n>Genres}',
Title : { Value: name },
Description : { Value: ID }
},
Facets : [{
$Type : 'UI.ReferenceFacet',
Label : '{i18n>SubGenres}',
Target : 'children/@UI.LineItem'
}, ],
});
////////////////////////////////////////////////////////////////////////////
@@ -120,8 +115,8 @@ annotate my.Genres with @(UI : {
// Genres Elements
//
annotate my.Genres with {
ID @title : '{i18n>ID}';
name @title : '{i18n>Genre}';
ID @title: '{i18n>ID}';
name @title: '{i18n>Genre}';
}
////////////////////////////////////////////////////////////////////////////
@@ -129,24 +124,24 @@ annotate my.Genres with {
// Authors List
//
annotate my.Authors with @(
Common.SemanticKey : [ID],
UI : {
Identification : [{Value : name}],
SelectionFields : [name],
LineItem : [
{Value : ID},
{Value : dateOfBirth},
{Value : dateOfDeath},
{Value : placeOfBirth},
{Value : placeOfDeath},
],
}
Common.SemanticKey : [ID],
UI : {
Identification : [{ Value: name}],
SelectionFields : [name],
LineItem : [
{ Value: ID },
{ Value: dateOfBirth },
{ Value: dateOfDeath },
{ Value: placeOfBirth },
{ Value: placeOfDeath },
],
}
) {
ID @Common: {
SemanticObject : 'Authors',
Text: name,
TextArrangement : #TextOnly,
};
ID @Common: {
SemanticObject : 'Authors',
Text: name,
TextArrangement : #TextOnly,
};
};
////////////////////////////////////////////////////////////////////////////
@@ -154,16 +149,16 @@ annotate my.Authors with @(
// Author Details
//
annotate my.Authors with @(UI : {
HeaderInfo : {
TypeName : '{i18n>Author}',
TypeNamePlural : '{i18n>Authors}',
Title : {Value : name},
Description : {Value : dateOfBirth}
},
Facets : [{
$Type : 'UI.ReferenceFacet',
Target : 'books/@UI.LineItem'
}, ],
HeaderInfo : {
TypeName : '{i18n>Author}',
TypeNamePlural : '{i18n>Authors}',
Title : { Value: name },
Description : { Value: dateOfBirth }
},
Facets : [{
$Type : 'UI.ReferenceFacet',
Target : 'books/@UI.LineItem'
}, ],
});
@@ -172,12 +167,12 @@ annotate my.Authors with @(UI : {
// Authors Elements
//
annotate my.Authors with {
ID @title : '{i18n>ID}';
name @title : '{i18n>Name}';
dateOfBirth @title : '{i18n>DateOfBirth}';
dateOfDeath @title : '{i18n>DateOfDeath}';
placeOfBirth @title : '{i18n>PlaceOfBirth}';
placeOfDeath @title : '{i18n>PlaceOfDeath}';
ID @title: '{i18n>ID}';
name @title: '{i18n>Name}';
dateOfBirth @title: '{i18n>DateOfBirth}';
dateOfDeath @title: '{i18n>DateOfDeath}';
placeOfBirth @title: '{i18n>PlaceOfBirth}';
placeOfDeath @title: '{i18n>PlaceOfDeath}';
}
////////////////////////////////////////////////////////////////////////////
@@ -185,18 +180,18 @@ annotate my.Authors with {
// Languages List
//
annotate common.Languages with @(
Common.SemanticKey : [code],
Identification : [{Value : code}],
UI : {
SelectionFields : [
name,
descr
],
LineItem : [
{Value : code},
{Value : name},
],
}
Common.SemanticKey : [code],
Identification : [{ Value: code}],
UI : {
SelectionFields : [
name,
descr
],
LineItem : [
{ Value: code },
{ Value: name },
],
}
);
////////////////////////////////////////////////////////////////////////////
@@ -204,22 +199,22 @@ annotate common.Languages with @(
// Language Details
//
annotate common.Languages with @(UI : {
HeaderInfo : {
TypeName : '{i18n>Language}',
TypeNamePlural : '{i18n>Languages}',
Title : {Value : name},
Description : {Value : descr}
},
Facets : [{
$Type : 'UI.ReferenceFacet',
Label : '{i18n>Details}',
Target : '@UI.FieldGroup#Details'
}, ],
FieldGroup #Details : {Data : [
{Value : code},
{Value : name},
{Value : descr}
]},
HeaderInfo : {
TypeName : '{i18n>Language}',
TypeNamePlural : '{i18n>Languages}',
Title : { Value: name },
Description : { Value: descr }
},
Facets : [{
$Type : 'UI.ReferenceFacet',
Label : '{i18n>Details}',
Target : '@UI.FieldGroup#Details'
}, ],
FieldGroup #Details : {Data : [
{ Value: code },
{ Value: name },
{ Value: descr }
]},
});
////////////////////////////////////////////////////////////////////////////
@@ -227,19 +222,19 @@ annotate common.Languages with @(UI : {
// Currencies List
//
annotate common.Currencies with @(
Common.SemanticKey : [code],
Identification : [{Value : code}],
UI : {
SelectionFields : [
name,
descr
],
LineItem : [
{Value : descr},
{Value : symbol},
{Value : code},
],
}
Common.SemanticKey : [code],
Identification : [{ Value: code}],
UI : {
SelectionFields : [
name,
descr
],
LineItem : [
{ Value: descr },
{ Value: symbol },
{ Value: code },
],
}
);
////////////////////////////////////////////////////////////////////////////
@@ -247,35 +242,35 @@ annotate common.Currencies with @(
// Currency Details
//
annotate common.Currencies with @(UI : {
HeaderInfo : {
TypeName : '{i18n>Currency}',
TypeNamePlural : '{i18n>Currencies}',
Title : {Value : descr},
Description : {Value : code}
HeaderInfo : {
TypeName : '{i18n>Currency}',
TypeNamePlural : '{i18n>Currencies}',
Title : { Value: descr },
Description : { Value: code }
},
Facets : [
{
$Type : 'UI.ReferenceFacet',
Label : '{i18n>Details}',
Target : '@UI.FieldGroup#Details'
},
Facets : [
{
$Type : 'UI.ReferenceFacet',
Label : '{i18n>Details}',
Target : '@UI.FieldGroup#Details'
},
{
$Type : 'UI.ReferenceFacet',
Label : '{i18n>Extended}',
Target : '@UI.FieldGroup#Extended'
},
],
FieldGroup #Details : {Data : [
{Value : name},
{Value : symbol},
{Value : code},
{Value : descr}
]},
FieldGroup #Extended : {Data : [
{Value : numcode},
{Value : minor},
{Value : exponent}
]},
{
$Type : 'UI.ReferenceFacet',
Label : '{i18n>Extended}',
Target : '@UI.FieldGroup#Extended'
},
],
FieldGroup #Details : {Data : [
{ Value: name },
{ Value: symbol },
{ Value: code },
{ Value: descr }
]},
FieldGroup #Extended : {Data : [
{ Value: numcode },
{ Value: minor },
{ Value: exponent }
]},
});
////////////////////////////////////////////////////////////////////////////
@@ -283,7 +278,7 @@ annotate common.Currencies with @(UI : {
// Currencies Elements
//
annotate common.Currencies with {
numcode @title : '{i18n>NumCode}';
minor @title : '{i18n>MinorUnit}';
exponent @title : '{i18n>Exponent}';
numcode @title: '{i18n>NumCode}';
minor @title: '{i18n>MinorUnit}';
exponent @title: '{i18n>Exponent}';
}

View File

@@ -1,8 +1,8 @@
const cds = require("@sap/cds")
// install OData v2 adapter
const cds = require("@sap/cds")
const proxy = require('@sap/cds-odata-v2-adapter-proxy')
const proxyOpts = global.it ? { target:'auto' } : {} // for tests, set 'auto' to detect port dynamically
cds.on('bootstrap', app => app.use(proxy(proxyOpts)))
const opts = global.it ? { target:'auto' } : {} // for tests, set 'auto' to detect port dynamically
cds.on('bootstrap', app => app.use(proxy(opts))) // install proxy
cds.log('cov2ap','silent') // suppress anoying log outpout, e.g. for `npm run mocha -- --reporter nyan`
module.exports = require('@capire/bookstore/server.js')

View File

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

76
loggers/app/loggers.html Normal file
View File

@@ -0,0 +1,76 @@
<!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>

22
loggers/package.json Normal file
View File

@@ -0,0 +1,22 @@
{
"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"
}
}
}

11
loggers/readme.md Normal file
View File

@@ -0,0 +1,11 @@
# 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`

3
loggers/srv/dummy.cds Normal file
View File

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

20
loggers/srv/loggers.cds Normal file
View File

@@ -0,0 +1,20 @@
@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;
}

56
loggers/srv/loggers.js Normal file
View File

@@ -0,0 +1,56 @@
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

@@ -0,0 +1,18 @@
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 = new Buffer(
const decodedMedia = Buffer.from(
mediaObj.media.split(';base64,').pop(),
'base64'
)

View File

@@ -16,23 +16,24 @@ using { OrdersService } from '../srv/orders-service';
@odata.draft.enabled
annotate OrdersService.Orders with @(
UI: {
SelectionFields: [ createdAt, createdBy ],
SelectionFields: [ createdBy ],
LineItem: [
{Value: OrderNo, Label:'OrderNo'},
{Value: buyer, Label:'Customer'},
{Value: createdAt, Label:'Date'}
{Value: OrderNo, Label:'{i18n>OrderNo}'},
{Value: buyer, Label:'{i18n>Customer}'},
{Value: currency.symbol, Label:'{i18n>Currency}'},
{Value: createdAt, Label:'{i18n>Date}'},
],
HeaderInfo: {
TypeName: 'Order', TypeNamePlural: 'Orders',
TypeName: '{i18n>Order}', TypeNamePlural: '{i18n>Orders}',
Title: {
Label: 'Order number ', //A label is possible but it is not considered on the ObjectPage yet
Label: '{i18n>OrderNo}', //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:'Customer'},
{Value: createdAt, Label:'Date'},
{Value: createdBy, Label:'{i18n>Customer}'},
{Value: createdAt, Label:'{i18n>Date}'},
{Value: OrderNo },
],
HeaderFacets: [
@@ -45,7 +46,7 @@ annotate OrdersService.Orders with @(
],
FieldGroup#Details: {
Data: [
{Value: currency.code, Label:'Currency'}
{Value: currency.code, Label:'{i18n>Currency}'}
]
},
FieldGroup#Created: {
@@ -64,6 +65,7 @@ annotate OrdersService.Orders with @(
) {
createdAt @UI.HiddenFilter:false;
createdBy @UI.HiddenFilter:false;
ID @UI.Hidden;
};
@@ -71,15 +73,15 @@ annotate OrdersService.Orders with @(
annotate OrdersService.Orders.Items with @(
UI: {
LineItem: [
{Value: product_ID, Label:'Product ID'},
{Value: title, Label:'Product Title'},
{Value: price, Label:'Unit Price'},
{Value: quantity, Label:'Quantity'},
{Value: product_ID, Label:'{i18n>ProductID}'},
{Value: title, Label:'{i18n>ProductTitle}'},
{Value: price, Label:'{i18n>UnitPrice}'},
{Value: quantity, Label:'{i18n>Quantity}'},
],
Identification: [ //Is the main field group
{Value: quantity, Label:'Quantity'},
{Value: title, Label:'Product'},
{Value: price, Label:'Unit Price'},
{Value: quantity, Label:'{i18n>Quantity}'},
{Value: title, Label:'{i18n>Product}'},
{Value: price, Label:'{i18n>UnitPrice}'},
],
Facets: [
{$Type: 'UI.ReferenceFacet', Label: '{i18n>OrderItems}', Target: '@UI.Identification'},
@@ -89,4 +91,7 @@ annotate OrdersService.Orders.Items with @(
quantity @(
Common.FieldControl: #Mandatory
);
ID @UI.Hidden;
up_ @UI.Hidden;
};

View File

@@ -13,7 +13,7 @@
applications: {
"manage-orders": {
title: "Manage Orders",
description: "... testing FE v42",
description: "CAP Sample App",
additionalInformation: "SAPUI5.Component=orders",
applicationType : "URL",
url: "/orders/webapp",

View File

@@ -3,8 +3,8 @@
"sap.app": {
"id": "orders",
"type": "application",
"title": "Order Books",
"description": "Sample Application",
"title": "Order Management",
"description": "CAP Sample Application",
"i18n": "i18n/i18n.properties",
"dataSources": {
"OrdersService": {

View File

@@ -2,7 +2,7 @@ using { Currency, User, managed, cuid } from '@sap/cds/common';
namespace sap.capire.orders;
entity Orders : cuid, managed {
OrderNo : String @title:'Order Number'; //> readable key
OrderNo : String(22) @title:'Order Number'; //> readable key
Items : Composition of many {
key ID : UUID;
product : Association to Products;

3539
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -8,10 +8,20 @@
"@sap/cds": ">=5.5.3"
},
"workspaces": [
"./*/"
"./bookshop",
"./bookstore",
"./common",
"./data-viewer",
"./fiori",
"./hello",
"./media",
"./orders",
"./loggers",
"./reviews"
],
"devDependencies": {
"axios": "^0",
"@sap/eslint-plugin-cds": "^2.6.1",
"axios": "^1",
"chai": "^4.3.4",
"chai-as-promised": "^7.1.1",
"chai-subset": "^1.6.0",
@@ -20,13 +30,12 @@
},
"scripts": {
"cleanup": "rm -rf node_modules && rm -rf */node_modules && rm -rf */*/node_modules",
"registry": "node .registry/server.js",
"bookshop": "cds watch bookshop",
"fiori": "cds watch fiori",
"hello": "cds watch hello",
"media": "cds watch media",
"mocha": "npx mocha || echo",
"jest": "npx jest",
"mocha": "CDS_TEST_SILENT=y npx mocha",
"jest": "npx jest --silent",
"start": "cds watch fiori",
"test": "npm run jest -- --silent",
"test:hello": "cd hello && npm test"
@@ -39,7 +48,8 @@
},
"mocha": {
"recursive": true,
"parallel": true
"parallel": true,
"timeout": 6666
},
"license": "SAP SAMPLE CODE LICENSE",
"private": true

View File

@@ -1,7 +1,7 @@
# Overview of Samples
The following list gives an overview of the samples provided in subdirectories.
Each sub directory essentially is an individual npm package arranged in an [all-in-one monorepo](all-in-one-monorepo) umbrella setup.
Each sub directory essentially is an individual npm package arranged in an [all-in-one monorepo](#all-in-one-monorepo) umbrella setup.
## [@capire/hello-world](hello)

View File

@@ -3,8 +3,9 @@ const cds = require('@sap/cds/lib')
describe('cap/samples - Custom Handlers', () => {
const { GET, POST, expect } = cds.test(__dirname+'/../bookshop')
if (cds.User.default) cds.User.default = cds.User.Privileged // hard core monkey patch
else cds.User = cds.User.Privileged // hard core monkey patch for older cds releases
beforeAll(()=>{
cds.User.default = cds.User.Privileged // hard core monkey patch
})
it('should reject out-of-stock orders', async () => {
await POST `/browse/submitOrder ${{ book: 201, quantity: 5 }}`

View File

@@ -1,10 +1,12 @@
const cds = require('@sap/cds/lib')
describe('cap/samples - Fiori APIs - v2', () => {
describe('cap/samples - Fiori APIs - v2', function() {
const { GET, expect, axios } = cds.test ('@capire/fiori', '--with-mocks')
axios.defaults.auth = { username: 'alice', password: 'admin' }
// if (this.timeout) this.timeout(1e6)
it('serves $metadata documents in v2', async () => {
const { headers, data } = await GET `/v2/browse/$metadata`
expect(headers).to.contain({

View File

@@ -16,21 +16,21 @@ describe('cap/samples - Hierarchical Data', ()=>{
before ('bootstrap sqlite in-memory db...', async()=>{
await cds.deploy (model) .to ('sqlite::memory:')
expect (cds.db) .to.exist
expect (cds.db.model) .to.exist
expect (cds.db.model) .to.exist
})
it ('supports deeply nested inserts', ()=> INSERT.into (Cats,
{ ID:100, name:'Some Cats...', children:[
{ ID:101, name:'Cat', children:[
{ ID:102, name:'Kitty', children:[
{ ID:103, name:'Kitty Cat', children:[
{ ID:104, name:'Aristocat' } ]},
{ ID:105, name:'Kitty Bat' } ]},
{ ID:106, name:'Catwoman', children:[
{ ID:107, name:'Catalina' } ]} ]},
{ ID:108, name:'Catweazle' }
]}
))
{ ID:100, name:'Some Cats...', children:[
{ ID:101, name:'Cat', children:[
{ ID:102, name:'Kitty', children:[
{ ID:103, name:'Kitty Cat', children:[
{ ID:104, name:'Aristocat' } ]},
{ ID:105, name:'Kitty Bat' } ]},
{ ID:106, name:'Catwoman', children:[
{ ID:107, name:'Catalina' } ]} ]},
{ ID:108, name:'Catweazle' }
]}
))
it ('supports nested reads', async()=>{
if (require('semver').gte(cds.version, '5.9.0')) {
@@ -101,12 +101,12 @@ describe('cap/samples - Hierarchical Data', ()=>{
})
it ('supports cascaded deletes', async()=>{
const affectedRows = await DELETE.from (Cats) .where ({ID:[102,106]})
expect (affectedRows) .to.be.greaterThan (0)
const affectedRows = await DELETE.from (Cats) .where ({ID:[102,106]})
expect (affectedRows) .to.be.greaterThan (0)
const expected = [
{ ID:100, name:'Some Cats...' },
{ ID:101, name:'Cat' },
{ ID:108, name:'Catweazle' }
{ ID:100, name:'Some Cats...' },
{ ID:101, name:'Cat' },
{ ID:108, name:'Catweazle' }
]
expect ( await SELECT`ID,name`.from(Cats) ).to.eql (expected)
})

View File

@@ -1,8 +1,12 @@
const cds = require('@sap/cds/lib')
describe('cap/samples - Localized Data', () => {
const { GET, expect, cds } = require('@sap/cds/lib').test (__dirname)
if (cds.User.default) cds.User.default = cds.User.Privileged // hard core monkey patch
else cds.User = cds.User.Privileged // hard core monkey patch for older cds releases
const { GET, expect } = cds.test (__dirname)
beforeAll(()=>{
cds.User.default = cds.User.Privileged // hard core monkey patch
})
it('serves localized $metadata documents', async () => {
const { data } = await GET(`/browse/$metadata?sap-language=de`, { headers: { 'accept-language': 'de' }})

View File

@@ -1,16 +1,13 @@
const cds = require('@sap/cds/lib')
const {resolve} = require('path')
describe('cap/samples - Messaging', ()=>{
const { expect } = cds.test
const { expect } = cds.test.in(__dirname,'..')
const _model = '@capire/reviews'
const Reviews = 'sap.capire.reviews.Reviews'
if (cds.User.default) cds.User.default = cds.User.Privileged // hard core monkey patch
else cds.User = cds.User.Privileged // hard core monkey patch for older cds releases
beforeAll(() => { cds.root = resolve(__dirname, '..') })
afterAll(() => { cds.root = process.cwd() })
beforeAll(()=>{
cds.User.default = cds.User.Privileged // hard core monkey patch
})
it ('should bootstrap sqlite in-memory db', async()=>{
const db = await cds.deploy (_model) .to ('sqlite::memory:')
@@ -35,6 +32,7 @@ describe('cap/samples - Messaging', ()=>{
it ('should add review', async ()=>{
const review = { subject: "201", title: "Captivating", rating: ++N }
cds._debug = 1
const response = await srv.create ('Reviews') .entries (review)
expect (response) .to.containSubset (review)
})

View File

@@ -4,47 +4,6 @@ describe('cap/samples - Bookshop APIs', () => {
const { GET, expect, axios } = cds.test ('@capire/bookshop')
axios.defaults.auth = { username: 'alice', password: 'admin' }
// Genres
const Drama = {
"name": "Drama",
"descr": null,
"ID": 11,
"parent_ID": 10
}
const Mystery = {
"name": "Mystery",
"descr": null,
"ID": 16,
"parent_ID": 10
}
const Fantasy = {
"name": "Fantasy",
"descr": null,
"ID": 13,
"parent_ID": 10
}
// Currencies
const GBP = {
"name": "British Pound",
"descr": null,
"code": "GBP",
"symbol": "£"
}
const USD = {
"name": "US Dollar",
"descr": null,
"code": "USD",
"symbol": "$"
}
const JPY = {
"name": "Yen",
"descr": null,
"code": "JPY",
"symbol": "¥"
}
it('serves $metadata documents in v4', async () => {
const { headers, status, data } = await GET `/browse/$metadata`
expect(status).to.equal(200)
@@ -57,12 +16,15 @@ describe('cap/samples - Bookshop APIs', () => {
})
it('serves ListOfBooks?$expand=genre,currency', async () => {
const Mystery = { ID: 16, name: 'Mystery', descr: null, parent_ID: 10 }
const Romance = { ID: 15, name: 'Romance', descr: null, parent_ID: 10 }
const USD = { code: 'USD', name: 'US Dollar', descr: null, symbol: '$' }
const { data } = await GET `/browse/ListOfBooks ${{
params: { $search: 'Po', $select: `title,author`, $expand:`genre,currency` },
}}`
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:Mystery, currency:USD },
{ ID: 252, title: 'Eleonora', author: 'Edgar Allen Poe', genre:Romance, currency:USD },
])
})
@@ -126,14 +88,10 @@ describe('cap/samples - Bookshop APIs', () => {
})
it('serves user info', async () => {
{
const { data } = await GET (`/user/me`)
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', tenant: null })
}
const { data: alice } = await GET `/user/me`
expect(alice).to.containSubset({ id: 'alice', locale:'en' })
const { data: joe } = await GET (`/user/me`, {auth: { username: 'joe' }})
expect(joe).to.containSubset({ id: 'joe', locale:'en' })
})
})

View File

@@ -1,57 +0,0 @@
const cds = require('@sap/cds/lib')
const { fork } = require('child_process')
const { resolve } = require('path')
const verbose = process.env.CDS_TEST_VERBOSE
describe('cap/samples - Local NPM registry', () => {
const { expect } = cds.test
// ||true
let registry
let axios
const cwd = resolve(__dirname, '..')
before(async ()=> {
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').default.create ({ baseURL: res.url, validateStatus: (status)=>status<500 })
})
after(() => { registry.kill() })
for (const mod of ['bookshop', 'data-viewer', 'fiori','orders','reviews']) {
it(`should serve ${mod}`, async () => {
const resp = await axios.get(`/@capire/${mod}`)
expect(resp.data).to.containSubset({name: `@capire/${mod}`, versions:{}})
const versions = Object.values(resp.data.versions)
await axios.get(versions[0].dist.tarball)
})
}
it(`should return 404 for unknown packages`, async () => {
let resp = await axios.get(`/@capire/foo`)
expect(resp.status).to.equal(404)
resp = await axios.get(`/foo`)
expect(resp.status).to.equal(404)
})
})
function exec (script, opts) {
return new Promise((resolve, reject)=> {
const cp = fork (script, [], opts)
.on('error', err => reject(new Error(err)))
cp.stdout.on('data', chunk => {
if (verbose) console.log(chunk.toString())
if (chunk.toString().match(/listening.*(http:.*:\d+)/i)) {
resolve({cp, url:RegExp.$1})
}
})
cp.stderr.on('data', chunk => {
if (verbose) console.error(chunk.toString())
})
})
}