Socket
Socket
Sign inDemoInstall

@sap/cds

Package Overview
Dependencies
Maintainers
3
Versions
183
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sap/cds - npm Package Compare versions

Comparing version 3.10.0 to 3.13.0

bin/disconnect.js

4

apis/models.d.ts

@@ -38,4 +38,4 @@ import { Query, expr } from "./specs/CQN"

(csn: csn) : {
for: ( output: 'json' | 'yaml' | 'yml' | 'sql' | 'cdl' | 'edm' | 'edmx', options? ) => csn
to: ( output: 'json' | 'yaml' | 'yml' | 'sql' | 'cdl' | 'edm' | 'edmx', options? ) => string
for: ( output: 'json' | 'yaml' | 'yml' | 'sql' | 'cdl' | 'edm' | 'edmx', options?:object ) => csn
to: ( output: 'json' | 'yaml' | 'yml' | 'sql' | 'cdl' | 'edm' | 'edmx', options?:object ) => string
}

@@ -42,0 +42,0 @@ }

@@ -23,3 +23,3 @@ import { SELECT, INSERT, UPDATE, DELETE, Query } from './ql'

*/
transaction (context) : Transaction
transaction (context : object) : Transaction
}

@@ -49,3 +49,3 @@

run (query : Query) : Promise<ResultSet>
foreach (query : Query, callback) : this
foreach (query : Query, callback: (row:object) => void) : this
}

@@ -52,0 +52,0 @@

