Socket
Socket
Sign inDemoInstall

@sap/cds-dk

Package Overview
Dependencies
Maintainers
1
Versions
146
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@sap/cds-dk - npm Package Compare versions

Comparing version 6.3.2 to 6.4.0

bin/migrate.js

2

bin/cds.js

@@ -97,3 +97,5 @@ #!/usr/bin/env node

const { readdirSync } = require('fs');
const { resolve } = require('path');
const commands = readdirSync(__dirname, { withFileTypes: true })
.concat(readdirSync(resolve(_local('@sap/cds'), '..', '..', 'bin'), { withFileTypes: true }))
.filter((f) => f.isFile() && !excludeList.includes(f.name))

@@ -100,0 +102,0 @@ .map((f) => f.name.split('.')[0]).sort();

3

bin/compile/index.js

@@ -276,3 +276,4 @@ module.exports = Object.assign ( compile, {

sql: '.sql',
edm: '.json'
edm: '.json',
xsuaa: '.json'
}[x] || '.'+x) }

@@ -279,0 +280,0 @@

module.exports = Object.assign(deploy, {
options: ['--to', '--tunnel-address', '--vcap-file'],
flags: [ '--no-save', '--auto-undeploy', '--dry', '--with-mocks', '--store-credentials', '--bind' ],
flags: [ '--no-save', '--auto-undeploy', '--dry', '--xdry', '--with-mocks', '--store-credentials', '--bind' ],
shortcuts: ['-2'],

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

cds deploy --to sqlite
cds deploy --to sqlite:db/my.db
cds deploy --to sqlite:db/my-db.sqlite
`)

@@ -85,0 +85,0 @@

exports.deploy = function deploy_to_sqlite (_model, _db, options) {
if (options.dialect === 'postgres' && !options.dry) console.error('\nDeploying to PostgreSQL is not yet supported\n')
const cds = require('../../lib/cds')
const {to:_dbrl} = options
const conf = cds.env.requires.db || {}
const conf = cds.env.requires.db ?? {}
const fts = cds.env.features.folders
const model = _model || conf.model || cds.resolve(!fts ? '*' : ['*',fts], false)
const file = _database4 (_db, _dbrl, conf)
// current 'sqlite' default is bad, as we want to default to 'plain', so ignore it
const env_dialect = cds.env.sql.dialect !== 'sqlite' ? cds.env.sql.dialect : 'plain'
const to_dialect = _dbrl && _dbrl.match(/^(\w+)/) && RegExp.$1
if (to_dialect) options.dialect = (to_dialect === 'sql')
? conf.dialect || env_dialect
: to_dialect
if (options.dialect === 'postgres' && !options.dry) console.error('\nDeploying to PostgreSQL is not yet supported\n')
return cds.deploy(model) .to ('sqlite:'+file, options)
.then (db => db && db.disconnect()) // REVISIT: we should NOT require to disconnect explicitly
let file = 'db'
if (options.to) {
file = 'sqlite:'+ _database4 (_db, options.to, conf)
// current 'sqlite' default is bad, as we want to default to 'plain', so ignore it
const env_dialect = cds.env.sql.dialect !== 'sqlite' ? cds.env.sql.dialect : 'plain'
const to_dialect = options.to && options.to.match(/^(\w+)/) && RegExp.$1
if (to_dialect) options.dialect = (to_dialect === 'sql')
? conf.dialect ?? env_dialect
: to_dialect
}
return cds.deploy(model) .to (file, options)
}

@@ -23,6 +24,7 @@

if (_db) return _db
if (_dbrl === 'sqlite') return 'db.sqlite'
if (conf.credentials?.database) return conf.credentials.database
if (conf.credentials?.url) return conf.credentials.url
if (_dbrl === 'sqlite') return 'db.sqlite'
if (_dbrl === 'sql') return ':memory:'
else return conf.credentials?.database ?? conf.credentials?.url
}
/* eslint-disable no-console */
module.exports = exports = Object.assign (help, {help:`
module.exports = exports = Object.assign (help, {formatHelp, help:`
# USAGE

@@ -42,8 +42,11 @@

const task = !topic ? help : this.load && this.load (this.Shortcuts[topic] || topic)
if (task && task.help) console.log (task.help
if (task && task.help) console.log (formatHelp (task.help))
else throw new Error(`Didn't find a help topic for '${ topic.name || topic }'.`)
}
function formatHelp (text) {
return text
.replace(/\n# ([^\n]*)\n/g, `\n\x1b[1m$1\x1b[0m\n`)
.replace(/ \*([^*]+)\*/g, ` \x1b[1m$1\x1b[0m`)
.replace(/ _([^_]+)_/g, ` \x1b[4m$1\x1b[0m`)
)
else throw new Error(`Didn't find a help topic for '${ topic.name || topic }'.`)
}

@@ -32,3 +32,3 @@ const { URLS } = require('../lib/init/constants')

*mtx* - prepares a multi-tenant project
*mtx* - prepares a multitenant project

@@ -35,0 +35,0 @@ This version only supports Node.js projects.

@@ -77,4 +77,2 @@ const { bold } = require('../lib/util/term');

Username and optionally password for authentication with Basic Auth in test scenarios.
See https://cap.cloud.sap/docs/guides/multitenancy/#send-subscribe-events for information
on suitable mock users.

@@ -121,6 +119,7 @@ When typing the colon but omitting <password>, the password is assumed empty.

*cds logout* to remove any authentication data
`
}});
https://cap.cloud.sap/docs/guides/extensibility/customization?q=mock#mock-users for information on suitable mock users.
`}});
async function login ([url], options = {}) {

@@ -127,0 +126,0 @@ const [username, password] = options.user?.split(':') ?? [];

@@ -42,3 +42,3 @@ module.exports = Object.assign(pull, {

*cds login* for more information on authentication options.
*cds login* to save authentication data, simplifying multiple runs of *cds pull* and *cds push* against the same app.
*cds login* to save project settings and authentication data, simplifying multiple runs of this command.

@@ -53,4 +53,4 @@ `});

delete options.client;
if (options.from) url = options.from
delete options.from
if (options.from) url = options.from;
delete options.from;

@@ -64,3 +64,3 @@ await require('../lib/client/pull').run({

clientsecret
})
});
}

@@ -49,3 +49,3 @@ module.exports = Object.assign(push, {

*cds login* for more information on authentication options.
*cds login* to save authentication data, simplifying multiple runs of *cds pull* and *cds push* against the same app.
*cds login* to save project settings and authentication data, simplifying multiple runs of this command.

@@ -52,0 +52,0 @@ `});

module.exports = Object.assign(subscribe, {
options: ['--to', '--user'],
flags: [],
shortcuts: ['-2', '-u'],
help: `
init: on => new (require('../lib/client/subscription'))(on),
options: ['--to', '--user'],
flags: ['--local'],
shortcuts: ['-2', '-u', '-l'],
help: `
# SYNOPSIS
*cds subscribe* <tenant>
*cds subscribe* <tenant>
Subscribe a tenant to a multi-tenant SaaS app.
Subscribe a tenant to a multitenant SaaS app.
*cds subscribe* only supports Basic Authentication and is intended for non-productive use,
including SaaS apps running on localhost with mock authentication.
Running *cds subscribe* with a URL is intended for non-productive use only, including against
SaaS apps running on localhost with mock authentication.
# OPTIONS
*-2* | *--to* <url>
*-2* | *--to* <url>
Specify the URL of the extensible SaaS app. Required setting.
Specify the URL of the SaaS app. Determined from the current user's active CDS or
Cloud Foundry login by default.
*-u* | *--user* <name>[:<password>]
*-u* | *--user* <name>[:[<password>]]
Username and optionally password for authentication. Required setting.
See https://cap.cloud.sap/docs/guides/multitenancy/#send-subscribe-events for information on suitable mock users.
Username and optionally password for authentication with Basic Auth in test scenarios.
Required setting if URL is given. (Tokens saved with *cds login* are not used because they
are unsuitable for this command.)
If password is omitted, it is assumed empty.
Note: productive passwords should not be specified on the command line.
*-l* | *--local*
`})
Run a locally-installed @sap/cds-mtxs and connect to it instead of a URL. Ignore settings
saved with *cds login*.
# SEE ALSO
async function subscribe([tenant], { to: url, user } = {}) {
*cds login* for more information on authentication options.
*cds login* to save project settings, simplifying multiple runs of this command.
const cds = require('../lib/cds')
`});
// check for application environment
// fails for edge cases (ignored for now):
// @sap/cds-mtx application with missing modules (no npm install)
// dev scenario with both @sap/cds-mtx and @sap/cds-mtxs installed
function _hasMtEnv() {
return cds.requires.multitenancy && !cds.mtx
}
async function subscribe([tenant], options = {}) {
const { CliError } = require('../lib/client/helper/errors');
if (!tenant) {
throw new CliError('Tenant not given.', { command: 'subscribe' });
}
const libOptions = { tenant };
if (options.local) {
libOptions.local = true;
delete options.local;
if (options.user) {
throw new CliError('Username cannot be specified when running @sap/cds-mtxs locally.', { command: 'subscribe' });
}
if (options.to) {
throw new CliError('URL cannot be specified when running @sap/cds-mtxs locally.', { command: 'subscribe' });
}
}
const [username, password] = options.user?.split(':') ?? [];
delete options.user;
if (!tenant) {
console.error('Must provide a tenant')
return this.help('subscribe')
}
if (!url) {
// check whether we are in a mt(xs) environment
if (!_hasMtEnv()) throw new Error('Local cds subscribe operation can only be run inside a multitenant application environment using @sap/cds-mtxs. Please specify application url (--to <url>) if you want to subscribe from remote')
console.log ('\nSubscribing', {tenant})
const { 'cds.xt.DeploymentService':ds } = await cds.serve ([
'@sap/cds-mtxs/srv/deployment-service',
'@sap/cds-mtxs/srv/model-provider'
])
cds.emit('served')
// await cds.connect.to('db')
await ds.subscribe(tenant)
} else {
// Connecting to a deployment service in a subscribed application
if (typeof user !== 'string') throw new Error('Must provide a username')
const [username, password = ''] = user.split(':');
console.log ('\nSubscribing', {tenant}, 'to', {url})
await require('axios').post (url+'/-/cds/deployment/subscribe', {
tenant
}, {
auth: { username, password }
});
}
console.log('Subscription succeeded.\n')
await subscribe.init(true).run({
...options,
username,
password
}, libOptions);
}
// cds subscribe t1 --to http://localhost:4004 -u yves

@@ -14,2 +14,5 @@ const watchOnlyOptions = ['--ext', '--livereload', '--open']

Actually, cds watch is just a convenient shortcut for:
*cds serve all --with-mocks --in-memory?*
# OPTIONS

@@ -40,5 +43,3 @@

Actually, *cds watch* is just a convenient shortcut for:
*cds serve* all --with-mocks --in-memory? ...
Check out *cds serve ?* to learn more.
*cds serve --help* for the different start options

@@ -45,0 +46,0 @@ `})

@@ -10,2 +10,29 @@

## Version 6.4.0 - 2022-12-15
### Added
- `cds add helm` now supports approuter.
- `cds subscribe --local` starts @sap/cds-mtxs locally instead of contacting a running instance via URL.
- `cds unsubscribe` removes the subscription of a tenant from a SaaS app.
### Changed
- `cds add multitenancy` will not compile internal roles into the `xs-security.json` any more.
- `cds add hana` does not create a `hdi-service-name: ${service-name}` for the database resource properties any more.
- MTX-related commands now print usage help in case of known errors.
- `cds import` now adds the annotation `@open` for all the Entities and ComplexTypes with attribute `Abstract` or `OpenType` and adds the same for those referred by the attribute `BaseType`.
- `cds import` now adds default value in the CSN for the optional parameters in action/function for OData V4 files.
- `cds init` uses latest Maven Java archetype version 1.30.0 for creating Java projects.
### Fixed
- `cds init` no longer creates `engines` entry in package.json to avoid `unsupported engine` warnings.
- `cds subscribe` correctly exits the process after deploying to a HANA database.
- `cds add multitenancy` doesn't create a duplicate `saas-registry` resource if there's one with `service-plan: service` any more.
- `cds bind` now correctly maps the `hana-mt` and `sql-mt` shortcuts to the `cds.requires.db` entry.
- `cds add mtx` no longer fails if the `mtx/sidecar` folder doesn't exist.
- `cds compile --to xsuaa` now rejects expressions leading to invalid XSUAA attributes like `$user.foo-bar`, `$user.foo/bar`, `$user.foo.bar`
- `cds compile --to xsuaa -o <file>` now sets `.json` as file ending instead of `.xsuaa`
## Version 6.3.2 - 2022-11-28

@@ -24,9 +51,5 @@

- `cds init` uses latest Maven Java archetype version 1.29.0 for creating Java projects.
- Include `@sap/cds` 6.3.1
- Include `@sap/cds-mtxs` 1.3.1
- Use `@sap/cds` 6.3.1
- Use `@sap/cds-mtxs` 1.3.1
### Fixed
- MTX Client no longer reports 'Request failed with status code 401' when sending a passcode to old MTX server.
## Version 6.3.0 - 2022-11-02

@@ -50,3 +73,3 @@

- MTX Client now treats keytar as optional unless explicitly running `cds login`
- `cds import` now caputres the documentation properly for all the EntitySet referring to same EntityType.
- `cds import` now captures the documentation properly for all the EntitySet referring to same EntityType.
- `cds deploy --to sql` now produces 'plain' SQL again, suitable for e.g. H2. In 6.2 it produced 'sqlite' dialect, erroneously.

@@ -261,2 +284,3 @@ - `cds compile --to openapi` now fixes the duplication of fields in `required` section.

- `cds add html5-repo` and `cds add destinations` throw an error if applied for MTA deployments, for which they are currently unsupported.
- `cds compile --to openapi` fixes annotations on bound action overloads.

@@ -263,0 +287,0 @@ - `cds add cf-manifest` now uses the correct `application` plan for the `xsuaa` service

@@ -9,2 +9,4 @@

hana: 'db',
'hana-mt': 'db',
'sql-mt': 'db',
destinations: 'destinations',

@@ -11,0 +13,0 @@ connectivity: 'connectivity',

@@ -9,2 +9,3 @@ const cp = require('child_process');

const path = require('path');
const term = require('../util/term');

@@ -154,3 +155,6 @@ const execAsync = util.promisify(cp.exec);

if (apiEndpoint && apiEndpoint !== target.apiEndpoint) {
throw new Error(`Current Cloud Foundry api endpoint "${target.apiEndpoint}" different than api endpoint "${apiEndpoint}" for service binding "${name}".`);
let message = `Current Cloud Foundry API endpoint "${target.apiEndpoint}" differs from API endpoint "${apiEndpoint}" for service binding "${name}".\n`;
message += `Use ${term.bold(`cf login -a ${apiEndpoint}`)} to log in to the target API endpoint.`;
console.log(message);
process.exit(1);
}

@@ -157,0 +161,0 @@

@@ -32,3 +32,3 @@ const fs = require('fs').promises;

if (status === JOB_STATUS.FAILED) {
return finisher.reject(new CliError(`Job ${jobId} failed`, error));
return finisher.reject(new CliError(`Job ${jobId} failed`, { error }));
}

@@ -70,3 +70,3 @@ console.log('Extension active');

} catch (error) {
this.handleHttpError(error, params);
this.handleHttpError(error, params, { command: 'activate' });
}

@@ -137,3 +137,3 @@ }

} catch (error) {
throw new CliError('No package.json file found', error);
throw new CliError('No package.json file found', { error });
}

@@ -140,0 +140,0 @@ allFiles.set('package.json', pkgJson);

@@ -63,3 +63,3 @@ const axios = require('axios');

} catch (error) {
throw new CliError('Failed to get authentication token', error);
throw new CliError('Failed to get authentication token', { error });
}

@@ -87,3 +87,3 @@ authData = response.data;

params.set('reqAuth', { auth: { username: params.get('username'), password: params.get('password') } });
} else {
} else if (!params.get('skipToken')) {
await retrieveTokenOrPasscodeUrl(params);

@@ -90,0 +90,0 @@ if (!params.has('token')) {

@@ -18,3 +18,3 @@ const path = require('path');

static handleHttpError(error, params, url) {
static handleHttpError(error, params, { url, command } = {}) {
url = url ?? params.get('appUrl');

@@ -24,11 +24,12 @@ const prefix = `Request to ${url} failed`;

case 401:
throw new CliError(prefix + ': invalid authentication. Retry with valid passcode' +
params.has('passcodeUrl') ? ` from ${params.get('passcodeUrl')}` : '', error);
throw new CliError(`${prefix}: invalid authentication. Retry with valid passcode${
params.has('passcodeUrl') ? ` from ${params.get('passcodeUrl')}` : ''
}.`, { error, command });
case 403:
throw new CliError(prefix + ': insufficient authorization. Ensure client has all necessary roles', error);
throw new CliError(prefix + ': insufficient authorization. Ensure client has all necessary roles.', { error, command });
case 404:
throw new CliError(prefix + ': resource not found.');
throw new CliError(prefix + ': resource not found.', { command });
case 422:
// Compilation or native-extension error.
throw new CliError(prefix, error);
throw new CliError(prefix + '.', { error, command });
default:

@@ -35,0 +36,0 @@ // Unexpected error should be transparent to user.

@@ -90,3 +90,3 @@ const fs = require('fs');

if (runOnExistingProject && !(params.get('force') || params.get('templates'))) {
throw new CliError(folderExists(params.get('projectFolder')));
throw new CliError(folderExists(params.get('projectFolder')), { command: 'extend' });
}

@@ -97,3 +97,3 @@

} catch (error) {
await Extend.handleHttpError(error, params);
await Extend.handleHttpError(error, params, { command: 'extend' });
}

@@ -100,0 +100,0 @@ }

@@ -5,9 +5,15 @@ const { getMessage } = require('./logging');

// noinspection JSAnnotator
constructor(message, error) {
throw getMessage(message, error);
constructor(message, { error, command } = {}) {
const help = command && getCommandHelp(command);
throw getMessage(message, { error, help });
}
}
function getCommandHelp(command) {
const cli = require('../../../bin/cds');
return cli?.load(command, () => ({ help: '' }))?.help ?? '';
}
module.exports = {
CliError
};

@@ -5,18 +5,20 @@ /* eslint-disable no-console */

if (process.env.DEBUG) {
console.log(getMessage(debugText, error));
console.log(getMessage(debugText, { error }));
}
}
function getMessage(errorText, error) {
function getMessage(errorText, { error, help } = {}) {
let message = errorText ? errorText : '';
if (!error) {
return message;
if (error) {
message += '\n' + (
error.response?.data?.message // response body == error
|| error.response?.data?.error?.message // response body == { error }
|| error.message // no response attached
);
if (process.env.DEBUG && error.stack) {
message += '\n' + error.stack;
}
}
message += '\n' + (
error.response?.data?.message // response body == error
|| error.response?.data?.error?.message // response body == { error }
|| error.message // no response attached
);
if (process.env.DEBUG && error.stack) {
message += '\n' + error.stack;
if (typeof help === 'string') {
message += require('../../../bin/help').formatHelp(help);
}

@@ -23,0 +25,0 @@ return message;

@@ -213,2 +213,5 @@ const log = require('./helper/logging');

// `login` PARAMS
this.skipToken = new Param('skipToken', false);
// `logout` PARAMS

@@ -215,0 +218,0 @@ this.deleteSettings = new Param('deleteSettings', false);

@@ -44,4 +44,4 @@ const cds = require ('../cds')

.then(response => Buffer.from(response.data))
.catch(error => this.handleHttpError(error, params, pullUrl));
.catch(error => this.handleHttpError(error, params, { url: pullUrl }));
}
}

@@ -36,3 +36,3 @@ const cds = require ('../cds'), { local } = cds.utils

if (!schemaRegex.test(src)) {
throw new CliError(`Nonexistent path: ${src}`);
throw new CliError(`Nonexistent path: ${src}`, { command: 'push' });
}

@@ -42,3 +42,3 @@ try {

} catch (error) {
this.handleHttpError(error, params, src);
this.handleHttpError(error, params, { url: src });
}

@@ -53,3 +53,3 @@ }

} catch (error) {
throw new CliError(`Extension project at ${projectFolder} is missing package.json file`, error);
throw new CliError(`Extension project at ${projectFolder} is missing package.json file`, { error, command: 'push' });
}

@@ -66,4 +66,4 @@ }

}, options)
.catch(error => this.handleHttpError(error, params, pushUrl));
.catch(error => this.handleHttpError(error, params, { url: pushUrl }));
}
}

@@ -174,3 +174,3 @@ const fs = require('fs');

if (!params.has('token')) {
if (params.get('skipToken') || !params.has('token')) {
return;

@@ -210,2 +210,5 @@ }

if (params.has('username')) {
params.set('skipToken', true);
}
await this.updateUrls(params, logout, loadedAppUrl);

@@ -221,3 +224,3 @@ await this.checkKeytar(params, logout);

// Subdomain needed for token retrieval.
return params.has('appUrl') && !localhostRegex.test(params.get('appUrl')) && !params.has('username');
return params.has('appUrl') && !localhostRegex.test(params.get('appUrl')) && !params.get('skipToken');
}

@@ -279,3 +282,3 @@

if (!logout) {
if (!logout && !params.get('skipToken')) {
await renewTokenUrl();

@@ -286,2 +289,5 @@ }

static async checkKeytar(params, logout) {
if (params.get('skipToken')) {
return;
}
if (isBas()) {

@@ -294,5 +300,2 @@ if (params.get('tokenStorage') === 'keyring') {

}
if (params.get('username')) {
return;
}
keytar = requireGlobal('keytar');

@@ -387,2 +390,6 @@ if (keytar) {

if (params.get('skipToken')) {
return;
}
if (params.get('clientid') && !params.get('clientsecret') && !logout) {

@@ -389,0 +396,0 @@ await addClientSecret();

@@ -17,27 +17,33 @@ const cds = require('../cds')

const findUserAttrInExpression = (expr, attributes = []) => {
if (Array.isArray(expr)) { // descend arrays
expr.forEach(e => findUserAttrInExpression(e, attributes))
}
else if (typeof expr === 'object' && expr.ref) {
const userIdx = expr.ref.indexOf('$user')
if (userIdx >= 0 && userIdx < expr.ref.length - 1) {
const attr = expr.ref[userIdx + 1]
if (!hardcoded.Attributes.includes(attr)) attributes.push(attr)
}
}
return attributes
}
const parseAttributes = (condition) => { // e.g. 'foo = $user.bar or baz = $user.boo'
if (!condition) return []
// first validate basic syntax of expression by parsing it
let expr
try {
// {"xpr":[{"ref":["foo"]},"=",{"ref":["$user","bar"]},"or",{"ref":["baz"]},"=",{"ref":["$user","boo"]}]}
const expr = cds.parse.expr(condition)
// find paths value following $user, i.e. 'bar' and 'boo'
return findUserAttrInExpression(expr.xpr)
expr = cds.parse.expr(condition).xpr
} catch (err) {
throw new Error(`${err.message} in '${condition}'`)
throw new Error(`Invalid expression': ${err.message}`)
}
// Reject expressions like `$user.foo.bar`, as xsuaa attributes are primitive, not structured
expr.forEach(expr => {
const userIdx = expr.ref?.indexOf('$user')
if (userIdx >= 0 && expr.ref.length > userIdx+2) {
throw new Error (`Structured attributes like '${expr.ref.join('.')}' are not supported`)
}
})
// Reject expressions like `$user.foo-bar`
// Impl. note: use the expression string rather than the parsed expression as the above example would be
// `[ { ref: [ '$user', 'foo' ] }, '-', { ref: [ 'bar' ] } ]`
// making it ambiguous to tell if it was `$user.foo-bar` or `$user.foo - bar`
return Array.from(condition.matchAll(/\$user\s*\.\s*(\S*)/g))
.map(m => m[1])
.filter(m => !hardcoded.Attributes.includes(m))
.map(m => {
// see https://help.sap.com/docs/CP_AUTHORIZ_TRUST_MNG/ae8e8427ecdf407790d96dad93b5f723/517895a9612241259d6941dbf9ad81cb.html#attributes
if (!/^[a-zA-Z0-9_]*$/.test(m)) throw new Error(`Illegal attribute name '${m}' in '${condition}'. Only characters a-z, A-Z, 0-9, _ are allowed.`)
return m
})
}

