@sap/cds-dk 9.7.1 → 9.8.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 +44 -1
- package/bin/bind.js +7 -2
- package/bin/build.js +14 -4
- package/bin/cds.js +2 -2
- package/bin/completion/completionFs.js +1 -1
- package/bin/completion/index.js +2 -2
- package/bin/data-products/get-csn-via-dp-cli.js +1 -1
- package/bin/debug.js +1 -1
- package/bin/deploy/index.js +3 -2
- package/bin/gen.js +1 -1
- package/bin/help.js +1 -1
- package/bin/import.js +3 -0
- package/bin/minify.js +1 -1
- package/bin/mock.js +1 -1
- package/bin/repl.js +212 -39
- package/bin/test.js +0 -2
- package/bin/up.js +27 -3
- package/bin/util/containerize.js +1 -3
- package/bin/version.js +27 -7
- package/bin/watch.js +20 -4
- package/lib/bind/cf.js +2 -2
- package/lib/bind/k8s.js +0 -1
- package/lib/bind/plugin.js +2 -0
- package/lib/bind/shared.js +6 -1
- package/lib/build/constants.js +0 -8
- package/lib/build/index.js +569 -25
- package/lib/build/{provider/edmxBuildPlugin.js → plugins/edmx.js} +6 -15
- package/lib/build/{provider/featureToggleBuildPlugin.js → plugins/featureToggles.js} +3 -23
- package/lib/build/{provider → plugins}/fiori/index.js +27 -38
- package/lib/build/{provider → plugins}/hana/index.js +61 -83
- package/lib/build/{provider → plugins}/hana/migrationtable.js +4 -3
- package/lib/build/plugins/helm/index.js +6 -6
- package/lib/build/{provider/internalBuildPlugin.js → plugins/internal.js} +7 -31
- package/lib/build/{provider → plugins}/java/index.js +18 -26
- package/lib/build/plugins/mtx/index.js +41 -0
- package/lib/build/plugins/mtx/resourcesTarBuilder.js +41 -0
- package/lib/build/{provider → plugins}/mtx-extension/extensionCompilation.js +1 -1
- package/lib/build/{provider → plugins}/mtx-extension/index.js +35 -44
- package/lib/build/{provider → plugins}/mtx-sidecar/index.js +18 -4
- package/lib/build/{provider → plugins}/nodejs/index.js +29 -28
- package/lib/build/{plugin.js → plugins/plugin.js} +45 -59
- package/lib/build/plugins.js +11 -8
- package/lib/build/util.js +18 -16
- package/lib/compile/to-xsuaa.js +2 -2
- package/lib/deploy/to-hana/hana.js +64 -56
- package/lib/import/common.js +1 -1
- package/lib/import/odata/metadataconverter/MetadataConverter.js +4 -3
- package/lib/import/odata/v2parser.js +28 -28
- package/lib/import/odata/v4parser.js +37 -2
- package/lib/import/openapi/index.js +1 -1
- package/lib/init/constants.js +0 -1
- package/lib/init/template/app-frontend/index.js +1 -1
- package/lib/init/template/approuter/files/package.json +1 -1
- package/lib/init/template/approuter/files/values.yaml.hbs +1 -0
- package/lib/init/template/completion/completionSetup.js +1 -1
- package/lib/init/template/data/as-csv.js +1 -1
- package/lib/init/template/github-actions/index.js +1 -1
- package/lib/init/template/handler/index.js +1 -1
- package/lib/init/template/helm/index.js +3 -3
- package/lib/init/template/initial/files/readme.md +2 -4
- package/lib/init/template/kyma/index.js +9 -5
- package/lib/init/template/lint/index.js +7 -21
- package/lib/init/template/multitenancy/files/package.json.hbs +0 -5
- package/lib/init/template/postgres/files/containerize.yaml.hbs +15 -0
- package/lib/init/template/postgres/files/package.json.hbs +35 -0
- package/lib/init/template/postgres/files/values.yaml.hbs +23 -0
- package/lib/init/template/postgres/index.js +34 -9
- package/lib/init/template/test/files/package.json +1 -1
- package/lib/init/template/typescript/files/package.json +1 -1
- package/lib/init/template/workzone-standard/files/mta.yaml.hbs +1 -0
- package/lib/lint/eslintHelp.json +1 -1
- package/lib/lint/io.js +9 -13
- package/lib/mtx/pull.js +1 -1
- package/lib/mtx/settings_manager.js +11 -5
- package/lib/mtx/tenant_action.js +1 -1
- package/lib/mtx/util/fs.js +2 -2
- package/lib/util/cf.js +1 -1
- package/lib/util/fs.js +3 -3
- package/lib/util/git.js +1 -1
- package/lib/util/glob.js +1 -1
- package/lib/watch/hot-reload.js +202 -0
- package/lib/watch/livereload-server.js +6 -4
- package/lib/watch/node-watch.js +5 -1
- package/lib/watch/watched.js +7 -3
- package/lib/watch/watcher.js +41 -3
- package/npm-shrinkwrap.json +35 -26
- package/package.json +1 -1
- package/lib/build/buildTaskEngine.js +0 -377
- package/lib/build/buildTaskFactory.js +0 -198
- package/lib/build/buildTaskProvider.js +0 -38
- package/lib/build/buildTaskProviderFactory.js +0 -233
- package/lib/build/provider/internalBuildTaskProvider.js +0 -227
- package/lib/build/provider/java-cf/index.js +0 -1
- package/lib/build/provider/mtx/index.js +0 -36
- package/lib/build/provider/mtx/resourcesTarBuilder.js +0 -102
- package/lib/build/provider/node-cf/index.js +0 -1
- package/lib/init/template/lint/files/.eslint/rules/no-entity-moo.js +0 -40
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/fixed/schema.cds +0 -4
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/invalid/schema.cds +0 -4
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/rule.test.js +0 -15
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/valid/schema.cds +0 -6
- package/lib/init/types.d.ts +0 -23
- /package/lib/build/{provider → plugins}/hana/2migration.js +0 -0
- /package/lib/build/{provider → plugins}/hana/template/.hdiconfig-all +0 -0
- /package/lib/build/{provider → plugins}/hana/template/.hdiconfig-cloud +0 -0
- /package/lib/build/{provider → plugins}/hana/template/.hdinamespace +0 -0
- /package/lib/build/{provider → plugins}/hana/template/package.json +0 -0
- /package/lib/build/{provider → plugins}/hana/template/undeploy.json +0 -0
|
@@ -1,20 +1,9 @@
|
|
|
1
1
|
const path = require('path')
|
|
2
2
|
const cds = require('../../cds')
|
|
3
|
-
const { DEFAULT_CSN_FILE_NAME
|
|
4
|
-
const InternalBuildPlugin = require('./internalBuildPlugin')
|
|
3
|
+
const { DEFAULT_CSN_FILE_NAME } = require('../constants')
|
|
5
4
|
const { getI18nDefaultFolder, filterFeaturePaths } = require('../util')
|
|
6
5
|
|
|
7
|
-
class
|
|
8
|
-
init() {
|
|
9
|
-
if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
|
|
10
|
-
this._result = {
|
|
11
|
-
dest: this.task.dest,
|
|
12
|
-
edmx: new Map(),
|
|
13
|
-
languages: new Set(),
|
|
14
|
-
services: new Set()
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
6
|
+
module.exports = class FeatureTogglesBuildPlugin extends require('./internal') {
|
|
18
7
|
|
|
19
8
|
async compileAll(csn, destBase, destFts) {
|
|
20
9
|
const sources = filterFeaturePaths(csn, this.task.options.model || this.task.src)
|
|
@@ -31,10 +20,6 @@ class FeatureToggleBuildPlugin extends InternalBuildPlugin {
|
|
|
31
20
|
const csnStr = await this.compileToJson(dictionary.base, path.join(destBase, DEFAULT_CSN_FILE_NAME))
|
|
32
21
|
const csnModel = JSON.parse(csnStr)
|
|
33
22
|
csnModel.meta = csn.meta
|
|
34
|
-
if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
|
|
35
|
-
this._result.csn = csnModel
|
|
36
|
-
}
|
|
37
|
-
|
|
38
23
|
if (sources.features) {
|
|
39
24
|
dictionary.features = await this._compileFeatures(sources.features, destBase, destFts, dictionary.base)
|
|
40
25
|
}
|
|
@@ -45,10 +30,7 @@ class FeatureToggleBuildPlugin extends InternalBuildPlugin {
|
|
|
45
30
|
const i18nFolder = getI18nDefaultFolder()
|
|
46
31
|
const ftsName = path.dirname(cds.env.features.folders || 'fts/*')
|
|
47
32
|
// create language bundle for base model
|
|
48
|
-
|
|
49
|
-
if (i18n && this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
|
|
50
|
-
this._result.languageBundles = i18n.bundles
|
|
51
|
-
}
|
|
33
|
+
await this.collectLanguageBundles(dictionary.base, path.join(destBase, i18nFolder))
|
|
52
34
|
|
|
53
35
|
if (dictionary.features) {
|
|
54
36
|
// create language bundles for all features
|
|
@@ -90,5 +72,3 @@ class FeatureToggleBuildPlugin extends InternalBuildPlugin {
|
|
|
90
72
|
cds.compiler.compileSources({ [ftCsn.requires[0]]: baseCsn, 'feature.csn': ftCsn }, { ...super.options(), ...cds.env.cdsc ?? {} })
|
|
91
73
|
}
|
|
92
74
|
}
|
|
93
|
-
|
|
94
|
-
module.exports = FeatureToggleBuildPlugin
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
const path = require('path')
|
|
1
|
+
const path = require('node:path')
|
|
2
2
|
const cds = require('../../../cds')
|
|
3
|
-
const
|
|
4
|
-
const {
|
|
5
|
-
const { OUTPUT_MODE, OUTPUT_MODE_RESULT, BUILD_TASK_FIORI, CDS_CONFIG_PATH_SEP, OUTPUT_MODE_FILESYSTEM } = require('../../constants')
|
|
3
|
+
const { relativePaths, normalizePath } = require('../../util')
|
|
4
|
+
const { BUILD_TASK_FIORI, CDS_CONFIG_PATH_SEP } = require('../../constants')
|
|
6
5
|
const DEBUG = cds.debug('cli|build')
|
|
7
6
|
|
|
8
7
|
/**
|
|
@@ -10,25 +9,25 @@ const DEBUG = cds.debug('cli|build')
|
|
|
10
9
|
* For SAP Web IDE Full-Stack compatibility a corresponding metadata.xml is still generated.
|
|
11
10
|
* Though, 'fiori' build tasks can still be configured for UI5 mock server usage - see cap/issues#8673
|
|
12
11
|
*/
|
|
13
|
-
class FioriBuildPlugin extends
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
edmx: new Map(),
|
|
19
|
-
languages: new Set(),
|
|
20
|
-
services: new Set()
|
|
21
|
-
}
|
|
22
|
-
}
|
|
12
|
+
module.exports = class FioriBuildPlugin extends require('../edmx') {
|
|
13
|
+
|
|
14
|
+
_cachedEdmx = new Map()
|
|
15
|
+
|
|
16
|
+
static get taskDefaults() { return { src: normalizePath(cds.env.folders.app) } }
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
static hasTask() { return false } // never auto-pulled, only if configured in build tasks
|
|
19
|
+
|
|
20
|
+
async _ensureCachesInitialized() {
|
|
21
|
+
this.context.for ??= {}
|
|
22
|
+
this.context.for[BUILD_TASK_FIORI] ??= {}
|
|
27
23
|
|
|
28
24
|
// cache for later use across multiple FioriBuildPlugin instances
|
|
29
25
|
const fioriBuildOptions = this.context.for[BUILD_TASK_FIORI]
|
|
30
|
-
fioriBuildOptions.
|
|
31
|
-
|
|
26
|
+
if (fioriBuildOptions._initialized) {
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
fioriBuildOptions.appModel ??= new Map()
|
|
30
|
+
fioriBuildOptions.appEdmx ??= new Map()
|
|
32
31
|
|
|
33
32
|
// group tasks that have a common application root folder
|
|
34
33
|
const appTaskGroups = new Map()
|
|
@@ -51,10 +50,6 @@ class FioriBuildPlugin extends EdmxBuildPlugin {
|
|
|
51
50
|
appModelGroups.set(appFolder, appModels)
|
|
52
51
|
}
|
|
53
52
|
|
|
54
|
-
// ensure edmx is cached as build result
|
|
55
|
-
const buildOption = this.context.options[OUTPUT_MODE]
|
|
56
|
-
this.context.options[OUTPUT_MODE] |= OUTPUT_MODE_RESULT
|
|
57
|
-
|
|
58
53
|
try {
|
|
59
54
|
for (let [appFolder, appModelGroup] of appModelGroups.entries()) {
|
|
60
55
|
DEBUG?.(`building module [${appFolder}] using [${this.constructor.name}]`)
|
|
@@ -64,7 +59,7 @@ class FioriBuildPlugin extends EdmxBuildPlugin {
|
|
|
64
59
|
}
|
|
65
60
|
DEBUG?.(`model: ${relativePaths(cds.root, modelPaths).join(", ")}`)
|
|
66
61
|
|
|
67
|
-
//cache model per fiori app root folder
|
|
62
|
+
// cache model per fiori app root folder
|
|
68
63
|
const options = this.options()
|
|
69
64
|
const model = await cds.load(modelPaths, options)
|
|
70
65
|
fioriBuildOptions.appModel.set(appFolder, model)
|
|
@@ -72,12 +67,13 @@ class FioriBuildPlugin extends EdmxBuildPlugin {
|
|
|
72
67
|
await this.compileToEdmx(model)
|
|
73
68
|
|
|
74
69
|
// cache edmx per fiori app root folder
|
|
75
|
-
|
|
70
|
+
this._cachedEdmx = new Map()
|
|
71
|
+
await this.compileToEdmx(model)
|
|
72
|
+
fioriBuildOptions.appEdmx.set(appFolder, this._cachedEdmx)
|
|
76
73
|
}
|
|
77
74
|
} finally {
|
|
78
|
-
|
|
75
|
+
fioriBuildOptions._initialized = true
|
|
79
76
|
}
|
|
80
|
-
return false
|
|
81
77
|
}
|
|
82
78
|
|
|
83
79
|
/**
|
|
@@ -87,10 +83,7 @@ class FioriBuildPlugin extends EdmxBuildPlugin {
|
|
|
87
83
|
* cannot be resolved based on the defined service URI
|
|
88
84
|
*/
|
|
89
85
|
async build() {
|
|
90
|
-
|
|
91
|
-
if (!model) {
|
|
92
|
-
return
|
|
93
|
-
}
|
|
86
|
+
await this._ensureCachesInitialized()
|
|
94
87
|
await this._writeEdmxToWebapp(this.task.src, this.task.dest)
|
|
95
88
|
}
|
|
96
89
|
|
|
@@ -100,7 +93,7 @@ class FioriBuildPlugin extends EdmxBuildPlugin {
|
|
|
100
93
|
|
|
101
94
|
try {
|
|
102
95
|
manifest = require(manifestPath)
|
|
103
|
-
} catch
|
|
96
|
+
} catch {
|
|
104
97
|
console.log(`UI module does not contain a manifest.json [${relativePaths(cds.root, manifestPath)}], skipping build`)
|
|
105
98
|
return
|
|
106
99
|
}
|
|
@@ -133,10 +126,8 @@ class FioriBuildPlugin extends EdmxBuildPlugin {
|
|
|
133
126
|
return
|
|
134
127
|
}
|
|
135
128
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
return this.write(edmx).to(edmxPath)
|
|
139
|
-
}
|
|
129
|
+
const edmxPath = path.resolve(path.join(dest, 'webapp'), this._strippedUrlPath(localUri))
|
|
130
|
+
return this.write(edmx).to(edmxPath)
|
|
140
131
|
}
|
|
141
132
|
|
|
142
133
|
_getEdmxForUri(model, appFolder, uri) {
|
|
@@ -161,5 +152,3 @@ class FioriBuildPlugin extends EdmxBuildPlugin {
|
|
|
161
152
|
return urlString.replace(/^(\/|\\)/, '').replace(/(\/|\\)$/, '') // strip leading and trailing slash or backslash
|
|
162
153
|
}
|
|
163
154
|
}
|
|
164
|
-
|
|
165
|
-
module.exports = FioriBuildPlugin
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
const fs = require('fs')
|
|
2
|
-
const path = require('path')
|
|
3
2
|
const cds = require('../../../cds')
|
|
3
|
+
const { exists, isdir, path } = cds.utils
|
|
4
4
|
const { compileToHdbMigration, getJournalEntities, getMigrationTableName } = require('./2migration')
|
|
5
|
-
const InternalBuildPlugin = require('../internalBuildPlugin')
|
|
6
5
|
const { find } = require('../../../util/fs')
|
|
7
|
-
const { BuildError, relativePaths, BuildMessage, hasOptionValue, getWorkspacePaths } = require('../../util')
|
|
8
|
-
const {
|
|
9
|
-
CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, CONTENT_NODE_MODULES, OUTPUT_MODE_RESULT, CONTINUE_UNRESOLVED_SCHEMA_CHANGES,
|
|
10
|
-
CSV_FILE_TARGET, OPTION_WS } = require('../../constants')
|
|
11
|
-
const { WARNING } = InternalBuildPlugin
|
|
6
|
+
const { BuildError, relativePaths, BuildMessage, hasOptionValue, getWorkspacePaths, normalizePath } = require('../../util')
|
|
7
|
+
const { CONTENT_PACKAGE_JSON, CONTENT_HDBTABLEDATA, CSV_FILE_DETECTION, CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON, CONTENT_NODE_MODULES, CONTINUE_UNRESOLVED_SCHEMA_CHANGES, CSV_FILE_TARGET, OPTION_WS, SEVERITY_WARNING } = require('../../constants')
|
|
12
8
|
const DEFAULT_COMPILE_DEST_FOLDER = path.normalize("src/gen")
|
|
13
9
|
const FILE_EXT_CSV = ".csv"
|
|
14
10
|
const FILE_EXT_HDBTABLEDATA = ".hdbtabledata"
|
|
@@ -26,14 +22,19 @@ const DEBUG = cds.debug('cli|build')
|
|
|
26
22
|
// This list contains exceptions which will be ignored during the consistency check.
|
|
27
23
|
const PLUGINLESS_HDB_FILES = new Set([".hdbgrants", ".hdbrevokes"])
|
|
28
24
|
|
|
29
|
-
class HanaBuildPlugin extends
|
|
25
|
+
module.exports = class HanaBuildPlugin extends require('../internal') {
|
|
26
|
+
|
|
27
|
+
static get taskDefaults() { return { src: normalizePath(cds.env.folders.db) } }
|
|
28
|
+
|
|
29
|
+
static hasTask() {
|
|
30
|
+
if (cds.env.extends) return false
|
|
31
|
+
const src = path.join(cds.root, this.taskDefaults?.src ?? 'db')
|
|
32
|
+
if (!exists(src)) return false
|
|
33
|
+
const db = cds.env.requires.db
|
|
34
|
+
return db?.kind === 'hana' || db?.dialect === 'hana'
|
|
35
|
+
}
|
|
36
|
+
|
|
30
37
|
init() {
|
|
31
|
-
if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
|
|
32
|
-
this._result = {
|
|
33
|
-
dest: this.task.dest,
|
|
34
|
-
hana: new Set()
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
38
|
this.task.options.compileDest = path.resolve(this.task.dest, this.task.options.compileDest || DEFAULT_COMPILE_DEST_FOLDER)
|
|
38
39
|
}
|
|
39
40
|
|
|
@@ -57,7 +58,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
57
58
|
// 1. compile
|
|
58
59
|
const hdiPlugins = await this._compileToHana(model, wsPaths)
|
|
59
60
|
|
|
60
|
-
if (!
|
|
61
|
+
if (!cds.cli.options.dry) {
|
|
61
62
|
// 2. copy resources
|
|
62
63
|
if (this.hasBuildOption(CSV_FILE_DETECTION, false)) {
|
|
63
64
|
await this._copyResources(src, dest)
|
|
@@ -83,13 +84,12 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
83
84
|
// common model artifacts that are not part of the current project
|
|
84
85
|
if (wsPaths.length || cds.cli.options?.[OPTION_WS] || hasOptionValue(this.task.options[OPTION_WS], true)) {
|
|
85
86
|
// first is winning, e.g. a .hdiconfig file might exist in multiple workspaces
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}, []);
|
|
87
|
+
const seen = new Set()
|
|
88
|
+
const wsFiles = (await this._getWorkspaceFiles(wsPaths)).filter(src => {
|
|
89
|
+
if (seen.has(src.filePath)) return false
|
|
90
|
+
seen.add(src.filePath)
|
|
91
|
+
return true
|
|
92
|
+
});
|
|
93
93
|
|
|
94
94
|
// copy artifacts to the src/gen folder in inplace mode
|
|
95
95
|
const dest = path.join(this.task.dest, this.isStagingBuild() ? 'src' : 'src/gen')
|
|
@@ -101,13 +101,12 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
101
101
|
)
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
|
-
return this._result
|
|
105
104
|
}
|
|
106
105
|
|
|
107
106
|
/**
|
|
108
107
|
* Deletes any content that has been created in folder '#this.task.dest/src/gen' by inplace mode.
|
|
109
108
|
* <br>
|
|
110
|
-
* Note: Content created in staging build will be deleted by
|
|
109
|
+
* Note: Content created in staging build will be deleted by default.
|
|
111
110
|
*/
|
|
112
111
|
async clean() {
|
|
113
112
|
if (this.isStagingBuild()) {
|
|
@@ -162,7 +161,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
162
161
|
if (entry.startsWith(dbSrc)) {
|
|
163
162
|
return true
|
|
164
163
|
}
|
|
165
|
-
if (
|
|
164
|
+
if (isdir(entry)) {
|
|
166
165
|
return !/(\/|\\)node_modules(\/|\\)?$/.test(entry) ||
|
|
167
166
|
(/(\/|\\)node_modules(\/|\\)?$/.test(entry) && this.hasBuildOption(CONTENT_NODE_MODULES, true))
|
|
168
167
|
}
|
|
@@ -188,7 +187,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
188
187
|
const regex = RegExp('\\.cds$|\\.csv$|\\.hdbtabledata$')
|
|
189
188
|
|
|
190
189
|
await this.copyNativeContent(src, dest, (entry) => {
|
|
191
|
-
if (
|
|
190
|
+
if (isdir(entry)) {
|
|
192
191
|
return !/(\/|\\)node_modules(\/|\\)?$/.test(entry)
|
|
193
192
|
}
|
|
194
193
|
return (!regex.test(entry) && entry !== cds.env.build.outputfile) ||
|
|
@@ -200,7 +199,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
200
199
|
// subfolders are not supported
|
|
201
200
|
const allFiles = []
|
|
202
201
|
for (const csvDir of csvDirs) {
|
|
203
|
-
allFiles.push(...await find(csvDir, { filter: entry => regexData.test(entry) && !
|
|
202
|
+
allFiles.push(...await find(csvDir, { filter: entry => regexData.test(entry) && !isdir(entry) }))
|
|
204
203
|
}
|
|
205
204
|
|
|
206
205
|
return Promise.all(allFiles.map((file) => {
|
|
@@ -224,7 +223,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
224
223
|
const destSrcDir = path.join(this.task.dest, "src")
|
|
225
224
|
|
|
226
225
|
const allCsvFiles = await find(destSrcDir, { filter: (entry) => {
|
|
227
|
-
if (
|
|
226
|
+
if (isdir(entry)) {
|
|
228
227
|
return true
|
|
229
228
|
}
|
|
230
229
|
if (/\.hdbtabledata$/.test(entry)) {
|
|
@@ -257,9 +256,6 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
257
256
|
// otherwise create in 'src/gen'
|
|
258
257
|
let tableDataPath = csvFolder.startsWith(this.task.options.compileDest) ? csvFolder : this.task.options.compileDest
|
|
259
258
|
tableDataPath = path.join(tableDataPath, file)
|
|
260
|
-
if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
|
|
261
|
-
this._result.hana.add(path.relative(this.task.dest, tableDataPath))
|
|
262
|
-
}
|
|
263
259
|
promises.push(this.write(tableData).to(tableDataPath))
|
|
264
260
|
}
|
|
265
261
|
await Promise.all(promises)
|
|
@@ -269,13 +265,11 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
269
265
|
async _stripCsvComments(csvFiles) {
|
|
270
266
|
// Note: modification of csv files is only allowed for files located in the compile destination folder,
|
|
271
267
|
// meaning having their origin location at db/data/* or db/csv/*
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
for (const file of csvFiles) {
|
|
268
|
+
await Promise.all(csvFiles.map(file => {
|
|
275
269
|
if (this.isStagingBuild() || file.startsWith(this.task.options.compileDest)) {
|
|
276
|
-
|
|
270
|
+
return cds.utils.csv?.stripComments(file, null, this.task.options.trimCsvWhitespaces)
|
|
277
271
|
}
|
|
278
|
-
}
|
|
272
|
+
}))
|
|
279
273
|
}
|
|
280
274
|
|
|
281
275
|
/**
|
|
@@ -300,7 +294,6 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
300
294
|
|
|
301
295
|
async _compileToHdb(model, format) {
|
|
302
296
|
const hdiPlugins = new Set()
|
|
303
|
-
const relDest = path.relative(this.task.dest, this.task.options.compileDest)
|
|
304
297
|
// enforces sqlNames option for compiler in tests
|
|
305
298
|
const options = { ...this.options(), sql_mapping: cds.env.sql.names }
|
|
306
299
|
const result = cds.compile.to[format](model, options)
|
|
@@ -311,9 +304,6 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
311
304
|
const file = key.file ? key.file : key.name + key.suffix
|
|
312
305
|
|
|
313
306
|
hdiPlugins.add(suffix)
|
|
314
|
-
if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
|
|
315
|
-
this._result.hana.add(path.join(relDest, file))
|
|
316
|
-
}
|
|
317
307
|
promises.push(this.write(content).to(path.join(this.task.options.compileDest, file)))
|
|
318
308
|
if (suffix === FILE_EXT_HDBTABLE) {
|
|
319
309
|
const name = key.name || path.parse(key.file).name
|
|
@@ -332,7 +322,6 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
332
322
|
|
|
333
323
|
async _compileToHdbmigration(model, format, wsPaths) {
|
|
334
324
|
const hdiPlugins = new Set()
|
|
335
|
-
const relDestDir = path.relative(this.task.dest, this.task.options.compileDest)
|
|
336
325
|
const relDbDestDir = path.relative(cds.root, this.task.options.compileDest)
|
|
337
326
|
const dbSrcDir = path.join(this.task.src, "src")
|
|
338
327
|
const relDbSrcDir = path.relative(cds.root, dbSrcDir)
|
|
@@ -371,9 +360,6 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
371
360
|
if (!wsMigrationTables.has(name)) {
|
|
372
361
|
migrationTableFiles.push(path.join(relDbSrcDir, fileName))
|
|
373
362
|
if (changed) {
|
|
374
|
-
if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
|
|
375
|
-
this._result.hana.add(path.join("src", fileName))
|
|
376
|
-
}
|
|
377
363
|
promises.push(this.write(content).to(path.join(dbSrcDir, fileName)))
|
|
378
364
|
} else {
|
|
379
365
|
DEBUG?.(`no change, keep existing ${fileName}`)
|
|
@@ -382,9 +368,6 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
382
368
|
DEBUG?.(`skip generation of migration table [${fileName}] as it originates from a different workspace`)
|
|
383
369
|
}
|
|
384
370
|
} else {
|
|
385
|
-
if (this.hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_RESULT)) {
|
|
386
|
-
this._result.hana.add(path.join(relDestDir, fileName))
|
|
387
|
-
}
|
|
388
371
|
promises.push(this.write(content).to(path.join(this.task.options.compileDest, fileName)))
|
|
389
372
|
if (suffix === FILE_EXT_HDBTABLE) {
|
|
390
373
|
// issue an error in case a .hdbmigrationtable file already exists
|
|
@@ -407,12 +390,12 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
407
390
|
} finally {
|
|
408
391
|
// update last-dev CSN version
|
|
409
392
|
if (afterImage) {
|
|
410
|
-
if (!
|
|
393
|
+
if (!_toEqualIgnoreMeta(lastDev, afterImage)) {
|
|
411
394
|
await this.write(afterImage).to(lastDevCsnDir)
|
|
412
395
|
}
|
|
413
396
|
// add src/.hdiconfig if not existing
|
|
414
397
|
if (migrationTableFiles.length > 0 && !fs.existsSync(path.join(dbSrcDir, FILE_NAME_HDICONFIG))) {
|
|
415
|
-
const template = await
|
|
398
|
+
const template = await _readTemplateAsJson('.hdiconfig-cloud')
|
|
416
399
|
await this.write(template).to(path.join(dbSrcDir, FILE_NAME_HDICONFIG))
|
|
417
400
|
}
|
|
418
401
|
}
|
|
@@ -428,7 +411,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
428
411
|
DEBUG?.(`skip create [${relativePaths(cds.root, pkgJson)}], already existing`)
|
|
429
412
|
}
|
|
430
413
|
if (this.isStagingBuild() && !exists) {
|
|
431
|
-
const content = await
|
|
414
|
+
const content = await _readTemplateAsJson(FILE_NAME_PACKAGE_JSON)
|
|
432
415
|
await this.write(content).to(path.join(this.task.dest, FILE_NAME_PACKAGE_JSON))
|
|
433
416
|
}
|
|
434
417
|
}
|
|
@@ -451,7 +434,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
451
434
|
// // without the need of creating a static .hdiconfig file in the 'db' folder
|
|
452
435
|
|
|
453
436
|
// // add all known plugins
|
|
454
|
-
// const defaultHdiConfig = await
|
|
437
|
+
// const defaultHdiConfig = await this._readTemplateAsJson('.hdiconfig-cloud')
|
|
455
438
|
// for (const plugin in defaultHdiConfig['file_suffixes']) {
|
|
456
439
|
// hdiPlugins.add('.' + plugin)
|
|
457
440
|
// }
|
|
@@ -463,7 +446,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
463
446
|
hdiConfigPath = path.join(this.task.options.compileDest, FILE_NAME_HDICONFIG)
|
|
464
447
|
// }
|
|
465
448
|
|
|
466
|
-
const template = await
|
|
449
|
+
const template = await _readTemplateAsJson('.hdiconfig-all')
|
|
467
450
|
let content = {
|
|
468
451
|
'file_suffixes': {}
|
|
469
452
|
}
|
|
@@ -490,7 +473,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
490
473
|
async _writeHdiNamespace() {
|
|
491
474
|
// see issue #64 - add .hdinamespace file to prevent HDI from adding gen/ folder to the namespace.
|
|
492
475
|
const hdiNamespace = path.join(this.task.options.compileDest, FILE_NAME_HDINAMESPACE)
|
|
493
|
-
const content = await
|
|
476
|
+
const content = await _readTemplateAsJson(FILE_NAME_HDINAMESPACE)
|
|
494
477
|
return await this.write(content).to(hdiNamespace)
|
|
495
478
|
}
|
|
496
479
|
|
|
@@ -502,7 +485,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
502
485
|
// see issue #64 - add .hdinamespace file to prevent HDI from adding gen/ folder to the namespace.
|
|
503
486
|
const undeployJsonDest = path.join(this.task.dest, FILE_NAME_UNDEPLOY_JSON)
|
|
504
487
|
const undeployJsonSrc = path.join(this.task.src, FILE_NAME_UNDEPLOY_JSON)
|
|
505
|
-
const templateEntries = await
|
|
488
|
+
const templateEntries = await _readTemplateAsJson(FILE_NAME_UNDEPLOY_JSON)
|
|
506
489
|
let newEntries = []
|
|
507
490
|
if (fs.existsSync(undeployJsonSrc)) {
|
|
508
491
|
newEntries = await JSON.parse((await fs.promises.readFile(undeployJsonSrc, 'utf-8')).toString())
|
|
@@ -532,7 +515,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
532
515
|
if (fs.existsSync(file)) {
|
|
533
516
|
const undeployList = JSON.parse((await fs.promises.readFile(file)).toString(), 'utf-8')
|
|
534
517
|
if (Array.isArray(undeployList)) {
|
|
535
|
-
const hdiconfig = await
|
|
518
|
+
const hdiconfig = await _readTemplateAsJson('.hdiconfig-all')
|
|
536
519
|
const keys = new Set(Object.keys(hdiconfig['file_suffixes']).map(key => '.' + key))
|
|
537
520
|
undeployList.forEach(entry => {
|
|
538
521
|
const extName = path.extname(entry)
|
|
@@ -540,7 +523,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
540
523
|
if (keys.has(extName)) {
|
|
541
524
|
hdiPlugins.add(extName)
|
|
542
525
|
} else {
|
|
543
|
-
this.pushMessage(`Ignoring invalid entry '${entry}' in undeploy.json file`,
|
|
526
|
+
this.pushMessage(`Ignoring invalid entry '${entry}' in undeploy.json file`, SEVERITY_WARNING)
|
|
544
527
|
}
|
|
545
528
|
}
|
|
546
529
|
})
|
|
@@ -566,7 +549,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
566
549
|
resolutionMessages.push(new BuildMessage(`Manual resolution required for file ${path.relative(cds.root, file)}. Check migration version content for further details.`))
|
|
567
550
|
}
|
|
568
551
|
} catch (e) {
|
|
569
|
-
throw new Error(`${path.relative(cds.root, file)}: ${e.
|
|
552
|
+
throw new Error(`${path.relative(cds.root, file)}: ${e.message}`, { cause: e })
|
|
570
553
|
}
|
|
571
554
|
}))
|
|
572
555
|
if (resolutionMessages.length) {
|
|
@@ -618,35 +601,30 @@ class HanaBuildPlugin extends InternalBuildPlugin {
|
|
|
618
601
|
|
|
619
602
|
return workspaceFiles
|
|
620
603
|
}
|
|
604
|
+
}
|
|
621
605
|
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
606
|
+
async function _readTemplateAsJson(template) {
|
|
607
|
+
const content = await fs.promises.readFile(path.join(__dirname, 'template', template), 'utf-8')
|
|
608
|
+
return JSON.parse(content.toString())
|
|
609
|
+
}
|
|
625
610
|
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
return JSON.
|
|
611
|
+
function _toEqualIgnoreMeta(csn1, csn2) {
|
|
612
|
+
function toString(csn) {
|
|
613
|
+
return JSON.stringify(csn, (k, v) => {
|
|
614
|
+
if (v?.creator) {
|
|
615
|
+
// make sure it's the compiler meta tag
|
|
616
|
+
if (k === 'meta' && v.creator?.startsWith('CDS Compiler'))
|
|
617
|
+
return
|
|
618
|
+
}
|
|
619
|
+
return v
|
|
620
|
+
})
|
|
629
621
|
}
|
|
630
622
|
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
if (k === 'meta' && v.creator?.startsWith('CDS Compiler'))
|
|
637
|
-
return
|
|
638
|
-
}
|
|
639
|
-
return v
|
|
640
|
-
})
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
if (csn1 === csn2) {
|
|
644
|
-
return true
|
|
645
|
-
}
|
|
646
|
-
if (!csn1 || !csn2) {
|
|
647
|
-
return false
|
|
648
|
-
}
|
|
649
|
-
return toString(csn1) === toString(csn2)
|
|
623
|
+
if (csn1 === csn2) {
|
|
624
|
+
return true
|
|
625
|
+
}
|
|
626
|
+
if (!csn1 || !csn2) {
|
|
627
|
+
return false
|
|
650
628
|
}
|
|
629
|
+
return toString(csn1) === toString(csn2)
|
|
651
630
|
}
|
|
652
|
-
module.exports = HanaBuildPlugin
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
const cds = require('../../../cds')
|
|
1
2
|
const fs = require('fs').promises
|
|
2
3
|
const {existsSync} = require('fs')
|
|
3
4
|
class MigrationTableParser {
|
|
@@ -306,7 +307,7 @@ class MigrationTableModel {
|
|
|
306
307
|
* Delete comments and return only those lines representing DDL statements.
|
|
307
308
|
*/
|
|
308
309
|
_compactLine(line) {
|
|
309
|
-
return line.
|
|
310
|
+
return line.replaceAll(' ', '')
|
|
310
311
|
}
|
|
311
312
|
}
|
|
312
313
|
|
|
@@ -354,7 +355,7 @@ class MigrationTable {
|
|
|
354
355
|
}
|
|
355
356
|
|
|
356
357
|
clone() {
|
|
357
|
-
return new MigrationTable(
|
|
358
|
+
return new MigrationTable(cds.clone(this.lines))
|
|
358
359
|
}
|
|
359
360
|
}
|
|
360
361
|
|
|
@@ -465,7 +466,7 @@ class Migration {
|
|
|
465
466
|
}
|
|
466
467
|
|
|
467
468
|
clone() {
|
|
468
|
-
return new Migration(
|
|
469
|
+
return new Migration(cds.clone(this.lines))
|
|
469
470
|
}
|
|
470
471
|
}
|
|
471
472
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
const cds = require('../../../cds')
|
|
2
|
-
const { exists, path, readFileSync, yaml } = cds.utils
|
|
3
|
-
const {
|
|
4
|
-
const { join } = path
|
|
2
|
+
const { exists, path: { join }, readFileSync, yaml } = cds.utils
|
|
3
|
+
const { BuildError } = require('../../util')
|
|
5
4
|
const { readProject } = require('../../../init/projectReader')
|
|
5
|
+
const { SEVERITY_WARNING } = require('../../constants')
|
|
6
6
|
|
|
7
|
-
module.exports = class HelmBuildPlugin extends
|
|
8
|
-
static taskDefaults
|
|
7
|
+
module.exports = class HelmBuildPlugin extends require('../plugin') {
|
|
8
|
+
static get taskDefaults() { return { src: "." } }
|
|
9
9
|
|
|
10
10
|
static hasTask() {
|
|
11
11
|
if (exists('chart/Chart.yaml')) {
|
|
@@ -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 kyma` to add the helm chart.",
|
|
30
|
+
this.pushMessage("Helm Chart not found. Execute `cds add kyma` to add the helm chart.", SEVERITY_WARNING)
|
|
31
31
|
return
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -1,20 +1,12 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
1
|
const path = require('path')
|
|
3
2
|
const cds = require('../../cds')
|
|
4
|
-
const
|
|
3
|
+
const { rimraf, isdir } = cds.utils
|
|
5
4
|
const { find } = require('../../util/fs')
|
|
6
5
|
const { hasOptionValue } = require('../util')
|
|
7
|
-
const { FOLDER_GEN
|
|
6
|
+
const { FOLDER_GEN } = require('../constants')
|
|
8
7
|
const TRACE = cds.debug('trace')
|
|
9
8
|
|
|
10
|
-
class InternalBuildPlugin extends
|
|
11
|
-
/**
|
|
12
|
-
* By default custom build plugins are executed before internal build plugins
|
|
13
|
-
* to ensure built-in plugin content isn't overwritten by mistake.
|
|
14
|
-
*/
|
|
15
|
-
get priority() {
|
|
16
|
-
return DEFAULT_BUILTIN_PRIORITY_MAX / 2
|
|
17
|
-
}
|
|
9
|
+
module.exports = class InternalBuildPlugin extends require('./plugin') {
|
|
18
10
|
|
|
19
11
|
init() {
|
|
20
12
|
// REVISIT: no default gen folder for now
|
|
@@ -24,26 +16,13 @@ class InternalBuildPlugin extends Plugin {
|
|
|
24
16
|
function _isSubDirectory(parent, child) {
|
|
25
17
|
return !path.relative(parent, child).startsWith('..')
|
|
26
18
|
}
|
|
27
|
-
// build results are deleted by
|
|
19
|
+
// build results are deleted by default if the build.target !== '.'
|
|
28
20
|
// make sure that src is not a subfolder of dest
|
|
29
21
|
if (cds.env.build.target === '.' && this.task.src !== this.task.dest && !_isSubDirectory(this.task.dest, this.task.src)) {
|
|
30
|
-
await
|
|
22
|
+
await rimraf(this.task.dest)
|
|
31
23
|
}
|
|
32
24
|
}
|
|
33
25
|
|
|
34
|
-
/**
|
|
35
|
-
* Called by the framework after {@link #init()}, used to perform more elaborate preparation.
|
|
36
|
-
* E.g. caching some pre-calculated data that can be used across multiple build tasks. This kind of data
|
|
37
|
-
* has to be stored in the plugin type specific options section.
|
|
38
|
-
* @returns {Promise<boolean>} A value 'false' indicates that {@link #prepare()} will not be called for other instances
|
|
39
|
-
* of this plugin type.
|
|
40
|
-
* True indicates that {@link #prepare()} will be called for other instances of this of this plugin type.
|
|
41
|
-
* @deprecated
|
|
42
|
-
*/
|
|
43
|
-
async prepare() {
|
|
44
|
-
// cancel subsequent prepare calls for other plugins of the same type by default
|
|
45
|
-
return false
|
|
46
|
-
}
|
|
47
26
|
|
|
48
27
|
/**
|
|
49
28
|
* Determines whether the given build option value has been set for this build task.
|
|
@@ -72,17 +51,17 @@ class InternalBuildPlugin extends Plugin {
|
|
|
72
51
|
}
|
|
73
52
|
|
|
74
53
|
async copyNativeContent(srcDir, destDir, customFilter) {
|
|
54
|
+
const regex = new RegExp(FOLDER_GEN + "\\b")
|
|
75
55
|
function commonStagingBuildFilter(src, destDir) {
|
|
76
56
|
if (typeof src !== "string" || typeof destDir !== "string") {
|
|
77
57
|
return false
|
|
78
58
|
}
|
|
79
|
-
if (!
|
|
59
|
+
if (!isdir(src)) {
|
|
80
60
|
return true //file
|
|
81
61
|
}
|
|
82
62
|
if (src === destDir) {
|
|
83
63
|
return false
|
|
84
64
|
}
|
|
85
|
-
const regex = new RegExp(FOLDER_GEN + "\\b")
|
|
86
65
|
if (src === path.resolve(cds.root, cds.env.build.target)) {
|
|
87
66
|
return false
|
|
88
67
|
}
|
|
@@ -192,6 +171,3 @@ function cds_compile_to_json (csn,o) {
|
|
|
192
171
|
}
|
|
193
172
|
finally { TRACE?.timeEnd('cds.compile 2json'.padEnd(22)) }
|
|
194
173
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
module.exports = InternalBuildPlugin
|