@sap/cds-dk 9.7.2 → 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.
Files changed (105) hide show
  1. package/CHANGELOG.md +35 -2
  2. package/bin/bind.js +7 -2
  3. package/bin/build.js +14 -4
  4. package/bin/cds.js +2 -2
  5. package/bin/completion/completionFs.js +1 -1
  6. package/bin/completion/index.js +2 -2
  7. package/bin/data-products/get-csn-via-dp-cli.js +1 -1
  8. package/bin/debug.js +1 -1
  9. package/bin/deploy/index.js +3 -2
  10. package/bin/gen.js +1 -1
  11. package/bin/help.js +1 -1
  12. package/bin/import.js +3 -0
  13. package/bin/minify.js +1 -1
  14. package/bin/mock.js +1 -1
  15. package/bin/repl.js +212 -39
  16. package/bin/test.js +0 -2
  17. package/bin/up.js +27 -3
  18. package/bin/util/containerize.js +1 -3
  19. package/bin/version.js +27 -7
  20. package/bin/watch.js +20 -4
  21. package/lib/bind/cf.js +2 -2
  22. package/lib/bind/k8s.js +0 -1
  23. package/lib/bind/plugin.js +2 -0
  24. package/lib/bind/shared.js +6 -1
  25. package/lib/build/constants.js +0 -8
  26. package/lib/build/index.js +569 -25
  27. package/lib/build/{provider/edmxBuildPlugin.js → plugins/edmx.js} +6 -15
  28. package/lib/build/{provider/featureToggleBuildPlugin.js → plugins/featureToggles.js} +3 -23
  29. package/lib/build/{provider → plugins}/fiori/index.js +27 -38
  30. package/lib/build/{provider → plugins}/hana/index.js +61 -83
  31. package/lib/build/{provider → plugins}/hana/migrationtable.js +4 -3
  32. package/lib/build/plugins/helm/index.js +6 -6
  33. package/lib/build/{provider/internalBuildPlugin.js → plugins/internal.js} +7 -31
  34. package/lib/build/{provider → plugins}/java/index.js +18 -26
  35. package/lib/build/plugins/mtx/index.js +41 -0
  36. package/lib/build/plugins/mtx/resourcesTarBuilder.js +41 -0
  37. package/lib/build/{provider → plugins}/mtx-extension/extensionCompilation.js +1 -1
  38. package/lib/build/{provider → plugins}/mtx-extension/index.js +35 -44
  39. package/lib/build/{provider → plugins}/mtx-sidecar/index.js +17 -3
  40. package/lib/build/{provider → plugins}/nodejs/index.js +29 -28
  41. package/lib/build/{plugin.js → plugins/plugin.js} +45 -59
  42. package/lib/build/plugins.js +11 -8
  43. package/lib/build/util.js +0 -8
  44. package/lib/compile/to-xsuaa.js +2 -2
  45. package/lib/deploy/to-hana/hana.js +64 -56
  46. package/lib/import/common.js +1 -1
  47. package/lib/import/odata/metadataconverter/MetadataConverter.js +4 -3
  48. package/lib/import/odata/v2parser.js +28 -28
  49. package/lib/import/odata/v4parser.js +37 -2
  50. package/lib/import/openapi/index.js +1 -1
  51. package/lib/init/constants.js +0 -1
  52. package/lib/init/template/app-frontend/index.js +1 -1
  53. package/lib/init/template/approuter/files/package.json +1 -1
  54. package/lib/init/template/completion/completionSetup.js +1 -1
  55. package/lib/init/template/data/as-csv.js +1 -1
  56. package/lib/init/template/github-actions/index.js +1 -1
  57. package/lib/init/template/handler/index.js +1 -1
  58. package/lib/init/template/helm/index.js +3 -3
  59. package/lib/init/template/kyma/index.js +3 -3
  60. package/lib/init/template/lint/index.js +7 -21
  61. package/lib/init/template/multitenancy/files/package.json.hbs +0 -5
  62. package/lib/init/template/postgres/files/containerize.yaml.hbs +15 -0
  63. package/lib/init/template/postgres/files/package.json.hbs +35 -0
  64. package/lib/init/template/postgres/files/values.yaml.hbs +23 -0
  65. package/lib/init/template/postgres/index.js +34 -9
  66. package/lib/init/template/test/files/package.json +1 -1
  67. package/lib/init/template/typescript/files/package.json +1 -1
  68. package/lib/init/template/workzone-standard/files/mta.yaml.hbs +1 -0
  69. package/lib/lint/eslintHelp.json +1 -1
  70. package/lib/lint/io.js +9 -13
  71. package/lib/mtx/pull.js +1 -1
  72. package/lib/mtx/settings_manager.js +11 -5
  73. package/lib/mtx/tenant_action.js +1 -1
  74. package/lib/mtx/util/fs.js +2 -2
  75. package/lib/util/fs.js +3 -3
  76. package/lib/util/git.js +1 -1
  77. package/lib/util/glob.js +1 -1
  78. package/lib/watch/hot-reload.js +202 -0
  79. package/lib/watch/livereload-server.js +6 -4
  80. package/lib/watch/node-watch.js +5 -1
  81. package/lib/watch/watched.js +7 -3
  82. package/lib/watch/watcher.js +41 -3
  83. package/npm-shrinkwrap.json +31 -22
  84. package/package.json +1 -1
  85. package/lib/build/buildTaskEngine.js +0 -377
  86. package/lib/build/buildTaskFactory.js +0 -198
  87. package/lib/build/buildTaskProvider.js +0 -38
  88. package/lib/build/buildTaskProviderFactory.js +0 -233
  89. package/lib/build/provider/internalBuildTaskProvider.js +0 -227
  90. package/lib/build/provider/java-cf/index.js +0 -1
  91. package/lib/build/provider/mtx/index.js +0 -36
  92. package/lib/build/provider/mtx/resourcesTarBuilder.js +0 -102
  93. package/lib/build/provider/node-cf/index.js +0 -1
  94. package/lib/init/template/lint/files/.eslint/rules/no-entity-moo.js +0 -40
  95. package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/fixed/schema.cds +0 -4
  96. package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/invalid/schema.cds +0 -4
  97. package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/rule.test.js +0 -15
  98. package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/valid/schema.cds +0 -6
  99. package/lib/init/types.d.ts +0 -23
  100. /package/lib/build/{provider → plugins}/hana/2migration.js +0 -0
  101. /package/lib/build/{provider → plugins}/hana/template/.hdiconfig-all +0 -0
  102. /package/lib/build/{provider → plugins}/hana/template/.hdiconfig-cloud +0 -0
  103. /package/lib/build/{provider → plugins}/hana/template/.hdinamespace +0 -0
  104. /package/lib/build/{provider → plugins}/hana/template/package.json +0 -0
  105. /package/lib/build/{provider → plugins}/hana/template/undeploy.json +0 -0