@@ -44,0 +50,0 @@

@@ -57,2 +57,3 @@ /**

parserContext.allInheritedComplexTypes = {};
parserContext.allInheritedEntityTypes = {};
parserContext.allowedNamespaces = [];

@@ -343,2 +344,5 @@ parserContext.allowAllNamespaces = false;

baseType = complexType[key].BaseType;
if (complexType[key].Abstract || complexType[key].OpenType) {
complexType.open = true;
}
} else if (key === "Property") {

@@ -350,3 +354,3 @@ properties = complexType.Property;

});
parserContext.allComplexTypes[complexTypeKey] = properties;
parserContext.allComplexTypes[complexTypeKey] = complexType;
if (complexTypeKey && baseType) {

@@ -387,3 +391,3 @@ parserContext.allInheritedComplexTypes[complexTypeKey] = baseType;

//preprocessing of datatype in case it is a collection
if (dataType.substring(0, 10) === 'Collection') {
if (dataType && dataType.substring(0, 10) === 'Collection') {
dataType = dataType.substring(11, dataType.length - 1);

@@ -490,11 +494,7 @@ isCollection = 1;

}
if (nullable == "false") {
if (nullable === "false")
propertyJson = propertyJson + ',\n"notNull": true';
}
else if(nullable=="true" || !nullable){
propertyJson = propertyJson + ',\n"notNull": false';
}
propertyJson = propertyJson + '\n}'
}
else{
else {
propertyJson = propertyJson + '"type":"' + cdsDataType + '"';

@@ -536,9 +536,4 @@ //if annotations to be added

if(isCollection == -1) {
if (nullable === "false") {
propertyJson = propertyJson + ',\n"notNull": true';
}
else if(nullable=="true" || !nullable){
propertyJson = propertyJson + ',\n"notNull": false';
}
if (isCollection === -1 && nullable === "false") {
propertyJson = propertyJson + ',\n"notNull": true';
}

@@ -551,7 +546,10 @@

function _getServiceComplexType(complexTypeKey, complexType, parserContext) {
function _getServiceComplexType(complexTypeKey, complexType, parserContext, isOpenType) {
let complexTypeCSN = '"' + complexTypeKey + '": {\n';
let complexTypeProperty;
let i;
complexTypeCSN = complexTypeCSN + '"kind": "type",\n';
// checking if the ComplexType is marked open or acts as a BaseType
if (isOpenType === true || Object.values(parserContext.allInheritedComplexTypes).indexOf(complexTypeKey) > -1) {
complexTypeCSN = complexTypeCSN + '"@open": true,\n';
}
complexTypeCSN = complexTypeCSN + '"@cds.external": true,\n';

@@ -567,3 +565,3 @@ if (parserContext.allComplexTypeNamespaces[complexTypeKey]) {

// More than one complex types
for (i = 0; i < complexType.length; i++) {
for (let i = 0; i < complexType.length; i++) {
complexTypeProperty = complexType[i]._attributes;

@@ -575,3 +573,3 @@ if (complexType[i].Documentation)

let complexProperty =
let complexProperty =
_getServiceEntityProperty(

@@ -629,3 +627,3 @@ complexTypeProperty.Name,

complexTypeCSN = complexTypeCSN + ",\n";
complexTypeCSN = complexTypeCSN +
complexTypeCSN = complexTypeCSN +
'"includes": ["' + parserContext.allInheritedComplexTypes[complexTypeKey] + '"]\n';

@@ -642,6 +640,8 @@ }

let complexType;
let isOpenType;
for (let i = 0; i < complexTypesKeys.length; i++) {
complexTypeKey = complexTypesKeys[i];
complexType = parserContext.allComplexTypes[complexTypesKeys[i]];
complexTypeCSN = complexTypeCSN + _getServiceComplexType(complexTypeKey, complexType, parserContext);
complexType = parserContext.allComplexTypes[complexTypeKey].Property;
isOpenType = parserContext.allComplexTypes[complexTypeKey].open;
complexTypeCSN = complexTypeCSN + _getServiceComplexType(complexTypeKey, complexType, parserContext, isOpenType);
if (i !== complexTypesKeys.length - 1) {

@@ -801,2 +801,3 @@ complexTypeCSN = complexTypeCSN + ",\n";

entityAttributes.Abstract = attributes.Abstract;
entityAttributes.OpenType = attributes.OpenType;
entityAttributes.allowedNamespaceAttributes = namespaceAttributeFilter(attributes, parserContext);

@@ -1319,2 +1320,7 @@

csn = csn + `"@cds.ambiguous": "missing on condition?",\n`;
//Code for notNull working but change is not reflecting when we use: cds compile {file-path} -2 edmx > {newFileName}
/*if (navPropAttributes.Nullable === "false")
csn = csn + '"notNull": true,\n';*/
// if documentation exists for navigation property

