Socket
Socket
Sign inDemoInstall

@sap/cds-ql

Package Overview
Dependencies
Maintainers
3
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sap/cds-ql - npm Package Compare versions

Comparing version 1.14.0 to 1.17.0

36

CHANGELOG.md

@@ -9,2 +9,38 @@ # Changelog

## Version 1.17.0 - 2019-08-21
### Added
- `options.kind` can also be an object
- Service related functions `create`, `insert`, `read`, `update` and `delete` to transaction
- Http related functions `get`, `post`, `put`, `patch` and `delete` to transaction
### Changed
- `.transaction(...).run` can be used with an array of queries
### Fixed
- Update with binary property
## Version 1.16.0 - 2019-07-23
### Changed
- Updated version of @sap/cds-sql to 1.15.0
- Updated version of @sap/cds-sqlite to 1.15.0
- Updated version of @sap/cds-hana to 1.15.0
## Version 1.15.0 - 2019-07-09
### Added
- Enhanced statements to be compatible to specification
- Support for views with parameters
### Removed
- `generateUUID` function and `uuid`dependency
- usage of xsenv for authorization (is provided by cds.env)
## Version 1.14.0 - 2019-06-24

@@ -11,0 +47,0 @@

126

lib/connect/options.js
const { IllegalFunctionArgumentError } = require('../errors')
const xsenv = require('./xsenv')
const runBlock = require('../statements/runBlock')
const cds = require('../cds')
const MAINKINDS = new Map([
['messaging', ['enterprise-messaging', 'file-based-messaging', 'in-process-messaging']],
// TODO: In the future there should be an intermediate layer ['db', ['sqlite', 'hana']],
['rest', ['rest', 'odata']]
])
/**

@@ -36,5 +40,13 @@ * The credentials might be configured at the package.json

return { url: url }
return { url }
}
const _getMainKind = kind => {
for (const [mainKind, kinds] of MAINKINDS) {
if (kinds.includes(kind)) {
return mainKind
}
}
return kind
}
/**

@@ -90,2 +102,18 @@ * Parse a string into options.

const _getDriverPackage = mainKind => {
switch (mainKind) {
case 'hana':
case 'sqlite':
case 'rest':
case 'messaging':
return require(`@sap/cds-${mainKind}`)
case 'odata':
return require(`@sap/cds-rest`)
case undefined:
case null:
default:
return require(mainKind)
}
}
/**

@@ -98,19 +126,34 @@ * Provided clients will have the @sap group and cds- prefix.

*/
const _getDriverPackage = kind => {
switch (kind) {
case 'hana':
case 'sqlite':
case 'rest':
return require(`@sap/cds-${kind}`)
case 'enterpriseMessaging':
return require(`@sap/cds-em`)
case undefined:
case null:
case '':
throw new IllegalFunctionArgumentError('options.kind')
default:
return require(kind)
const _getDriverPackages = kind => {
if (typeof kind === 'string') {
return _getDriverPackages({ [kind]: {} })
}
const drivers = new Map()
for (const singleKind of Object.keys(kind)) {
const mainKind = _getMainKind(singleKind)
drivers.set(mainKind, Object.assign(_getDriverPackage(mainKind), { kind: singleKind }))
}
return drivers
}
const _addConnectionOptions = options => {
const baseOptions = Object.assign({}, options)
options.connectionOptions = new Map()
if (typeof options.kind === 'string') {
options.connectionOptions.set(_getMainKind(options.kind), baseOptions)
return
}
delete baseOptions.kind
for (const _kind of Object.keys(options.kind)) {
options.connectionOptions.set(
_getMainKind(_kind),
Object.assign({}, baseOptions, options.kind[_kind], { kind: _kind })
)
}
}
/**

@@ -122,3 +165,3 @@ * In case the kind is provided as string, require and use the package

const _addClientToOptions = options => {
if (options.package) {
if (options.packages) {
return

@@ -128,19 +171,24 @@ }

if (typeof options.kind === 'function') {
options.package = { Client: options.kind }
options.packages = new Map([[options.kind.name, { Client: options.kind }]])
return
}
options.package = _getDriverPackage(options.kind)
options.packages = _getDriverPackages(options.kind)
if (options.multiTenant !== true) {
options.package.options(options)
}
for (const [mainKind, _package] of options.packages) {
if (options.multiTenant !== true) {
// TODO: Is it really options?
if (_package.options) {
_package.options(options.connectionOptions.get(mainKind))
}
}
options.package.inject(cds.cds)
_package.inject(cds.cds)
if (!options.package.Client.prototype._runBlock) {
options.package.Client.prototype._runBlock = runBlock
if (!_package.Client.prototype._runBlock) {
_package.Client.prototype._runBlock = runBlock
if (process.env.DEBUG) {
_addDebugToClient(options.package.Client)
if (process.env.DEBUG) {
_addDebugToClient(_package.Client)
}
}

@@ -163,3 +211,5 @@ }

options =
datasource || !options ? Object.assign(_parseOptionsString(datasource), options) : Object.assign({}, options)
(datasource && datasource.includes(':')) || !options
? Object.assign(_parseOptionsString(datasource), options)
: Object.assign({}, options)

@@ -175,2 +225,6 @@ if (options.credentials) {

if (!options.kind) {
throw new IllegalFunctionArgumentError('options.kind')
}
options.pool = Object.assign(

@@ -186,19 +240,7 @@ {

if (
!options.credentials ||
(options.credentials &&
!options.credentials.user &&
!options.credentials.database &&
!options.credentials.mock &&
!options.credentials.sources &&
!options.credentials.targets)
) {
xsenv(options)
}
_addConnectionOptions(options)
_addClientToOptions(options)
return options
}
module.exports = checkOptions
module.exports = { checkOptions }

@@ -13,26 +13,28 @@ const genericPool = require('generic-pool')

* @param {string} poolKey - Identifier the clients are tagged with.
* @param {Object} options - Pool and Client settings
* @param {Object} [options.pool] - The min and max pool settings.
* @param {number} [options.pool.min] - The minimum number of db connection clients.
* @param {number} [options.pool.max] - The maximum number of db connection clients.
* @param {number} [options.pool.evictionRunIntervalMillis] - The time interval in ms for an eviction check of idle db
* @param {string} Client - To be used client.
* @param {Object} connectionOptions - Pool and Client settings
* @param {Object} [connectionOptions.pool] - The min and max pool settings.
* @param {number} [connectionOptions.pool.min] - The minimum number of db connection clients.
* @param {number} [connectionOptions.pool.max] - The maximum number of db connection clients.
* @param {number} [connectionOptions.pool.evictionRunIntervalMillis] - The time interval in ms for an eviction check of idle db
* clients in a pool.
* @param {number} [options.pool.numTestsPerEvictionRun] - The number of db clients to be checked in each eviction run.
* @param {number} [options.pool.softIdleTimeoutMillis] - The time interval in ms until a db client in idle state is
* @param {number} [connectionOptions.pool.numTestsPerEvictionRun] - The number of db clients to be checked in each eviction run.
* @param {number} [connectionOptions.pool.softIdleTimeoutMillis] - The time interval in ms until a db client in idle state is
* considered as 'to be evicted'. Does not evict idle db clients if number of available clients would fall below
* options.pool.min.
* @param {number} [options.pool.idleTimeoutMillis] - The time interval in ms until a db client in idle state is
* @param {number} [connectionOptions.pool.idleTimeoutMillis] - The time interval in ms until a db client in idle state is
* considered as 'to be evicted'. If number of available clients would fall below options.pool.min it evicts this
* client and creates a new one to meet options.pool.min.
* @param {Object} options.kind - The to be used DB client.
* @param {Object} [options.credentials] - Credentials how to connect with a client
* @param {string} [options.credentials.host] - Address to the db
* @param {string} [options.credentials.port] - Port for db
* @param {string} [options.credentials.user] - Username for authentication
* @param {string} [options.credentials.password] - Password for authentication
* @param {string} [options.reflectedModel] - Reflected model, that belongs to the data source
* @param {Object} [connectionOptions.credentials] - Credentials how to connect with a client
* @param {string} [connectionOptions.credentials.host] - Address to the db
* @param {string} [connectionOptions.credentials.port] - Port for db
* @param {string} [connectionOptions.credentials.user] - Username for authentication
* @param {string} [connectionOptions.credentials.password] - Password for authentication
* @param {string} [connectionOptions.reflectedModel] - Reflected model, that belongs to the data source
*/
constructor (poolKey, options) {
constructor (poolKey, Client, connectionOptions) {
this._poolKey = poolKey
this._pool = genericPool.createPool(this._getPoolFactory(options), options.pool)
this._Client = Client
this._connectOptions = connectionOptions
this._pool = genericPool.createPool(this._getPoolFactory(connectionOptions), connectionOptions.pool)
}

@@ -49,5 +51,4 @@

create: () => {
const Client = options.package.Client
const client = new Client(options.credentials || options)
return client.connect()
const Client = this._Client
return new Client(options).connect()
},

@@ -54,0 +55,0 @@

const Pool = require('./Pool')
const Transaction = require('./Transaction')
const TenantManager = require('./TenantManager')
const _options = require('./options')
const { checkOptions } = require('./options')
const resolved = require('./resolved')
const { resolve } = require('../utils/thenable')
const cds = require('../cds')

@@ -40,4 +40,4 @@ const { IllegalFunctionArgumentError } = require('../errors')

* Default 480000 ms (8 min).
* @param {Object} options.kind - The to be used DB client.
* @param {Object} [options.model] - The to be used model.
* @param {Object|String} [options.kind] - The to be used kind(s).
* @param {Object} [options.service] - if options.model, the to be used service name.

@@ -52,61 +52,72 @@ * @param {Object} [options.credentials] - Credentials how to connect with a client

constructor (datasource, options) {
this.options = _options(datasource, options)
this.options = checkOptions(datasource, options)
this._addTenantManagers()
this._includeStaticPackageMethods()
this._init(datasource)
this._pools = new Map()
// Create cache for accessing entities
Object.defineProperties(this, { _entities: { value: {} } })
}
_addTenantManagers () {
if (this.options.multiTenant === true) {
if (this.options.package) {
this._enrichOptions = this.options.package.options
if (!this._tenantManagers) {
this._tenantManagers = new Map()
for (const [mainKind, _package] of this.options.packages) {
const TenantManager = _package.TenantManager
if (TenantManager) {
this._tenantManagers.set(mainKind, new TenantManager(this.options.connectionOptions.get(mainKind)))
}
}
}
if (!this._tenantManager) {
this._tenantManager = new TenantManager(this.options)
}
}
}
if (this.options.package) {
if (this.options.package.serviceFunctions) {
_includeStaticPackageMethods () {
for (const [, _package] of this.options.packages) {
if (_package.serviceFunctions) {
Object.defineProperties(this, {
create: { value: this.options.package.serviceFunctions.create, writable: true },
read: { value: this.options.package.serviceFunctions.read, writable: true },
update: { value: this.options.package.serviceFunctions.update, writable: true },
delete: { value: this.options.package.serviceFunctions.delete, writable: true },
insert: { value: this.options.package.serviceFunctions.insert, writable: true }
create: { value: _package.serviceFunctions.create, writable: true },
read: { value: _package.serviceFunctions.read, writable: true },
update: { value: _package.serviceFunctions.update, writable: true },
delete: { value: _package.serviceFunctions.delete, writable: true },
insert: { value: _package.serviceFunctions.insert, writable: true }
})
}
if (this.options.package.httpFunctions) {
if (_package.httpFunctions) {
Object.defineProperties(this, {
get: { value: this.options.package.httpFunctions.get, writable: true },
post: { value: this.options.package.httpFunctions.post, writable: true },
put: { value: this.options.package.httpFunctions.put, writable: true },
patch: { value: this.options.package.httpFunctions.patch, writable: true },
delete: { value: this.options.package.httpFunctions.delete, writable: true }
get: { value: _package.httpFunctions.get, writable: true },
post: { value: _package.httpFunctions.post, writable: true },
put: { value: _package.httpFunctions.put, writable: true },
patch: { value: _package.httpFunctions.patch, writable: true },
delete: { value: _package.httpFunctions.delete, writable: true }
})
}
if (this.options.package.messagingFunctions) {
if (_package.messagingFunctions) {
Object.defineProperties(this, {
on: { value: this.options.package.messagingFunctions.on, writable: true },
emit: { value: this.options.package.messagingFunctions.emit, writable: true },
removeAllListeners: { value: this.options.package.messagingFunctions.removeAllListeners, writable: true },
putQueue: { value: this.options.package.messagingFunctions.putQueue, writable: true },
deleteQueue: { value: this.options.package.messagingFunctions.deleteQueue, writable: true },
addSubscription: { value: this.options.package.messagingFunctions.addSubscription, writable: true }
removeAllListeners: { value: _package.messagingFunctions.removeAllListeners, writable: true },
putQueue: { value: _package.messagingFunctions.putQueue, writable: true },
deleteQueue: { value: _package.messagingFunctions.deleteQueue, writable: true },
addSubscription: { value: _package.messagingFunctions.addSubscription, writable: true }
})
this.on.error = this.options.package.messagingFunctions.onError.bind(this)
this.on.topic = this.options.package.messagingFunctions.onTopic.bind(this)
this.emit.to = Object.defineProperties(this, {
topic: { value: this.options.package.messagingFunctions.emitToTopic, writable: true },
queue: { value: this.options.package.messagingFunctions.emitToQueue, writable: true }
})
}
}
}
this._init()
this._pools = new Map()
// Create cache for accessing entities
Object.defineProperties(this, { _entities: { value: {} } })
_init (datasource) {
if (this.options.model && typeof this.options.model === 'object' && this.options.model.childrenOf) {
// if csn is already there, just use it
this._useReflectedModel(this.options.model)
this._addBoundMessagingFunctions(datasource)
} else {
this._loadModelAndHandleMethods(datasource)
}
}
_init () {
_loadModelAndHandleMethods (datasource) {
// 1. Save current functions

@@ -129,2 +140,7 @@ const _acquire = this.acquire

const _removeAllListeners = this.removeAllListeners
const _putQueue = this.putQueue
const _deleteQueue = this.deleteQueue
const _addSubscription = this.addSubscription
// 2. Load the model asynchronously

@@ -158,5 +174,19 @@ const done = this._loadServiceModel(this.options.model)

if (_removeAllListeners) {
this._addBoundMessagingFunctions(datasource)
this.removeAllListeners = _removeAllListeners
this.putQueue = _putQueue
this.deleteQueue = _deleteQueue
this.addSubscription = _addSubscription
}
return this
})
this._deferMainMethods(done, _create, _get, _removeAllListeners)
return done
}
_deferMainMethods (done, _create, _get, _removeAllListeners) {
// 3. Add placeholder methods to defer operations until the model is loaded

@@ -185,4 +215,49 @@ this.then = (resolve, reject) => done.then(resolve).catch(reject)

}
if (_removeAllListeners) {
this.emit = (...args) => {
done.then(() => this.emit(...args))
return this
}
this.emit.to = {
topic: (...args) => {
done.then(() => this.emit.to.topic(...args))
return this
}
}
this.on = (...args) => {
done.then(() => this.on(...args))
return this
}
this.on.topic = (...args) => {
done.then(() => this.on.topic(...args))
return this
}
this.removeAllListeners = (...args) => done.then(() => this.removeAllListeners(...args))
this.putQueue = (...args) => done.then(() => this.putQueue(...args))
this.deleteQueue = (...args) => done.then(() => this.deleteQueue(...args))
this.addSubscription = (...args) => done.then(() => this.addSubscription(...args))
}
}
_addBoundMessagingFunctions (datasource) {
let model
// This is needed since model is implemented as a getter.
// Once we get already loaded models in the future, it's not needed anymore.
try {
model = this.model
} catch (err) {}
for (const [, _package] of this.options.packages) {
if (_package.messagingFunctions) {
const boundMessagingFunctions = _package.messagingFunctions.bind.call(this, datasource, model)
Object.defineProperties(this, {
messagingOptions: { value: boundMessagingFunctions.messagingOptions, writable: true },
emit: { value: boundMessagingFunctions.emit, writable: true },
on: { value: boundMessagingFunctions.on, writable: true }
})
return
}
}
}
_loadServiceModel (model) {

@@ -192,22 +267,3 @@ if (model) {

const model = cds.linked(cds.unfold.for.odata(csn))
this.model = model
const services = this.model.all('service')
if (services.length === 1) {
this.entities = this.model.childrenOf(services[0], child => child.kind === 'entity')
} else if (this.options.service) {
this.entities = this.model.childrenOf(
services.find(srv => srv.name === this.options.service),
child => child.kind === 'entity'
)
} else {
this.entities = this.model.entities
}
if (this.options.credentials) {
this.options.credentials.reflectedModel = model
} else {
this.options.reflectedModel = model
}
this._useReflectedModel(model)
})

@@ -219,12 +275,26 @@ }

_useReflectedModel (model) {
this.model = model
const services = this.model.all('service')
if (services.length === 1) {
this.entities = this.model.childrenOf(services[0], child => child.kind === 'entity')
} else if (this.options.service) {
this.entities = this.model.childrenOf(
services.find(srv => srv.name === this.options.service),
child => child.kind === 'entity'
)
} else {
this.entities = this.model.entities
}
for (const [, connectionOption] of this.options.connectionOptions) {
if (!connectionOption.credentials) {
connectionOption.credentials = {}
}
connectionOption.credentials.reflectedModel = model
}
}
// TODO: Get model for mainKind
get model () {
// throw an error unless model is loaded
const target =
(this.options.credentials ? this.options.credentials.database : '') || this.options.url || this.options.host || ''
throw new Error(
`${this.options.model ? 'Model not yet loaded' : 'No model configured'} for service ${
this.options.kind
}: ${target}`
)
throw new Error(`${this.options.model ? 'Model not yet loaded' : 'No model configured'}`)
}

@@ -248,13 +318,23 @@

* @param {Object} [context] - Context object
* @param {string} [context.user.id] - The user name for the db connection.
* @param {string} [context.user.locale] - The language identifier.
* @param {string} [context.attr.token] - Full JWT from (HTTP) request.
* @param {string} [context.attr.identityZone] - GUID of a tenant.
* @returns {Promise.<Object>} A promise for the acquired db client.
* @param {string} [context.user.id] - The user name for the db connection
* @param {string} [context.user.locale] - The language identifier
* @param {string} [context.attr.token] - Full JWT from (HTTP) request
* @param {string} [context.attr.identityZone] - GUID of a tenant
* @param {string} [mainKind] - Kind to be acquired (for compound services)
* @returns {Promise.<Object>} A promise for the acquired db client
*/
async acquire (context = {}) {
const poolKey = this._getPoolIdentifier(context.attr)
async acquire (context = {}, mainKind = null) {
if (!mainKind) {
if (this.options.packages.size === 1) {
mainKind = this.options.packages.keys().next().value
} else {
throw new Error('You need to specify a kind to acquire a connection.')
}
}
const tenantId = this._getTenantId(context.attr)
const poolKey = `${tenantId}-${mainKind}`
// Fallback in case of first call, or pool has been invalidated
let pool = this._pools.get(poolKey) || this._createPool(poolKey)
let pool = this._pools.get(poolKey) || this._createPool(poolKey, tenantId, mainKind)

@@ -269,9 +349,3 @@ // Test connect or instance manager call is not finished yet

/**
* Get the identifier for the pool.
* @param {string} tenantId
* @returns {string}
* @private
*/
_getPoolIdentifier ({ identityZone } = {}) {
_getTenantId ({ identityZone } = {}) {
if (this.options.multiTenant) {

@@ -290,3 +364,8 @@ if (identityZone) {

// Hack if deploy is called, then no model must be loaded.
return this.options.model && this.hasOwnProperty('model') ? this.model : context[MODEL]
if (this.options.model && this.hasOwnProperty('model')) {
// Another hack, check if model is already compiled (otherwise e.g. DraftAdminData is missing)
this.model = this.model['@sql_mapping'] ? this.model : cds.linked(cds.compile.for.odata(this.model))
return this.model
}
return context[MODEL]
}

@@ -320,7 +399,8 @@

* @param {Object} [context]
* @param {string} [mainKind] - Kind to be acquired (for compound services).
* @returns {Promise} Promise, that resolves with stream if successful or rejects with error if not.
* Result object can be undefined if no rows obtained.
*/
stream (query, values, context = {}) {
return this.acquire(context).then(client => {
stream (query, values, context = {}, mainKind = null) {
return this.acquire(context, mainKind).then(client => {
return client.stream(query, values).then(result => {

@@ -334,2 +414,3 @@ return this.release(client).then(() => {

// TODO: Instead of a getter, use a function getTenantManager(mainKind) to support multiple tenantManagers
/**

@@ -340,3 +421,7 @@ * Getter for TenantManager

get tenantManager () {
return this._tenantManager
if (this._tenantManagers.size === 1) {
for (const [, tenantManager] of this._tenantManagers) {
return tenantManager
}
}
}

@@ -379,6 +464,6 @@

*/
_createPool (poolKey) {
const ready = this._getAndCheckCredentials(poolKey)
_createPool (poolKey, tenantId, mainKind) {
const ready = this._getAndCheckCredentials(tenantId, mainKind)
.then(options => {
return this._createPoolInstance(options, poolKey)
return this._createPoolInstance(poolKey, this.options.packages.get(mainKind).Client, options)
})

@@ -404,4 +489,4 @@ .catch(err => {

_createPoolInstance (options, poolKey) {
const pool = new Pool(poolKey, options)
_createPoolInstance (poolKey, Client, connectionOptions) {
const pool = new Pool(poolKey, Client, connectionOptions)
pool._name = poolKey

@@ -420,20 +505,27 @@ this._pools.set(poolKey, pool)

*/
_getAndCheckCredentials (tenantId) {
_getAndCheckCredentials (tenantId, mainKind) {
if (this.options.multiTenant) {
return this._tenantManager.get(tenantId).then(credentials => {
// Get defaults from general options; mostly pool options are relevant
const options = Object.assign({}, this.options, { kind: this.options.kind })
options.pool = Object.assign({}, options.pool)
options.credentials = Object.assign({}, options.credentials, credentials)
return this._tenantManagers
.get(mainKind)
.get(tenantId)
.then(credentials => {
// Get defaults from general options; mostly pool options are relevant
const options = Object.assign({}, this.options.connectionOptions.get(mainKind))
options.credentials = Object.assign({}, options.credentials || {}, credentials)
options.pool = Object.assign({}, options.pool)
// A client might not provide the "options" function
if (this._enrichOptions) {
this._enrichOptions(options)
}
const _package = this.options.packages.get(mainKind)
// A client might not provide the "options" function
if (_package && _package.options) {
_package.options(options)
}
return this._testConnection(options)
})
return this._testConnection(options, _package.Client)
})
}
return this._testConnection(this.options)
return this._testConnection(
this.options.connectionOptions.get(mainKind),
this.options.packages.get(mainKind).Client
)
}

@@ -443,18 +535,15 @@

* Test the credentials by doing a test connect.
* @param {Object} options
* @param {Object} connectionOptions
* @returns {Promise<Object>}
* @private
*/
_testConnection (options) {
const Client = options.package.Client
const client = new Client(options.credentials || options)
async _testConnection (connectionOptions, Client) {
if (!Client) {
return resolve(connectionOptions)
}
return client
.connect()
.then(() => {
return client.end()
})
.then(() => {
return options
})
const client = new Client(connectionOptions)
await client.connect()
await client.end()
return connectionOptions
}

@@ -550,8 +639,10 @@

* @param {Object} [context] Event context.
* @param {string} [mainKind] - Kind to be acquired (for compound services).
* @returns {Object} thenable, that resolves with result object (array) if successful or rejects with error if not.
*
*/
run (query, values, context = {}) {
run (query, values, context = {}, mainKind = null) {
const runs = []
const promise = this.acquire(context).then(client => {
const promise = this.acquire(context, mainKind).then(client => {
if (this.options.model && !client._csn) client.setCSN(this.model)
let chain = client.run(query, values)

@@ -605,6 +696,8 @@

* @param {function} cb - synchronous function to process each row of the result set.
* @param {Object} [context] Event context.
* @param {string} [mainKind] - Kind to be acquired (for compound services).
* @returns {Promise} Promise, that resolves with undefined if successful or rejects with error if not.
*/
foreach (query, values, cb) {
return this.acquire().then(client => {
foreach (query, values, cb, context = {}, mainKind = null) {
return this.acquire(context, mainKind).then(client => {
return client

@@ -624,6 +717,8 @@ .foreach(query, values, cb)

* @param {object} csn the unreflected CSN.
* @param {Object} [context] Event context.
* @param {string} [mainKind] - Kind to be acquired (for compound services).
* @returns {Promise} Promise, that resolves with undefined if successful or rejects with error if not.
*/
deploy (csn) {
return this.acquire().then(client => {
deploy (csn, context = {}, mainKind = null) {
return this.acquire(context, mainKind).then(client => {
return this._load(csn).then(csn => {

@@ -630,0 +725,0 @@ return client

@@ -18,2 +18,24 @@ // Support for legacy push down of model

this._context = context
for (const [, _package] of this._service.options.packages) {
if (_package.serviceFunctions) {
Object.defineProperties(this, {
create: { value: _package.serviceFunctions.create, writable: true },
read: { value: _package.serviceFunctions.read, writable: true },
update: { value: _package.serviceFunctions.update, writable: true },
delete: { value: _package.serviceFunctions.delete, writable: true },
insert: { value: _package.serviceFunctions.insert, writable: true }
})
}
if (_package.httpFunctions) {
Object.defineProperties(this, {
get: { value: _package.httpFunctions.get, writable: true },
post: { value: _package.httpFunctions.post, writable: true },
put: { value: _package.httpFunctions.put, writable: true },
patch: { value: _package.httpFunctions.patch, writable: true },
delete: { value: _package.httpFunctions.delete, writable: true }
})
}
}
}

@@ -45,3 +67,3 @@

this.client = this._service
.acquire(this._context)
.acquire(this._context, args[3])
.then(client => {

@@ -60,2 +82,5 @@ this.client = client

.then(() => {
if (args.length === 1 && Array.isArray(args[0])) {
return this._executedChainOfStatements(clientFn, args)
}
return this.client[clientFn](...args)

@@ -67,2 +92,10 @@ })

_executedChainOfStatements (clientFn, args) {
let chain = Promise.resolve()
for (const stmt of args[0]) {
chain = chain.then(() => this.client[clientFn](stmt))
}
return chain
}
_removeNoLongerNeededConnection () {

@@ -69,0 +102,0 @@ const dbc = this.client

@@ -7,7 +7,2 @@ const dependencies = {

},
get generateUUID () {
const uuid = require('./id-generation/uuid')
Object.defineProperty(dependencies, 'generateUUID', { value: uuid })
return uuid
},
get statements () {

@@ -14,0 +9,0 @@ const statements = require('./statements/index')

@@ -67,4 +67,8 @@ const { addToQueue } = require('./queue')

}
get _isQuery () {
return true
}
}
module.exports = BaseStatement

@@ -172,2 +172,11 @@ const BaseStatement = require('./BaseStatement')

module.exports = Insert
const insert = (...entries) => {
return {
into: entity => {
return Insert.into(entity).entries(...entries)
}
}
}
insert.into = Insert.into
module.exports = insert

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

fn.one = Select.one
fn.distinct = Select.distinct

@@ -47,2 +48,16 @@ return fn

static distinct (entity, model) {
if (!entity) {
throw new IllegalFunctionArgumentError('entity')
}
const cqn = new Select()
if (model) {
Object.defineProperty(cqn, MODEL, { value: model })
}
cqn._parseEntity(entity)
return cqn.distinct()
}
/**

@@ -61,7 +76,5 @@ * Select entries of an entity.

const cqn = new Select()
if (model) {
Object.defineProperty(cqn, MODEL, { value: model })
}
if (model) Object.defineProperty(cqn, MODEL, { value: model })
cqn._parseEntity(entity)
cqn._parseColumns(columns, entity)
cqn._parseEntity(entity)

@@ -108,2 +121,8 @@ return cqn

this._parseString(entity)
} else if (
typeof entity === 'object' &&
entity.hasOwnProperty('params') &&
Object.keys(entity.params).length !== 0
) {
this._fromViewWithParams(entity)
} else if (typeof entity === 'object' && entity.hasOwnProperty('name')) {

@@ -442,2 +461,10 @@ this._from(entity.name)

_fromViewWithParams (entity, asName) {
this.SELECT.from = { ref: [{ id: entity.name }] }
if (asName) {
this.SELECT.from.as = asName
}
}
_addColumnToOrderByAsObject (columnObject) {

@@ -625,3 +652,3 @@ this._extractKeysAndValuesFromObject(columnObject).forEach(item => {

valueOf () {
return `SELECT * FROM ${Select._quoteElement(this.SELECT.from.ref[0])} `
return `SELECT * FROM ${Select._quoteElement(this.SELECT.from.ref.join('.'))} `
}

@@ -628,0 +655,0 @@ }

@@ -37,2 +37,14 @@ const Where = require('./Where')

/**
* Sets the values that should be updated
*
* @example
* UPDATE('Authors').set({NAME: 'Jon Doe', STOCK: 123})
*
* @param {object} valueObject contains the properties that should be updated
*/
with (valueObject) {
return this.set(valueObject)
}
_convertToCqnObject (valueObject) {

@@ -51,2 +63,6 @@ const cqnObj = {}

if (value instanceof Buffer) {
return { val: value }
}
if (['-=', '+=', '*=', '/=', '%='].includes(Object.keys(value)[0])) {

@@ -83,2 +99,3 @@ const op = Object.keys(value)[0]

typeof valueObject[key] === 'object' &&
!(valueObject[key] instanceof Buffer) &&
!Array.isArray(valueObject[key]) &&

@@ -85,0 +102,0 @@ Object.keys(valueObject[key]).length === 0)

@@ -20,3 +20,3 @@ const _asyncReturn = returned => {

try {
return _asyncReturn(reject(err))
return reject ? _asyncReturn(reject(err)) : this
} catch (e) {

@@ -23,0 +23,0 @@ return rejectedThenable(e)

{
"name": "@sap/cds-ql",
"version": "1.14.0",
"version": "1.17.0",
"lockfileVersion": 1,

@@ -8,14 +8,17 @@ "requires": true,

"@sap/cds-hana": {
"version": "1.13.0",
"version": "1.16.0",
"requires": {
"@sap/cds-sql": "1.13.0"
"@sap/cds-sql": "1.16.0"
}
},
"@sap/cds-sql": {
"version": "1.13.0"
"version": "1.16.0",
"requires": {
"uuid": "3.3.2"
}
},
"@sap/cds-sqlite": {
"version": "1.13.0",
"version": "1.16.0",
"requires": {
"@sap/cds-sql": "1.13.0"
"@sap/cds-sql": "1.16.0"
}

@@ -22,0 +25,0 @@ },

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

{"bundleDependencies":false,"dependencies":{"@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"},"deprecated":false,"description":"This package deals with creating a pool of connection clients, connecting to a driver (read: db) and using these connection clients from the pool to insert, delete, select and update values or rows from a specific table. Performing these insert, delete, select and update operations also includes executing embedded queries and plain statements.","engines":{"node":">= 8.9.0"},"husky":{"hooks":{"pre-commit":"lint-staged"}},"lint-staged":{"{lib,test}/**/*.js":["prettier-standard","standard --fix","git add"]},"main":"lib/index.js","name":"@sap/cds-ql","version":"1.14.0","license":"SEE LICENSE IN developer-license-3.1.txt"}
{"bundleDependencies":false,"dependencies":{"@sap/cds-hana":"1.16.0","@sap/cds-sql":"1.16.0","@sap/cds-sqlite":"1.16.0","generic-pool":"3.7.1"},"deprecated":false,"description":"This package deals with creating a pool of connection clients, connecting to a driver (read: db) and using these connection clients from the pool to insert, delete, select and update values or rows from a specific table. Performing these insert, delete, select and update operations also includes executing embedded queries and plain statements.","engines":{"node":">= 8.9.0"},"husky":{"hooks":{"pre-commit":"lint-staged"}},"lint-staged":{"{lib,test}/**/*.js":["prettier-standard","standard --fix","git add"]},"main":"lib/index.js","name":"@sap/cds-ql","version":"1.17.0","license":"SEE LICENSE IN developer-license-3.1.txt"}

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