@@ -1,198 +0,0 @@
1
- // @ts-check
2
- const cds = require('../cds')
3
- const BuildTaskProviderFactory = require('./buildTaskProviderFactory')
4
- const { hasJavaNature, getDefaultModelPaths, hasOptionValue, BuildError } = require('./util')
5
- const { OPTION_WS, IGNORE_DEFAULT_MODELS, NODEJS_MODEL_EXCLUDE_LIST, BUILD_TASK_NODEJS, BUILD_TASK_NODE_CF } = require("./constants")
6
- const DEBUG = cds.debug('cli|build')
7
-
8
- module.exports = class BuildTaskFactory {
9
- constructor(options) {
10
- this._providerFactory = new BuildTaskProviderFactory(options)
11
- }
12
- get providerFactory() {
13
- return this._providerFactory
14
- }
15
- get options() {
16
- return this.providerFactory.options
17
- }
18
-
19
- // the following order for determining build tasks is used
20
- // 1. create from command line input, e.g. cds build/all --for hana --src db --model srv --dest db
21
- // 2. read using cds.env.build.tasks
22
- // 3. create from cds.env.folders config data
23
- async getTasks() {
24
- const tasks = await this._createTasks()
25
- // always resolve tasks for input validation
26
- const resolvedTasks = this.providerFactory.resolveTasks(tasks)
27
- if (this.options.resolve) {
28
- return resolvedTasks
29
- }
30
- return tasks
31
- }
32
-
33
- createPlugin(task) {
34
- return this.providerFactory.createPlugin(task)
35
- }
36
-
37
- async _createTasks() {
38
- DEBUG?.(`determining build tasks for project [${cds.root}].`)
39
-
40
- let tasks = BuildTaskFactory._getExistingTasks()
41
- if (tasks.length === 0) {
42
- tasks = await this.providerFactory.lookupTasks()
43
- this._applyCliOptions(tasks)
44
- } else {
45
- this._applyCliOptions(tasks)
46
- // 1. apply default values including task.for and ensure that for all tasks a provider exists - throwing error otherwise
47
- await this.providerFactory.applyTaskDefaults(tasks)
48
- // ensure that dependencies get wired up before filtering
49
- await this.providerFactory.lookupTasks(tasks, true)
50
- }
51
-
52
- // 2. filters the list of build tasks
53
- // Note: A new task might get created, e.g. 'cds build --for hana' will enforce a hana build even if sqlite has been configured
54
- let existingTasks = tasks
55
- tasks = await this._filterTasksForCli(tasks)
56
- if (tasks.length === 0) {
57
- return tasks
58
- }
59
-
60
- // 3. add dependencies
61
- existingTasks = [...tasks]
62
- await this.providerFactory.lookupTasks(tasks, true)
63
- if (tasks.length > existingTasks.length) {
64
- const newTasks = tasks.filter(task => !existingTasks.includes(task))
65
- // a dependant task was added
66
- this._applyCliOptions(newTasks)
67
- }
68
-
69
- // obligatory task defaults shared by all tasks
70
- await BuildTaskFactory._applyCommonTaskDefaults(tasks)
71
-
72
- BuildTaskFactory._setDefaultBuildTargetFolder()
73
- return tasks
74
- }
75
-
76
- static _getExistingTasks() {
77
- return Array.isArray(cds.env.build?.tasks) ? structuredClone(cds.env.build.tasks) : []
78
- }
79
-
80
- static async _applyCommonTaskDefaults(tasks) {
81
- // normalize model options
82
- tasks.forEach(task => {
83
- if (task.options?.model && !Array.isArray(task.options.model)) {
84
- task.options.model = [task.options.model]
85
- }
86
- })
87
- const modelPaths = await getDefaultModelPaths(false)
88
- let wsModelPaths
89
- // calculate only once
90
- if (cds.cli.options?.[OPTION_WS] || tasks.some(task => hasOptionValue(task.options?.[OPTION_WS], true))) {
91
- wsModelPaths = await getDefaultModelPaths(true)
92
- }
93
- // set default model options
94
- tasks.forEach(task => {
95
- if (!task.src) {
96
- throw new BuildError(`Mandatory property 'src' not defined for build task '${task.for}'.`)
97
- }
98
- const optionWs = cds.cli.options?.[OPTION_WS] || hasOptionValue(task.options?.[OPTION_WS], true)
99
- // shallow copy model paths
100
- this._setTaskModelOptions(task, optionWs ? [...wsModelPaths] : [...modelPaths])
101
- })
102
- }
103
-
104
- static _setDefaultBuildTargetFolder() {
105
- // Java projects use "." as the default build target folder
106
- if (hasJavaNature() && this._adaptBuildTargetSettingForJava()) {
107
- DEBUG?.("using inplace build for java project instead of default staging build")
108
- }
109
- }
110
-
111
- /**
112
- * Use inplace build for java projects if build.target has not been configured.
113
- * @returns {boolean} true if changed, false otherwise
114
- */
115
- static _adaptBuildTargetSettingForJava() {
116
- if (cds.env.build.target !== ".") {
117
- // filter user settings of cds.env
118
- const userEnv = cds.env.for("cds", cds.root, false)
119
-
120
- // use helper as env.build might be undefined
121
- if (!userEnv.build?.target) {
122
- cds.env.build.target = "."
123
- return true
124
- }
125
- }
126
- return false
127
- }
128
-
129
- async _filterTasksForCli(tasks) {
130
- const options = this.options
131
- // filter tasks using either option for, use, src
132
- let resultTasks = tasks.filter(task => {
133
- return (!options.for || options.for === task.for)
134
- && (!options.src || options.src === task.src)
135
- })
136
- if (resultTasks.length === 0) {
137
- if (options.for) {
138
- const task = this.providerFactory.getTask({ for: options.for })
139
- if (options.src) {
140
- task.src = options.src
141
- }
142
- resultTasks.push(task)
143
- this._applyCliOptions(resultTasks)
144
- await this.providerFactory.applyTaskDefaults(resultTasks)
145
- }
146
- } else if (resultTasks.length <= tasks.length) {
147
- // return the same array as long as it contains a subset of the given tasks
148
- tasks.length = 0
149
- resultTasks.forEach(task => tasks.push(task))
150
- resultTasks = tasks
151
- }
152
- return resultTasks
153
- }
154
-
155
- _applyCliOptions(tasks) {
156
- const options = this.options
157
- // apply remaining cli options to filtered tasks
158
- tasks.forEach(task => {
159
- if (options.dest) {
160
- task.dest = options.dest
161
- }
162
- if (options.taskOptions) {
163
- const taskOptions = JSON.parse(JSON.stringify(options.taskOptions))
164
- task.options = task.options ? Object.assign(task.options, taskOptions) : taskOptions
165
- }
166
- })
167
- }
168
-
169
- static _setTaskModelOptions(task, defaultModelPaths) {
170
- // bootstrap service model is only required for Nodejs build task - issues/12770#issuecomment-1805719
171
- if (task.for !== BUILD_TASK_NODEJS && task.for !== BUILD_TASK_NODE_CF) {
172
- defaultModelPaths = defaultModelPaths.filter(p => !NODEJS_MODEL_EXCLUDE_LIST.includes(p))
173
- }
174
-
175
- let taskModelPaths = task.options?.model
176
- if (taskModelPaths && !Array.isArray(taskModelPaths)) {
177
- taskModelPaths = [taskModelPaths]
178
- }
179
- const allowList = new RegExp(`^@sap/cds${cds.env.requires.toggles ? '|^' + cds.env.features.folders.replace('*', '') : ''}`)
180
- task.options = task.options || {}
181
- let modelPaths = []
182
- if (taskModelPaths?.length) {
183
- if (!hasOptionValue(task.options?.[IGNORE_DEFAULT_MODELS], true)) {
184
- modelPaths = defaultModelPaths.filter(p => p.match(allowList))
185
- }
186
- } else {
187
- modelPaths = [...defaultModelPaths]
188
- if (!modelPaths.includes(task.src)) {
189
- modelPaths.push(task.src)
190
- }
191
- if (hasOptionValue(task.options?.[IGNORE_DEFAULT_MODELS], true)) {
192
- // all default models except the built-in models
193
- modelPaths = modelPaths.filter(p => !p.match(allowList))
194
- }
195
- }
196
- task.options.model = [...new Set(taskModelPaths?.length ? taskModelPaths.concat(modelPaths) : modelPaths)]
197
- }
198
- }
@@ -1,38 +0,0 @@
1
- /* eslint-disable no-unused-vars */
2
-
3
- /** @typedef {import("./buildTaskProviderFactory").Task} Task */
4
- /** @typedef {import("./plugin")} Plugin_ */
5
-
6
- /**
7
- * @abstract
8
- */
9
- module.exports = class BuildTaskProvider {
10
- /**
11
- * @abstract
12
- * @param {{for: string}} key
13
- * @returns {boolean | undefined}
14
- */
15
- providesTask(key) { }
16
- /**
17
- * @param {{for: string}} key
18
- * @returns {} task
19
- */
20
- getTask(key) { return key }
21
- /**
22
- * @abstract
23
- * @param {Task} task
24
- * @returns {typeof Plugin_}
25
- */
26
- getPlugin(task) { /** abstract */ }
27
- /**
28
- * @abstract
29
- * @param {Array} tasks
30
- * @param {boolean} dependencies
31
- */
32
- async lookupTasks(tasks, dependencies) { /* abstract */ }
33
- /**
34
- * @abstract
35
- * @param {Task} task
36
- */
37
- async applyTaskDefaults(task) { /** abstract */ }
38
- }
@@ -1,233 +0,0 @@
1
- // @ts-check
2
- const fs = require('fs')
3
- const path = require('path')
4
- const cds = require('../cds')
5
- const { OUTPUT_MODE_FILESYSTEM, DEFAULT_SRC_FOLDER } = require('./constants')
6
- const InternalBuildTaskProvider = require('./provider/internalBuildTaskProvider')
7
- const BuildTaskProvider = require('./buildTaskProvider')
8
- const { BuildError, normalizePath } = require('./util')
9
- const DEBUG = cds.debug('cli|build')
10
-
11
- /**
12
- * @typedef {import('./plugin').Task} Task
13
- */
14
-
15
- class BuildTaskProviderFactory {
16
- /**
17
- * @param {import('./index').BuildOptions} options - build options
18
- */
19
- constructor(options = {}) {
20
- options.outputMode = options.outputMode || OUTPUT_MODE_FILESYSTEM
21
- if (options.clean === undefined) {
22
- options.clean = true
23
- }
24
- ['for', 'src', 'dest'].forEach(key => {
25
- if (options[key]) {
26
- if (typeof options[key] !== 'string') {
27
- throw new BuildError(`Invalid build options - property '${key}' must be a string`)
28
- }
29
- if (key === 'src' || key === 'dest') {
30
- // normalize path separator and remove trailing slash
31
- options[key] = normalizePath(options[key])
32
- }
33
- }
34
- })
35
- /** @type {{ options: import('./index').BuildOptions, tasks: Task[]}} */
36
- this._context = { options, tasks: [] } // resolved tasks
37
- }
38
- get options() {
39
- return this._context.options
40
- }
41
- get context() {
42
- return this._context
43
- }
44
- get providers() {
45
- if (!this._providers) {
46
- this._providers = this._loadProviders()
47
- }
48
- return this._providers
49
- }
50
-
51
- getTask(key) {
52
- return this._getProvider(key).getTask(key)
53
- }
54
-
55
- async applyTaskDefaults(tasks) {
56
- return Promise.all(tasks.map(async (task) => {
57
- if (!task.for) {
58
- throw new BuildError(`Mandatory property 'for' not defined for build task.`)
59
- }
60
- return this._applyTaskDefaults(this._getProvider(task), [task])
61
- }))
62
- }
63
-
64
- async lookupTasks(tasks = [], dependencies) {
65
- for (const provider of this.providers) {
66
- const existingTasks = [...tasks]
67
- await this._lookupTasks(provider, tasks, dependencies)
68
- if (existingTasks.length < tasks.length) {
69
- // apply defaults
70
- const newTasks = tasks.filter(task => !existingTasks.includes(task))
71
- await this._applyTaskDefaults(provider, newTasks)
72
- DEBUG?.(`Build task provider ${provider.constructor.name} returned build tasks ${JSON.stringify(newTasks)}`)
73
- }
74
- }
75
- return tasks
76
- }
77
-
78
- /**
79
- * Create a Plugin instance for the given build task.
80
- * The implementation is loaded based on the build task's 'for' or 'use' option.
81
- * @param {Task} task
82
- */
83
- createPlugin(task) {
84
- const Plugin = this.getPlugin(task)
85
- const resolvedTask = this._resolveTask(task)
86
- DEBUG?.(`loaded build plugin [${resolvedTask.for}]`)
87
-
88
- const plugin = new Plugin()
89
- if (!(plugin instanceof Plugin)) {
90
- throw new Error(`Invalid Build plugin type ${task.for}`)
91
- }
92
- plugin._task = resolvedTask
93
- plugin._context = this.context
94
- this.context.tasks.push(resolvedTask)
95
- DEBUG?.(`created build plugin [${resolvedTask.for}]`)
96
- return plugin
97
- }
98
-
99
- /**
100
- * Loads the build plugin implementation for the given build task.
101
- * 'for' defines an alias for built-in plugins like 'hana', 'java', 'node', 'fiori' or 'mtx'.
102
- * 'use' defines the fully qualified module name of custom build plugins implementations.
103
- * @param {Task} task
104
- * @returns {typeof import('./plugin')}
105
- */
106
- getPlugin(task) {
107
- const provider = this._getProvider(task)
108
- try {
109
- return provider.getPlugin(task)
110
- } catch (e) {
111
- console.error(`Provider failed to load build plugin class ${task.for} - provider: ${provider.constructor.name}`)
112
- throw e
113
- }
114
- }
115
-
116
- /**
117
- * @param {Task[]} tasks
118
- */
119
- resolveTasks(tasks) {
120
- return tasks.map(task => this._resolveTask(task))
121
- }
122
-
123
- /**
124
- * Resolves the given build task based on the project root folder.<br>
125
- * The task is validated in order to ensure that 'src' refers to a valid folder and 'for' or 'use' reference can be required.
126
- * @private
127
- * @param {Task} task
128
- */
129
- _resolveTask(task) {
130
- // second validate src path
131
- const resolvedTask = JSON.parse(JSON.stringify(task))
132
-
133
- // Do not store resolved symlinks as this is causing issues on Windows, e.g. if git projects are
134
- // located under 'C:\SAPDevelop\git\...' using a sym-link from '%USERHOME%\git' to 'C:\SAPDevelop\git'.
135
- // see cap/issues/#8694
136
- resolvedTask.src = path.resolve(cds.root, task.src)
137
- // if --ws is passed, the db/ folder is not required, as the task will gather the model from the workspaces
138
- if (!this.options.ws) {
139
- try {
140
- //validate source path
141
- fs.realpathSync(resolvedTask.src)
142
- } catch {
143
- throw new BuildError(`The 'src' folder '${path.resolve(cds.root, task.src)}' for build task '${resolvedTask.for}' does not exist`)
144
- }
145
- }
146
- resolvedTask.dest = path.resolve(cds.root, cds.env.build.target, task.dest || task.src)
147
- resolvedTask.options = task.options || {}
148
- return resolvedTask
149
- }
150
-
151
- _getProvider(key) {
152
- const provider = this.providers.find(provider => {
153
- try {
154
- return provider.providesTask(key)
155
- } catch (e) {
156
- console.error(`Build task provider ${provider.constructor.name} returned an error`)
157
- throw e
158
- }
159
- })
160
- if (!provider) {
161
- throw new BuildError(`No provider found for build task '${key.for}'. Ensure that all required dependencies have been added and 'npm install' has been executed.`)
162
- }
163
- return provider
164
- }
165
-
166
- async _lookupTasks(provider, tasks, dependencies) {
167
- return provider.lookupTasks(tasks, dependencies)
168
- }
169
-
170
- async _applyTaskDefaults(provider, tasks) {
171
- return Promise.all(tasks.map(task => provider.applyTaskDefaults(task)))
172
- }
173
-
174
- _loadProviders() {
175
- return [
176
- new InternalBuildTaskProvider(),
177
- new PluginBuildTaskProvider()
178
- ]
179
- }
180
- }
181
-
182
- /**
183
- * Default provider implementation handling fully qualified custom build task declarations.
184
- */
185
- class PluginBuildTaskProvider extends BuildTaskProvider {
186
- #plugins = require('./plugins').plugins
187
- get plugins() {
188
- return this.#plugins
189
- }
190
-
191
- /**
192
- * @param {{for: string}} key
193
- */
194
- providesTask(key) {
195
- return this.plugins.has(key.for)
196
- }
197
-
198
- getPlugin(task) {
199
- return this.plugins.get(task.for)
200
- }
201
-
202
- async lookupTasks(tasks, dependencies) {
203
- if (!dependencies) {
204
- for (const [id, plugin] of this.plugins) {
205
- if (plugin.hasTask()) {
206
- tasks.push(this.getTask({ for: id }))
207
- }
208
- }
209
- }
210
- }
211
-
212
- async applyTaskDefaults(task) {
213
- const defaultTask = this.getTask(task)
214
- const names = Object.getOwnPropertyNames(defaultTask)
215
- names.forEach(name => {
216
- task[name] ??= defaultTask[name]
217
- })
218
- }
219
-
220
- /**
221
- * @param {{for: string}} key
222
- * @returns {Task}
223
- */
224
- getTask(key) {
225
- // plugin entry is already validated, a taskDefaults default member exists
226
- const task = JSON.parse(JSON.stringify(this.plugins.get(key.for)?.taskDefaults ?? {}))
227
- task.for = key.for
228
- task.src ??= DEFAULT_SRC_FOLDER
229
- task.src = task.src.replace(/\/$/, '')
230
- return task
231
- }
232
- }
233
- module.exports = BuildTaskProviderFactory
@@ -1,227 +0,0 @@
1
- const cds = require('../../cds')
2
- const { exists, isdir, path } = cds.utils
3
- const { hasJavaNature, BuildError, normalizePath } = require('../util')
4
- const BuildTaskProvider = require('../buildTaskProvider')
5
- const { FILE_EXT_CDS, BUILD_TASK_HANA, BUILD_TASK_FIORI, BUILD_TASK_JAVA, BUILD_TASK_JAVA_CF, BUILD_TASK_NODEJS, BUILD_TASK_NODE_CF, BUILD_TASK_MTX,
6
- BUILD_TASKS, BUILD_TASK_MTX_SIDECAR, MTX_SIDECAR_FOLDER, BUILD_TASK_MTX_EXTENSION } = require("../constants")
7
- const ResourcesTarBuilder = require('./mtx/resourcesTarBuilder')
8
- const DEBUG = cds.debug('cli|build')
9
- const ModelProviderService = 'cds.xt.ModelProviderService'
10
-
11
- module.exports = class InternalBuildTaskProvider extends BuildTaskProvider {
12
- providesTask(key) {
13
- return BUILD_TASKS.includes(key.for)
14
- }
15
-
16
- async lookupTasks(tasks, dependencies) {
17
- return this._createTasks(tasks, dependencies)
18
- }
19
-
20
- async applyTaskDefaults(task) {
21
- InternalBuildTaskProvider._setDefaultSrcFolder(task)
22
- }
23
-
24
- getPlugin(task) {
25
- return require(`./${task.for}`)
26
- }
27
-
28
- async _createTasks(tasks, dependencies) {
29
- let db = typeof cds.env.folders.db === "string" ? [normalizePath(cds.env.folders.db)] : cds.env.folders.db
30
- let srv = typeof cds.env.folders.srv === "string" ? [normalizePath(cds.env.folders.srv)] : cds.env.folders.srv
31
-
32
- const folder4 = filesOrFolders => {
33
- const entry = filesOrFolders
34
- .flatMap(r => path.extname(r) === FILE_EXT_CDS ? [r] : [r, r + FILE_EXT_CDS])
35
- .find(r => exists(r))
36
- return entry && (isdir(entry) ? entry : path.dirname(entry))
37
- }
38
- const dbOptions = { model: [] }
39
- const srvOptions = { model: [] }
40
- if (Array.isArray(db) && db.length > 0) {
41
- db = folder4(db)
42
- if (!db && !dependencies) { // log once
43
- DEBUG?.("No database module found")
44
- }
45
- }
46
- if (Array.isArray(srv) && srv.length > 0) {
47
- srv = folder4(srv)
48
- if (!srv && !dependencies) { // log once
49
- DEBUG?.("No service module found")
50
- }
51
- }
52
-
53
- // order of creation is relevant
54
- if (dependencies) {
55
- const mtxTask = tasks.find(task => task.for === BUILD_TASK_MTX || task.for === BUILD_TASK_MTX_SIDECAR)
56
- if (mtxTask) {
57
- //restore used tasks as they might have been filtered by 'cds build --for mtx'
58
- if (mtxTask._uses) {
59
- mtxTask._uses.map(use => use.task).forEach(task => {
60
- if (!tasks.includes(task)) {
61
- tasks.push(task)
62
- }
63
- })
64
- }
65
- let dbTask = ResourcesTarBuilder.getHanaTenantDbTask(tasks, mtxTask)
66
- if (!dbTask) {
67
- // db task might be missing if mtx task is enforced by 'cds build --for mtx'
68
- if (cds.env.build.tasks) {
69
- dbTask = ResourcesTarBuilder.getHanaTenantDbTask(cds.env.build.tasks, mtxTask)
70
- }
71
- if (!dbTask) {
72
- dbTask = this._createDbTask(db, dbOptions)
73
- }
74
- if (dbTask) {
75
- tasks.push(dbTask)
76
- }
77
- }
78
- if (dbTask && !mtxTask._uses?.map(use => use.task).includes(dbTask)) {
79
- const use = { task: dbTask }
80
- mtxTask._uses ? mtxTask._uses.push(use) : mtxTask._uses = [use]
81
- }
82
- }
83
- } else {
84
- !db && DEBUG?.(`project doesn't have a database module '${cds.env.folders.db}'`)
85
- !srv && DEBUG?.(`project doesn't have a service module '${cds.env.folders.srv}'`)
86
-
87
- // create hana build task
88
- const dbTask = this._createDbTask(db, dbOptions)
89
- if (dbTask) {
90
- tasks.push(dbTask)
91
- }
92
- // create java or node build task
93
- const srvTask = this._createSrvTask(srv, srvOptions)
94
- if (srvTask) {
95
- tasks.push(srvTask)
96
- }
97
-
98
- // create mtx build task
99
- const mtxTask = this._createMtxTask(srv)
100
- if (mtxTask) {
101
- tasks.push(mtxTask)
102
- }
103
- }
104
- }
105
-
106
- _createDbTask(src, taskOptions) {
107
- if (!src || InternalBuildTaskProvider._isMtxExtension()) {
108
- return null
109
- }
110
- let task = null
111
- if (this._useHana()) {
112
- DEBUG?.("found HANA database")
113
- task = {
114
- src: src,
115
- for: BUILD_TASK_HANA,
116
- options: taskOptions
117
- }
118
- } else {
119
- DEBUG?.("found sqlite database - skipping HANA build task")
120
- }
121
- return task
122
- }
123
-
124
- _useHana() {
125
- if (cds.env.requires.db?.kind === "hana" || cds.env.requires.db?.dialect === "hana") {
126
- return true
127
- }
128
- // false if other db has been defined
129
- if (cds.env.requires.db?.kind) {
130
- return false
131
- }
132
- }
133
-
134
- _createMtxTask(src) {
135
- const main = cds.env
136
- if (main.extends) {
137
- return { for: BUILD_TASK_MTX_EXTENSION }
138
- }
139
- const isMtxs = main.requires.toggles || main.requires.multitenancy || main.requires[ModelProviderService]
140
- if (isMtxs) {
141
- if (main.requires?.[ModelProviderService]?._in_sidecar) {
142
- throw new BuildError(`Seems that you are executing 'cds build' in the 'mtx/sidecar' folder. Execute 'cds build' in the project root folder instead.`)
143
- }
144
- const sidecarPath = path.join(cds.root, MTX_SIDECAR_FOLDER)
145
- const sidecar = cds.env.for("cds", sidecarPath)
146
- if (sidecar?.requires[ModelProviderService]?._in_sidecar) {
147
- if (!exists(sidecarPath)) {
148
- throw new BuildError(`MTX sidecar directory '${MTX_SIDECAR_FOLDER}' does not exist. Custom build task configuration required if the folder is named differently.`)
149
- }
150
- return { src: MTX_SIDECAR_FOLDER, for: BUILD_TASK_MTX_SIDECAR }
151
- }
152
- if (!hasJavaNature()) { // only Node.js: embedded multitenancy
153
- return { src, for: BUILD_TASK_MTX }
154
- }
155
- }
156
- }
157
-
158
- _createSrvTask(src, taskOptions) {
159
- if (!src || InternalBuildTaskProvider._isMtxExtension()) {
160
- return null
161
- }
162
- let task = null
163
- if (hasJavaNature()) {
164
- task = this._createJavaTask(src, taskOptions)
165
- } else {
166
- task = this._createNodeTask(src, taskOptions)
167
- }
168
- return task
169
- }
170
-
171
- _createJavaTask(src, taskOptions) {
172
- DEBUG?.("found Java runtime")
173
- return {
174
- src: src,
175
- for: BUILD_TASK_JAVA,
176
- options: taskOptions
177
- }
178
- }
179
-
180
- _createNodeTask(src, taskOptions) {
181
- DEBUG?.("found Nodejs runtime")
182
- if (!exists('package.json')) {
183
- throw new BuildError(`No 'package.json' found in project root folder '${cds.root}'`)
184
- }
185
- return {
186
- src: src,
187
- for: BUILD_TASK_NODEJS,
188
- options: taskOptions
189
- }
190
- }
191
-
192
- static _isMtxExtension() {
193
- return !!cds.env.extends
194
- }
195
-
196
- static _setDefaultSrcFolder(task) {
197
- switch (task.for) {
198
- case BUILD_TASK_HANA:
199
- task.src ||= normalizePath(cds.env.folders.db)
200
- break
201
- case BUILD_TASK_JAVA:
202
- case BUILD_TASK_JAVA_CF:
203
- case BUILD_TASK_NODEJS:
204
- case BUILD_TASK_NODE_CF:
205
- task.src ||= normalizePath(cds.env.folders.srv)
206
- break
207
- case BUILD_TASK_FIORI:
208
- task.src ||= normalizePath(cds.env.folders.app)
209
- break
210
- case BUILD_TASK_MTX_SIDECAR:
211
- task.src ||= MTX_SIDECAR_FOLDER
212
- break
213
- case BUILD_TASK_MTX_EXTENSION:
214
- if (task.src && task.src !== cds.root) {
215
- throw new BuildError("Invalid 'src' property value for build task 'mtx-extension', the only allowed value is '.'")
216
- }
217
- task.src ||= "."
218
- break
219
- case BUILD_TASK_MTX:
220
- // mtxs with nodejs, but without sidecar
221
- task.src ||= normalizePath(cds.env.folders.srv)
222
- break
223
- default:
224
- throw new Error(`Unknown build task '${task.for}'`)
225
- }
226
- }
227
- }
@@ -1 +0,0 @@
1
- module.exports = require('../java')