@@ -1412,4 +1418,4 @@ if (navPropDoc)

if (entityAttributes.Abstract && entityAttributes.Abstract.toUpperCase() === "TRUE") {
csnEntity = csnEntity + '"abstract": true,\n';
if ((entityAttributes.Abstract && entityAttributes.Abstract.toUpperCase() === "TRUE") || (entityAttributes.OpenType && entityAttributes.OpenType.toUpperCase() === "TRUE")) {
csnEntity = csnEntity + '"@open": true,\n'
}

@@ -1542,2 +1548,3 @@

parserContext.allEntities.push(_extractEntityFromNamespace(entityAttributes.BaseType));
parserContext.allInheritedEntityTypes[_extractEntityFromNamespace(entityAttributes.BaseType)] = entity["_attributes"].Name;
}

@@ -1632,2 +1639,8 @@ // adding blob element if entity has m:HasStream as true

ignorePersistenceSkip, mockServerUc, parserContext);
// adding @open annotation to BaseTypes
for (let j = 0; j < parsedEntities[i].length; j++) {
if (parserContext.allInheritedEntityTypes[_extractEntityFromNamespace(parserContext.allEntitySetMap[entitiesWithNames[i][j].name])] != undefined || parserContext.allInheritedEntityTypes[entitiesWithNames[i][j].name]) {
parsedEntities[i][j] = parsedEntities[i][j].replace(/}$/, ',"@open": true' + '}');
}
}
}

@@ -1634,0 +1647,0 @@ }

@@ -7,3 +7,2 @@ /* eslint-disable no-prototype-builtins */

"use strict";
let messages = require("../message").getMessages();

@@ -75,2 +74,4 @@ let common = require("../common");

parserContext.entityTypes = [];
parserContext.entityTypeOpenEntries = [];
parserContext.complexTypeOpenEntries = [];
parserContext.namespace = "";

@@ -105,7 +106,3 @@ parserContext.complexTypes = {};

function _isValidJSON(jsonObj, parserContext) {
let tempNamespace = jsonObj.$EntityContainer;
parserContext.namespace = tempNamespace.substring(0, tempNamespace.lastIndexOf('.'));
parserContext.jsonEntityContainerName = tempNamespace.substring(tempNamespace.lastIndexOf('.') + 1);
if (jsonObj.$Version && jsonObj.$EntityContainer && jsonObj[parserContext.namespace]) {
if (jsonObj.$Version && _hasEntityContainer(jsonObj, parserContext) && jsonObj[parserContext.namespace]) {
return true;

@@ -119,7 +116,11 @@ }

function _hasEntityContainer(jsonObj, parserContext) {
if (jsonObj[parserContext.namespace][parserContext.jsonEntityContainerName] &&
jsonObj[parserContext.namespace][parserContext.jsonEntityContainerName] instanceof Object
) {
return true;
} else {
let jsonObjEntityContainer = jsonObj.$EntityContainer;
try {
if (jsonObjEntityContainer) [parserContext.namespace, parserContext.jsonEntityContainerName] = jsonObjEntityContainer.split('.');
if (jsonObj[parserContext.namespace][parserContext.jsonEntityContainerName] &&
jsonObj[parserContext.namespace][parserContext.jsonEntityContainerName] instanceof Object
) {
return true;
}
} catch (err) {
throw new Error(messages.MISSING_ENTITY_CONTAINER);

@@ -129,9 +130,2 @@ }

function _validateJSON(jsonObj, parserContext) {
return (
_isValidJSON(jsonObj, parserContext) &&
_hasEntityContainer(jsonObj, parserContext)
);
}
function _includeExternalNamespaceAnnotation(source, target) {

@@ -145,2 +139,7 @@ Object.entries(source).forEach(element => {

function _addNotNull(property, isCollection) {
if (isCollection) property.items["notNull"] = true;
else property["notNull"] = true;
}
function _typeWithCollections(property, type, isCollection) {

@@ -175,3 +174,5 @@ if (isCollection === true) {

else {
typeProperties["notNull"] = propertyType.$Nullable ? false : true;
if ((propertyType.$Nullable !== true) && (propertyType.$Kind !== 'TypeDefinition')) {
typeProperties["notNull"] = true;
}
}

@@ -235,2 +236,3 @@ _includeExternalNamespaceAnnotation(propertyType, property);

_typeWithCollections(property, type, propertyType.$Collection);
if (!propertyType.$Nullable) _addNotNull(property, propertyType.$Collection);

@@ -242,6 +244,7 @@ return property;

let property = {};
let type = { type: propertyType.$Type }
let type = { type: propertyType.$Type };
_includeExternalNamespaceAnnotation(propertyType, property);
_typeWithCollections(property, type, propertyType.$Collection);
if (!propertyType.$Nullable) _addNotNull(property, propertyType.$Collection);

@@ -263,2 +266,7 @@ return property;

// associationProperty.target = associationNode.$Type;
//Code for NavigationProperty for notNull
/*if(associationProperty.$Nullable != true){
associationProperty["notNull"] = true;
}*/
if (mockServerUc && parserContext.entitySetToEntityTypeMap && parserContext.entitySetToEntityTypeMap.get(associationNode.$Type)) {

@@ -346,2 +354,3 @@ if (parserContext.entitySetToEntityTypeMap.get(associationNode.$Type).length > 1) {

let isAbstract = element[key].$Abstract;
let isOpenType = element[key].$OpenType;
if (key) {

@@ -369,5 +378,6 @@ entityCsn[key] = {};

entityCsn[key].includes.push(baseType);
if (!parserContext.entityTypeOpenEntries.includes(baseType)) parserContext.entityTypeOpenEntries.push(baseType);
}
if (isAbstract) {
entityCsn[key].abstract = isAbstract;
if ((isAbstract || isOpenType) && !parserContext.entityTypeOpenEntries.includes(key)) {
parserContext.entityTypeOpenEntries.push(key);
}

@@ -423,2 +433,8 @@ entityCsn[key].elements = {};

});
// add @open annotations
parserContext.entityTypeOpenEntries.forEach(key => {
if (entityCsn[key]) entityCsn[key]['@open'] = true;
});
return entityCsn;

@@ -595,2 +611,22 @@ }

function _captureOptionalParameter(annotation, path) {
let param = annotation[0].split('/');
let defaultvalue = annotation[1]["@Core.OptionalParameter"]["DefaultValue"];
if (path.params === undefined) {
_addDefaultValueObject(path, defaultvalue);
}
else {
_addDefaultValueObject(path.params[param[1]], defaultvalue);
}
return path;
}
function _addDefaultValueObject(path, defaultvalue) {
// for collection, default value isin't expected
if (path.items === undefined) {
path.default = {};
path.default.val = (defaultvalue) ? defaultvalue : null;
}
}
function _collectBounded(schemaDataList, flag, parserContext) {

@@ -694,10 +730,12 @@ let schemaData;

csnDefs[boundedEntityName].actions[name].params[paramName].items = paramType;
csnDefs[boundedEntityName].actions[name].params[paramName].items["notNull"] = paramObj?.$Nullable ? false : true;
if(paramObj.$Nullable != true){
csnDefs[boundedEntityName].actions[name].params[paramName].items["notNull"] = true;
}
} else {
csnDefs[boundedEntityName].actions[name].params[paramName] = paramType;
if (!paramType.items) {
csnDefs[boundedEntityName].actions[name].params[paramName].notNull = paramObj?.$Nullable ? false : true;
if(paramObj.$Nullable != true){
csnDefs[boundedEntityName].actions[name].params[paramName].notNull = true;
}
}
}
}

@@ -736,3 +774,5 @@ }

csnDefs[boundedEntityName].actions[name].returns.items = returnType;
csnDefs[boundedEntityName].actions[name].returns.items["notNull"] = obj[j].$ReturnType?.$Nullable ? false : true
if(obj[j].$ReturnType.$Nullable != true){
csnDefs[boundedEntityName].actions[name].returns.items["notNull"] = true;
}
}

@@ -742,3 +782,5 @@ else {

if (!returnType.items) {
csnDefs[boundedEntityName].actions[name].returns["notNull"] = obj[j].$ReturnType?.$Nullable ? false : true
if(obj[j].$ReturnType.$Nullable != true){
csnDefs[boundedEntityName].actions[name].returns["notNull"] = true;
}
}

@@ -756,2 +798,3 @@ }

}
}
});

@@ -789,3 +832,3 @@ }

let propertyType;
let baseType;
let baseType, isAbstract, isOpenType;
let enumType;

@@ -800,6 +843,12 @@ cTypes = _collectComplexType(schemaData, parserContext);

baseType = cTypes[element].$BaseType;
isAbstract = cTypes[element].$Abstract;
isOpenType = cTypes[element].$OpenType;
if (baseType) {
complexCsn[element].includes = [];
complexCsn[element].includes.push(baseType);
if (!parserContext.complexTypeOpenEntries.includes(baseType)) parserContext.complexTypeOpenEntries.push(baseType);
}
if ((isAbstract || isOpenType) && !parserContext.complexTypeOpenEntries.includes(element)) {
parserContext.complexTypeOpenEntries.push(element);
}
Object.keys(cTypes[element]).forEach(property => { // cTypes[element][property].$Type.startsWith('Edm.')

@@ -816,2 +865,5 @@ if (cTypes[element][property] instanceof Object) {

complexCsn[element].elements[property] = _generateComplexTypePropertyCsn(propertyType);
} else if (parserContext.typeDefinitions[cTypes[element][property].$Type]) {
propertyType = cTypes[element][property];
complexCsn[element].elements[property] = _generateTypeDefinitionPropertyCsn(propertyType);
} else if (parserContext.enumTypes[cTypes[element][property].$Type]) {

@@ -829,2 +881,8 @@ enumType = cTypes[element][property];

});
// add @open annotations
parserContext.complexTypeOpenEntries.forEach(key => {
if (complexCsn[key]) complexCsn[key]['@open'] = true;
});
return complexCsn;

@@ -895,7 +953,11 @@ }

obj[objType].params[objData.$Parameter[i].$Name].items = paramType;
obj[objType].params[objData.$Parameter[i].$Name].items["notNull"] = objData.$Parameter[i]?.$Nullable ? false : true;
if(objData.$Parameter[i].$Nullable != true){
obj[objType].params[objData.$Parameter[i].$Name].items["notNull"] = true;
}
} else {
obj[objType].params[objData.$Parameter[i].$Name] = paramType;
if (!paramType.items) {
obj[objType].params[objData.$Parameter[i].$Name]["notNull"] = objData.$Parameter[i]?.$Nullable ? false : true;
if(objData.$Parameter[i].$Nullable != true){
obj[objType].params[objData.$Parameter[i].$Name]["notNull"] = true;
}
}

@@ -935,8 +997,12 @@ }

obj[objType].returns.items = returnValue;
obj[objType].returns.items["notNull"] = objData.$ReturnType?.$Nullable ? false : true;
if(objData.$ReturnType.$Nullable != true){
obj[objType].returns.items["notNull"] = true;
}
} else {
obj[objType].returns = returnValue;
if (!returnValue.items) {
obj[objType].returns["notNull"] = objData.$ReturnType?.$Nullable ? false : true;
if(objData.$ReturnType.$Nullable != true){
obj[objType].returns["notNull"] = true;
}
}
}

@@ -1048,5 +1114,8 @@ }

}
else if (vocab) {
else if (targetString === "@Core.OptionalParameter" && annotation[1]["@Core.OptionalParameter"]) {
_captureOptionalParameter(annotation, path);
}
else if (vocab) {
if (vocab.includes(targetString.substring(targetString.indexOf('@') + 1, targetString.lastIndexOf('.')))) {
path[targetString] = annotation[1][targetString];
path[targetString] = annotation[1][targetString] === null ? true : annotation[1][targetString];
}

@@ -1222,3 +1291,3 @@ }

}
if (_validateJSON(json, parserContext)) {
if (_isValidJSON(json, parserContext)) {
resolve(json);

@@ -1250,3 +1319,3 @@ }

edmjConverted = JSON.parse(edmx);
if (_validateJSON(edmjConverted, parserContext)) {
if (_isValidJSON(edmjConverted, parserContext)) {
csn = _generateCSN(edmjConverted, ignorePersistenceSkip, mockServerUc, parserContext);

@@ -1253,0 +1322,0 @@ if (csn) resolve(csn);

const os = require('os');
const MAVEN_ARCHETYPE_VERSION = '1.29.0';
const MAVEN_ARCHETYPE_VERSION = '1.30.0';

@@ -5,0 +5,0 @@ const constants = {

@@ -270,4 +270,4 @@ const path = require('path');

this.templateList = Array.from(templates.entries()).sort((a, b) => {
return OPTIONS_PRIORITY.indexOf(a[0]) - OPTIONS_PRIORITY.indexOf(b[0]);
this.templateList = Array.from(templates.entries()).sort(([a], [b]) => {
return OPTIONS_PRIORITY.indexOf(a) - OPTIONS_PRIORITY.indexOf(b);
}).map((entry) => entry[1]);

@@ -274,0 +274,0 @@

@@ -126,5 +126,2 @@ // Registry of sequence matchers in mta.yaml files

isEqualTo: 'saas-registry',
}, {
property: 'parameters.service-plan',
isEqualTo: 'application'
}]

@@ -131,0 +128,0 @@ }

{
"name": "approuter",
"dependencies": {
"@sap/approuter": "^11.0.0"
"@sap/approuter": "^12.0.0"
},

@@ -6,0 +6,0 @@ "engines": {

@@ -12,2 +12,3 @@ const { join } = require('path')

} = require('../_merging/registry-mta')
const { copyAndTrack, parseMd5File, writeMd5File } = require('../../util/md5Tracking')

@@ -25,12 +26,3 @@ module.exports = class ApprouterTemplate extends require('../templateBase') {

async canRun() {
const projectDescriptor = await this.projectReader.read(this.options)
const { hasMta, hasHelm } = projectDescriptor.cap
if (hasHelm && !hasMta) {
throw `'cds add approuter' is not available for Kyma yet`
}
return true
}
async getDependencies() {
getDependencies() {
return [OPTION_XSUAA]

@@ -71,5 +63,5 @@ }

async runDependentMerging() {
async runDependentMerging(context = {}) {
const projectDescriptor = await this.projectReader.read(this.options)
const { isNodejs, isJava, isExtensible, isMultitenant, hasMta } = projectDescriptor.cap
const { isNodejs, isJava, isExtensible, isMultitenant, hasMta, hasHelm } = projectDescriptor.cap

@@ -95,2 +87,58 @@ if (hasMta) {

if (hasHelm) {
let isIndependentCommand = false;
if (Object.keys(context).length == 0) {
isIndependentCommand = true;
context.projectPath = this.projectPath;
context.oldTrackingData = context.newTrackingData = await parseMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'));
}
await mergeYAML(
join(this.projectPath, 'chart', 'values.yaml'),
join(__dirname, 'files', 'values.yaml.hbs'),
projectDescriptor
)
await mergeYAML(
join(this.projectPath, 'chart', 'Chart.yaml'),
join(__dirname, 'files', 'chart.yaml'),
projectDescriptor,
{ additions: [{
ref: `web-application-approuter`,
in: `dependencies`,
where: [{
property: 'alias',
isEqualTo: 'approuter'
}]
}]}
)
await mergeYAML(
join(this.projectPath, 'chart', 'values.yaml'),
{
approuter: {
envFrom: [
{
configMapRef: {
name: "{{ .Release.Name }}-approuter-configmap",
tpl: true
}
}
]
}
},
projectDescriptor
)
const fileName = isMultitenant ? 'approuter-mtxs-configmap.yaml' : 'approuter-configmap.yaml';
await copyAndTrack(
join(__dirname, 'files', fileName),
join(this.projectPath, 'chart', 'templates', 'approuter-configmap.yaml'),
context,
true
)
if (isIndependentCommand) await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), context.newTrackingData);
}
const appPath = join(this.projectPath, projectDescriptor.ui.appPath || 'app')

@@ -97,0 +145,0 @@ const additions = isExtensible && isJava ? [{ ...approuterExtensibilityJava, at: 0 }] :

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

const path = require('path')
const { copy } = require('../../../cds').utils
const { join } = require('path')
const ProjectReader = require('../../util/projectReader')
const { mergeYAML } = require('../../util/merge')
const { copyAndTrack, parseMd5File, writeMd5File } = require('../../util/md5Tracking')
const { srvNode, srvJava, auditlog } = require('../_merging/registry-mta')

@@ -21,3 +21,3 @@

async runDependentMerging() {
async runDependentMerging(context = {}) {
const projectDescriptor = await this.projectReader.read(this.options)

@@ -27,3 +27,3 @@ const { isNodejs, hasMta, hasHelm } = projectDescriptor.cap

if (hasMta) {
const mtaYAMLPath = path.join(this.projectPath, 'mta.yaml')
const mtaYAMLPath = join(this.projectPath, 'mta.yaml')
const srv = isNodejs ? srvNode : srvJava

@@ -45,4 +45,12 @@ await mergeYAML(

if (hasHelm) {
//in case facet is being added to the already exisiting charts folder
let isIndependentCommand = false
if(Object.keys(context).length == 0){
isIndependentCommand = true
context.projectPath = this.projectPath
context.oldTrackingData = context.newTrackingData = await parseMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'))
}
await mergeYAML(
path.join(this.projectPath, 'chart', 'values.yaml'),
join(this.projectPath, 'chart', 'values.yaml'),
{

@@ -56,8 +64,8 @@ srv: { bindings: {

}
},
null, { forceOverwrite: true }
}
)
await copy(path.join(__dirname, 'files', 'auditlog.yaml'), path.join(this.projectPath, 'chart', 'templates', 'auditlog.yaml'))
await copyAndTrack(join(__dirname, 'files', 'auditlog.yaml'), join(this.projectPath, 'chart', 'templates', 'auditlog.yaml'), context)
if(isIndependentCommand) await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), context.newTrackingData)
}
}
}

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

const path = require('path')
const { join } = require('path')
const { exists } = require('../../../cds').utils

@@ -24,3 +24,3 @@ const ProjectReader = require('../../util/projectReader');

if (exists(path.join(this.projectPath, MANIFEST_FILE)) || exists(path.join(this.projectPath, SERVICES_MANIFEST_FILE))) {
if (exists(join(this.projectPath, MANIFEST_FILE)) || exists(join(this.projectPath, SERVICES_MANIFEST_FILE))) {
throw new Error(`File ${MANIFEST_FILE} or ${SERVICES_MANIFEST_FILE} already exist in current folder. Use --force to overwrite.`);

@@ -33,4 +33,4 @@ }

const projectDescriptor = await this.projectReader.read()
await copyFiles(path.join(__dirname, 'files'), this.projectPath, projectDescriptor, this.options.force);
await copyFiles(join(__dirname, 'files'), this.projectPath, projectDescriptor, this.options.force);
}
}

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

const path = require('path')
const { join } = require('path')
const ProjectReader = require('../../util/projectReader')
const { mergeYAML } = require('../../util/merge')
const cds = require('../../../cds'), { copy } = cds.utils
const { copyAndTrack, parseMd5File, writeMd5File } = require('../../util/md5Tracking')

@@ -16,3 +16,3 @@ module.exports = class ConnectivityTemplate extends require('../templateBase') {

async runDependentMerging() {
async runDependentMerging(context = {}) {
const projectDescriptor = await this.projectReader.read(this.options)

@@ -22,5 +22,13 @@ const { hasHelm } = projectDescriptor.cap

if (hasHelm) {
//in case facet is being added to the already exisiting charts folder
let isIndependentCommand = false
if(Object.keys(context).length == 0){
isIndependentCommand = true
context.projectPath = this.projectPath
context.oldTrackingData = context.newTrackingData = await parseMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'))
}
await mergeYAML(
path.join(this.projectPath, 'chart', 'values.yaml'),
path.join(__dirname, 'files', 'values.yaml.hbs'),
join(this.projectPath, 'chart', 'values.yaml'),
join(__dirname, 'files', 'values.yaml.hbs'),
projectDescriptor,

@@ -36,9 +44,10 @@ { additions: [{

)
const filesPath = path.join(__dirname, 'files')
const templatesPath = path.join(this.projectPath, 'chart', 'templates')
await copy(path.join(filesPath, 'connectivity-binding.yaml'), path.join(templatesPath, 'connectivity-binding.yaml'))
await copy(path.join(filesPath, 'connectivity-proxy-info.yaml'), path.join(templatesPath, 'connectivity-proxy-info.yaml'))
await copy(path.join(filesPath, 'connectivity.yaml'), path.join(templatesPath, 'connectivity.yaml'))
const filesPath = join(__dirname, 'files')
const templatesPath = join(this.projectPath, 'chart', 'templates')
await copyAndTrack(join(filesPath, 'connectivity-binding.yaml'), join(templatesPath, 'connectivity-binding.yaml'), context)
await copyAndTrack(join(filesPath, 'connectivity-proxy-info.yaml'), join(templatesPath, 'connectivity-proxy-info.yaml'), context)
await copyAndTrack(join(filesPath, 'connectivity.yaml'), join(templatesPath, 'connectivity.yaml'), context)
if(isIndependentCommand) await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), context.newTrackingData)
}
}
}

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

const path = require('path')
const { join } = require('path')
const ProjectReader = require('../../util/projectReader')
const { mergeYAML } = require('../../util/merge')
const { copy } = require('../../../cds').utils
const { copyAndTrack, parseMd5File, writeMd5File } = require('../../util/md5Tracking')

@@ -12,2 +12,11 @@ module.exports = class DestinationsTemplate extends require('../templateBase') {

async canRun() {
const projectDescriptor = await this.projectReader.read(this.options)
const { hasMta, hasHelm } = projectDescriptor.cap
if (!hasHelm && hasMta) {
throw `'cds add destinations' is not available for Cloud Foundry yet`
}
return true
}
static hasFacet(env) {

@@ -22,3 +31,3 @@ const kinds = { odata: 1, 'odata-v2': 1, 'odata-v4': 1, rest: 1 }

async runDependentMerging() {
async runDependentMerging(context = {}) {
const projectDescriptor = await this.projectReader.read(this.options)

@@ -32,4 +41,11 @@ const { hasHelm, hasDestination, hasHtml5Repo } = projectDescriptor.cap

//in case facet is being added to the already exisiting charts folder
let isIndependentCommand = false
if(Object.keys(context).length == 0){
isIndependentCommand = true
context.projectPath = this.projectPath
context.oldTrackingData = context.newTrackingData = await parseMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'))
}
await mergeYAML(
path.join(this.projectPath, 'chart', 'values.yaml'),
join(this.projectPath, 'chart', 'values.yaml'),
{

@@ -46,8 +62,8 @@ ...binding,

}
},
null, { forceOverwrite: true }
}
)
await copy(path.join(__dirname, 'files', 'destination.yaml'), path.join(this.projectPath, 'chart', 'templates', 'destination.yaml'))
await copyAndTrack(join(__dirname, 'files', 'destination.yaml'), join(this.projectPath, 'chart', 'templates', 'destination.yaml'), context)
if(isIndependentCommand) await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), context.newTrackingData)
}
}
}

@@ -5,4 +5,3 @@ {

"messaging": {
"kind": "enterprise-messaging",
"format": "cloudevents"
"kind": "enterprise-messaging"
}

@@ -9,0 +8,0 @@ }

{
"requires": {
"messaging": {
"kind": "enterprise-messaging",
"format": "cloudevents"
"kind": "enterprise-messaging"
}
}
}

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

const path = require('path')
const { copy } = require('../../../cds').utils
const { join } = require('path')
const ProjectReader = require('../../util/projectReader')
const { mergeJSON, mergeYAML } = require('../../util/merge')
const { copyAndTrack, parseMd5File, writeMd5File } = require('../../util/md5Tracking')
const { srvNode, srvJava, enterpriseMessaging } = require('../_merging/registry-mta')

@@ -20,6 +20,6 @@

const { for: forProfile, isNodejs } = projectDescriptor.cap
const templatePath = path.join(__dirname, 'files')
const templatePath = join(__dirname, 'files')
const cdsTemplateFile = (isNodejs ? 'cds.package.json' : 'cdsrc.json') + (forProfile ? '.hbs' : '')
const cdsTemplatePath = path.join(templatePath, cdsTemplateFile)
const configPath = path.join(this.projectPath, isNodejs ? 'package.json' : '.cdsrc.json')
const cdsTemplatePath = join(templatePath, cdsTemplateFile)
const configPath = join(this.projectPath, isNodejs ? 'package.json' : '.cdsrc.json')
await mergeJSON(configPath, cdsTemplatePath, projectDescriptor)

@@ -29,3 +29,3 @@ await this.runDependentMerging()

async runDependentMerging() {
async runDependentMerging(context = {}) {
const projectDescriptor = await this.projectReader.read(this.options)

@@ -35,3 +35,3 @@ const { hasHelm, hasMta, isNodejs } = projectDescriptor.cap

if (hasMta) {
const mtaYAMLPath = path.join(this.projectPath, 'mta.yaml')
const mtaYAMLPath = join(this.projectPath, 'mta.yaml')
const srv = isNodejs ? srvNode : srvJava

@@ -50,16 +50,29 @@ await mergeYAML(

)
await mergeJSON(
join(this.projectPath, 'event-mesh.json'),
join(__dirname, 'files', 'event-mesh.json.hbs'),
projectDescriptor
)
}
if (hasHelm) {
//in case facet is being added to the already exisiting charts folder
let isIndependentCommand = false
if(Object.keys(context).length == 0){
isIndependentCommand = true
context.projectPath = this.projectPath
context.oldTrackingData = context.newTrackingData = await parseMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'))
}
await mergeYAML(
path.join(this.projectPath, 'chart', 'values.yaml'),
path.join(__dirname, 'files', 'values.yaml'),
null, { forceOverwrite: true }
join(this.projectPath, 'chart', 'values.yaml'),
join(__dirname, 'files', 'values.yaml')
)
await copy(
path.join(__dirname, 'files', 'event-mesh.yaml'),
path.join(this.projectPath, 'chart', 'templates', 'event-mesh.yaml')
await copyAndTrack(
join(__dirname, 'files', 'event-mesh.yaml'),
join(this.projectPath, 'chart', 'templates', 'event-mesh.yaml'),
context
)
if(isIndependentCommand) await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), context.newTrackingData)
}
}
}

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

const cds = require('../../../cds')
const { copy, path } = cds.utils
const { join } = require('path')
const ProjectReader = require('../../util/projectReader')
const { mergeJSON } = require('../../util/merge')
const { copyAndTrack, parseMd5File, writeMd5File } = require('../../util/md5Tracking')

@@ -19,9 +19,9 @@ module.exports = class ExtensibilityTemplate extends require('../templateBase') {

const { for: forProfile, isJava } = projectDescriptor.cap
const cdsConfigPath = path.join(this.projectPath, isJava ? '.cdsrc.json' : 'package.json')
const cdsConfigPath = join(this.projectPath, isJava ? '.cdsrc.json' : 'package.json')
const cdsTemplateFile = forProfile ? (isJava ? 'cdsrc.json.hbs' : 'cds.package.json.hbs') : (isJava ? 'cdsrc.json' : 'cds.package.json')
await mergeJSON(cdsConfigPath, path.join(__dirname, 'files', cdsTemplateFile), projectDescriptor)
await mergeJSON(cdsConfigPath, join(__dirname, 'files', cdsTemplateFile), projectDescriptor)
await this.runDependentMerging()
}
async runDependentMerging() {
async runDependentMerging(context = {}) {
const projectDescriptor = await this.projectReader.read()

@@ -31,4 +31,4 @@ const { hasXsuaa, hasHelm } = projectDescriptor.cap

await mergeJSON(
path.join(this.projectPath, 'xs-security.json'),
path.join(__dirname, 'files', 'xs-security.json.hbs'),
join(this.projectPath, 'xs-security.json'),
join(__dirname, 'files', 'xs-security.json.hbs'),
projectDescriptor,

@@ -53,9 +53,18 @@ {

if (hasXsuaa && hasHelm) {
//in case facet is being added to the already exisiting charts folder
let isIndependentCommand = false
if(Object.keys(context).length == 0){
isIndependentCommand = true
context.projectPath = this.projectPath
context.oldTrackingData = context.newTrackingData = await parseMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'))
}
// REVISIT: Shared xs-security.json location for Helm and MTA?
await copy(
path.join(this.projectPath, 'xs-security.json'),
path.join(this.projectPath, 'chart', 'xs-security.json')
await copyAndTrack(
join(this.projectPath, 'xs-security.json'),
join(this.projectPath, 'chart', 'xs-security.json'),
context
)
if(isIndependentCommand) await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), context.newTrackingData)
}
}
}

@@ -1,8 +0,9 @@

const path = require('path');
const { join } = require('path');
const cds = require('../../../cds')
const { fs, read, write } = cds.utils
const { read, write, exists, rm } = cds.utils
const commandUtil = require('../../util/commandUtil');
const mvnArchetypes = require('../../util/mvnArchetypeUtil');
const term = require('../../../util/term');
const { mergeJSON, mergeYAML } = require('../../util/merge')
const { mergeJSON, mergeYAML, removeFromYAML } = require('../../util/merge')
const { copyAndTrack, parseMd5File, writeMd5File } = require('../../util/md5Tracking')
const { copyFiles } = require('../../util/templateUtil')

@@ -37,8 +38,8 @@ const ProjectReader = require('../../util/projectReader');

const hdiConfigPath = path.join(this.projectPath, env.folders.db, 'src', '.hdiconfig');
const hdiConfigTemplatePath = path.join(__dirname, 'files', 'common', 'src', '.hdiconfig');
const hdiConfigPath = join(this.projectPath, env.folders.db, 'src', '.hdiconfig');
const hdiConfigTemplatePath = join(__dirname, 'files', 'common', 'src', '.hdiconfig');
await mergeJSON(hdiConfigPath, hdiConfigTemplatePath);
const undeployJSONPath = path.join(this.projectPath, env.folders.db, 'undeploy.json');
const undeployJSONTemplatePath = path.join(__dirname, 'files', 'common', 'undeploy.json');
const undeployJSONPath = join(this.projectPath, env.folders.db, 'undeploy.json');
const undeployJSONTemplatePath = join(__dirname, 'files', 'common', 'undeploy.json');
await mergeJSON(undeployJSONPath, undeployJSONTemplatePath);

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

case PROJECT_TYPE.java: {
await copyFiles(path.join(__dirname, 'files', 'java', 'db'), path.join(this.projectPath, env.folders.db), {}, this.options.force);
await copyFiles(join(__dirname, 'files', 'java', 'db'), join(this.projectPath, env.folders.db), {}, this.options.force);
await this._updatePomXml();

@@ -65,3 +66,3 @@ await this._updateCdsConfiguration();

async runDependentMerging() {
async runDependentMerging(context = {}) {
const projectDescriptor = await this.projectReader.read(this.options)

@@ -91,3 +92,3 @@ const { hasMta, hasHelm, isNodejs, isJava, isMultitenant } = projectDescriptor.cap

const mtaYAMLPath = path.join(this.projectPath, 'mta.yaml')
const mtaYAMLPath = join(this.projectPath, 'mta.yaml')

@@ -124,10 +125,45 @@ const relationships = [{

if (hasHelm) {
await mergeYAML(
path.join(this.projectPath, 'chart', 'values.yaml'),
path.join(__dirname, 'files', 'values.yaml.hbs'),
projectDescriptor, { forceOverwrite: true })
await fs.copy(
path.join(__dirname, 'files', 'hana-deployer-job.yaml'),
path.join(this.projectPath, 'chart', 'templates', 'hana-deployer-job.yaml')
)
//in case facet is being added to the already exisiting charts folder
let shouldUpdateTrackingFile = false;
if(Object.keys(context).length == 0){
shouldUpdateTrackingFile = true;
context.projectPath = this.projectPath;
context.oldTrackingData = context.newTrackingData = await parseMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'));
}
if(isMultitenant){
shouldUpdateTrackingFile = true;
const key = "templates/hana-deployer-job.yaml";
// remove entry from oldTrackingData
if(context.oldTrackingData !== undefined && context.oldTrackingData[key] !== undefined) {
delete context.oldTrackingData[key];
}
// remove entry from newTrackingData
if(context.newTrackingData !== undefined && context.newTrackingData[key] !== undefined) {
delete context.newTrackingData[key];
}
// remove hana entries from values.yaml
await removeFromYAML(join(this.projectPath, 'chart', 'values.yaml'), ['hana_deployer', 'srv.bindings.db']);
const hanaDeployerPath = join(this.projectPath, 'chart', 'templates', 'hana-deployer-job.yaml');
if(exists(hanaDeployerPath)) {
await rm(hanaDeployerPath, { force: true });
}
}
else{
await mergeYAML(
join(this.projectPath, 'chart', 'values.yaml'),
join(__dirname, 'files', 'values.yaml.hbs'),
projectDescriptor
)
await copyAndTrack(
join(__dirname, 'files', 'hana-deployer-job.yaml'),
join(this.projectPath, 'chart', 'templates', 'hana-deployer-job.yaml'),
context
)
}
if(shouldUpdateTrackingFile) await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), context.newTrackingData);
}

@@ -154,4 +190,4 @@ }

async _updatePackageJson() {
const packageJsonPath = path.join(this.projectPath, 'package.json')
const dependenciesTemplatePath = path.join(__dirname, 'files', 'nodejs', 'dependencies.package.json');
const packageJsonPath = join(this.projectPath, 'package.json')
const dependenciesTemplatePath = join(__dirname, 'files', 'nodejs', 'dependencies.package.json');
await mergeJSON(packageJsonPath, dependenciesTemplatePath);

@@ -171,3 +207,3 @@

const configFile = projectType === PROJECT_TYPE.nodejs ? 'package.json' : '.cdsrc.json';
configPath = configPath ?? path.join(this.projectPath, configFile)
configPath = configPath ?? join(this.projectPath, configFile)
const projectDescriptor = await this.projectReader.read(this.options);

@@ -181,5 +217,5 @@ const { for: forProfile } = projectDescriptor.cap;

const { pLanguage } = projectDescriptor.cap;
const cdsTemplatePath = path.join(__dirname, 'files', pLanguage, cdsTemplateFile);
const cdsTemplatePath = join(__dirname, 'files', pLanguage, cdsTemplateFile);
await mergeJSON(configPath, cdsTemplatePath, projectDescriptor, { forceOverwrite: true })
}
}

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

Thank you for installing {{ .Chart.Name }} version {{ .Chart.Version }}.
{{- printf "Thank you for installing %s version %s." .Chart.Name .Chart.Version }}
The release "{{ .Release.Name }}" is installed in namespace "{{ .Release.Namespace }}".
{{ printf "The release %s is installed in namespace %s." .Release.Name .Release.Namespace }}

@@ -10,3 +10,4 @@ Your services are available at:

{{- $ := merge (dict "name" $name "deployment" $deployment) $root }}
- https://{{ include "cap.deploymentHostFull" $ }}
{{- $url := include "cap.deploymentHostFull" $ }}
{{ printf "%s - https://%s" $name $url }}
{{- end }}

@@ -9,4 +9,9 @@ {

"$ref": "./charts/web-application/values.schema.json"
},
"approuter": {
"$id": "#/properties/approuter",
"description": "Deployment",
"$ref": "./charts/web-application/values.schema.json"
}
}
}

@@ -45,2 +45,29 @@ {

},
"approuter": {
"$id": "#/properties/approuter",
"description": "Deployment"
},
"approuterDestinations": {
"$id": "#/properties/approuterDestinations",
"title": "Backend Destinations for Approuter",
"type": "object",
"patternProperties": {
"^[-._a-zA-Z][-._a-zA-Z0-9]*$": {
"description": "Name of the backend Destination",
"required": [
"service"
],
"properties": {
"service": {
"type": "string",
"description": "Target Kubernetes service"
},
"path": {
"type": "string",
"description": "This path will be appended to the URL"
}
}
}
}
},
"auditlog": {

@@ -47,0 +74,0 @@ "$id": "#/properties/auditlog",

@@ -1,5 +0,6 @@

const path = require('path');
const { exists, read, copy, rimraf } = require('../../../cds').utils;
const { join } = require('path');
const { exists, read, rimraf } = require('../../../cds').utils;
const ProjectReader = require('../../util/projectReader');
const { mergeYAML } = require('../../util/merge')
const { parseMd5File, writeMd5File, copyAndTrack } = require('../../util/md5Tracking')
//const { yaml } = require('@sap/cds-foss')

@@ -11,2 +12,4 @@

this.projectReader = new ProjectReader(projectPath);
this.oldTrackingData = undefined;
this.newTrackingData = {};
}

@@ -17,3 +20,3 @@

if (options?.add.has('mta') && !options?.add.has('helm')) return false
return exists(path.join(projectPath, 'chart', 'values.yaml'))
return exists(join(projectPath, 'chart', 'values.yaml'))
}

@@ -23,3 +26,3 @@

if (this.options.force) {
await rimraf(path.join(this.projectPath, 'chart'))
await rimraf(join(this.projectPath, 'chart'))
return true;

@@ -32,29 +35,28 @@ }

const projectDescriptor = await this.projectReader.read(this.options)
this.oldTrackingData = await parseMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'));
await copy(
path.join(__dirname, 'subchart'),
path.join(this.projectPath, 'chart', 'charts', 'web-application'),
await copyAndTrack(
join(__dirname, 'subchart'),
join(this.projectPath, 'chart', 'charts', 'web-application'),
this
)
await copy(
path.join(__dirname, 'chart'),
path.join(this.projectPath, 'chart')
await copyAndTrack(
join(__dirname, 'chart'),
join(this.projectPath, 'chart'),
this
)
const webApplicationChartPath = process.env.WEB_APPLICATION_CHART ?? path.join(__dirname, 'subchart')
const chartFilePath = path.join(webApplicationChartPath, 'Chart.yaml')
const chartFile = await read(chartFilePath)
//const { version } = yaml.parse(chartFile)
await mergeYAML(
path.join(this.projectPath, 'chart', 'Chart.yaml'),
path.join(__dirname, 'files', 'Chart.yaml.hbs'),
projectDescriptor, { forceOverwrite: true }
join(this.projectPath, 'chart', 'Chart.yaml'),
join(__dirname, 'files', 'Chart.yaml.hbs'),
projectDescriptor
)
await mergeYAML(
path.join(this.projectPath, 'chart', 'values.yaml'),
path.join(__dirname, 'files', 'values.yaml.hbs'),
projectDescriptor, { forceOverwrite: true }
join(this.projectPath, 'chart', 'values.yaml'),
join(__dirname, 'files', 'values.yaml.hbs'),
projectDescriptor
)
await this.runDependentMerging();
await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), this.newTrackingData);
}

@@ -64,9 +66,9 @@

// Re-applying the dependent merging part of other facets if necessary.
const dependentFacets = ['hana', 'xsuaa', 'auditlog', 'enterprise-messaging', 'destinations' , 'multitenancy', 'extensibility']
const dependentFacets = ['hana', 'xsuaa', 'auditlog', 'enterprise-messaging', 'destinations' , 'multitenancy', 'extensibility', 'approuter']
for (const facet of dependentFacets) {
const Template = require('../'+facet)
const template = new Template(this.projectPath, this.generator)
if (Template.hasFacet(await this.getEnv(), this.projectPath, this.options)) await template.runDependentMerging()
if (Template.hasFacet(await this.getEnv(), this.projectPath, this.options)) await template.runDependentMerging(this)
}
}
};

@@ -313,2 +313,3 @@ {

"title": "Health-check configuration",
"description": "[Deprecated] Use health instead",
"type": "object",

@@ -325,4 +326,3 @@ "additionalProperties": false,

"description": "HTTP path used by Kubernetes, to perform health-check calls.",
"type": "string",
"default": "/healthz"
"type": "string"
}

@@ -339,2 +339,22 @@ }

"description": "HTTP path used by Kubernetes, to perform health-check calls.",
"type": "string"
}
}
}
}
},
"health": {
"$id": "#/properties/health",
"title": "Health-check configuration",
"type": "object",
"additionalProperties": false,
"properties": {
"liveness": {
"$id": "#/properties/health/properties/liveness",
"description": "Liveness-probe configuration.",
"type": "object",
"additionalProperties": false,
"properties": {
"path": {
"description": "HTTP path used by Kubernetes, to perform liveness-probe calls.",
"type": "string",

@@ -344,2 +364,15 @@ "default": "/healthz"

}
},
"readiness": {
"$id": "#/properties/health/properties/readiness",
"description": "Readiness-probe configuration.",
"type": "object",
"additionalProperties": false,
"properties": {
"path": {
"description": "HTTP path used by Kubernetes, to perform readiness-probe calls.",
"type": "string",
"default": "/healthz"
}
}
}

@@ -367,6 +400,3 @@ }

"description": "Plain value of an environment variable.",
"type": [
"integer",
"string"
]
"type": ["integer", "string"]
},

@@ -459,6 +489,3 @@ {

"value": {
"type": [
"string",
"integer"
]
"type": ["string", "integer"]
},

@@ -529,3 +556,3 @@ "configMapKeyRef": {

"$id": "#/properties/envSecretNames",
"description": "List of Kubernetes Secret names, used as sources for the Pod's environment variables.",
"description": "[Deprecated] Use `envFrom` instead",
"type": "array",

@@ -535,5 +562,61 @@ "uniqueItems": true,

"$ref": "#/definitions/KubernetesName"
},
"default": []
}
},
"envFrom": {
"$id": "#/properties/envFrom",
"description": "List of sources to populate environment variables in the pod.",
"type": "array",
"default": [],
"items": {
"type": "object",
"oneOf": [
{
"additionalProperties": false,
"properties": {
"configMapRef": {
"description": "The contents of the target ConfigMap's Data field will represent the key-value pairs as environment variables.",
"properties": {
"name": {
"description": "Name of a ConfigMap.",
"type": "string"
},
"tpl": {
"description": "Flag which tells whether the name is a template string or not.",
"type": "boolean",
"default": false
}
},
"required": [ "name" ],
"additionalProperties": false,
"type": "object"
}
},
"required": [ "configMapRef" ]
},
{
"additionalProperties": false,
"properties": {
"secretRef": {
"description": "The contents of the target Secret's Data field will represent the key-value pairs as environment variables.",
"properties": {
"name": {
"description": "Name of a Secret.",
"type": "string"
},
"tpl": {
"description": "Flag which tells whether the name is a template string or not.",
"type": "boolean",
"default": false
}
},
"required": [ "name" ],
"additionalProperties": false,
"type": "object"
}
},
"required": [ "secretRef" ]
}
]
}
},
"expose": {

@@ -540,0 +623,0 @@ "$id": "#/properties/expose",

@@ -1,5 +0,6 @@

const path = require('path')
const { exists, copy } = require('../../../cds').utils
const { join } = require('path')
const { exists } = require('../../../cds').utils
const ProjectReader = require('../../util/projectReader')
const { mergeYAML } = require('../../util/merge')
const { copyAndTrack, parseMd5File, writeMd5File } = require('../../util/md5Tracking')
const { OPTION_DESTINATIONS } = require('../../constants')

@@ -13,9 +14,18 @@

async getDependencies() {
getDependencies() {
return [OPTION_DESTINATIONS]
}
async canRun() {
const projectDescriptor = await this.projectReader.read(this.options)
const { hasMta, hasHelm } = projectDescriptor.cap
if (!hasHelm && hasMta) {
throw `'cds add html5-repo' is not available for Cloud Foundry yet`
}
return true
}
static hasFacet(_, projectPath) {
// REVISIT: Should be detectable without helm charts
return exists(path.join(projectPath, 'chart', 'templates', 'html5-apps-repo-host.yaml'))
return exists(join(projectPath, 'chart', 'templates', 'html5-apps-repo-host.yaml'))
}

@@ -27,3 +37,3 @@

async runDependentMerging() {
async runDependentMerging(context = {}) {
const projectDescriptor = await this.projectReader.read(this.options)

@@ -33,4 +43,11 @@ const { appName, hasHelm } = projectDescriptor.cap

if (hasHelm) {
//in case facet is being added to the already exisiting charts folder
let isIndependentCommand = false
if(Object.keys(context).length == 0){
isIndependentCommand = true
context.projectPath = this.projectPath
context.oldTrackingData = context.newTrackingData = await parseMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'))
}
await mergeYAML(
path.join(this.projectPath, 'chart', 'values.yaml'),
join(this.projectPath, 'chart', 'values.yaml'),
{

@@ -58,10 +75,10 @@ html5_apps_repo_host: {

}
},
null, { forceOverwrite: true }
}
)
await copy(path.join(__dirname, 'files', '_html5_deployment_helpers.tpl'), path.join(this.projectPath, 'chart', 'templates', '_html5_deployment_helpers.tpl'))
await copy(path.join(__dirname, 'files', 'html5-apps-deployer-job.yaml'), path.join(this.projectPath, 'chart', 'templates', 'html5-apps-deployer-job.yaml'))
await copy(path.join(__dirname, 'files', 'html5-apps-repo-host.yaml'), path.join(this.projectPath, 'chart', 'templates', 'html5-apps-repo-host.yaml'))
await copyAndTrack(join(__dirname, 'files', '_html5_deployment_helpers.tpl'), join(this.projectPath, 'chart', 'templates', '_html5_deployment_helpers.tpl'), context)
await copyAndTrack(join(__dirname, 'files', 'html5-apps-deployer-job.yaml'), join(this.projectPath, 'chart', 'templates', 'html5-apps-deployer-job.yaml'), context)
await copyAndTrack(join(__dirname, 'files', 'html5-apps-repo-host.yaml'), join(this.projectPath, 'chart', 'templates', 'html5-apps-repo-host.yaml'), context)
if(isIndependentCommand) await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), context.newTrackingData)
}
}
}
const fs = require('fs').promises;
const os = require('os');
const path = require('path');
const { join, relative } = require('path');