module.exports = Object.assign(activate, {
options: ['--username', '--tenant', '--to'],
options: ['--username', '--passcode', '--subdomain', '--to', ],
flags: ['--undeploy'],
shortcuts: ['-u', '-t'],
shortcuts: ['-u', '-p', '-s'],
help: `

@@ -15,10 +15,10 @@ # SYNOPSIS

*-p* | *--passcode* <passcode>
The passcode for authentication
*-u* | *--username* <name>
The username for authentication.
Deprecated. Use passcode parameter instead.
*-t* | *--tenant* <tenant>
Override the tenant to extend (Otherwise taken from JWT token).
*--to* <url>

@@ -39,22 +39,8 @@ The url to activate.

const client = require('@sap/cds-sidecar-client')
const { askQuestion, askBooleanQuestion } = client.question
const askQuestion = client.question.askQuestion
if (!folder) {
folder = await askQuestion('Project root folder: ')
if (options.username && !options.passcode) {
options.password = await askQuestion('Password: ', undefined, true)
}
if (!options.to) {
options.to = await askQuestion('Application URL: ')
}
if (!options.username) {
options.username = await askQuestion('Username: ')
}
if (options.undeploy === undefined) {
options.undeploy = await askBooleanQuestion('Undeploy previously deployed extension [yN]')
}
options.password = await askQuestion('Password: ', undefined, true)
const collectSources = require('../lib/models/cdsv').collectSources

@@ -61,0 +47,0 @@ const cds = require('../lib/cds')

@@ -61,4 +61,4 @@ const _cds = require('../../lib/cds')

const fs = require('fs-extra')
const BuildTaskEngine = require('./buildTaskEngine')
const BuildTaskFactory = require('./buildTaskFactory')
const BuildTaskEngine = require('../../lib/build/buildTaskEngine')
const BuildTaskFactory = require('../../lib/build/buildTaskFactory')

@@ -65,0 +65,0 @@ if (!project) {

@@ -43,2 +43,5 @@ #!/usr/bin/env node

// 'cds cds' --> 'cds compile cds'
if (/^cds$/i.test(cmd)) { args.unshift(cmd); cmd = './compile' }
try {

@@ -51,3 +54,8 @@ // one of our built-in cli commands?

}
const cmdPath = cmd
cmd = require (cmd)
if (typeof cmd !== 'function') {
// we have resolved something unknown, as with 'cds ..'
throw new Error('Unsupported command: ' + cmdPath)
}

@@ -75,3 +83,3 @@ // parse arguments and options for specific command

require('../lib/cds').on ('compilationMessage', (m) => messages.push (m))
process.on('beforeExit', () => logMessages (messages))
process.once('beforeExit', () => logMessages (messages))
}

@@ -78,0 +86,0 @@

module.exports = Object.assign(deploy, {
options: ['--to'], flags: ['--no-save'],
options: ['--to'], flags: ['--no-save', '--auto-undeploy'],
shortcuts: ['-2'],

@@ -7,3 +7,3 @@ help: `

*cds deploy* [ <model> ] [ --to <database> ]
*cds deploy* [ <model> ] [ <options> ]

@@ -14,2 +14,10 @@ Deploys the given model to a database. If no model is given it looks up

Supported databases: sqlite
# OPTIONS
*-2* | *--to* <database>
*--no-save*
`})

@@ -19,38 +27,51 @@

function deploy ([model], { to:url, 'no-save':no_save = cds.env.deploy.no_save }) {
async function deploy ([_model], { to:_to, 'no-save':no_save = cds.env.deploy.no_save, 'auto-undeploy': autoUndeploy = false}) { // NOSONAR
const db = cds.connect(url)
if (!model) model = db.options && db.options.model
|| cds.env.requires.db && cds.env.requires.db.model
|| ['db','srv']
if (!_to && !cds.env.requires.db) throw new Error(`
db.then(()=> db.load(model) .then (csn=> db.deploy (csn))
.then (() => require ('./etc/init-from-csv') (model))
.then (() => cds.disconnect()))
.then (url && !no_save && (() => registerDatasource(db,model)))
.catch (e => {
if (!model && e.code === 'MODEL_NOT_FOUND') {
throw new Error('Please specify a data model or configure one in package.json#cds.requires.db.model')
} else throw e
})
There's no database configured in 'cds.require.db'.
Please do so or specify one, e.g.:
cds deploy --to sqlite:db/my.db
`)
let url = _to
const [,_kind,_database] = /(\w+)?(?::(.*))?/.exec(url||'')
const conf = cds.env.requires.db || {}
const kind = _kind || conf.kind
const model = _model || conf.model || ['db','srv']
const database = _database || conf.credentials && conf.credentials.database
if (!url && kind && database) url = kind + ':' + database // reconstruct URL out of config
try {
if (kind === 'hana') {
const deployHana = require('../lib/deploy/hana');
await deployHana(model, null, null, null, { autoUndeploy });
} else {
const db = await cds.deploy(model) .to (url || kind)
db.disconnect() // REVISIT: we should NOT require to explicitly disconnect
if (_to && !no_save) await registerDatasource (kind,model,database)
console.log (`/> successfully deployed database to ./${database || (kind+'.db')}`)
}
} catch (e) {
if (!model && e.code === 'MODEL_NOT_FOUND') {
throw new Error('Please specify a data model or configure one in package.json#cds.requires.db.model')
} else throw e
}
}
function registerDatasource ({options}, model) { try {
function registerDatasource (kind,model,database) { try {
const package_json = require('path') .resolve ('package.json')
const pj = require (package_json)
if (pj.cds && pj.requires && pj.requires.db) return
const conf = (pj.cds || (pj.cds={})) .requires || (pj.cds.requires = {})
cds.env.requires.db = conf.db = {
kind: options.kind,
model: model,
credentials: options.credentials,
}
const conf = require (package_json)
const requires = ['cds','requires'] .reduce ((p,n)=>p[n] || (p[n]={}), conf)
cds.env.requires.db = requires.db = { kind, model }
if (database) requires.db.credentials = {database}
const write = require('util').promisify (require('fs').writeFile)
write (package_json, JSON.stringify(pj,null,' ')).then (()=>
console.log (' - updated package.json')
return write (package_json, JSON.stringify(conf,null,' ')).then (()=>
console.log (' > updated package.json')
)
} catch(e){/* ignore */}}
/* eslint no-console: off */
/* eslint no-console: off */
module.exports = Object.assign(extend, {
options: ['--username', '--tenant'],
shortcuts: ['-u', '-t'],
options: ['--username', '--directory', '--subdomain', '--passcode'],
shortcuts: ['-u', '-d', '-s', '-p'],
help: `
# SYNOPSIS
*cds extend* [ <model> ]
*cds extend* [ <url> ]

@@ -14,10 +14,18 @@ Create an extension project from url [url]

*-u* | *--username* <name>
*-d* | *--directory* <directory>
The target directory.
The username for authentication.
*-s* | *--subdomain* <subdomain>
The subdomain to extend.
*-t* | *--tenant* <tenant>
*-p* | *--passcode* <passcode>
Override the tenant to extend (Otherwise taken from JWT token).
The passcode for authentication
*-u* | *--username* <name>
Deprecated. Use passcode parameter instead.
`})

@@ -27,2 +35,3 @@

async function extend ([url], options = {}) {
try {

@@ -32,13 +41,10 @@ const client = require('@sap/cds-sidecar-client')

if (!url) {
url = await askQuestion('Extension Url: ')
url = await askQuestion('Extension Url: ');
}
if (!options.username) {
options.username = await askQuestion('Username: ')
if (options.username && !options.passcode) {
options.password = await askQuestion('Password: ', undefined, true)
}
options.password = await askQuestion('Password: ', undefined, true)
client.extend(url, options)

@@ -45,0 +51,0 @@ } catch (e) {

@@ -10,3 +10,3 @@ module.exports = Object.assign (help, {help:`

*c* | *compile* ...individual models (= the default)
*d* | *deploy* ...data models to a database
*d* | *deploy* ...data models to a database (sqlite)
*s* | *serve* ...service models to REST clients

@@ -13,0 +13,0 @@ *b* | *build* ...whole modules or projects

@@ -53,2 +53,3 @@ module.exports = Object.assign (repl, { options: [], help: `

.replace(/{ (xpr|ref|val): /g, '{$1:')
.replace(/\[Object: null prototype\] /g, '')
}

@@ -55,0 +56,0 @@

@@ -34,4 +34,4 @@ module.exports = Object.assign ( serve, {

})
cds.on ('serve', ({name,path,impl})=>{
console.log (`[cds] - serving ${name} at ${path}${impl ? ' - impl: ' + _local(impl._source) : ''}`)
cds.on ('serve', ({name,path,_impl})=>{
console.log (`[cds] - serving ${name} at ${path}${_impl ? ' - impl: ' + _local(_impl._source || '<unknown source>') : ''}`)
})

@@ -43,2 +43,2 @@ cds.on ('served', ({_sources})=>{

const _local = (filename) => relative('', filename)
/* eslint no-console:off */
/* eslint no-console:off */

@@ -9,2 +9,56 @@ # Change Log

## Version 3.13.0 - 2019-06-26
### Added
- `cds serve` now provides a preview of the services in a list page of SAP Fiori Elements
### Changed
- `cds serve` now yields an error if there are no services defined in the model
### Also see
- Changes of `@sap/cds-compiler` 1.15.0
- Changes of `@sap/cds-ql` 1.14.0
- Changes of `@sap/cds-services` 1.14.0
- Changes of `@sap/generator-cds` 2.4.11
## Version 3.12.0 - 2019-06-17
### Added
- On request, `cds build/all` now generates OData EDMX files for node.js services
- Performance optimizations for `cds build/all`
### Fixed
- `cds deploy` no longer fails if `data` dir is not present
- `cds build/all` no longer prints a message if `mta.yaml` does not exist
### Also see
- Changes of `@sap/cds-compiler` 1.14.1
- Changes of `@sap/cds-ql` 1.13.0
- Changes of `@sap/cds-services` 1.13.0
## Version 3.11.1 - 2019-06-03
### Fixed
- `cds deploy` honors saved datasource configuration again
- localization works again for sqlite datasources defined in `package.json`
## Version 3.11.0 - 2019-06-03
### Added
- `cds deploy` now also finds `.csv` files in imported reuse packages
- Better error messages for various `cds` CLI calls
### Changed
- `cds build/all` for Node.js projects generates proper CSN in `gen/csn.json`.
A warning is emitted if `cds serve` is run with the previous format. Rebuild the project if you see this warning.
### Also see
- Changes of `@sap/cds-compiler` 1.14.0
- Changes of `@sap/cds-ql` 1.12.0
- Changes of `@sap/cds-services` 1.12.0
- Changes of `@sap/generator-cds` 2.4.10
## Version 3.10.0 - 2019-05-21

@@ -11,0 +65,0 @@

@@ -1,2 +0,2 @@

const DEBUG = process.env.DEBUG_COMPILE && console.warn // eslint-disable-line
const DEBUG = /\b(y|all|alpha|_localized)\b/.test (process.env.DEBUG) && console.warn // eslint-disable-line
const cds = require('../cds')

@@ -32,3 +32,3 @@ const _4sqlite = ['de','fr']

for (let each of _4sqlite)
srv.model.definitions [`localized.${each}.${d.name}`] = d
srv.model.definitions [`localized.${each}.${d.name}`] = Object.assign({name: `localized.${each}.${d.name}`}, d)
}

@@ -49,3 +49,2 @@

_add_placebos4 (srv,each) // only required until the cds compiler gives us the correct views for exposed entities
srv.before ('READ', each, _read_from_localized_entity)
}

@@ -56,16 +55,2 @@ }

// Redirect incoming read requests to localized. views unless in Fiori draft
function _read_from_localized_entity (req) {
if (!req._is_in_fiori_draft) { // TODO: how to correctly detect draft mode
const {SELECT} = req.query, entity = req.target.name
SELECT.from.ref[0] = `localized.${entity}`
if (_4sqlite) { // experimental variant for sqlite
const locale = req.user.locale
if (_4sqlite.includes(locale)) SELECT.from.ref[0] = `localized.${locale}.${entity}`
}
}
}
///////////////////////////////////////////////////////////

@@ -72,0 +57,0 @@ // cds.connect part

@@ -1,19 +0,20 @@

const OUTPUT_MODE_DEFAULT = 'default'
exports.OUTPUT_MODE_DEFAULT = OUTPUT_MODE_DEFAULT
const OUTPUT_MODE_PREVIEW = 'preview'
exports.OUTPUT_MODE_PREVIEW = OUTPUT_MODE_PREVIEW
const OUTPUT_MODE_RESULT = 'result'
exports.OUTPUT_MODE_RESULT = OUTPUT_MODE_RESULT
exports.BUILD_OPTION_OUTPUT_MODE = "outputMode"
// use "/" for cds config entries and not path.sep which is platform specific
const CDS_CONFIG_PATH_SEP = '/'
exports.CDS_CONFIG_PATH_SEP = CDS_CONFIG_PATH_SEP
exports.OUTPUT_MODE_DEFAULT = "default"
exports.OUTPUT_MODE_PREVIEW = "preview"
exports.OUTPUT_MODE_RESULT_ONLY = "resultOnly"
const BUILD_TASK_JAVA = "java-cf"
exports.BUILD_TASK_JAVA = BUILD_TASK_JAVA
const BUILD_TASK_NODE = "node-cf"
exports.BUILD_TASK_NODE = BUILD_TASK_NODE
const BUILD_TASK_HANA = "hana"
exports.BUILD_TASK_HANA = BUILD_TASK_HANA
const BUILD_TASK_FIORI = "fiori"
exports.BUILD_TASK_FIORI = BUILD_TASK_FIORI
exports.BUILD_TASK_JAVA = "java-cf"
exports.BUILD_TASK_NODE = "node-cf"
exports.BUILD_TASK_HANA = "hana"
exports.BUILD_TASK_FIORI = "fiori"
exports.BUILD_TASK_MTX = "mtx"
exports.ODATA_VERSION = "odata.version"
exports.ODATA_VERSION_V2 = "v2"
exports.ODATA_VERSION_V4 = "v4"
exports.BUILD_MODE_INPLACE = "inplace"
exports.BUILD_NODEJS_EDMX_GENERAION = "build.nodejs.edmxgeneration"
exports.CDS_CONFIG_PATH_SEP = "/"

@@ -1,3 +0,3 @@

const BuildTaskEngine = require('../../bin/build/buildTaskEngine');
const BuildTaskFactory = require('../../bin/build/buildTaskFactory');
const BuildTaskEngine = require('./buildTaskEngine');
const BuildTaskFactory = require('./buildTaskFactory');

@@ -4,0 +4,0 @@ module.exports = {

@@ -15,2 +15,3 @@ const core = require ('@sap/cds-reflect'), $=require; require = (id)=> lazy=> $(id) // eslint-disable-line

connect: require ('./runtime/connect'),
deploy: require ('./runtime/deploy'),
service: require ('./runtime/service'),

@@ -21,2 +22,4 @@ serve: require ('./runtime/serve'),

deployHana: require ('./deploy/hana'),
// Multitenancy and Extensibility

@@ -23,0 +26,0 @@ mtx: require('./mtx'),

@@ -50,9 +50,2 @@ const cds = require('../cds'), cdsv = _emitting ( cds._compiler )

// keep _locations as hidden properties
const defs = csn.definitions; for (let each in defs) {
const d = defs[each], loc = xsn.definitions[each].location
Object.defineProperty (d, '_location', {value:loc})
if (!d['@source'] && d.kind === 'service') d['@source'] = loc.filename //> enumerable
}
// cache _csn to _xsn only in normalized models, i.e. not the flattened OData csn

@@ -59,0 +52,0 @@ if (!_csn) Object.defineProperty (xsn, '_csn', {value:csn, configurable:1, writable:1 })

@@ -6,5 +6,5 @@ const cdsv = require('./cdsv')

// alpha fixes for gaps
const {unfold:_unfold_compositions} = require ('../alpha/_unfold_compositions')
const {unfold:_unfold_localized} = require ('../alpha/_localized')
// const {unfold:_unfold_temporal} = require ('../alpha/_temporal')
const DEBUG = process.env.DEBUG_COMPILE && console.warn
const _skip_unused = require ('../alpha/_skip_unused')

@@ -37,9 +37,9 @@ const compile = (csn) => ({

json: x => JSON.stringify(x,null,2),
edmx: (csn,o) => _2edm (csn,o, {off: 'metadata', only: 'annotations'}[o && o.annos]),
edm: (csn,o) => _2edm (csn,o, 'metadata_json'),
edmx: (csn,o) => _2edm (_unfold_compositions(csn),o, {off: 'metadata', only: 'annotations'}[o && o.annos]),
edm: (csn,o) => _2edm (_unfold_compositions(csn),o, 'metadata_json'),
annos: (csn,o) => _2edm (csn,o, 'annotations'),
swgr: (csn,o) => _2many (cdsv.toSwagger(csn,o).services, '.swgr.json'),
cdl: (csn,o) => _2many (cdsv.toCdl(csn,o),'.cds'),
sql: (csn,o) => _2sql (_unfold_localized (_sql (cdsv.toSql (_skipUnused(csn),o)), csn, o), o),
hana: (csn,o) => _2many (cdsv.toHana(_skipUnused(csn),o).hdbcds, '.hdbcds'),
sql: (csn,o) => _2sql (_unfold_localized (_sql (cdsv.toSql (_skip_unused(csn),o)), csn, o), o),
hana: (csn,o) => _2many (cdsv.toHana(_skip_unused(csn),o).hdbcds, '.hdbcds'),
xsuaa: (csn,o) => require('./xsuaa').xsuaaConfig (csn,o)

@@ -49,49 +49,2 @@ }

/** Skip unused entities marked with @cds.persistence.skip:'if-unused' */
function _skipUnused (csn) { // NOSONAR
const m = cds.linked (csn)
const services = RegExp (Object.keys (m.services).map(n => '^'+n+'\\.').join('|'))
const localized_ = /^localized\./
// for each entity e1 marked with @cds.persistence.skip:'if-unused'...
m.foreach (e => !e.abstract && e['@cds.persistence.skip']=='if-unused', e1 => { // NOSONAR
if (localized_.test(e1.name)) return
if (services.test(e1.name)) return
// fetch other entities e2 that contain references to e1 ...
for (let e2 of m.each(cds.entity)) {
if (e2 === e1) continue
if (localized_.test(e2.name)) continue // ignore ref from derived entities
// is e2 a view on e1?
const q = e2.query; if (q && q.target === e1) { // found reference
return DEBUG && DEBUG (`NOT skipping ${e1.name} due to view ${e2.name}`)
}
const x = e2.includes; if (x && x.includes (e1.name)) { // found reference
return DEBUG && DEBUG (`NOT skipping ${e1.name} due to ${e2.name}`)
}
// does e2 contain Associations to e1?
for (let e in e2.elements) {
let a = e2.elements[e]
if (a._target === e1) { // found reference
return DEBUG && DEBUG (`NOT skipping ${e1.name} due to ${e2.name}[${a.name}]`)
}
}
}
// skip e1 if no fererences have been found
skip (e1.name)
})
function skip (entry) {
if (csn.definitions [entry]) {
DEBUG && DEBUG (`Skipping ${entry}`)
delete csn.definitions [entry]
if (csn._xsn) delete csn._xsn.definitions [entry]
if (!/_texts$/.test(entry)) skip (entry+'_texts')
if (!localized_.test(entry)) skip ('localized.'+entry)
}
}
return csn
}
/** Return output of 2hana as an iterable */

@@ -98,0 +51,0 @@ function* _2many (result, suffix='.hdbcds') {

@@ -45,2 +45,10 @@ module.exports = Object.assign (load, {only:get})

if (!collectedSources || !collectedSources.sources) {
return
}
// deprecated collectedSources åformat - log warning
// TODO - delete later on which requires a cds rebuild to adopt the new csn format
console.warn(`[WARNING] - Model [${file}] has deprecated format - cds rebuild required`)
const parsed = cdsv.parse (collectedSources, options)

@@ -51,4 +59,4 @@ let srv = collectedSources.srv

for (let each in parsed.definitions) {
let d = parsed.definitions[each], src = d['@source']
if (src) d['@source'] = src.replace(srv,'')
let d = parsed.definitions[each]
if (d.kind === 'service' && d.$location) d.$location = { file: d.$location.file.replace(srv,'') }
}

@@ -68,1 +76,3 @@ }

const _local = (path) => ('' + path).replace(_cwd, '')
/* eslint no-console: off */

@@ -10,2 +10,5 @@ /** Both, a namespace and a shortcut for cds.parse.cdl */

/** @returns {object} the parsed query as a CQN object */
csv: (...args) => (parse.csv = require('../utils/csv').parse) (...args),
/** @returns {object} the parsed expression as a CQN expr object */

@@ -12,0 +15,0 @@ expr: (...args) => (parse.expr = require('./cdsv').parseExpr) (...args),

@@ -12,3 +12,3 @@ const cds = require('../cds')

function xsuaaConfig (model, options) {
function xsuaaConfig(model, options) {
const base = getBaseModel(options)

@@ -20,24 +20,8 @@ const generated = generateConfig(model)

function generateConfig(model) {
const roleTemplates = {}
const scopes = {}
const attributes = {}
const updateRoleTemplate = (scope, attributes=[]) => {
if (roleTemplates[scope]) {
attributes.forEach(a => {
if (!roleTemplates[scope]['attribute-references'].includes(a)) {
roleTemplates[scope]['attribute-references'].push(a)
}
})
} else {
roleTemplates[scope] = {
name: scope,
description: 'generated',
'scope-references': ['$XSAPPNAME.' + scope],
'attribute-references': attributes
}
}
}
const findUserAttrInExpression = (expr, attributes=[]) => {
const findUserAttrInExpression = (expr, attributes = []) => {
if (Array.isArray(expr)) { // descend arrays

@@ -48,5 +32,5 @@ expr.forEach(e => findUserAttrInExpression(e, attributes))

const userIdx = expr.ref.indexOf('$user')
if (userIdx >= 0 && userIdx < expr.ref.length-1) {
if (userIdx >= 0 && userIdx < expr.ref.length - 1) {
const attr = expr.ref[userIdx + 1]
if (!hardcoded.Attributes.includes(attr)) attributes.push(attr)
if (!hardcoded.Attributes.includes(attr)) attributes.push(attr)
}

@@ -58,3 +42,3 @@ }

const parseAttributes = (condition) => { // e.g. 'foo = $user.bar or baz = $user.boo'
if (!condition) return []
if (!condition) return []

@@ -75,3 +59,2 @@ try {

scopes[scope] = scope
updateRoleTemplate(scope)
}

@@ -86,3 +69,2 @@

scopes[scope] = scope
updateRoleTemplate(scope, lattributes)
}

@@ -93,2 +75,19 @@ lattributes.forEach(attr => attributes[attr] = true)

})
var roleTemplates = Object.keys(scopes).map((s) => {
return {
name: s,
description: 'generated',
'scope-references': ['$XSAPPNAME.' + s],
'attribute-references': []
}
});
if (Object.keys(attributes).length !== 0) {
roleTemplates.push({
name: 'userattributes',
description: 'generated',
'default-role-name': 'Attributes of a User',
'scope-references': [],
'attribute-references': Object.keys(attributes)
})
}

@@ -106,6 +105,7 @@ return {

description: a,
valueType: 's'
valueType: 's',
valueRequired: false
}
}),
'role-templates': Object.values(roleTemplates)
'role-templates': roleTemplates
}

@@ -120,8 +120,8 @@ }

const mergeByName = (type) => {
if (!generated[type]) return
if (!generated[type]) return
if (!result[type]) result[type] = []
if (!result[type]) result[type] = []
result[type] = result[type].concat(generated[type].filter((g) => {
if (!base[type].find) throw new Error(`Array expected for '${type}', but was: ${JSON.stringify(base)}`)
return !(base[type].find((b) => b.name === g.name ))
if (!base[type].find) throw new Error(`Array expected for '${type}', but was: ${JSON.stringify(base)}`)
return !(base[type].find((b) => b.name === g.name))
}))

@@ -136,3 +136,3 @@ }

function getBaseModel(options={}) {
function getBaseModel(options = {}) {
if (typeof options.base === 'string') {

@@ -155,3 +155,3 @@ try {

try {
name = require (path.resolve ('package.json')).name
name = require(path.resolve('package.json')).name
} catch (err) { // no package.json

@@ -158,0 +158,0 @@ name = path.basename(process.cwd())

@@ -75,3 +75,6 @@ const cds = require('../cds')

const conf = configured [datasource]
if (!conf) _error (`didn't find a configuration for 'cds.requires.${datasource}'`)
if (!conf) {
if (datasource === 'sqlite') return [ undefined, {kind:'sqlite'}, primary ]
_error (`didn't find a configuration for 'cds.requires.${datasource}'`)
}
if (!conf.kind && !conf.driver) _error (`configuration for 'cds.requires.${datasource}' lacks mandatory property 'kind'`)

@@ -110,3 +113,3 @@ }

})
for (let p of [ 'transaction', 'run', 'stream', 'foreach', 'read', 'insert', 'update', 'delete', 'acquire', 'release', 'disconnect', 'deploy' ]) {
for (let p of [ 'transaction', 'run', 'stream', 'foreach', 'read', 'insert', 'update', 'delete', 'acquire', 'release', 'disconnect' ]) {
Object.defineProperty (cds, p, {configurable: true, value: (...a) => ds[p](...a)})

@@ -121,6 +124,6 @@ }

const _disconnect = client.disconnect
client.disconnect = ()=>{
if (client === cds.session) cds.session = undefined
client.disconnect = param => {
if (!param && client === cds.session) cds.session = undefined
delete cached [datasource]
return _disconnect.call (client)
return _disconnect.call (client, param)
}

@@ -127,0 +130,0 @@ }

const cds = require ('../cds'), lib = require ('@sap/cds-ql'); lib.inject (cds)
const knownKinds = {sqlite:1}
const ql = module.exports = $$(lib.statements, {
connect: lib.connect.connect //> goes to ./connect.js
connect: (datasource, options, primary)=>{
if (!options) options = cds.env.requires[datasource]
if (options && options.kind in knownKinds && !options.credentials) options.credentials = {database: options.kind+'.db'}
return lib.connect.connect (datasource, options, primary) //> goes to ./connect.js
}
})

@@ -26,7 +31,7 @@ if (cds.env.features.localized) {

ENABLE (
_ANY_isQuery,
_SELECT_from_valueOf, _SELECT_distinct, // _SELECT_from_with_key,
_INSERT_into_valueOf, _INSERT_entry_into,
_UPDATE_entity_valueOf, _UPDATE_set_fluent, _UPDATE_with, //_UPDATE_with_key,
_DELETE_from_valueOf,
_ANY_isQuery,
_SELECT_from_valueOf, _SELECT_distinct, // _SELECT_from_with_key,
_INSERT_into_valueOf, _INSERT_entry_into,
_UPDATE_entity_valueOf, _UPDATE_set_fluent, _UPDATE_with, //_UPDATE_with_key,
_DELETE_from_valueOf,
)

@@ -181,3 +186,2 @@ DISABLED (

// Add support for UPDATE('Foo') + '... plain sql tail...'

@@ -184,0 +188,0 @@ function _UPDATE_entity_valueOf(){

@@ -1,12 +0,2 @@

/*USAGE:*/()=>{
const app = require('express')()
cds.serve('all').in(app) //> no subsequent .at() or .with() possible
cds.serve('CatalogService').from('all').in(app).at('/mount-point').with(function(){
const { Books } = this.entities
this.on('READ', Books, (req) => req.reply([]))
})
}
module.exports = cds_serve
const cds = require('../cds')
const service = require ('./service')

@@ -30,28 +20,19 @@ const isIdentifier = (x) => typeof x === 'string' && /^[A-Za-z_$][\w$]*$/.test (x)

*/
function cds_serve (service_or_model, givenOptions={}) { // NOSONAR
const options = Object.assign({}, givenOptions)
function cds_serve (service_or_model, _options) { // NOSONAR
if (!isIdentifier(service_or_model)) {
return cds_serve('all',options).from(service_or_model)
return cds_serve('all',_options).from(service_or_model)
}
const cds = this.serve === cds_serve ? this : global.cds
const ready = Promise.resolve().then (_loadModel) .then (_constructProviders)
const providers=[] //> filled in _constructProviders
const ready = Promise.resolve().then (_loadModel) .then (_constructProviders)
const fluent = _fluent (options)
return fluent
/**
* Fluent API used to fill in options subsequently
*/
function _fluent (o=options) {
return {
from (model) { o.service = service_or_model; o.model = model; return this },
to (protocol) { if (protocol) { o.to = protocol } return this },
at (path) { if (path) { o.at = path } return this },
with (impl) { if (impl) { o.with = impl } return this },
in (app) { ready.then (()=>_addProviders2(app)); return this },
then (r,e) { return ready.then (()=> r(_returnProviders()), e) },
catch (e) { return ready.catch(e) },
}
const o = Object.assign({}, _options); return { // fluent API to fill in options subsequently
from (model) { o.service = service_or_model; o.model = model; return this },
to (protocol) { if (protocol) { o.to = protocol } return this },
at (path) { if (path) { o.at = path } return this },
with (impl) { if (impl) { o.with = impl } return this },
in (app) { ready.then (()=>_addProviders2(app)); return this },
then (r,e) { return ready.then (()=> r(_returnProviders()), e) },
catch (e) { return ready.catch(e) },
}

@@ -63,10 +44,23 @@

function _loadModel(){
let model = options.model
if (typeof model === 'object' && !Array.isArray(model)) return model //> already a csn
//> cds.serve(...).from('app')
let model = o.model
//> cds.serve(...).from(csn)
if (typeof model === 'object' && !Array.isArray(model)) return model
//> cds.serve(...)
if (!model) {
if (options.service) model = service_or_model //> compat to cds.serve('all',{service})
else { options.service = service_or_model; model = 'all' }
//> cds.serve(..., {service}) ==> cds.serve(service) .from (...)
//> Note: this is for compatibility only; it's not documented anymore
if (o.service) model = service_or_model
//> cds.serve('all') ==> cds.serve('all').from('all')
//> cds.serve(service) ==> cds.serve(service).from('all')
else { model = 'all'; o.service = service_or_model }
}
if (model === 'all' || model[0] === 'all') {
model = [ cds.env.folders.app, cds.env.folders.srv, 'services', '.' ].find (m => cds.resolve(m))
const {app,srv} = cds.env.folders
model = [ app, srv, 'services', '.' ].find (m => cds.resolve(m))
if (!model) throw new Error (`[cds] - \n

@@ -77,6 +71,8 @@ No service models found in current working directory.

}
const key = Array.isArray(model) ? model.join(';') : model
const cached = cache[key]
if (cached) return cached
else return cache[key] = cds.load (model)
return cache[key] = cds.load (model)
}

@@ -89,3 +85,3 @@

const o=options, external = cds.env.requires
const external = cds.env.requires
const chosen = o.service && o.service !== 'all' ? def => def.name.endsWith (o.service) : ()=>true

@@ -97,10 +93,11 @@ o.passport = o.passport || (cds.env.auth && cds.env.auth.passport)

const name = def.name
if (def['@cds.ignore'] || !chosen(def) || external[name]) return
if (def['@cds.serve.ignore'] || !chosen(def) || external[name]) return
if ((o.at || o.with) && ++n > 1) throw new Error('You cannot specify `path` or `impl` for multiple services')
const serviceOptions = {...o, at: service.path4 (def, o.at) }
const provider = service.for (csn, {service: name, __proto__: serviceOptions})
provider.path = serviceOptions.at
provider.impl = service.impl4 (def, o.with)
const options = {...o, at: service.path4 (def, o.at) }
const provider = _asEventEmitter ( //> pull down
service.for (csn, {service: name, __proto__: options})
)
provider.path = options.at
providers.push (provider)
// cds.services [name] = provider
cds.services [name] = provider
//> only possible when ServiceProvider == ServiceClient

@@ -112,5 +109,7 @@ Object.defineProperty (cds.services, name, { configurable:1,

})
if (providers.length === 0) throw new Error (`No service models found in ${csn._sources}`)
// invoke all service impl functions --> in a pass 2 to allow them connect to local services
_addImpls()
return providers

@@ -126,7 +125,7 @@ }

service.performanceMeasurement(app)
service.passport(each, app, each._auditLogger, options)
service.passport(each, app, each._auditLogger, o)
// add use method to services for backward compatibility
each.use = app.use
app.use (each.path+'/webapp/*', (_,res)=> res.status(400).send()) // REVISIT: this is to avoid ugly warnings by Fiori requests --> should go into Fiori protocol adapter
app.use (each.path, ProtocolAdapter.for (each, options.to))
app.use (each.path, ProtocolAdapter.for (each, o.to))
cds.emit ('serve', each)

@@ -142,16 +141,4 @@ }

for (let each of providers) {
let impl = each.impl
if (typeof impl === 'object') impl = each.impl = impl [each.name]
if (typeof impl !== 'function') continue;
if (/^class\s/.test(Function.prototype.toString.call(impl))) {
const clazz = impl; impl = each.impl = (srv)=>{ // NOSONAR
const inst = new clazz (srv)
for (let e of Reflect.ownKeys (clazz.prototype)) {
if (e in {constructor:1, prototype:1}) continue
srv.on (e, (...args) => inst[e](...args))
}
}
}
each.with (impl)
// each.impl (each)
let impl = each._impl = service.impl4 (each.definition, o.with)
each.impl (impl)
}

@@ -164,18 +151,44 @@ }

function _returnProviders() {
let all={}, fn='none'
let all={}, srv='none'
for (let each of providers) {
const handler = ProtocolAdapter.for (each, options.to)
fn = all[each.name] = (...args) => handler(...args)
// returned objects are handlers + instances to support code like this:
// const { CatalogService } = cds.serve(...)
// app.use ('/cats', CatalogService)
Object.setPrototypeOf (fn, each)
Object.defineProperty (fn, 'name', {value:each.name})
srv = all[each.name] = _asHandlerFunction (each)
}
if (providers.length === 1 && fn.name === options.service) { // NOSONAR
if (!(fn.name in fn)) Object.assign (fn,all) // NOSONAR
return fn
if (providers.length === 1 && srv.name === o.service) { // NOSONAR
if (!(srv.name in srv)) Object.assign (srv,all) // NOSONAR
return srv
}
else return all
}
/**
* Decorates services as handler functions to delegate requests to the default protocol adapter.
* This supports usages like this:
* @example
* const { CatalogService } = cds.serve(...)
* app.use ('/cats', CatalogService)
*/
function _asHandlerFunction (srv) {
const adapter = ProtocolAdapter.for (srv, o.to)
const fn = (...args) => adapter(...args)
Object.setPrototypeOf (fn, srv)
Object.defineProperty (fn, 'name', {value:srv.name})
return fn
}
/**
* Adds an .emit() function to services, which dispatches events to registered '.on' handlers.
* This supports usages like this:
* @example
* const { CatalogService } = cds.serve(...)
* CatalogService.on ('some-event', msg => console.log(msg))
* CatalogService.emit ('some-event', {some:'data'})
*/
function _asEventEmitter (srv) {
srv.emit = (event, data) => {
const subscription = srv._handlers.on._handlers.find (h => h.event === srv.name+'.'+event)
if (subscription) return subscription.handler ({event, data})
}
return srv
}
}

@@ -20,3 +20,3 @@ const cds = require ('../cds')

if (cds.env.features.localized && cds.options && cds.options.kind === 'sqlite') {
if (cds.env.features.localized && ((cds.options && cds.options.kind === 'sqlite') || (cds.env.requires && cds.env.requires.db && cds.env.requires.db.kind === 'sqlite'))) {
const _for = exports.for

@@ -39,19 +39,21 @@ const {serve} = require('../alpha/_localized')

*/
exports.impl4 = function (def, _impl = def['@impl']) {
const _source = def['@source'] || def._location && def._location.filename
exports.impl4 = function (def, _impl = def['@impl']) { // NOSONAR
const _source = def.$location && def.$location.file || /*legacy:*/ def['@source']
const dir = _source && isdir(dirname(_source)) ? dirname(_source) : process.cwd()
if (typeof _impl === 'function') return found (_impl)
if (_impl) return load (_impl, true)
if (typeof _impl === 'function') return _found (_impl)
if (_impl) return _load (_impl, true)
if (_source) {
const impl = parse(_source).name + '.js'
return load(impl) || load('js/'+impl) || load('handlers/'+impl)
return _load(impl) || _load('js/'+impl) || _load('handlers/'+impl)
}
function found (impl, _source = impl.name || '<inline>') {
function _found (impl, _source = impl.name || '<inline>') {
return Object.defineProperty (impl, '_source', {value:_source})
}
function load (file, fail=false) {
function _load (file, fail=false) {
const resolved = resolve(dir,file)
if (fs.isfile (resolved)) return found (require (resolved), file)
if (fs.isfile (resolved)) return _found (require (resolved), file)
else if (fail) throw new Error(`No such handler for ${def.name}: ${resolved}`)

@@ -58,0 +60,0 @@ }

@@ -34,3 +34,3 @@ module.exports = {

provisioning: true,
metadata: false
metadata: true
},

@@ -37,0 +37,0 @@ domain: '__default__'

const path = require ('path'), { dirname, join } = path
const fs = require ('fs')
const fs = require('fs')
const rw = fs.constants.R_OK | fs.constants.W_OK
module.exports = {__proto__:fs,
const utils = module.exports = Object.assign ({
path, mkdirp, rimraf, rimrafSync, isdir, isfile, find, copy,
get write(){
}, fs)
Object.defineProperty (utils, 'write', {
get: ()=>{
const write = require('./write')
Object.defineProperty (this,'write',{value:write})
Object.defineProperty (utils,'write',{value:write})
return write
}
}
})
if (!fs.copyFile) fs.copyFile = (src, dst, callback) => {

@@ -16,0 +18,0 @@ const wr = fs.createWriteStream(dst) .on ('error',_cleanup) .on ('finish',_done)

{
"name": "@sap/cds",
"version": "3.10.0",
"version": "3.13.0",
"lockfileVersion": 1,

@@ -8,3 +8,3 @@ "requires": true,

"@babel/runtime": {
"version": "7.4.4",
"version": "7.4.5",
"requires": {

@@ -15,3 +15,3 @@ "regenerator-runtime": "^0.13.2"

"@sap/cds-compiler": {
"version": "1.13.4",
"version": "1.15.0",
"requires": {

@@ -24,14 +24,14 @@ "antlr4": "4.7.1",

"@sap/cds-hana": {
"version": "1.11.1",
"version": "1.13.0",
"requires": {
"@sap/cds-sql": "1.11.1"
"@sap/cds-sql": "1.13.0"
}
},
"@sap/cds-ql": {
"version": "1.11.1",
"version": "1.14.0",
"requires": {
"@sap/cds-hana": "1.11.1",
"@sap/cds-sql": "1.11.1",
"@sap/cds-sqlite": "1.11.1",
"generic-pool": "3.4.2",
"@sap/cds-hana": "1.13.0",
"@sap/cds-sql": "1.13.0",
"@sap/cds-sqlite": "1.13.0",
"generic-pool": "3.7.1",
"uuid": "3.3.2"

@@ -44,19 +44,19 @@ }

"@sap/cds-services": {
"version": "1.11.1",
"version": "1.14.0",
"requires": {
"@sap/cds-ql": "1.11.1",
"@sap/odata-server": "1.3.3"
"@sap/cds-ql": "1.14.0",
"@sap/odata-server": "1.3.4"
}
},
"@sap/cds-sql": {
"version": "1.11.1"
"version": "1.13.0"
},
"@sap/cds-sqlite": {
"version": "1.11.1",
"version": "1.13.0",
"requires": {
"@sap/cds-sql": "1.11.1"
"@sap/cds-sql": "1.13.0"
}
},
"@sap/generator-cds": {
"version": "2.4.8",
"version": "2.4.11",
"requires": {

@@ -66,12 +66,7 @@ "fs-extra": "7.0.1",

"xml2js": "0.4.19",
"yaml": "1.2.0"
},
"dependencies": {
"yaml": {
"version": "1.2.0"
}
"yaml": "1.5.1"
}
},
"@sap/odata-commons": {
"version": "2.1.0",
"version": "2.1.1",
"requires": {

@@ -82,5 +77,5 @@ "big.js": "=5.2.2"

"@sap/odata-server": {
"version": "1.3.3",
"version": "1.3.4",
"requires": {
"@sap/odata-commons": "^2.1.0",
"@sap/odata-commons": "^2.1.1",
"xmlbuilder": "=10.1.0"

@@ -104,3 +99,3 @@ }

"generic-pool": {
"version": "3.4.2"
"version": "3.7.1"
},

@@ -107,0 +102,0 @@ "graceful-fs": {

@@ -1,1 +0,1 @@

{"bin":{"cds":"bin/cds.js"},"bundleDependencies":false,"dependencies":{"@sap/cds-compiler":"1.13.4","@sap/cds-ql":"1.11.1","@sap/cds-reflect":"2.5.0","@sap/cds-services":"1.11.1","@sap/generator-cds":"2.4.8","fs-extra":"7.0.1","yaml":"1.5.1"},"deprecated":false,"description":"Entry Point and API Facade for CDS","engines":{"node":">=8.9"},"eslintConfig":{"extends":"eslint:recommended","env":{"es6":true,"node":true},"parserOptions":{"ecmaVersion":2018},"rules":{"no-unused-vars":["warn",{"argsIgnorePattern":"lazy"}]}},"eslintIgnore":["tests/","gen/","reports/"],"main":"lib/cds.js","name":"@sap/cds","scripts":{"start":"node server.js"},"typings":"apis/cds.d.ts","version":"3.10.0","license":"SEE LICENSE IN developer-license-3.1.txt"}
{"bin":{"cds":"bin/cds.js"},"bundleDependencies":false,"dependencies":{"@sap/cds-compiler":"1.15.0","@sap/cds-ql":"1.14.0","@sap/cds-reflect":"2.5.0","@sap/cds-services":"1.14.0","@sap/generator-cds":"2.4.11","fs-extra":"7.0.1","yaml":"1.5.1"},"deprecated":false,"description":"Entry Point and API Facade for CDS","engines":{"node":">=8.9"},"eslintConfig":{"extends":"eslint:recommended","env":{"es6":true,"node":true},"parserOptions":{"ecmaVersion":2018},"rules":{"no-unused-vars":["warn",{"argsIgnorePattern":"lazy"}]}},"eslintIgnore":["tests/","gen/","reports/","node_modules/"],"main":"lib/cds.js","name":"@sap/cds","scripts":{"start":"node server.js"},"typings":"apis/cds.d.ts","version":"3.13.0","license":"SEE LICENSE IN developer-license-3.1.txt"}
const express = require('express')
const cds = require('./lib/cds')
const fioriPreview = require ('./lib/utils/fiori-preview')

@@ -12,2 +13,3 @@ /** that's our pretty standard express server.js setup... */

app.get ('/', (_,res) => res.send (index.html)) //> if none in ./app
app.get ('/\\$fiori-preview', fioriPreview.middleware)
app.use (logger)

@@ -39,4 +41,5 @@

<style>
body { margin: 44px; font-family: sans-serif }
h1 { font-weight:200 }
body { margin: 44px; font-family: Avenir Next, sans-serif }
h1 { }
.small { font-size: 10px }
</style>

@@ -48,17 +51,29 @@ </head>

${ _has_fiori_html ? `<h3><a href="/fiori.html">/fiori.html</a></h3>` : '' }
${ cds.service.providers.map (service => {
const {path,entities} = service
const exposed=[]; for (let e in entities) exposed.push (e)
return `
${ cds.service.providers.map (service => `
<h3>
<a href="${path}">${path}</a> /
<a href="${path}/$metadata">$metadata</a>
<a href="${service.path}">${service.path}</a> /
<a href="${service.path}/$metadata">$metadata</a>
</h3>
<ul>${exposed.map (e => `
<li><a href="${path}/${e}">${e}</a></li>`).join('')}
</ul>`
}) .join('')}
<ul>${_exposedEntities4(service).map (e =>`
<li>
<a href="${service.path}/${e}">${e}</a>
<a class="small" href="/$fiori-preview?${fioriPreview.buildQueryParams(service.name, e)}"
title="Fiori elements list page"> &hellip;in Fiori</a>
</li>`).join('')}
</ul>
`) .join('')}
</body>
</html>
`
function _exposedEntities4 (service) {
const exposed=[], {entities} = service
for (let e in entities) {
if (entities[e]['@cds.autoexposed'] && !entities[e]['@cds.autoexpose']) continue
if (e.endsWith('_texts')) continue
if (e.endsWith('DraftAdministrativeData')) continue
exposed.push(e)
}
return exposed
}
}}

@@ -65,0 +80,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc