@sap/cds-dk 9.7.2 → 9.8.1

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 +42 -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 +30 -9
  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} +8 -27
  29. package/lib/build/{provider → plugins}/fiori/index.js +27 -40
  30. package/lib/build/{provider → plugins}/hana/index.js +67 -85
  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} +57 -60
  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 +1 -2
  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 +4 -4
  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 +46 -31
  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,13 +1,13 @@
1
1
  const path = require('node:path')
2
2
  const fs = require('node:fs')
3
3
  const os = require('node:os');
4
- const cds = require('../cds')
4
+ const cds = require('../../cds')
5
5
  const IS_WIN = os.platform() === 'win32';
6
6
 
7
- const { OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM, SEVERITY_INFO, SEVERITY_WARNING, SEVERITY_ERROR } = require('./constants')
7
+ const { SEVERITY_INFO, SEVERITY_WARNING, SEVERITY_ERROR } = require('../constants')
8
8
 
9
- const { find } = require('../util/fs')
10
- const { hasOptionValue, relativePaths, BuildMessage, filterFeaturePaths } = require('./util')
9
+ const { find } = require('../../util/fs')
10
+ const { hasOptionValue, relativePaths, BuildMessage, filterFeaturePaths } = require('../util')
11
11
 
12
12
  const DEBUG = cds.debug('cli|build')
13
13
 
@@ -28,18 +28,17 @@ const DEBUG = cds.debug('cli|build')
28
28
  * the fully qualified node module path of the build plugin implementation.
29
29
  * The build task engine defines the following protocol. The methods are invoked in descending order:
30
30
  * - `init()` - optional
31
- * - `get priority()` - optional
32
31
  * - `async clean()`
33
32
  * - `async build()`
34
33
  * The reflected CSN can be accessed using the async method `model()`.
35
34
  */
36
- class Plugin {
35
+ module.exports = class Plugin {
37
36
  static INFO = SEVERITY_INFO
38
37
  static WARNING = SEVERITY_WARNING
39
38
  static ERROR = SEVERITY_ERROR
40
39
 
41
40
  /** @type {TaskDefaults} */
42
- static taskDefaults // injected externally
41
+ taskDefaults // injected externally
43
42
 
44
43
  /**
45
44
  * @type {Task | undefined}
@@ -103,17 +102,7 @@ class Plugin {
103
102
  return this._context
104
103
  }
105
104
 
106
- /**
107
- * Returns the priority of this plugin as number, where 1024 represents the default value
108
- * to ensure that custom plugins are by default executed before the built-in plugins.
109
- * The higher the priority value, the sooner the build plugin will be run.
110
- * The range of valid priority values is from -1024 to +1024.
111
- * Built-in plugins have a priority value range from 0 - 524.
112
- * @returns the priority for this plugin as integer.
113
- */
114
- get priority() {
115
- return 1024
116
- }
105
+ get requires() { return [] }
117
106
 
118
107
  /**
119
108
  * Called by the framework immediately after this instance has been created.
@@ -133,7 +122,7 @@ class Plugin {
133
122
 
134
123
  /**
135
124
  * Called by the framework immediately before 'build' to delete any output created by this build plugin.
136
- * Note: The [`BuildTaskEngine`]({@link ./buildTaskEngine.js)}) is cleaning the common generation target folder if the build is
125
+ * Note: The common generation target folder is cleaned by default if the build is
137
126
  * executed in staging mode, e.g. build.target: "gen".
138
127
  */
139
128
  async clean() {
@@ -162,15 +151,13 @@ class Plugin {
162
151
  write(data) {
163
152
  return {
164
153
  to: async (/** @type {string} */ dest) => {
165
- if (this._hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM)) {
166
- if (!path.isAbsolute(dest)) {
167
- // relative to build task's destination path
168
- dest = path.resolve(this.task.dest, dest)
169
- }
170
- this.pushFile(dest)
171
- await fs.promises.mkdir(path.dirname(dest), { recursive: true })
172
- await fs.promises.writeFile(dest, typeof data === "object" && !Buffer.isBuffer(data) ? JSON.stringify(data, null, 2) : data)
154
+ if (!path.isAbsolute(dest)) {
155
+ // relative to build task's destination path
156
+ dest = path.resolve(this.task.dest, dest)
173
157
  }
158
+ this.pushFile(dest)
159
+ await fs.promises.mkdir(path.dirname(dest), { recursive: true })
160
+ await fs.promises.writeFile(dest, typeof data === "object" && !Buffer.isBuffer(data) ? JSON.stringify(data, null, 2) : data)
174
161
  }
175
162
  }
176
163
  }
@@ -188,28 +175,26 @@ class Plugin {
188
175
  copy(src) {
189
176
  return {
190
177
  to: async (/** @type {string} */ dest) => {
191
- if (this._hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM)) {
192
- if (!path.isAbsolute(src)) {
193
- // relative to build task's source path
194
- src = path.resolve(this.task.src, src)
195
- }
196
- if (!path.isAbsolute(dest)) {
197
- // relative to build task's destination path
198
- dest = path.resolve(this.task.dest, dest)
199
- }
200
- // list all copied files recursively
201
- if (cds.utils.isdir(src)) {
202
- await fs.promises.cp(src, dest, { recursive: true })
203
- const files = await find(dest)
204
- files.forEach(file => this.pushFile(file))
205
- } else {
206
- this.pushFile(dest)
207
- if (IS_WIN && fs.lstatSync(src).isSymbolicLink()) {
208
- const linkTarget = await fs.promises.readlink(src);
209
- src = path.resolve(path.dirname(src), linkTarget);
210
- }
211
- return fs.promises.cp(src, dest, { recursive: true })
178
+ if (!path.isAbsolute(src)) {
179
+ // relative to build task's source path
180
+ src = path.resolve(this.task.src, src)
181
+ }
182
+ if (!path.isAbsolute(dest)) {
183
+ // relative to build task's destination path
184
+ dest = path.resolve(this.task.dest, dest)
185
+ }
186
+ // list all copied files recursively
187
+ if (cds.utils.isdir(src)) {
188
+ await fs.promises.cp(src, dest, { recursive: true })
189
+ const files = await find(dest)
190
+ files.forEach(file => this.pushFile(file))
191
+ } else {
192
+ this.pushFile(dest)
193
+ if (IS_WIN && fs.lstatSync(src).isSymbolicLink()) {
194
+ const linkTarget = await fs.promises.readlink(src);
195
+ src = path.resolve(path.dirname(src), linkTarget);
212
196
  }
197
+ return fs.promises.cp(src, dest, { recursive: true })
213
198
  }
214
199
  }
215
200
  }
@@ -221,7 +206,7 @@ class Plugin {
221
206
  * User messages will be logged after CDS build has been finished based on the log-level that has been set.
222
207
  * By default messages with severity <em>warning</em> and <em>error</em> will be logged.
223
208
  * @param {string} message - the message text
224
- * @param {import('./constants').Severity} severity - the severity of the message
209
+ * @param {import('../constants').Severity} severity - the severity of the message
225
210
  */
226
211
  pushMessage(message, severity) {
227
212
  this.messages.push(new BuildMessage(message, severity))
@@ -233,21 +218,23 @@ class Plugin {
233
218
  * @returns {Promise<import('@sap/cds').csn.CSN | null>} the compiled CSN model
234
219
  */
235
220
  async model() {
236
- const files = cds.resolve(this.task.options.model || this.task.src)
237
-
221
+ const { src, options: { model }, for: type } = this.task
222
+ const files = cds.resolve(model || src)
238
223
  if (!files || files.length === 0) {
239
- console.log(`no CDS model found for [${this.task.for}] build task [${this.task.src}] - nothing to be done`)
240
- return null
224
+ console.log(`no CDS model found for [${type}] build task [${src}] - nothing to be done`)
225
+ return
241
226
  }
242
227
  DEBUG?.(`model: ${relativePaths(cds.root, files).join(", ")}`)
243
- // $location paths are relative to current working dir by default - make sure a given project root folder is taken
228
+
244
229
  const options = { ...this.options(), cwd: cds.root }
245
230
 
246
- const model = await cds.load(files, options)
247
- if (!model) {
248
- return null
231
+ this.context._modelCache ??= new Map()
232
+ const cacheKey = JSON.stringify({ files, options })
233
+ if (!this.context._modelCache.has(cacheKey)) {
234
+ const _load = cds.load(files, options)
235
+ this.context._modelCache.set(cacheKey, _load)
249
236
  }
250
- return model
237
+ return this.context._modelCache.get(cacheKey)
251
238
  }
252
239
 
253
240
  /**
@@ -261,7 +248,18 @@ class Plugin {
261
248
  return model
262
249
  }
263
250
  const sources = filterFeaturePaths(model, this.task.options.model || this.task.src)
264
- return sources.features ? cds.load(sources.base, this.options()) : model
251
+ if (!sources.features) {
252
+ return model
253
+ }
254
+
255
+ const options = this.options()
256
+ this.context._modelCache ??= new Map()
257
+ const cacheKey = JSON.stringify({ files: sources.base, options })
258
+ if (!this.context._modelCache.has(cacheKey)) {
259
+ const _load = cds.load(sources.base, options)
260
+ this.context._modelCache.set(cacheKey, _load)
261
+ }
262
+ return this.context._modelCache.get(cacheKey)
265
263
  }
266
264
 
267
265
  options() {
@@ -293,4 +291,3 @@ class Plugin {
293
291
  return value
294
292
  }
295
293
  }
296
- module.exports = Plugin
@@ -1,22 +1,20 @@
1
1
  // @ts-check
2
2
  const cds = require('../cds')
3
+ const { isdir, fs, path } = cds.utils
3
4
  const DEBUG = cds.debug('cli|build')
4
5
 
5
- /** @typedef {typeof import('./plugin')} BuildPlugin */
6
+ /** @typedef {typeof import('./plugins/plugin')} BuildPlugin */
6
7
 
7
8
  module.exports = new (class Plugins {
8
9
 
9
10
  /** @type {Map<string, BuildPlugin>} */
10
11
  #plugins = new Map()
12
+ #registeredDefaults = false
11
13
 
12
- get plugins() {
14
+ get all() {
13
15
  return this.#plugins
14
16
  }
15
17
 
16
- constructor() {
17
- this.#registerDefaults()
18
- }
19
-
20
18
  /**
21
19
  * @param {string} id - unique ID of the plugin
22
20
  * @param {BuildPlugin} plugin - build plugin implementation
@@ -32,7 +30,12 @@ module.exports = new (class Plugins {
32
30
  this.#plugins.set(id, plugin)
33
31
  }
34
32
 
35
- #registerDefaults() {
36
- this.register('helm', require('./plugins/helm'))
33
+ registerDefaults() {
34
+ if (this.#registeredDefaults) return
35
+ const plugins = fs.readdirSync(path.join(__dirname, 'plugins'))
36
+ for (const plugin of plugins) if (isdir(__dirname, 'plugins', plugin)) {
37
+ this.register(plugin, require(`./plugins/${plugin}`))
38
+ }
39
+ this.#registeredDefaults = true
37
40
  }
38
41
  })
package/lib/build/util.js CHANGED
@@ -21,13 +21,6 @@ const FLATTEN_MAX_DEPTH = 20 // should suffice, was infinite in earlier versions
21
21
  /** @typedef {object[] | object} Credentials */
22
22
  /** @typedef {(string | NestedStringArray)[]} NestedStringArray */
23
23
 
24
- /**
25
- * Returns whether this project is a java project or not.
26
- */
27
- function hasJavaNature() {
28
- return [cds.env.folders.srv, '.'].some(f => f && fs.existsSync(path.join(cds.root, f, 'pom.xml')))
29
- }
30
-
31
24
  /**
32
25
  * Determines whether the both values are identical.
33
26
  * @template {number | boolean} T
@@ -494,7 +487,6 @@ class BuildError extends Error {
494
487
  }
495
488
 
496
489
  module.exports = {
497
- hasJavaNature,
498
490
  hasOptionValue,
499
491
  relativePaths,
500
492
  resolveRequiredSapModels,
@@ -158,10 +158,10 @@ function getBaseModel(options = {}) {
158
158
  if (typeof options.base === 'string') {
159
159
  try {
160
160
  return JSON.parse(options.base) // plain object
161
- } catch (err) {
161
+ } catch {
162
162
  try {
163
163
  return JSON.parse(fs.readFileSync(path.resolve(options.base))); // file
164
- } catch (err2) {
164
+ } catch {
165
165
  throw new Error('Neither a JSON object nor a file path: ' + options.base)
166
166
  }
167
167
  }
@@ -11,8 +11,8 @@ const mtaUtil = require('./mtaUtil');
11
11
 
12
12
  const { bold, info, warn } = require('../../util/term');
13
13
 
14
- const { bind, storeBindings } = require('../../bind/shared');
15
- const { BUILD_TASK_HANA, OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM, OUTPUT_MODE_RESULT } = require('../../build/constants');
14
+ const { bind, storeBindings, env: bindingEnv } = require('../../bind/shared');
15
+ const { BUILD_TASK_HANA } = require('../../build/constants');
16
16
 
17
17
  const { options, flags } = require('../index');
18
18
  const allOptions = [...options, ...flags];
@@ -43,7 +43,7 @@ module.exports = new class HanaDeployer {
43
43
  if (process.env[varName]) {
44
44
  try {
45
45
  result[varName] = JSON.parse(process.env[varName]);
46
- } catch (err) {
46
+ } catch {
47
47
  throw new Error(`Error parsing environment variable ${varName}`);
48
48
  }
49
49
  }
@@ -52,6 +52,9 @@ module.exports = new class HanaDeployer {
52
52
  }
53
53
 
54
54
  async deploy(options = {}) {
55
+ if (options['store-credentials']) {
56
+ console.warn(warn('The option \'--store-credentials\' has been deprecated and will be removed with the next major release. Use command \'cds bind\' instead.'));
57
+ }
55
58
 
56
59
  if (options.dry && options.out) { // dry run equals cds compile to hana
57
60
  return await this._runCompileToHana(options);
@@ -92,11 +95,10 @@ Therefore, specifying the CDS model is not required when calling 'cds deploy'.`;
92
95
  }
93
96
  }
94
97
 
95
- let buildResult
96
98
  if (cds.cli.options?.['no-build']) {
97
99
  console.log(`Provided flag '--no-build', skipping cds build`)
98
100
  } else {
99
- buildResult = await this._build();
101
+ await build({ for: BUILD_TASK_HANA });
100
102
  }
101
103
 
102
104
  if (options.out) {
@@ -112,7 +114,6 @@ Therefore, specifying the CDS model is not required when calling 'cds deploy'.`;
112
114
  }
113
115
 
114
116
  // the primary database is always built and deployed
115
- // const dest = buildResult.dest
116
117
  const dest = path.join(cds.root, cds.env.build.target, cds.env.folders.db);
117
118
 
118
119
  if (undeployWhitelist) {
@@ -123,56 +124,78 @@ Therefore, specifying the CDS model is not required when calling 'cds deploy'.`;
123
124
  const hasVCAPEnv = Object.keys(vcapEnv).length > 0;
124
125
 
125
126
  let bindOptions
126
- if (cds.cli.options.on === 'k8s') {
127
+ let usesExistingK8sBinding = false
128
+
129
+ const { readProject } = require('../../init/projectReader')
130
+ const { hasKyma, hasMta } = readProject()
131
+ const onKyma = cds.cli.options.on === 'k8s' || (hasKyma && !hasMta && cds.cli.options.on !== 'cf')
132
+ if (onKyma) {
127
133
  const cp = require('node:child_process')
128
- const appName = pServiceName ?? path.basename(cds.root)
129
- const instance =
134
+
135
+ const existing = cds.requires.db?.binding
136
+ if (!pServiceName && existing && (existing.name || existing.secret)) {
137
+ const envVars = await bindingEnv({ env: cds.env, silent: true })
138
+ if (envVars?.VCAP_SERVICES) {
139
+ vcapEnv.VCAP_SERVICES = JSON.parse(envVars.VCAP_SERVICES)
140
+ usesExistingK8sBinding = true
141
+ console.log(`using existing Kubernetes binding ${bold(existing.name || existing.secret)}`)
142
+ }
143
+ }
144
+
145
+ if (!usesExistingK8sBinding) {
146
+ const baseName = pServiceName ?? path.basename(cds.root)
147
+ const instanceName = baseName.endsWith('-db') ? baseName : `${baseName}-db`
148
+ const bindingName = `${instanceName}-binding`
149
+ const secretName = `${instanceName}-secret`
150
+
151
+ const instance =
130
152
  `apiVersion: services.cloud.sap.com/v1
131
153
  kind: ServiceInstance
132
154
  metadata:
133
- name: ${appName}-db
155
+ name: ${instanceName}
134
156
  spec:
135
157
  serviceOfferingName: hana
136
158
  servicePlanName: hdi-shared
137
159
  `
138
160
 
139
- const binding =
161
+ const binding =
140
162
  `apiVersion: services.cloud.sap.com/v1
141
163
  kind: ServiceBinding
142
164
  metadata:
143
- name: ${appName}-db-binding
165
+ name: ${bindingName}
144
166
  spec:
145
- serviceInstanceName: ${appName}-db
146
- secretName: ${appName}-db-secret
167
+ serviceInstanceName: ${instanceName}
168
+ secretName: ${secretName}
147
169
  `
148
170
 
149
- try {
150
- cp.execSync('kubectl apply -f -', { input: instance })
151
- cp.execSync('kubectl apply -f -', { input: binding })
152
- cp.execSync(`kubectl wait --for=condition=Ready servicebinding/${appName}-db-binding --timeout=180s`)
153
- cp.execSync(`kubectl wait --for=condition=Ready serviceinstance/${appName}-db --timeout=180s`)
154
- } catch (error) {
155
- const descr = cp.execSync(`kubectl describe serviceinstance/${appName}-db`).toString()
156
- const message = descr.match(/Message:\s+(.*)/)?.[1] || 'None'
157
- throw error.message + `\nInstance Message: ${message}`
158
- }
171
+ try {
172
+ cp.execSync('kubectl apply -f -', { input: instance })
173
+ cp.execSync('kubectl apply -f -', { input: binding })
174
+ cp.execSync(`kubectl wait --for=condition=Ready servicebinding/${bindingName} --timeout=180s`)
175
+ cp.execSync(`kubectl wait --for=condition=Ready serviceinstance/${instanceName} --timeout=180s`)
176
+ } catch (error) {
177
+ const descr = cp.execSync(`kubectl describe serviceinstance/${instanceName}`).toString()
178
+ const message = descr.match(/Message:\s+(.*)/)?.[1] || 'None'
179
+ throw error.message + `\nInstance Message: ${message}`
180
+ }
159
181
 
160
- const { data: encoded } = JSON.parse(cp.execSync(`kubectl get secrets/${appName}-db-secret -o json`).toString())
161
- const credentials = {}
162
- for (const [key, value] of Object.entries(encoded)) {
163
- credentials[key] = Buffer.from(value, 'base64').toString('utf-8');
164
- }
165
- vcapEnv.VCAP_SERVICES ??= {
166
- hana: [{
167
- tags: ['hana'],
168
- credentials
169
- }]
170
- }
171
- bindOptions = {
172
- ...options,
173
- to: `${appName}-db-binding`,
174
- for: options.for,
175
- kind: BUILD_TASK_HANA
182
+ const { data: encoded } = JSON.parse(cp.execSync(`kubectl get secrets/${secretName} -o json`).toString())
183
+ const credentials = {}
184
+ for (const [key, value] of Object.entries(encoded)) {
185
+ credentials[key] = Buffer.from(value, 'base64').toString('utf-8');
186
+ }
187
+ vcapEnv.VCAP_SERVICES ??= {
188
+ hana: [{
189
+ tags: ['hana'],
190
+ credentials
191
+ }]
192
+ }
193
+ bindOptions = {
194
+ ...options,
195
+ to: `${bindingName}`,
196
+ for: options.for,
197
+ kind: BUILD_TASK_HANA
198
+ }
176
199
  }
177
200
  } else {
178
201
  let serviceName = pServiceName;
@@ -223,7 +246,7 @@ spec:
223
246
  DEBUG?.({ dest, vcapEnv, hdiOptions })
224
247
  await hdi.deploy(dest, vcapEnv, hdiOptions);
225
248
 
226
- if (!hasVCAPEnv) {
249
+ if (!hasVCAPEnv && !usesExistingK8sBinding) {
227
250
  const services = await bind(bindOptions)
228
251
  await storeBindings(services, bindOptions)
229
252
  }
@@ -239,8 +262,6 @@ spec:
239
262
  console.warn(warn('\nWARNING:'));
240
263
  console.warn(warn(warnings.join('\n')));
241
264
  }
242
-
243
- return buildResult;
244
265
  }
245
266
 
246
267
  async _runCompileToHana(options) {
@@ -307,19 +328,6 @@ spec:
307
328
  }
308
329
  }
309
330
 
310
-
311
- async _build() {
312
- const buildTaskOptions = {
313
- for: BUILD_TASK_HANA,
314
- // src: cds.env.folders.db,
315
- [OUTPUT_MODE]: OUTPUT_MODE_FILESYSTEM | OUTPUT_MODE_RESULT
316
- }
317
-
318
- // cds build throws an error if the src folder does not exist
319
- const buildResult = await build(buildTaskOptions);
320
- return buildResult[0].result;
321
- }
322
-
323
331
  _injectTunnelAddress(credentials, tunnelAddress) {
324
332
  if (!/\w+:\d+/.test(tunnelAddress)) {
325
333
  throw `Invalid tunnel address '${tunnelAddress}' - must be in form 'host:port'`;
@@ -35,7 +35,7 @@ async function _isValidXML(edmx) {
35
35
  try {
36
36
  generateEDMX2JSON(edmx);
37
37
  isValid = true;
38
- } catch (err) {
38
+ } catch {
39
39
  isValid = false;
40
40
  }
41
41
  return isValid;
@@ -1621,10 +1621,11 @@ class PropertyPathExpression extends Expression {
1621
1621
  if (targetOption === MetadataConverter.TARGETS.LIBRARY) {
1622
1622
  target = { [this._targetName]: this.getElement().elements[0].text };
1623
1623
  } else if (!this.getElement().elements && this._targetName === '$NavigationPropertyPath') {
1624
- //elements are not given, when <NavigationPropertyPath/> is in EDMX, which is used to refresh the current context
1624
+ // elements are not given, when <NavigationPropertyPath/> is in EDMX, which is used to refresh the current context
1625
+ // OData tsc decided this should now be represented with a null value
1625
1626
  return {
1626
- "=": "($self)"
1627
- };
1627
+ "=": '(null)'
1628
+ };;
1628
1629
  } else {
1629
1630
  target = this.getElement().elements[0].text;
1630
1631
  }