@@ -20,3 +20,3 @@ const commandUtil = require('../../util/commandUtil');

static hasFacet(_, projectPath) {
return exists(path.join(projectPath, 'pom.xml'))
return exists(join(projectPath, 'pom.xml'))
}

@@ -42,3 +42,3 @@

const tempFolder = await fs.mkdtemp(path.join(os.tmpdir(), `${this.projectName}_`));
const tempFolder = await fs.mkdtemp(join(os.tmpdir(), `${this.projectName}_`));
try {

@@ -49,3 +49,3 @@ await commandUtil.spawnCommand('mvn', cmdLine, {

await copy(path.join(tempFolder, artifactId), this.projectPath);
await copy(join(tempFolder, artifactId), this.projectPath);
} catch (err) {

@@ -62,3 +62,3 @@ if (err.code === 'ENOENT' && err.path === 'mvn') {

async finalize() {
const relativeProjectPath = path.relative(this.cwd, this.projectPath);
const relativeProjectPath = relative(this.cwd, this.projectPath);
if (relativeProjectPath && relativeProjectPath !== '.') {

@@ -65,0 +65,0 @@ LOG.info(`Continue with 'cd ${relativeProjectPath}'`);

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

const path = require('path')
const { join } = require('path')
const cds = require('../../../cds')

@@ -20,2 +20,3 @@ const ProjectReader = require('../../util/projectReader')

}
return true
}

@@ -36,4 +37,4 @@

const cdsTemplateFile = forProfile ? 'cds.profile.package.json.hbs' : 'cds.package.json'
const cdsTemplatePath = path.join(__dirname, 'files', cdsTemplateFile)
await mergeJSON(path.join(this.projectPath, 'package.json'), cdsTemplatePath, projectDescriptor)
const cdsTemplatePath = join(__dirname, 'files', cdsTemplateFile)
await mergeJSON(join(this.projectPath, 'package.json'), cdsTemplatePath, projectDescriptor)
}

@@ -51,3 +52,3 @@ }

const mtaYAMLPath = path.join(this.projectPath, 'mta.yaml')
const mtaYAMLPath = join(this.projectPath, 'mta.yaml')
await mergeYAML(

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

const { join } = require('path');
const { exists, path } = require('../../../cds').utils
const { exists } = require('../../../cds').utils
const { copyFiles } = require('../../util/templateUtil')

@@ -20,3 +20,3 @@ const ProjectReader = require('../../util/projectReader');

if (!exists(join(this.projectPath, 'mta.yaml'))) {
await copyFiles(path.join(__dirname, 'files'), this.projectPath, projectDescriptor);
await copyFiles(join(__dirname, 'files'), this.projectPath, projectDescriptor);
}

@@ -23,0 +23,0 @@

@@ -10,5 +10,5 @@ const ProjectReader = require('../../util/projectReader')

async getDependencies() {
getDependencies() {
return [OPTION_MULTITENANCY, OPTION_TOGGLES, OPTION_EXTENSIBILITY]
}
}
{
"name": "cap-mtx-sidecar",
"dependencies": {
"@sap/cds": "^6.0.2",
"@sap/cds-mtxs": "^1.0.1",
"@sap/hdi-deploy": "^4.4.1",
"@sap/xssec": "^3.2.13",
"express": "^4.18.1",
"hdb": "^0.19.3",
"@sap/cds": "^6.3.1",
"@sap/cds-mtxs": "^1.3.1",
"@sap/hdi-deploy": "^4.5.1",
"@sap/xssec": "^3.2.14",
"express": "^4.18.2",
"hdb": "^0.19.5",
"passport": "^0.6.0"

@@ -16,5 +16,2 @@ },

},
"engines": {
"node": "^16.15.0"
},
"cds": {

@@ -21,0 +18,0 @@ "requires": {

@@ -0,5 +1,7 @@

const { join } = require('path')
const cds = require('../../../cds')
const { path, copy, exists } = cds.utils
const { copy, exists } = cds.utils
const ProjectReader = require('../../util/projectReader')
const { mergeJSON, mergeYAML, sortDependencies } = require('../../util/merge')
const { copyAndTrack, parseMd5File, writeMd5File } = require('../../util/md5Tracking')
const {

@@ -22,3 +24,3 @@ srvNode, srvJava, // Server

!!env.requires?.multitenancy || !!env.requires?.db?.multiTenant ||
this.isJava && exists(path.join(projectPath, 'mtx', 'sidecar')) || false
this.isJava && exists(join(projectPath, 'mtx', 'sidecar')) || false
}

@@ -30,11 +32,11 @@

if (isNodejs) {
const packageJSONPath = path.join(this.projectPath, 'package.json')
const packageJSONPath = join(this.projectPath, 'package.json')
const cdsTemplateFile = forProfile ? 'cds.package.json.hbs' : 'cds.package.json'
await mergeJSON(packageJSONPath, path.join(__dirname, 'files', cdsTemplateFile), projectDescriptor)
await mergeJSON(packageJSONPath, path.join(__dirname, 'files', 'dependencies.package.json'))
await mergeJSON(packageJSONPath, join(__dirname, 'files', cdsTemplateFile), projectDescriptor)
await mergeJSON(packageJSONPath, join(__dirname, 'files', 'dependencies.package.json'))
await sortDependencies(packageJSONPath)
} else if (isJava) {
const cdsrcJSONPath = path.join(this.projectPath, '.cdsrc.json')
await mergeJSON(cdsrcJSONPath, path.join(__dirname, 'files', 'java', '.cdsrc.json'))
await copy(path.join(__dirname, 'files', 'java', 'package.json'), path.join(this.projectPath, 'mtx', 'sidecar', 'package.json'))
const cdsrcJSONPath = join(this.projectPath, '.cdsrc.json')
await mergeJSON(cdsrcJSONPath, join(__dirname, 'files', 'java', '.cdsrc.json'))
await copy(join(__dirname, 'files', 'java', 'package.json'), join(this.projectPath, 'mtx', 'sidecar', 'package.json'))
}

@@ -44,3 +46,3 @@ await this.runDependentMerging()

async runDependentMerging() {
async runDependentMerging(context = {}) {
const projectDescriptor = await this.projectReader.read()

@@ -72,4 +74,4 @@ const { isNodejs, isJava, hasMta, hasHelm, hasApprouter, hasXsuaa, hasHana } = projectDescriptor.cap

relationships.push({
insert: [serviceManager, 'name'],
into: [mtxSidecar, 'requires', 'name'],
insert: [serviceManager, 'name'],
into: [mtxSidecar, 'requires', 'name'],
})

@@ -79,4 +81,4 @@ }

const templateMtaPath = path.join(__dirname, `files`, `mta.yaml.hbs`)
const mtaPath = path.join(this.projectPath, 'mta.yaml')
const templateMtaPath = join(__dirname, `files`, `mta.yaml.hbs`)
const mtaPath = join(this.projectPath, 'mta.yaml')
const mergingRules = { additions, overwrites, relationships }

@@ -86,23 +88,69 @@ await mergeYAML(mtaPath, templateMtaPath, projectDescriptor, mergingRules)

let isIndependentCommand = false
if (hasHelm) {
//in case facet is being added to the already exisiting charts folder
if (Object.keys(context).length == 0) {
isIndependentCommand = true
context.projectPath = this.projectPath
context.oldTrackingData = context.newTrackingData = await parseMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'))
}
await mergeYAML(
path.join(this.projectPath, 'chart', 'values.yaml'),
join(this.projectPath, 'chart', 'values.yaml'),
join(__dirname, 'files', 'values.yaml.hbs'),
projectDescriptor
)
await mergeYAML(
join(this.projectPath, 'chart', 'values.yaml'),
{
xsuaa: {
serviceOfferingName: 'saas-registry',
servicePlanName: 'application'
srv: {
envFrom: [
{
configMapRef: {
name: "{{ .Release.Name }}-mtxs-configmap",
tpl: true
}
}
]
}
},
null, { forceOverwrite: true }
projectDescriptor
)
//if (hasXsuaa) { // REVISIT: Can we get rid of this dependency?
await copy(
path.join(__dirname, 'files', 'xsuaa.yaml'),
path.join(this.projectPath, 'chart', 'templates', 'xsuaa.yaml')
if (isJava) {
await mergeYAML(
join(this.projectPath, 'chart', 'Chart.yaml'),
join(__dirname, 'files', 'chart.yaml'),
projectDescriptor,
{
additions: [{
ref: `web-application-sidecar`,
in: `dependencies`,
where: [{
property: 'alias',
isEqualTo: 'sidecar'
}]
}]
}
)
//}
await copy(
path.join(__dirname, 'files', 'saas-registry.yaml'),
path.join(this.projectPath, 'chart', 'templates', 'saas-registry.yaml')
}
const mtxsConfigmapPath = isNodejs
? join(__dirname, 'files', 'mtxs-configmap.yaml')
: join(__dirname, 'files', 'java', 'mtxs-configmap.yaml');
// add mtxs configmap
await copyAndTrack(
mtxsConfigmapPath,
join(this.projectPath, 'chart', 'templates', 'mtxs-configmap.yaml'),
context
)
await copyAndTrack(
join(__dirname, 'files', 'saas-registry.yaml'),
join(this.projectPath, 'chart', 'templates', 'saas-registry.yaml'),
context
)
if (isIndependentCommand) await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), context.newTrackingData)
}

@@ -113,3 +161,3 @@

const template = new ApprouterTemplate(this.projectPath, this.generator)
await template.runDependentMerging()
await template.runDependentMerging(context)
}

@@ -120,3 +168,3 @@

const template = new HanaTemplate(this.projectPath, this.generator)
await template.runDependentMerging()
await template.runDependentMerging(context)
}

@@ -126,4 +174,4 @@

await mergeJSON(
path.join(this.projectPath, 'xs-security.json'),
path.join(__dirname, 'files', 'xs-security.json.hbs'),
join(this.projectPath, 'xs-security.json'),
join(__dirname, 'files', 'xs-security.json.hbs'),
projectDescriptor,

@@ -135,6 +183,2 @@ {

where: [{ property: 'name', isEqualTo: '$XSAPPNAME.mtcallback' }],
}, {
ref: 'scope-subscriber',
in: 'scopes',
where: [{ property: 'name', isEqualTo: '$XSAPPNAME.cds.Subscriber' }],
}]

@@ -147,8 +191,10 @@ }

// REVISIT: Shared xs-security.json location for Helm and MTA?
await copy(
path.join(this.projectPath, 'xs-security.json'),
path.join(this.projectPath, 'chart', 'xs-security.json')
await copyAndTrack(
join(this.projectPath, 'xs-security.json'),
join(this.projectPath, 'chart', 'xs-security.json'),
context
)
if (isIndependentCommand) await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), context.newTrackingData)
}
}
}

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

