@sap/cds-dk 9.4.3 → 9.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +115 -0
- package/bin/compile/index.js +1 -1
- package/bin/env.js +3 -3
- package/bin/export.js +1 -1
- package/bin/help.js +0 -1
- package/bin/import.js +8 -3
- package/bin/repl.js +7 -11
- package/bin/up.js +159 -23
- package/bin/util/containerize.js +79 -25
- package/bin/version.js +4 -4
- package/lib/bind/k8s.js +1 -1
- package/lib/build/plugins/helm/files/templates/_deployment_helpers.tpl +1 -1
- package/lib/build/plugins/helm/index.js +1 -1
- package/lib/build/provider/hana/2migration.js +16 -24
- package/lib/build/provider/hana/index.js +1 -1
- package/lib/build/provider/hana/template/.hdiconfig-all +7 -1
- package/lib/build/provider/hana/template/package.json +1 -1
- package/lib/build/provider/internalBuildPlugin.js +15 -1
- package/lib/build/provider/java/index.js +12 -1
- package/lib/build/provider/mtx-sidecar/index.js +2 -1
- package/lib/build/provider/nodejs/index.js +2 -1
- package/lib/build/util.js +36 -19
- package/lib/compile/to_openapi.js +1 -5
- package/lib/import/common.js +9 -2
- package/lib/import/odata/ParserContext.js +1 -0
- package/lib/import/odata/v4parser.js +57 -25
- package/lib/import/openapi/importOpenAPI.js +6 -1
- package/lib/init/constants.js +1 -1
- package/lib/init/index.js +20 -6
- package/lib/init/merge.js +16 -0
- package/lib/init/projectReader.js +34 -8
- package/lib/init/registries/mta.js +2 -2
- package/lib/init/template/ams/index.js +3 -3
- package/lib/init/template/app-frontend/files/app-package.json.hbs +1 -7
- package/lib/init/template/app-frontend/files/ui5.yaml.hbs +21 -1
- package/lib/init/template/app-frontend/index.js +2 -6
- package/lib/init/template/application-logging/index.js +11 -16
- package/lib/init/template/approuter/files/mta.yaml.hbs +0 -2
- package/lib/init/template/approuter/index.js +13 -10
- package/lib/init/template/attachments/index.js +4 -2
- package/lib/init/template/audit-logging/index.js +4 -2
- package/lib/init/template/cloud-logging/index.js +6 -5
- package/lib/init/template/connectivity/index.js +2 -2
- package/lib/init/template/console/files/package.json +5 -0
- package/lib/init/template/console/index.js +25 -0
- package/lib/init/template/containerize/index.js +4 -6
- package/lib/init/template/data/as-json.js +18 -20
- package/lib/init/template/destination/index.js +4 -2
- package/lib/init/template/dynatrace/files/package.json.hbs +2 -2
- package/lib/init/template/dynatrace/index.js +4 -4
- package/lib/init/template/enterprise-messaging/files/mta.yaml.hbs +3 -1
- package/lib/init/template/enterprise-messaging/index.js +4 -2
- package/lib/init/template/enterprise-messaging-shared/index.js +4 -2
- package/lib/init/template/github-actions/files/workflows/cf.yaml.hbs +16 -1
- package/lib/init/template/github-actions/files/workflows/release.yaml.hbs +2 -2
- package/lib/init/template/github-actions/files/workflows/test.yaml.hbs +20 -0
- package/lib/init/template/github-actions/index.js +7 -10
- package/lib/init/template/hana/files/db/package.json +2 -2
- package/lib/init/template/hana/files/mta.yaml.hbs +0 -4
- package/lib/init/template/hana/index.js +7 -9
- package/lib/init/template/helm/index.js +8 -10
- package/lib/init/template/helm-unified-runtime/index.js +1 -4
- package/lib/init/template/html5-repo/files/app-package.json.hbs +1 -7
- package/lib/init/template/html5-repo/files/ui5.yaml.hbs +21 -1
- package/lib/init/template/html5-repo/index.js +14 -18
- package/lib/init/template/ias/files/values.yaml.hbs +6 -6
- package/lib/init/template/ias/index.js +13 -21
- package/lib/init/template/java/index.js +14 -0
- package/lib/init/template/kafka/index.js +4 -2
- package/lib/init/template/{containerize → kyma}/files/containerize.yaml.hbs +17 -2
- package/lib/init/template/kyma/index.js +129 -5
- package/lib/init/template/malware-scanner/files/mta.yaml.hbs +3 -1
- package/lib/init/template/malware-scanner/files/values.yaml +3 -1
- package/lib/init/template/malware-scanner/index.js +4 -2
- package/lib/init/template/multitenancy/files/mta.yaml.hbs +1 -3
- package/lib/init/template/multitenancy/files/values.yaml.hbs +8 -0
- package/lib/init/template/multitenancy/index.js +15 -7
- package/lib/init/template/nodejs/files/.vscode/extensions.json +0 -3
- package/lib/init/template/nodejs/files/package.json.hbs +1 -1
- package/lib/init/template/pipeline/files/app-package.json.hbs +1 -7
- package/lib/init/template/pipeline/files/ui5.yaml.hbs +21 -1
- package/lib/init/template/pipeline/index.js +1 -2
- package/lib/init/template/portal/files/mta.yaml.hbs +5 -3
- package/lib/init/template/portal/index.js +8 -8
- package/lib/init/template/postgres/index.js +2 -2
- package/lib/init/template/redis/index.js +2 -3
- package/lib/init/template/redis-messaging/index.js +2 -3
- package/lib/init/template/sample/files/_i18n/i18n_de.properties +21 -0
- package/lib/init/template/sample/files/_i18n/i18n_en.properties +21 -0
- package/lib/init/template/sample/files/_i18n/i18n_fr.properties +21 -0
- package/lib/init/template/sample/files/_i18n/messages_de.properties +34 -0
- package/lib/init/template/sample/files/_i18n/messages_en.properties +34 -0
- package/lib/init/template/sample/files/_i18n/messages_fr.properties +34 -0
- package/lib/init/template/sample/files/app/_i18n/i18n.properties +13 -25
- package/lib/init/template/sample/files/app/_i18n/i18n_de.properties +13 -25
- package/lib/init/template/sample/files/app/admin-authors/fiori-service.cds +52 -0
- package/lib/init/template/sample/files/app/admin-authors/webapp/Component.js.hbs +3 -0
- package/lib/init/template/sample/files/app/admin-authors/webapp/i18n/i18n.properties +3 -0
- package/lib/init/template/sample/files/app/admin-authors/webapp/i18n/i18n_de.properties +3 -0
- package/lib/init/template/sample/files/app/admin-authors/webapp/i18n/i18n_en.properties +3 -0
- package/lib/init/template/sample/files/app/admin-authors/webapp/manifest.json +130 -0
- package/lib/init/template/sample/files/app/admin-books/fiori-service.cds +81 -88
- package/lib/init/template/sample/files/app/admin-books/webapp/Component.js.hbs +3 -0
- package/lib/init/template/sample/files/app/admin-books/webapp/i18n/i18n.properties +3 -3
- package/lib/init/template/sample/files/app/admin-books/webapp/i18n/i18n_de.properties +3 -3
- package/lib/init/template/sample/files/app/admin-books/webapp/i18n/i18n_en.properties +3 -3
- package/lib/init/template/sample/files/app/admin-books/webapp/manifest.json +24 -48
- package/lib/init/template/sample/files/app/appconfig/fioriSandboxConfig.json +56 -5
- package/lib/init/template/sample/files/app/browse/fiori-service.cds +30 -30
- package/lib/init/template/sample/files/app/browse/webapp/Component.js.hbs +3 -0
- package/lib/init/template/sample/files/app/browse/webapp/i18n/i18n.properties +3 -4
- package/lib/init/template/sample/files/app/browse/webapp/i18n/i18n_de.properties +3 -3
- package/lib/init/template/sample/files/app/browse/webapp/i18n/i18n_en.properties +3 -4
- package/lib/init/template/sample/files/app/browse/webapp/manifest.json +19 -24
- package/lib/init/template/sample/files/app/common.cds +127 -158
- package/lib/init/template/sample/files/app/fiori-apps.html +50 -0
- package/lib/init/template/sample/files/app/genres/fiori-service.cds +33 -0
- package/lib/init/template/sample/files/app/genres/tree-view.cds +42 -0
- package/lib/init/template/sample/files/app/genres/value-help.cds +6 -0
- package/lib/init/template/sample/files/app/genres/webapp/Component.js.hbs +3 -0
- package/lib/init/template/sample/files/app/genres/webapp/i18n/i18n.properties +3 -0
- package/lib/init/template/sample/files/app/genres/webapp/i18n/i18n_de.properties +3 -0
- package/lib/init/template/sample/files/app/genres/webapp/i18n/i18n_en.properties +3 -0
- package/lib/init/template/sample/files/app/genres/webapp/manifest.json +126 -0
- package/lib/init/template/sample/files/app/services.cds +6 -2
- package/lib/init/template/sample/files/db/currencies.cds +13 -0
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Books.csv +5 -5
- package/lib/init/template/sample/files/db/data/{sap.capire.bookshop-Books_texts.csv → sap.capire.bookshop-Books.texts.csv} +4 -4
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Genres.csv +42 -15
- package/lib/init/template/sample/files/db/data/sap.capire.bookshop-Genres.texts.csv +43 -0
- package/lib/init/template/sample/files/db/data/sap.common-Currencies.csv +12 -0
- package/lib/init/template/sample/files/db/data/sap.common-Currencies.texts.csv +15 -0
- package/lib/init/template/sample/files/db/hana/index.cds +10 -0
- package/lib/init/template/sample/files/db/schema.cds +35 -22
- package/lib/init/template/sample/files/db/sqlite/index.cds +10 -0
- package/lib/init/template/sample/files/package.json.hbs +14 -1
- package/lib/init/template/sample/files/srv/access-control.cds +3 -0
- package/lib/init/template/sample/files/srv/admin-service.cds +3 -2
- package/lib/init/template/sample/files/srv/cat-service.cds +7 -11
- package/lib/init/template/sample/index.js +40 -18
- package/lib/init/template/sqlite/files/package.json.hbs +13 -0
- package/lib/init/template/sqlite/index.js +1 -1
- package/lib/init/template/telemetry/index.js +1 -3
- package/lib/init/template/typescript/files/package.json +1 -1
- package/lib/init/template/workzone-standard/files/mta.yaml.hbs +0 -5
- package/lib/init/template/workzone-standard/index.js +0 -1
- package/lib/init/template/xsuaa/files/mta.yaml.hbs +4 -0
- package/lib/init/template/xsuaa/index.js +7 -6
- package/lib/lint/Linter.js +10 -4
- package/lib/lint/eslintHelp.json +1 -1
- package/lib/mtx/tenant_action.js +12 -4
- package/lib/util/checksum.js +41 -0
- package/lib/util/fs.js +8 -1
- package/lib/util/glob.js +26 -13
- package/lib/util/question.js +60 -7
- package/npm-shrinkwrap.json +141 -118
- package/package.json +2 -2
- package/lib/init/template/app-frontend/files/ui5-deploy.yaml.hbs +0 -25
- package/lib/init/template/github-actions/files/cf-setup/action.yaml +0 -53
- package/lib/init/template/html5-repo/files/ui5-deploy.yaml.hbs +0 -25
- package/lib/init/template/pipeline/files/ui5-deploy.yaml.hbs +0 -25
- package/lib/init/template/sample/files/app/admin-books/webapp/Component.js +0 -8
- package/lib/init/template/sample/files/app/browse/webapp/Component.js +0 -7
- package/lib/init/template/sample/files/app/index.html +0 -32
- package/lib/init/template/sqlite/files/package.json +0 -5
- /package/lib/init/template/{helm → kyma}/files/Chart.yaml.hbs +0 -0
- /package/lib/init/template/{helm → kyma}/files/values.schema.json +0 -0
- /package/lib/init/template/{helm → kyma}/files/values.yaml.hbs +0 -0
package/bin/util/containerize.js
CHANGED
|
@@ -2,7 +2,8 @@ const cds = require('../../lib/cds')
|
|
|
2
2
|
const { path } = cds.utils
|
|
3
3
|
const { join } = path
|
|
4
4
|
const { execSync } = require('node:child_process')
|
|
5
|
-
const { highlight } = require('../../lib/util/term')
|
|
5
|
+
const { highlight, info } = require('../../lib/util/term')
|
|
6
|
+
const { calcDirChecksum } = require('../../lib/util/checksum')
|
|
6
7
|
|
|
7
8
|
const buildpacks = new Set([
|
|
8
9
|
'java', 'nodejs', 'sap-machine', 'executable-jar', 'spring-boot', 'syft'
|
|
@@ -17,15 +18,20 @@ const keyProcessorMap = {
|
|
|
17
18
|
buildpack: processBuildpack
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
const run = cmd => {
|
|
21
|
+
const run = (cmd, { continueOnFail = false, silent = false } = {}) => {
|
|
21
22
|
cmd = Array.isArray(cmd) ? cmd.join(' ') : cmd
|
|
22
23
|
console.log(highlight(cmd))
|
|
23
24
|
try {
|
|
24
25
|
return execSync(cmd, {
|
|
25
|
-
stdio: 'inherit',
|
|
26
|
+
stdio: silent ? 'pipe' : 'inherit',
|
|
26
27
|
env: { ...process.env, FORCE_COLOR: cds.utils.colors.enabled }
|
|
27
28
|
})
|
|
28
29
|
} catch (error) {
|
|
30
|
+
if (continueOnFail) {
|
|
31
|
+
if (!silent)
|
|
32
|
+
console.error(error.message)
|
|
33
|
+
return
|
|
34
|
+
}
|
|
29
35
|
throw error.message
|
|
30
36
|
}
|
|
31
37
|
}
|
|
@@ -72,41 +78,46 @@ function processBuildpack(bp, name, tag, clearCache = false) {
|
|
|
72
78
|
* @param {string} filename - The path to the YAML file to parse.
|
|
73
79
|
* @param {string} [repoOpt=''] - Optional repository override. If not provided, uses the repository defined in the YAML file.
|
|
74
80
|
* @param {boolean} [clearCache=false] - Whether to clear cache for buildpack builds.
|
|
75
|
-
* @returns {{
|
|
81
|
+
* @returns {Promise<{
|
|
76
82
|
* commands: Array<{
|
|
77
83
|
* name: string,
|
|
78
84
|
* tag: string,
|
|
79
85
|
* buildCmd: Array<string>,
|
|
80
86
|
* tagCmd: Array<string>,
|
|
81
|
-
* pushCmd: Array<string
|
|
87
|
+
* pushCmd: Array<string>,
|
|
88
|
+
* image: string,
|
|
89
|
+
* checksum: string|null
|
|
90
|
+
* path: string
|
|
82
91
|
* }>,
|
|
83
92
|
* before_all: Array<Array<string>>,
|
|
84
93
|
* repository: string
|
|
85
|
-
* }} An object containing the commands for each module, any global pre-commands, and the repository name.
|
|
94
|
+
* }>} An object containing the commands for each module, any global pre-commands, and the repository name.
|
|
86
95
|
* @throws {Error} If modules are not defined in the YAML file or if build-parameters are invalid.
|
|
87
96
|
*/
|
|
88
|
-
function parseYAML(filename, repoOpt = '', options) {
|
|
97
|
+
async function parseYAML(filename, repoOpt = '', options) {
|
|
89
98
|
const file = cds.load.yaml(join(cds.root, filename))
|
|
90
99
|
const { repository: repoFile, modules, tag: globalTag = 'latest' } = file
|
|
91
100
|
const repository = repoOpt || repoFile
|
|
92
101
|
const before_all = file['before-all'] ? file['before-all'].map(c => c.trim().split(' ')) : []
|
|
93
|
-
if (!modules) throw
|
|
94
|
-
|
|
95
|
-
const commands = modules.map(m => {
|
|
102
|
+
if (!modules) throw `no modules defined in ${filename}`
|
|
103
|
+
const commands = await Promise.all(modules.map(async (m) => {
|
|
96
104
|
const name = m.name, tag = m.tag || globalTag, bp = m['build-parameters']
|
|
97
|
-
const source = `${name}:${tag}`, repoImg = `${repository}/${source}`
|
|
105
|
+
const rawImg = `${repository}/${name}`, source = `${name}:${tag}`, repoImg = `${repository}/${source}`
|
|
98
106
|
const key = Object.keys(bp)[0]
|
|
99
107
|
const buildType = keyProcessorMap[key]
|
|
100
|
-
|
|
108
|
+
|
|
109
|
+
if (!buildType) throw `'build-parameters' ${Object.keys(bp)} in ${filename} is invalid`
|
|
101
110
|
return {
|
|
102
|
-
name,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
tagCmd: ['docker', 'tag', source, repoImg],
|
|
107
|
-
|
|
111
|
+
name,
|
|
112
|
+
tag,
|
|
113
|
+
buildCmd: buildType(bp, name, tag, key === 'buildpack' && options.clearCache),
|
|
114
|
+
pushCmd: ['docker', 'push', repoImg],
|
|
115
|
+
tagCmd: [['docker', 'tag', source, repoImg]],
|
|
116
|
+
image: rawImg,
|
|
117
|
+
source,
|
|
118
|
+
path: bp.buildpack?.path
|
|
108
119
|
}
|
|
109
|
-
})
|
|
120
|
+
}))
|
|
110
121
|
return { commands, before_all, repository }
|
|
111
122
|
}
|
|
112
123
|
|
|
@@ -117,26 +128,69 @@ function parseYAML(filename, repoOpt = '', options) {
|
|
|
117
128
|
*/
|
|
118
129
|
async function executeModules(modules, options) {
|
|
119
130
|
for (const m of modules) {
|
|
120
|
-
|
|
131
|
+
if (m.checksum && process.env.SKIP_CHECK != 'true') {
|
|
132
|
+
try {
|
|
133
|
+
run(`docker inspect --format='{{index .RepoTags 0}}' ${m.image}:${m.checksum}`, { silent: true })
|
|
134
|
+
console.log(info(`image ${m.image}:${m.checksum} already exists – skipping build and push`))
|
|
135
|
+
continue
|
|
136
|
+
} catch (error) {
|
|
137
|
+
// ignore
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
121
141
|
for (const cmd of m.buildCmd) run(cmd)
|
|
122
142
|
if (options.push) {
|
|
123
|
-
|
|
143
|
+
for (const cmd of m.tagCmd) run(cmd)
|
|
124
144
|
run(m.pushCmd)
|
|
125
145
|
}
|
|
126
146
|
}
|
|
127
147
|
}
|
|
128
148
|
|
|
149
|
+
/**
|
|
150
|
+
* Calculates checksums for the specified modules based on their directory contents.
|
|
151
|
+
* @param {*} modules - The list of modules to calculate checksums for.
|
|
152
|
+
* @param {string} filename - The filename to include in the checksum calculation.
|
|
153
|
+
*/
|
|
154
|
+
async function calculateChecksums(modules, filename) {
|
|
155
|
+
for (const m of modules) {
|
|
156
|
+
if (m.path) {
|
|
157
|
+
m.checksum = await calcDirChecksum(
|
|
158
|
+
join(cds.root, m.path),
|
|
159
|
+
(dir) => !dir.includes('node_modules'),
|
|
160
|
+
'sha256',
|
|
161
|
+
[
|
|
162
|
+
join(cds.root, filename),
|
|
163
|
+
join(cds.root, 'package.json')
|
|
164
|
+
]
|
|
165
|
+
)
|
|
166
|
+
m.tagCmd = m.tagCmd
|
|
167
|
+
.concat(m.checksum ? [['docker', 'tag', m.source, `${m.image}:${m.checksum}`]] : [])
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
129
172
|
/**
|
|
130
173
|
* Main function to containerize modules based on a YAML configuration file.
|
|
131
174
|
* @param {string} filename - The path to the YAML configuration file.
|
|
132
175
|
* @param {{ push: boolean, clearCache: boolean }} options - Options object, e.g., { push: true } to push images after building.
|
|
133
|
-
* @returns {Promise<
|
|
176
|
+
* @returns {Promise<Array<{
|
|
177
|
+
* name: string,
|
|
178
|
+
* tag: string,
|
|
179
|
+
* buildCmd: Array<string>,
|
|
180
|
+
* tagCmd: Array<string>,
|
|
181
|
+
* pushCmd: Array<string>,
|
|
182
|
+
* image: string,
|
|
183
|
+
* checksum: string|null
|
|
184
|
+
* path: string
|
|
185
|
+
* }>} - The list of modules that were containerized.
|
|
134
186
|
*/
|
|
135
|
-
async function containerize(filename, options = {
|
|
136
|
-
const { repository, before_all, commands: modules } = parseYAML(filename, '', options)
|
|
187
|
+
async function containerize(filename = 'containerize.yaml', options = { clearCache: !!process.env.CLEAR_CACHE, push: true }) {
|
|
188
|
+
const { repository, before_all, commands: modules } = await parseYAML(filename, '', options)
|
|
137
189
|
if (!repository || !modules) return
|
|
138
|
-
for (const cmd of before_all)
|
|
190
|
+
for (const cmd of before_all) run(cmd)
|
|
191
|
+
await calculateChecksums(modules, filename)
|
|
139
192
|
await executeModules(modules, options)
|
|
193
|
+
return modules
|
|
140
194
|
}
|
|
141
195
|
|
|
142
196
|
module.exports = { containerize }
|
package/bin/version.js
CHANGED
|
@@ -52,7 +52,7 @@ function list_versions (args, options) {
|
|
|
52
52
|
|
|
53
53
|
process.stdout.isTTY && console.log()
|
|
54
54
|
if (options.markdown || options.info) {
|
|
55
|
-
_markdown (versions)
|
|
55
|
+
_markdown (versions, options)
|
|
56
56
|
} else {
|
|
57
57
|
const mark = !colors ? s => s : require('../lib/util/term').info
|
|
58
58
|
for (let each of Object.keys(versions)) console.log(`${mark(each)}: ${versions[each]}`)
|
|
@@ -81,7 +81,7 @@ function info({ root: cwd = process.cwd() }) {
|
|
|
81
81
|
|
|
82
82
|
// Sort entries, with @sap/cds packages on top, followed by @cap-js packages
|
|
83
83
|
const keys = Object.keys(versions).sort(), sorted={}
|
|
84
|
-
for (let k of ['@sap/cds'
|
|
84
|
+
for (let k of ['@sap/cds']) if (!(k in sorted)) sorted[k] = versions[k]
|
|
85
85
|
for (let k of keys) if (!(k in sorted) && k.startsWith('@sap/cds')) sorted[k] = versions[k]
|
|
86
86
|
for (let k of keys) if (!(k in sorted) && k.startsWith('@cap-js')) sorted[k] = versions[k]
|
|
87
87
|
for (let k of keys) if (!(k in sorted)) sorted[k] = versions[k]
|
|
@@ -115,9 +115,9 @@ function _versions_from(pkg_path, pkg_label) {
|
|
|
115
115
|
return versions
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
function _markdown (versions) {
|
|
118
|
+
function _markdown (versions, { root: cwd = process.cwd() }) {
|
|
119
119
|
const pkg = { name:'', repository:'', version:'' }; try {
|
|
120
|
-
Object.assign (pkg, require (resolve('package.json')))
|
|
120
|
+
Object.assign (pkg, require (require.resolve('./package.json', { paths:[cwd] })))
|
|
121
121
|
} catch (e) {/* ignored */}
|
|
122
122
|
const repo = pkg.repository.url || pkg.repository || 'https://github.com/<your/repo>'
|
|
123
123
|
const valLength = Math.max(repo.length, versions.home.length)
|
package/lib/bind/k8s.js
CHANGED
|
@@ -32,7 +32,7 @@ module.exports = new class K8SBind extends require('./plugin') {
|
|
|
32
32
|
|
|
33
33
|
services4(app) {
|
|
34
34
|
const { execSync } = require('node:child_process')
|
|
35
|
-
const json = cmd => JSON.parse(execSync(cmd, { encoding: 'utf8' }))
|
|
35
|
+
const json = cmd => JSON.parse(execSync(cmd, { encoding: 'utf8', maxBuffer: 10 * 1024 * 1024 }))
|
|
36
36
|
|
|
37
37
|
const bindings = json('kubectl get servicebindings -o json').items
|
|
38
38
|
.filter(b => b.metadata.name.startsWith(app))
|
|
@@ -23,7 +23,7 @@ copied from web-application: web-application.fullname
|
|
|
23
23
|
*/}}
|
|
24
24
|
{{- define "cap.deploymentHost" -}}
|
|
25
25
|
{{- if .deployment.expose.host }}
|
|
26
|
-
{{- .deployment.expose.host }}
|
|
26
|
+
{{- tpl .deployment.expose.host . }}
|
|
27
27
|
{{- else }}
|
|
28
28
|
{{- $name := (include "cap.web-application.fullname" .) }}
|
|
29
29
|
{{- if hasPrefix $name .Release.Namespace }}
|
|
@@ -27,7 +27,7 @@ module.exports = class HelmBuildPlugin extends Plugin {
|
|
|
27
27
|
|
|
28
28
|
async build() {
|
|
29
29
|
if (!HelmBuildPlugin.hasTask()) {
|
|
30
|
-
this.pushMessage("Helm Chart not found. Execute `cds add
|
|
30
|
+
this.pushMessage("Helm Chart not found. Execute `cds add kyma` to add the helm chart.", Plugin.WARNING)
|
|
31
31
|
return
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -48,31 +48,23 @@ function _compileToHana(model, options, beforeImage) {
|
|
|
48
48
|
let migrations = []
|
|
49
49
|
let afterImage
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
definitions.push({ name, suffix, sql: content })
|
|
67
|
-
}
|
|
51
|
+
const result = cds.compile.to.hana(model, options, beforeImage);
|
|
52
|
+
|
|
53
|
+
for (const [content, { file }] of result) {
|
|
54
|
+
switch (file) {
|
|
55
|
+
case 'deletions.json':
|
|
56
|
+
break
|
|
57
|
+
case 'migrations.json':
|
|
58
|
+
migrations = content
|
|
59
|
+
break
|
|
60
|
+
case 'afterImage.json':
|
|
61
|
+
afterImage = content
|
|
62
|
+
break
|
|
63
|
+
default: {
|
|
64
|
+
const { name, ext: suffix } = path.parse(file)
|
|
65
|
+
definitions.push({ name, suffix, sql: content })
|
|
68
66
|
}
|
|
69
67
|
}
|
|
70
|
-
} else {
|
|
71
|
-
// compatibility with cds < 8.0.0
|
|
72
|
-
const result = cdsc.to.hdi.migration(cds.minify(model), options, beforeImage)
|
|
73
|
-
definitions = result.definitions
|
|
74
|
-
migrations = result.migrations
|
|
75
|
-
afterImage = result.afterImage
|
|
76
68
|
}
|
|
77
69
|
let migrationTableNames = new Set()
|
|
78
70
|
if (afterImage) {
|
|
@@ -97,7 +89,7 @@ function _compileToHana(model, options, beforeImage) {
|
|
|
97
89
|
* @param {String} srcPath Fully qualified path of the directory containing .hdbmigrationtable files
|
|
98
90
|
* @param {String} migration the migration descriptor
|
|
99
91
|
* @param {String} tableSql SQL TABLE definition
|
|
100
|
-
* @returns {Object} Providing access to 'content' and 'fileName'.
|
|
92
|
+
* @returns {Promise<Object>} Providing access to 'content' and 'fileName'.
|
|
101
93
|
*/
|
|
102
94
|
async function _2migrationtable(srcPath, migration, tableSql) {
|
|
103
95
|
let migrationTableModel = null
|
|
@@ -586,7 +586,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
586
586
|
/**
|
|
587
587
|
* Returns all hana native artifacts located in db/src/** workspace folders.
|
|
588
588
|
* @param {Array} workspacePaths Array of workspace paths, 'cds.root' is excluded from the list
|
|
589
|
-
* @returns {Array} Array of workspace files, each entry contains the db src directory,
|
|
589
|
+
* @returns {Promise<Array>} Array of workspace files, each entry contains the db src directory,
|
|
590
590
|
* the relative file path and the file name.
|
|
591
591
|
*/
|
|
592
592
|
async _getWorkspaceFiles(workspacePaths) {
|
|
@@ -167,6 +167,12 @@
|
|
|
167
167
|
},
|
|
168
168
|
"hdbschedulerjob" : {
|
|
169
169
|
"plugin_name" : "com.sap.hana.di.schedulerjob"
|
|
170
|
+
},
|
|
171
|
+
"hdblogicalschema" : {
|
|
172
|
+
"plugin_name" : "com.sap.hana.di.logicalschema"
|
|
173
|
+
},
|
|
174
|
+
"hdblogicalschemaconfig" : {
|
|
175
|
+
"plugin_name" : "com.sap.hana.di.logicalschema.config"
|
|
170
176
|
}
|
|
171
177
|
}
|
|
172
|
-
}
|
|
178
|
+
}
|
|
@@ -4,6 +4,7 @@ const cds = require('../../cds')
|
|
|
4
4
|
const Plugin = require('../plugin')
|
|
5
5
|
const { hasOptionValue, getFiles } = require('../util')
|
|
6
6
|
const { FOLDER_GEN, DEFAULT_BUILTIN_PRIORITY_MAX } = require('../constants')
|
|
7
|
+
const TRACE = cds.debug('trace')
|
|
7
8
|
|
|
8
9
|
class InternalBuildPlugin extends Plugin {
|
|
9
10
|
/**
|
|
@@ -116,7 +117,7 @@ class InternalBuildPlugin extends Plugin {
|
|
|
116
117
|
cwd: cds.root,
|
|
117
118
|
src: this.hasBuildOption('flatDeployLayout', true) || this.task.src === this.task.dest ? this.task.src : cds.root
|
|
118
119
|
}
|
|
119
|
-
const csnStr =
|
|
120
|
+
const csnStr = cds_compile_to_json(model, jsonOptions)
|
|
120
121
|
await this.write(csnStr).to(csnFile)
|
|
121
122
|
return csnStr
|
|
122
123
|
}
|
|
@@ -156,4 +157,17 @@ class InternalBuildPlugin extends Plugin {
|
|
|
156
157
|
return null
|
|
157
158
|
}
|
|
158
159
|
}
|
|
160
|
+
|
|
161
|
+
// Emits the 'compile.for.runtime' event, as the produced CSN is for runtime usage.
|
|
162
|
+
// Plugins use it to modify the CSN before it is stringified.
|
|
163
|
+
function cds_compile_to_json (csn,o) {
|
|
164
|
+
TRACE?.time('cds.compile 2json'.padEnd(22)); try {
|
|
165
|
+
let result, next = ()=> result ??= cds.compile.to.json (csn,o)
|
|
166
|
+
cds.emit ('compile.for.runtime', csn, o, next)
|
|
167
|
+
return next() //> in case no handler called next
|
|
168
|
+
}
|
|
169
|
+
finally { TRACE?.timeEnd('cds.compile 2json'.padEnd(22)) }
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
159
173
|
module.exports = InternalBuildPlugin
|
|
@@ -7,6 +7,7 @@ const { OUTPUT_MODE, OUTPUT_MODE_RESULT, FILE_EXT_CDS, CONTENT_LANGUAGE_BUNDLES,
|
|
|
7
7
|
const { getI18nDefaultFolder } = require('../../util')
|
|
8
8
|
const DEFAULT_COMPILE_DEST_FOLDER = path.normalize('src/main/resources/edmx')
|
|
9
9
|
const DEBUG = cds.debug('cli|build')
|
|
10
|
+
const LOG = cds.log('cli|build')
|
|
10
11
|
|
|
11
12
|
class JavaBuildPlugin extends EdmxBuildPlugin {
|
|
12
13
|
init() {
|
|
@@ -25,7 +26,17 @@ class JavaBuildPlugin extends EdmxBuildPlugin {
|
|
|
25
26
|
|
|
26
27
|
if (!this.hasBuildOption(CONTENT_EDMX, false)) {
|
|
27
28
|
// generate edmx files containing all features - localized edmx for backward compatibility
|
|
28
|
-
|
|
29
|
+
let localized = this.hasBuildOption(CONTENT_LOCALIZED_EDMX, true)
|
|
30
|
+
|
|
31
|
+
// Force localized to true for OData v2
|
|
32
|
+
if (cds.env.odata.version === 'v2') {
|
|
33
|
+
if (!localized) {
|
|
34
|
+
LOG.info('Forcing localized EDMX generation for OData v2')
|
|
35
|
+
localized = true
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (localized) {
|
|
29
40
|
await this.compileToEdmx(model, compileDest, { [FLAVOR_LOCALIZED_EDMX]: true })
|
|
30
41
|
}
|
|
31
42
|
// non-localized edmx
|
|
@@ -86,7 +86,8 @@ class MtxSidecarBuildPlugin extends NodejsBuildPlugin {
|
|
|
86
86
|
return
|
|
87
87
|
}
|
|
88
88
|
const { dictionary, sources } = await this.compileAll(model, destMainSrv, destMain)
|
|
89
|
-
await this.collectAllLanguageBundles(dictionary, sources, destMainSrv, destMain)
|
|
89
|
+
// await this.collectAllLanguageBundles(dictionary, sources, destMainSrv, destMain)
|
|
90
|
+
await this.collectAllLanguageBundles(dictionary, sources, destMain, destMain)
|
|
90
91
|
|
|
91
92
|
if (!this.hasBuildOption(CONTENT_EDMX, false)) {
|
|
92
93
|
//inferred model expected by cds.compile.to.edmx()
|
|
@@ -53,7 +53,8 @@ class NodejsBuildPlugin extends EdmxBuildPlugin {
|
|
|
53
53
|
if (model) {
|
|
54
54
|
const { dictionary, sources } = await this.compileAll(model, destSrv, destRoot)
|
|
55
55
|
// collect and write language bundles into single i18n.json file
|
|
56
|
-
await this.collectAllLanguageBundles(dictionary, sources,
|
|
56
|
+
await this.collectAllLanguageBundles(dictionary, sources, destRoot, destRoot)
|
|
57
|
+
// await this.collectAllLanguageBundles(dictionary, sources, destSrv, destRoot)
|
|
57
58
|
|
|
58
59
|
if (!this.hasBuildOption(CONTENT_EDMX, false)) {
|
|
59
60
|
const compileOptions = { [FLAVOR_LOCALIZED_EDMX]: this.hasBuildOption(FLAVOR_LOCALIZED_EDMX, true) }
|
package/lib/build/util.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
// @ts-check
|
|
2
|
-
const
|
|
3
|
-
const
|
|
2
|
+
const cp = require('node:child_process');
|
|
3
|
+
const fs = require('node:fs')
|
|
4
|
+
const path = require('node:path')
|
|
5
|
+
|
|
4
6
|
const cds = require('../cds')
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
7
|
+
const execAsync = require('node:util').promisify(cp.exec)
|
|
8
|
+
const { isRoot } = require('../util/fs')
|
|
9
|
+
|
|
10
|
+
const IS_WIN = require('node:os').platform() === 'win32'
|
|
8
11
|
const { SEVERITY_ERROR, FILE_EXT_CDS, NODEJS_MODEL_EXCLUDE_LIST } = require('./constants');
|
|
9
12
|
const DEBUG = cds.debug('cli|build')
|
|
10
|
-
|
|
13
|
+
|
|
14
|
+
// failsafe to avoid too deep recursions
|
|
15
|
+
// increased from 2 to 5, adding a config options in the future
|
|
16
|
+
const WS_MAX_DEPTH = 5
|
|
11
17
|
|
|
12
18
|
/** @typedef {{col?: number, endCol?: number, line?: number, endLine?: number, file: string}} SourceLocation */
|
|
13
19
|
/** @typedef {object[] | object} Credentials */
|
|
@@ -165,9 +171,9 @@ function flatten(modelPaths) {
|
|
|
165
171
|
|
|
166
172
|
function getI18nDefaultFolder() {
|
|
167
173
|
// keep '_i18n' as preferred folder for compatibility reasons
|
|
168
|
-
if (cds.env.i18n.folders.includes('_i18n')) return '_i18n'
|
|
169
|
-
if (cds.env.i18n.folders.includes('i18n')) return 'i18n'
|
|
170
|
-
return cds.env.i18n.folders[0] ?? '
|
|
174
|
+
// if (cds.env.i18n.folders.includes('_i18n')) return '_i18n'
|
|
175
|
+
// if (cds.env.i18n.folders.includes('i18n')) return 'i18n'
|
|
176
|
+
return cds.env.i18n.folders?.[0] ?? '_i18n'
|
|
171
177
|
}
|
|
172
178
|
|
|
173
179
|
async function pathExists(path) {
|
|
@@ -279,22 +285,32 @@ async function getWorkspaces(wsRoot, resolve = false, devDependencies = true, vi
|
|
|
279
285
|
}
|
|
280
286
|
|
|
281
287
|
function findWorkspaceRoot(currentPath, depth = 0) {
|
|
282
|
-
if (depth > WS_MAX_DEPTH) {
|
|
283
|
-
DEBUG?.(`No workspaces
|
|
288
|
+
if (isRoot(currentPath) || depth > WS_MAX_DEPTH) {
|
|
289
|
+
DEBUG?.(`No workspaces found, filesystem root or max depth of ${WS_MAX_DEPTH} reached`)
|
|
284
290
|
return
|
|
285
291
|
}
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
292
|
+
|
|
293
|
+
const packageJsonPath = path.join(currentPath, 'package.json')
|
|
294
|
+
try {
|
|
295
|
+
const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8')
|
|
296
|
+
const packageJson = JSON.parse(packageJsonContent)
|
|
297
|
+
if (packageJson.workspaces?.length > 0) {
|
|
289
298
|
return currentPath
|
|
290
299
|
}
|
|
300
|
+
} catch (e) {
|
|
301
|
+
if (e.code !== 'ENOENT') {
|
|
302
|
+
if (e.name === 'SyntaxError') {
|
|
303
|
+
throw `Corrupt package.json found at ${packageJsonPath}: ${e.message}`
|
|
304
|
+
}
|
|
305
|
+
throw e
|
|
306
|
+
}
|
|
291
307
|
}
|
|
308
|
+
|
|
292
309
|
if (fs.existsSync(path.join(currentPath, '.gitmodules'))) {
|
|
293
310
|
return // project root reached
|
|
294
311
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
312
|
+
|
|
313
|
+
return findWorkspaceRoot(path.dirname(currentPath), depth + 1)
|
|
298
314
|
}
|
|
299
315
|
|
|
300
316
|
/**
|
|
@@ -415,15 +431,16 @@ function _filterModelPaths(modelPaths, filter = undefined) {
|
|
|
415
431
|
* @param {string} srcDir - the directory to search for files
|
|
416
432
|
* @param {(file: string) => boolean} [filter] - the filter function to apply to the found files
|
|
417
433
|
* @param {string[]} files - the set of files to add the found files to
|
|
434
|
+
* @param {boolean} [ignoreSymlinks=false] - whether to ignore symlinks
|
|
418
435
|
* @returns {string[]} files found in the given directory and its subdirectories
|
|
419
436
|
*/
|
|
420
|
-
function getFiles(srcDir, filter, files = []) {
|
|
437
|
+
function getFiles(srcDir, filter, files = [], ignoreSymlinks = false) {
|
|
421
438
|
function handleResource(/** @type {string} entry */ entry) {
|
|
422
439
|
if (!filter || filter.call(this, entry)) {
|
|
423
440
|
const stats = fs.lstatSync(entry)
|
|
424
441
|
if (cds.utils.isdir(entry)) {
|
|
425
442
|
getFiles(entry, filter, files)
|
|
426
|
-
} else if (stats.isFile() || stats.isSymbolicLink()) {
|
|
443
|
+
} else if (stats.isFile() || (!ignoreSymlinks && stats.isSymbolicLink())) {
|
|
427
444
|
files.push(entry)
|
|
428
445
|
}
|
|
429
446
|
}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
const cds = require('../cds')
|
|
2
|
-
const { compile } = cds._local('@cap-js/openapi') // load a local cap-js/openapi (fallback to our own)
|
|
3
|
-
|
|
4
|
-
function cds_compile_to_openapi (csn, options) {
|
|
5
|
-
return compile(csn, options)
|
|
6
|
-
}
|
|
2
|
+
const { compile: cds_compile_to_openapi } = cds._local('@cap-js/openapi') // load a local cap-js/openapi (fallback to our own)
|
|
7
3
|
|
|
8
4
|
module.exports = cds_compile_to_openapi
|
package/lib/import/common.js
CHANGED
|
@@ -357,7 +357,13 @@ async function _updateNodeConfig(dest, services, kind, cwd, options) {
|
|
|
357
357
|
config = {};
|
|
358
358
|
options.config.trim().split(',').forEach(kv => {
|
|
359
359
|
const [key, val] = kv.split('=');
|
|
360
|
-
|
|
360
|
+
if (val === 'true' || val === 'false') {
|
|
361
|
+
config[key] = (val === 'true');
|
|
362
|
+
} else if (!isNaN(val)) {
|
|
363
|
+
config[key] = Number(val);
|
|
364
|
+
} else {
|
|
365
|
+
config[key] = val;
|
|
366
|
+
}
|
|
361
367
|
})
|
|
362
368
|
normalizeToDeepObject(config);
|
|
363
369
|
}
|
|
@@ -510,7 +516,8 @@ async function postProcess(filePath, options, csn, cwd) {
|
|
|
510
516
|
usingStatements.push(`using from './${path.basename(csnFile.replace(`'`, `''`))}';`);
|
|
511
517
|
}
|
|
512
518
|
|
|
513
|
-
|
|
519
|
+
if (!options.dry)
|
|
520
|
+
_printUsageHint(csnFile, services, cwd);
|
|
514
521
|
|
|
515
522
|
if (!options.dry && !options.no_copy)
|
|
516
523
|
await _copyToSrvExternal(filePath, destFilePath, cwd);
|
|
@@ -38,6 +38,7 @@ module.exports = class ParserContext {
|
|
|
38
38
|
this.schemaAliasToNamespace = {};
|
|
39
39
|
this.schemaToSchemaDataIndex = {};
|
|
40
40
|
this.schemaToPrimarySchema = {};
|
|
41
|
+
this.schemaDetails = {};
|
|
41
42
|
this.vocabNamespaceToAlias = {};
|
|
42
43
|
this.entityToBoundActions = {};
|
|
43
44
|
this.entityToBoundFunctions = {};
|