const path = require('path');
const { join, relative } = require('path');
const { mkdirp } = require('../../../cds').utils

@@ -31,15 +31,12 @@ const { COMMAND_ADD, OPTION_JAVA, OPTION_NODEJS, URLS } = require('../../constants')

const env = await this.getEnv();
const { projectPath, projectName } = this
await copyFiles(join(__dirname, 'files'), projectPath, { projectName }, this.options.force)
const values = {
projectName: this.projectName
}
await copyFiles(path.join(__dirname, 'files'), this.projectPath, values, this.options.force)
await mkdirp(this.projectPath, env.folders.db);
await mkdirp(this.projectPath, env.folders.srv);
await mkdirp(this.projectPath, env.folders.app);
await mkdirp(projectPath, env.folders.db);
await mkdirp(projectPath, env.folders.srv);
await mkdirp(projectPath, env.folders.app);
}
async finalize() {
const relativeProjectPath = path.relative(this.cwd, this.projectPath);
const relativeProjectPath = relative(this.cwd, this.projectPath);
if (relativeProjectPath && relativeProjectPath !== '.') {

@@ -46,0 +43,0 @@ LOG.info(`Continue with 'cd ${relativeProjectPath}'`);

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

const path = require('path');
const { join } = require('path');
const { exists } = require('../../../cds').utils

@@ -17,4 +17,4 @@ const { copyFiles } = require('../../util/templateUtil')

if (exists(path.join(this.projectPath, 'Jenkinsfile')) ||
exists(path.join(this.projectPath, '.pipeline/config.yml'))) {
if (exists(join(this.projectPath, 'Jenkinsfile')) ||
exists(join(this.projectPath, '.pipeline/config.yml'))) {
throw new Error(`Pipeline support file exists. Use --force to overwrite.`);

@@ -27,3 +27,3 @@ }

async run() {
await copyFiles(path.join(__dirname, 'files'), this.projectPath, {}, this.options.force);
await copyFiles(join(__dirname, 'files'), this.projectPath, {}, this.options.force);
}

@@ -30,0 +30,0 @@

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

const path = require('path');
const { join } = require('path');
const { copyFiles } = require('../../util/templateUtil')

@@ -53,7 +53,7 @@ const commandUtil = require('../../util/commandUtil');

const folders = (await this.getEnv()).folders;
const dbFolder = path.join(this.projectPath, folders.db);
await copyFiles(path.join(__dirname, 'files', 'nodejs', 'db'), dbFolder, {}, this.options.force);
const dbFolder = join(this.projectPath, folders.db);
await copyFiles(join(__dirname, 'files', 'nodejs', 'db'), dbFolder, {}, this.options.force);
const srvFolder = path.join(this.projectPath, folders.srv);
await copyFiles(path.join(__dirname, 'files', 'nodejs', 'srv'), srvFolder, {
const srvFolder = join(this.projectPath, folders.srv);
await copyFiles(join(__dirname, 'files', 'nodejs', 'srv'), srvFolder, {
dbFolder: folders.db.replace(/[\\/]+$/, '')

@@ -60,0 +60,0 @@ }, this.options.force);

const cds = require('../../cds');
const path = require('path');
const TemplateUtil = require('../util/templateUtil');
const { PROJECT_TYPE } = require('../constants');

@@ -30,6 +28,5 @@ const { exists } = require('../../cds').utils;

* Returns an array of required templates. These templates will also be added if not already included.
* Declared async to allow complex calculation of the dependencies.
* @returns an array with depending templates, might be empty or null
*/
async getDependencies() {
getDependencies() {
}

@@ -36,0 +33,0 @@

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

const cds = require('../../../cds'), { path } = cds.utils
const { join } = require('path')
const ProjectReader = require('../../util/projectReader')

@@ -19,9 +19,9 @@ const { mergeJSON, sortDependencies } = require('../../util/merge')

if (isNodejs) {
const packageJSONPath = path.join(this.projectPath, 'package.json')
const packageJSONPath = join(this.projectPath, 'package.json')
const cdsTemplateFile = forProfile ? 'cds.package.json.hbs' : 'cds.package.json'
await mergeJSON(packageJSONPath, path.join(__dirname, 'files', cdsTemplateFile), projectDescriptor)
await mergeJSON(packageJSONPath, join(__dirname, 'files', cdsTemplateFile), projectDescriptor)
await sortDependencies(packageJSONPath)
} else if (isJava) {
const cdsrcPath = path.join(this.projectPath, '.cdsrc.json')
const cdsTemplateFile = path.join(__dirname, 'files', forProfile ? 'cdsrc.json.hbs' : 'cdsrc.json')
const cdsrcPath = join(this.projectPath, '.cdsrc.json')
const cdsTemplateFile = join(__dirname, 'files', forProfile ? 'cdsrc.json.hbs' : 'cdsrc.json')
await mergeJSON(cdsrcPath, cdsTemplateFile, projectDescriptor)

@@ -28,0 +28,0 @@ }

@@ -1,6 +0,5 @@

const path = require('path')
const cds = require('../../../cds')
const { copy } = cds.utils
const { join } = require('path')
const ProjectReader = require('../../util/projectReader')
const { mergeJSON, mergeYAML } = require('../../util/merge')
const { copyAndTrack, parseMd5File, writeMd5File } = require('../../util/md5Tracking')
const { srvNode, srvJava, xsuaa, mtxSidecar } = require('../_merging/registry-mta')

@@ -21,3 +20,3 @@ const { PROJECT_TYPE } = require('../../constants')

const { projectPath } = this
const templatePath = path.join(__dirname, 'files')
const templatePath = join(__dirname, 'files')
const projectDescriptor = await this.projectReader.read(this.options)

@@ -28,12 +27,12 @@ const projectType = await this.getProjectType();

if (projectType === PROJECT_TYPE.java) {
const cdsrcJSONPath = path.join(projectPath, '.cdsrc.json')
const cdsrcJSONPath = join(projectPath, '.cdsrc.json')
const cdsTemplateFile = forProfile ? 'cds.cdsrc.json.hbs' : 'cds.cdsrc.json'
const cdsTemplatePath = path.join(templatePath, cdsTemplateFile)
const cdsTemplatePath = join(templatePath, cdsTemplateFile)
await mergeJSON(cdsrcJSONPath, cdsTemplatePath, projectDescriptor)
} else if (projectType === PROJECT_TYPE.nodejs) {
const packageJSONPath = path.join(projectPath, 'package.json')
const packageJSONPath = join(projectPath, 'package.json')
const cdsTemplateFile = forProfile ? 'cds.package.json.hbs' : 'cds.package.json'
const cdsTemplatePath = path.join(templatePath, cdsTemplateFile)
const cdsTemplatePath = join(templatePath, cdsTemplateFile)
await mergeJSON(packageJSONPath, cdsTemplatePath, projectDescriptor)
const dependenciesTemplatePath = path.join(templatePath, 'dependencies.package.json')
const dependenciesTemplatePath = join(templatePath, 'dependencies.package.json')
await mergeJSON(packageJSONPath, dependenciesTemplatePath)

@@ -45,3 +44,3 @@ }

async runDependentMerging() {
async runDependentMerging( context = {}) {
const projectDescriptor = await this.projectReader.read(this.options)

@@ -52,3 +51,3 @@ const { isMultitenant, isExtensible, hasMta, hasHelm, isNodejs, isJava } = projectDescriptor.cap

const xsSecurity = await (async () => { try {
const models = await cds.load(path.join(this.projectPath, cds.env.folders.srv))
const models = await cds.load(join(this.projectPath, cds.env.folders.srv))
return cds.compile.to.xsuaa(models)

@@ -65,3 +64,3 @@ } catch (error) { /* ignore */ }

}))}
const xsSecurityPath = path.join(this.projectPath, 'xs-security.json')
const xsSecurityPath = join(this.projectPath, 'xs-security.json')
await mergeJSON(xsSecurityPath, xsSecurity, projectDescriptor, mergingSemantics)

@@ -74,3 +73,3 @@

const mtaYAMLPath = path.join(this.projectPath, 'mta.yaml')
const mtaYAMLPath = join(this.projectPath, 'mta.yaml')
const relationships = [{

@@ -97,16 +96,26 @@ insert: [xsuaa, 'name'],

if (hasHelm) {
await copy(
path.join(__dirname, 'files', 'xsuaa.yaml'),
path.join(this.projectPath, 'chart', 'templates', 'xsuaa.yaml')
//in case facet is being added to the already exisiting charts folder
let isIndependentCommand = false;
if(Object.keys(context).length == 0){
isIndependentCommand = true;
context.projectPath = this.projectPath;
context.oldTrackingData = context.newTrackingData = await parseMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'));
}
await copyAndTrack(
join(__dirname, 'files', 'xsuaa.yaml'),
join(this.projectPath, 'chart', 'templates', 'xsuaa.yaml'),
context
)
await mergeYAML(
path.join(this.projectPath, 'chart', 'values.yaml'),
path.join(__dirname, 'files', 'values.yaml.hbs'),
projectDescriptor, { forceOverwrite: true }
join(this.projectPath, 'chart', 'values.yaml'),
join(__dirname, 'files', 'values.yaml.hbs'),
projectDescriptor
)
// REVISIT: Shared xs-security.json location for Helm and MTA?
await copy(
path.join(this.projectPath, 'xs-security.json'),
path.join(this.projectPath, 'chart', 'xs-security.json')
await copyAndTrack(
join(this.projectPath, 'xs-security.json'),
join(this.projectPath, 'chart', 'xs-security.json'),
context
)
if(isIndependentCommand) await writeMd5File(join(this.projectPath, 'chart', '.cds-add-helm-files.md5'), context.newTrackingData);
}

@@ -120,10 +129,11 @@

const multitenancyTemplate = new MultitenancyTemplate(this.projectPath, this.generator)
await multitenancyTemplate.runDependentMerging()
await multitenancyTemplate.runDependentMerging(context)
}
if (isExtensible) {
const ExtensibilityTemplate = require(`../extensibility`)
const extensibilityTemplate = new ExtensibilityTemplate(this.projectPath, this.generator)
await extensibilityTemplate.runDependentMerging()
await extensibilityTemplate.runDependentMerging(context)
}
}
}

@@ -58,3 +58,3 @@ const YAML = require('@sap/cds-foss').yaml

async function mergeYAML(into, from, projectDescriptor, semantics) {
async function mergeYAML(into, from, projectDescriptor, semantics = {}) {
const target =

@@ -316,6 +316,23 @@ typeof into === 'string' ? await readYAML(into) :

async function removeFromYAML(name, keyPaths) {
const yaml = await readYAML(name)
for (const keyPath of keyPaths) {
let node = yaml
const keys = keyPath.split('.')
for (const [index, key] of keys.entries()) {
if (index === keys.length - 1) {
node.delete(key)
} else {
node = node.get(key)
}
}
}
await writeYAML(name, yaml)
}
module.exports = {
sortDependencies,
mergeJSON,
mergeYAML
mergeYAML,
removeFromYAML
}

@@ -92,8 +92,11 @@ const path = require('path')

const root = this.projectPath
const nullLogger = { debug: () => {}, log: () => {}, warn: () => {}, error: () => {}, write: () => {}}
const buildTasks = await new BuildTaskFactory(nullLogger, cds).getTasks({ root, resolve: true, mta: false })
const nullLogger = { debug: () => { }, log: () => { }, warn: () => { }, error: () => { }, write: () => { } }
// no file path resolving as the directories might not exist - e.g. cds add will create the mtx/sidecar folder
const buildTasks = await new BuildTaskFactory(nullLogger, cds).getTasks({ root: this.projectPath, resolve: false, mta: false })
await Promise.all(buildTasks.map(async (task) => {
const relDestPath = path.relative(root, task.dest)?.replace(/\\/g, '/')
const srcPath = path.resolve(this.projectPath, task.src)
const srcFolder = path.basename(srcPath)
const relDestPath = path.join(env?.build?.target ?? "gen", task.dest || task.src)?.replace(/\\/g, '/')

@@ -104,3 +107,3 @@ switch (task.for) {

if (this._hasHanaServiceBinding(env)) {
cap.db.push({ path: relDestPath, name: path.basename(task.src) })
cap.db.push({ path: relDestPath, name: srcFolder })
}

@@ -114,4 +117,4 @@ break

path: relDestPath,
name: path.basename(task.src),
ext: await this._getJavaExtDescriptor(task)
name: srcFolder,
ext: await this._getJavaExtDescriptor(srcPath)
}

@@ -124,3 +127,3 @@ break

path: relDestPath,
name: path.basename(task.src)
name: srcFolder
}

@@ -149,8 +152,8 @@ break

/**
* Determines java specific properties for the given build task.
* @param {object} task
* Determines java specific properties for the given module source path.
* @param {object} srcPath
*/
async _getJavaExtDescriptor(task) {
async _getJavaExtDescriptor(srcPath) {
// by default spring-boot:repackage is used creating an executable jar archive
const pomJson = await this._parseXml(path.join(task.src, 'pom.xml'))
const pomJson = await this._parseXml(path.join(srcPath, 'pom.xml'))
if (pomJson) {

@@ -157,0 +160,0 @@ const dependencies = pomJson?.project?.dependencies?.[0]?.dependency

{
"name": "@sap/cds-dk",
"version": "6.3.2",
"version": "6.4.0",
"description": "Command line client and development toolkit for the SAP Cloud Application Programming Model",

@@ -19,3 +19,3 @@ "homepage": "https://cap.cloud.sap/",

"dependencies": {
"@sap/cds": "^6.3.2",
"@sap/cds": "^6.4.0",
"@sap/cds-foss": "^4",

@@ -38,3 +38,3 @@ "@sap/eslint-plugin-cds": "^2.6.0",

"optionalDependencies": {
"@sap/cds-mtxs": "^1.3.0",
"@sap/cds-mtxs": "^1.4.0",
"sqlite3": "^5.0.4"

@@ -41,0 +41,0 @@ },

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

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