@sap/cds-dk 8.9.5 → 9.0.5

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 (109) hide show
  1. package/CHANGELOG.md +101 -2012
  2. package/LICENSE +15 -21
  3. package/bin/bind.js +1 -1
  4. package/bin/build.js +35 -37
  5. package/bin/cds.js +13 -30
  6. package/bin/compile/index.js +2 -2
  7. package/bin/debug.js +27 -7
  8. package/bin/deploy/index.js +6 -23
  9. package/bin/deploy/to-hana.js +4 -2
  10. package/bin/help.js +5 -3
  11. package/bin/init.js +1 -1
  12. package/bin/up.js +45 -12
  13. package/bin/watch.js +45 -63
  14. package/lib/bind/cf.js +2 -1
  15. package/lib/bind/k8s.js +2 -2
  16. package/lib/bind/plugin.js +1 -1
  17. package/lib/bind/shared.js +16 -25
  18. package/lib/build/buildTaskEngine.js +26 -10
  19. package/lib/build/buildTaskFactory.js +3 -2
  20. package/lib/build/buildTaskProvider.js +18 -7
  21. package/lib/build/buildTaskProviderFactory.js +35 -13
  22. package/lib/build/constants.js +4 -0
  23. package/lib/build/index.js +1 -1
  24. package/lib/build/plugin.js +89 -54
  25. package/lib/build/plugins/helm/files/subcharts/web-application/Chart.yaml +3 -1
  26. package/lib/build/plugins/helm/files/subcharts/web-application/templates/_helpers.tpl +4 -2
  27. package/lib/build/plugins/helm/files/subcharts/web-application/templates/api-rule.yaml +4 -2
  28. package/lib/build/plugins/helm/files/subcharts/web-application/templates/deployment.yaml +18 -1
  29. package/lib/build/plugins/helm/files/subcharts/web-application/templates/service-binding.yaml +0 -1
  30. package/lib/build/plugins/helm/files/subcharts/web-application/values.schema.json +34 -2
  31. package/lib/build/plugins/helm/files/subcharts/web-application/values.yaml +9 -2
  32. package/lib/build/plugins/helm/index.js +2 -1
  33. package/lib/build/plugins.js +24 -10
  34. package/lib/build/provider/edmxBuildPlugin.js +1 -11
  35. package/lib/build/provider/fiori/index.js +4 -4
  36. package/lib/build/provider/hana/index.js +12 -5
  37. package/lib/build/provider/hana/template/package.json +1 -1
  38. package/lib/build/provider/internalBuildPlugin.js +1 -1
  39. package/lib/build/provider/internalBuildTaskProvider.js +3 -24
  40. package/lib/build/provider/java/index.js +1 -1
  41. package/lib/build/provider/mtx-extension/index.js +15 -8
  42. package/lib/build/provider/nodejs/index.js +28 -6
  43. package/lib/build/util.js +186 -125
  44. package/lib/deploy/index.js +5 -0
  45. package/lib/deploy/to-hana/hana.js +27 -33
  46. package/lib/deploy/to-hana/hdiDeployUtil.js +2 -2
  47. package/lib/import/odata/v2parser.js +34 -3
  48. package/lib/import/openapi/importOpenAPI.js +4 -0
  49. package/lib/index.js +2 -11
  50. package/lib/init/constants.js +1 -2
  51. package/lib/init/merge.js +101 -77
  52. package/lib/init/mvn.js +3 -3
  53. package/lib/init/projectReader.js +1 -1
  54. package/lib/init/template/ams/files/mta.yaml.hbs +6 -1
  55. package/lib/init/template/ams/files/package.json.hbs +1 -1
  56. package/lib/init/template/approuter/files/mta.yaml.hbs +5 -0
  57. package/lib/init/template/cf-manifest/files/manifest.yml.hbs +1 -1
  58. package/lib/init/template/cloud-logging/files/package.json.hbs +3 -3
  59. package/lib/init/template/data/as-json.js +3 -3
  60. package/lib/init/template/dynatrace/files/mta.yaml.hbs +1 -1
  61. package/lib/init/template/dynatrace/files/package.json.hbs +2 -2
  62. package/lib/init/template/dynatrace/index.js +2 -1
  63. package/lib/init/template/enterprise-messaging/files/mta.yaml.hbs +6 -0
  64. package/lib/init/template/enterprise-messaging/index.js +5 -1
  65. package/lib/init/template/extensibility/files/package.json.hbs +1 -1
  66. package/lib/init/template/hana/files/db/package.json +1 -1
  67. package/lib/init/template/hana/files/package.json.hbs +2 -4
  68. package/lib/init/template/hana/index.js +2 -2
  69. package/lib/init/template/handler/index.js +16 -12
  70. package/lib/init/template/helm/index.js +13 -22
  71. package/lib/init/template/helm-unified-runtime/index.js +2 -1
  72. package/lib/init/template/html5-repo/files/values.yaml.hbs +12 -1
  73. package/lib/init/template/html5-repo/index.js +10 -5
  74. package/lib/init/template/http/index.js +1 -1
  75. package/lib/init/template/ias/files/mta.yaml.hbs +1 -1
  76. package/lib/init/template/ias/files/sidecar.package.json.hbs +0 -7
  77. package/lib/init/template/ias/index.js +5 -4
  78. package/lib/init/template/lint/files/package.json +6 -0
  79. package/lib/init/template/lint/index.js +61 -204
  80. package/lib/init/template/mta/files/package.json +1 -1
  81. package/lib/init/template/multitenancy/files/mta.yaml.hbs +2 -2
  82. package/lib/init/template/multitenancy/files/package.json.hbs +1 -1
  83. package/lib/init/template/multitenancy/files/package.sidecar.json.hbs +7 -4
  84. package/lib/init/template/multitenancy/index.js +3 -0
  85. package/lib/init/template/nodejs/files/package.json.hbs +6 -3
  86. package/lib/init/template/postgres/files/package.json.hbs +1 -1
  87. package/lib/init/template/redis/files/package.json.hbs +1 -1
  88. package/lib/init/template/sample/files/app/admin-books/fiori-service.cds +6 -0
  89. package/lib/init/template/sample/files/app/admin-books/webapp/manifest.json +1 -0
  90. package/lib/init/template/sample/files/app/browse/fiori-service.cds +3 -2
  91. package/lib/init/template/sample/files/app/common.cds +0 -11
  92. package/lib/init/template/sqlite/files/package.json +1 -1
  93. package/lib/init/template/toggles/files/package.json.hbs +1 -1
  94. package/lib/init/template/typescript/files/package.json +2 -4
  95. package/lib/init/template/workzone-standard/index.js +2 -0
  96. package/lib/init/template/xsuaa/index.js +2 -6
  97. package/lib/lint/Linter.js +203 -331
  98. package/lib/lint/generators.js +52 -46
  99. package/lib/lint/io.js +77 -289
  100. package/lib/util/fs.js +2 -1
  101. package/lib/util/git.js +1 -1
  102. package/lib/util/glob.js +77 -0
  103. package/lib/watch/livereload-server.js +3 -4
  104. package/lib/watch/node-watch.js +3 -4
  105. package/lib/watch/watched.js +1 -1
  106. package/npm-shrinkwrap.json +200 -858
  107. package/package.json +6 -8
  108. package/readme.md +1 -1
  109. package/lib/lint/checks.js +0 -135
@@ -12,7 +12,7 @@ module.exports = { build, register, Plugin, BuildError }
12
12
  * @param {object} options - command options as defined by build command.
13
13
  */
14
14
  async function build(options = {}) {
15
- if (!fs.existsSync(cds.root) || !fs.lstatSync(cds.root).isDirectory()) {
15
+ if (!fs.existsSync(cds.root) || !cds.utils.isdir(cds.root)) {
16
16
  throw `Project folder '${cds.root}' does not exist`
17
17
  }
18
18
  try {
@@ -1,76 +1,104 @@
1
- const path = require('path')
2
- const fs = require('fs')
1
+ const path = require('node:path')
2
+ const fs = require('node:fs')
3
+ const os = require('node:os');
3
4
  const cds = require('../cds')
5
+ const IS_WIN = os.platform() === 'win32';
6
+
4
7
  const { OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM, SEVERITY_INFO, SEVERITY_WARNING, SEVERITY_ERROR } = require('./constants')
5
8
  const { hasOptionValue, getProperty, relativePaths, BuildMessage, pathExists, filterFeaturePaths, getFiles } = require('./util')
6
9
  const DEBUG = cds.debug('cli|build')
7
10
 
11
+ /**
12
+ * @typedef {{ src?: string, dest?: string, options?: object } & Record<string, any>} TaskDefaults
13
+ * @typedef {{ src: string, dest: string, for: string, options: object } & Record<string, any>} Task
14
+ * @typedef {{ options: Record<string, any>, tasks: Task[] }} Context
15
+ * @callback FileWriterTo
16
+ * @param {string} dest - absolute or relative file path. Relative paths will be resolved to this task's destination path.
17
+ * @returns {Promise<void>} - resolves when the file has been written
18
+ * @typedef {Object} FileWriter
19
+ * @property {FileWriterTo} to
20
+ */
21
+
8
22
  /**
9
23
  * The build plugin creates the build output for a dedicated build task. It is uniquely identified
10
- * by the build task's <code>for</code> or <code>use</code>property. The <code>use</code> property represents
24
+ * by the build task's `for<` or `use` property. The `use` property represents
11
25
  * the fully qualified node module path of the build plugin implementation.
12
- * <p>
13
26
  * The build task engine defines the following protocol. The methods are invoked in descending order:
14
- * <ul>
15
- * <li>init() - optional</li>
16
- * <li>get priority() - optional</li>
17
- * <li>async clean()</li>
18
- * <li>async build()</li>
19
- * </ul>
20
- * The reflected CSN can be accessed using the async method <code>model()</code>.
27
+ * - `init()` - optional
28
+ * - `get priority()` - optional
29
+ * - `async clean()`
30
+ * - `async build()`
31
+ * The reflected CSN can be accessed using the async method `model()`.
21
32
  */
22
33
  class Plugin {
23
- /**
24
- * @constructor
25
- */
26
- constructor() {
27
- this._files = new Set()
28
- this._messages = []
29
- }
30
-
31
34
  static INFO = SEVERITY_INFO
32
35
  static WARNING = SEVERITY_WARNING
33
36
  static ERROR = SEVERITY_ERROR
34
37
 
38
+ /** @type {TaskDefaults} */
39
+ static taskDefaults // injected externally
40
+
35
41
  /**
36
- * Determines whether a task of this type will be created when cds build is executed,
37
- * returns true by default.
42
+ * @type {Task | undefined}
43
+ * @private
38
44
  */
39
- static hasTask() {
40
- return true
41
- }
45
+ _task
42
46
 
43
47
  /**
44
- * Returns the build task executed by this build plugin.
45
- * @return {object}
48
+ * @type {Context | undefined}
49
+ * @private
46
50
  */
47
- get task() {
48
- //injected by framework
49
- return this._task
51
+ _context
52
+
53
+ /**
54
+ * @type {Set<string>}
55
+ * @private
56
+ */
57
+ _files = new Set()
58
+
59
+ /**
60
+ * Returns the list of files and folders written by this build plugin.
61
+ */
62
+ get files() {
63
+ return [...this._files]
50
64
  }
51
65
 
66
+ /**
67
+ * @type {(string | BuildMessage)[]}
68
+ * @private
69
+ */
70
+ _messages = []
52
71
  /**
53
72
  * Returns a list of build and compiler messages created by this build plugin.
54
73
  * Supported message severities are 'Info', 'Warning', and 'Error'.
55
- * @return {Array}
56
74
  */
57
75
  get messages() {
58
76
  return this._messages
59
77
  }
60
78
 
61
79
  /**
62
- * Returns the list of files and folders written by this build plugin.
63
- * @return {Array}
80
+ * Determines whether a task of this type will be created when cds build is executed,
81
+ * returns true by default.
64
82
  */
65
- get files() {
66
- return [...this._files]
83
+ static hasTask() {
84
+ return true
85
+ }
86
+
87
+ /**
88
+ * Returns the build task executed by this build plugin.
89
+ * @returns {Task}
90
+ */
91
+ get task() {
92
+ // @ts-expect-error - possibly undefined, but expected to be injected by framework
93
+ return this._task
67
94
  }
68
95
 
69
96
  /**
70
97
  * Returns the build context
71
- * @returns {object}
98
+ * @returns {Context}
72
99
  */
73
100
  get context() {
101
+ // @ts-expect-error - possibly undefined, but expected to be injected by framework
74
102
  return this._context
75
103
  }
76
104
 
@@ -80,7 +108,7 @@ class Plugin {
80
108
  * The higher the priority value, the sooner the build plugin will be run.
81
109
  * The range of valid priority values is from -1024 to +1024.
82
110
  * Built-in plugins have a priority value range from 0 - 524.
83
- * @return {number} the priority for this plugin as integer.
111
+ * @returns the priority for this plugin as integer.
84
112
  */
85
113
  get priority() {
86
114
  return 1024
@@ -100,15 +128,18 @@ class Plugin {
100
128
  * @abstract
101
129
  * Called by the framework to create the artifacts of this build plugin.
102
130
  */
103
- async build() { }
131
+ async build() { /* abstract */}
104
132
 
105
133
  /**
106
134
  * Called by the framework immediately before 'build' to delete any output created by this build plugin.
107
- * <p>
108
- * Note: The <code>BuildTaskEngine</code> is cleaning the common generation target folder if the build is
135
+ * Note: The [`BuildTaskEngine`]({@link ./buildTaskEngine.js)}) is cleaning the common generation target folder if the build is
109
136
  * executed in staging mode, e.g. build.target: "gen".
110
137
  */
111
138
  async clean() {
139
+ /**
140
+ * @param {string} parent - absolute path of the parent directory
141
+ * @param {string} child - absolute path of the child directory
142
+ */
112
143
  function isSubDirectory(parent, child) {
113
144
  return !path.relative(parent, child).startsWith('..')
114
145
  }
@@ -124,12 +155,12 @@ class Plugin {
124
155
  * Asynchronously write the given content to a given file path.
125
156
  * If the file exists the content is replaced. If the file does not exist, a new file will be created.
126
157
  * The file name is stored in the list of files written by this build plugin.
127
- * @param {string} dest - absolute or relative file path. Relative paths will be resolved to this task's destination path.
128
- * @param {any} data - If data is of type object the JSON-stringified version is written.
158
+ * @param {object | Buffer} data - If data is of type object the JSON-stringified version is written.
159
+ * @returns {FileWriter}
129
160
  */
130
161
  write(data) {
131
162
  return {
132
- to: async (dest) => {
163
+ to: async (/** @type {string} */ dest) => {
133
164
  if (this._hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM)) {
134
165
  if (!path.isAbsolute(dest)) {
135
166
  // relative to build task's destination path
@@ -145,17 +176,17 @@ class Plugin {
145
176
 
146
177
  /**
147
178
  * Asynchronously copies a single file or the entire directory structure from 'src' to 'dest', including subdirectories and files.
148
- * <p>
179
+ *
149
180
  * Note: The file names are stored in the list of files written by this build plugin.
150
- * </p>
151
- * @param {string} src The absolute or relative source path of the file or directory to copy.
181
+ *
182
+ * @param {string} src - The absolute or relative source path of the file or directory to copy.
152
183
  * Relative paths will be resolved to this task's source path.
153
- * @param {string} dest The absolute or relative target path. Relative paths will be resolved to this task's destination path.
184
+ * @returns {FileWriter}
154
185
  *
155
186
  */
156
187
  copy(src) {
157
188
  return {
158
- to: async (dest) => {
189
+ to: async (/** @type {string} */ dest) => {
159
190
  if (this._hasBuildOption(OUTPUT_MODE, OUTPUT_MODE_FILESYSTEM)) {
160
191
  if (!path.isAbsolute(src)) {
161
192
  // relative to build task's source path
@@ -166,12 +197,16 @@ class Plugin {
166
197
  dest = path.resolve(this.task.dest, dest)
167
198
  }
168
199
  // list all copied files recursively
169
- if (fs.lstatSync(src).isDirectory()) {
200
+ if (cds.utils.isdir(src)) {
170
201
  await fs.promises.cp(src, dest, { recursive: true })
171
202
  const files = getFiles(dest)
172
203
  files.forEach(file => this.pushFile(file))
173
204
  } else {
174
205
  this.pushFile(dest)
206
+ if (IS_WIN && fs.lstatSync(src).isSymbolicLink()) {
207
+ const linkTarget = await fs.promises.readlink(src);
208
+ src = path.resolve(path.dirname(src), linkTarget);
209
+ }
175
210
  return fs.promises.cp(src, dest, { recursive: true })
176
211
  }
177
212
  }
@@ -181,11 +216,11 @@ class Plugin {
181
216
 
182
217
  /**
183
218
  * Adds the given user message and severity to the list of messages issued by this build task.
184
- * <p>
219
+ *
185
220
  * User messages will be logged after CDS build has been finished based on the log-level that has been set.
186
221
  * By default messages with severity <em>warning</em> and <em>error</em> will be logged.
187
- * @param {string} message the message text
188
- * @param {string} severity the severity of the message
222
+ * @param {string} message - the message text
223
+ * @param {import('./constants').Severity} severity - the severity of the message
189
224
  */
190
225
  pushMessage(message, severity) {
191
226
  this.messages.push(new BuildMessage(message, severity))
@@ -194,7 +229,7 @@ class Plugin {
194
229
  /**
195
230
  * Returns a compiled CSN model according to the model paths defined by this build task.
196
231
  * The model includes model enhancements defined by feature toggles, if any.
197
- * @return {object} the compiled CSN model
232
+ * @returns {Promise<import('@sap/cds').csn.CSN | null>} the compiled CSN model
198
233
  */
199
234
  async model() {
200
235
  const files = cds.resolve(this.task.options.model || this.task.src)
@@ -217,7 +252,7 @@ class Plugin {
217
252
  /**
218
253
  * Returns a compiled base model CSN according to the model paths defined by this build task.
219
254
  * The base model does not include any model enhancements defined by feature toggles.
220
- * @return {object} the compiled base model CSN
255
+ * @returns {ReturnType<Plugin['model']>} the compiled base model CSN
221
256
  */
222
257
  async baseModel() {
223
258
  const model = await this.model()
@@ -234,7 +269,7 @@ class Plugin {
234
269
 
235
270
  /**
236
271
  * Adds the given fully qualified file path to the list of files that are written by this build task.
237
- * @param {string} filePath
272
+ * @param {string} filePath - fully qualified file path
238
273
  */
239
274
  pushFile(filePath) {
240
275
  this._files.add(filePath)
@@ -2,5 +2,7 @@ apiVersion: v2
2
2
  description: A Helm chart for web app
3
3
  kubeVersion: '>= 1.21'
4
4
  name: web-application
5
+ sources:
6
+ - https://github.tools.sap/unified-runtime/web-application
5
7
  type: application
6
- version: 1.24.0
8
+ version: 1.27.0
@@ -215,8 +215,10 @@ If release name contains chart name it will be used as service instance name.
215
215
  port: {{ .values.port | default .context.Values.port}}
216
216
  {{- end }}
217
217
  {{- if eq .checkName "startupProbe" }}
218
- periodSeconds: 2
219
- failureThreshold: {{ div (add1 .context.Values.startupTimeoutSeconds) 2 }}
218
+ {{- $period := default .checkValues.periodSeconds 2 }}
219
+ periodSeconds: {{ $period }}
220
+ failureThreshold: {{ div (add1 .context.Values.startupTimeoutSeconds) $period }}
221
+ timeoutSeconds: {{ .checkValues.timeoutSeconds }}
220
222
  {{- else }}
221
223
  {{- if .checkValues.periodSeconds }}
222
224
  periodSeconds: {{ .checkValues.periodSeconds }}
@@ -1,8 +1,10 @@
1
1
  {{- if .Values.expose.enabled -}}
2
2
  {{- if .Values.expose.APIRule.experimental -}}
3
3
  apiVersion: gateway.kyma-project.io/v2alpha1
4
- {{ else }}
4
+ {{ else if .Values.expose.APIRule.legacy -}}
5
5
  apiVersion: gateway.kyma-project.io/v1beta1
6
+ {{ else }}
7
+ apiVersion: gateway.kyma-project.io/v2
6
8
  {{- end }}
7
9
  kind: APIRule
8
10
  metadata:
@@ -10,7 +12,7 @@ metadata:
10
12
  labels: {{- include "web-application.labels" . | nindent 4 }}
11
13
  spec:
12
14
  gateway: {{ tpl .Values.expose.gateway $ }}
13
- {{- if .Values.expose.APIRule.experimental }}
15
+ {{- if or .Values.expose.APIRule.experimental (not .Values.expose.APIRule.legacy)}}
14
16
  hosts:
15
17
  {{- include "web-application.internal.exposeHosts" . | indent 4 }}
16
18
  {{- else }}
@@ -36,6 +36,14 @@ spec:
36
36
  imagePullPolicy: {{ .Values.imagePullPolicy | default .Values.global.imagePullPolicy }}
37
37
  {{- end }}
38
38
  name: {{ include "web-application.name" . }}
39
+ {{- if .Values.command }}
40
+ command:
41
+ {{- .Values.command | toYaml | nindent 8 }}
42
+ {{- end }}
43
+ {{- if .Values.args }}
44
+ args:
45
+ {{- .Values.args | toYaml | nindent 8 }}
46
+ {{- end }}
39
47
  ports:
40
48
  - name: http
41
49
  containerPort: {{ .Values.port }}
@@ -108,6 +116,14 @@ spec:
108
116
  imagePullPolicy: {{ $sidecar.imagePullPolicy | default $.Values.global.imagePullPolicy }}
109
117
  {{- end }}
110
118
  name: {{ $key }}
119
+ {{- if $sidecar.command }}
120
+ command:
121
+ {{- $sidecar.command | toYaml | nindent 8 }}
122
+ {{- end }}
123
+ {{- if $sidecar.args }}
124
+ args:
125
+ {{- $sidecar.args | toYaml | nindent 8 }}
126
+ {{- end }}
111
127
  envFrom:
112
128
  {{- $envFromVars := (include "web-application.internal.processEnvFrom" (dict "envFrom" $sidecar.envFrom "context" $) | fromJson) }}
113
129
  {{- if not (eq (len $envFromVars.vars) 0) }}
@@ -173,7 +189,8 @@ spec:
173
189
  {{- end }}
174
190
  {{- if .Values.nodeAffinity }}
175
191
  affinity:
176
- {{- .Values.nodeAffinity | toYaml | nindent 8 }}
192
+ nodeAffinity:
193
+ {{- .Values.nodeAffinity | toYaml | nindent 10 }}
177
194
  {{- end }}
178
195
  topologySpreadConstraints:
179
196
  {{- range $constraint := .Values.availability.topologySpreadConstraints }}
@@ -28,7 +28,6 @@ spec:
28
28
  {{- end }}
29
29
  {{- if $mergedParams.parametersFrom }}
30
30
  parametersFrom: {{ tpl ($mergedParams.parametersFrom | toYaml) $ | nindent 4 }}
31
- watchParametersFromChanges: true
32
31
  {{- end }}
33
32
  {{- if $mergedParams.credentialsRotationPolicy }}
34
33
  credentialsRotationPolicy: {{ $mergedParams.credentialsRotationPolicy | toYaml | nindent 4 }}
@@ -136,6 +136,20 @@
136
136
  }
137
137
  }
138
138
  },
139
+ "command": {
140
+ "$id": "#/properties/command",
141
+ "type": "array",
142
+ "items": {
143
+ "type": "string"
144
+ }
145
+ },
146
+ "args": {
147
+ "$id": "#/properties/args",
148
+ "type": "array",
149
+ "items": {
150
+ "type": "string"
151
+ }
152
+ },
139
153
  "additionalVolumes": {
140
154
  "$id": "#/properties/additionalVolumes",
141
155
  "type": "array",
@@ -221,7 +235,7 @@
221
235
  },
222
236
  "limits": {
223
237
  "type": "object",
224
- "additionalProperties": false,
238
+ "additionalProperties": true,
225
239
  "required": [
226
240
  "memory"
227
241
  ],
@@ -588,6 +602,9 @@
588
602
  "properties": {
589
603
  "experimental": {
590
604
  "type": "boolean"
605
+ },
606
+ "legacy": {
607
+ "type": "boolean"
591
608
  }
592
609
  }
593
610
  },
@@ -651,7 +668,8 @@
651
668
  "PUT",
652
669
  "PATCH",
653
670
  "DELETE",
654
- "HEAD"
671
+ "HEAD",
672
+ "OPTIONS"
655
673
  ],
656
674
  "path": "/.*"
657
675
  }
@@ -917,6 +935,20 @@
917
935
  "imagePullPolicy": {
918
936
  "$ref": "#/definitions/ImagePullPolicy"
919
937
  },
938
+ "command": {
939
+ "$id": "#/properties/command",
940
+ "type": "array",
941
+ "items": {
942
+ "type": "string"
943
+ }
944
+ },
945
+ "args": {
946
+ "$id": "#/properties/args",
947
+ "type": "array",
948
+ "items": {
949
+ "type": "string"
950
+ }
951
+ },
920
952
  "envFrom": {
921
953
  "$id": "#/properties/envFrom",
922
954
  "type": "array",
@@ -14,7 +14,7 @@ global:
14
14
  _internal:
15
15
  web-application:
16
16
  versions:
17
- 1.24.0: true
17
+ 1.27.0: true
18
18
  ## Will be used instead of the `.Chart.Name`, e.g. when generating the Deployment name.
19
19
  # nameOverride: name
20
20
 
@@ -46,6 +46,10 @@ imagePullSecret: {}
46
46
  ## The content for the dynamically generated Kubernetes Secret, which will be used as an image pull secret. Can't be used with the `name` option.
47
47
  # dockerconfigjson: ""
48
48
 
49
+ ## Command and arguments used to run the container, see https://kubernetes.io/docs/tasks/inject-data-application/define-command-argument-container/#define-a-command-and-arguments-when-you-create-a-pod
50
+ # command: []
51
+ # args: []
52
+
49
53
  ## Setting the imagePullPolicy, see https://kubernetes.io/docs/concepts/containers/images/#image-pull-policy
50
54
  # imagePullPolicy: Always
51
55
 
@@ -64,6 +68,7 @@ additionalVolumes: []
64
68
  # cpu: 100m
65
69
  # ephemeral-storage: 1G
66
70
  # memory: 1G
71
+ # gpu-vendor.example/example-gpu: 1
67
72
  # requests:
68
73
  # cpu: 100m
69
74
  # ephemeral-storage: 1G
@@ -154,7 +159,8 @@ envFrom: []
154
159
  # name: my-secret-ref1
155
160
 
156
161
  expose:
157
- APIRule: {}
162
+ APIRule:
163
+ legacy: true
158
164
  # experimental: true
159
165
  ## Specifies the service's dns name for inbound external traffic. If it doesn't contain a dot, the default cluster domain will be appended.
160
166
  # host: ""
@@ -180,6 +186,7 @@ expose:
180
186
  - PATCH
181
187
  - DELETE
182
188
  - HEAD
189
+ - OPTIONS
183
190
  path: /.*
184
191
  ## APIRule CORS policy configuration
185
192
  ## https://kyma-project.io/#/api-gateway/user/custom-resources/apirule/04-10-apirule-custom-resource
@@ -1,5 +1,6 @@
1
1
  const cds = require('../../../cds')
2
- const { exists, path, readFileSync, yaml } = cds.utils
2
+ const yaml = require('yaml')
3
+ const { exists, path, readFileSync } = cds.utils
3
4
  const { Plugin, BuildError } = require('../../../build')
4
5
  const { join } = path
5
6
  const { readProject } = require('../../../init/projectReader')
@@ -1,32 +1,46 @@
1
+ // @ts-check
1
2
  const cds = require('../cds')
2
3
  const Plugin = require('./plugin')
3
4
  const DEBUG = cds.debug('cli|build')
4
5
 
5
6
  module.exports = new (class Plugins {
6
- constructor() {
7
- this._plugins = new Map()
8
- this._registerDefaults()
9
- }
7
+ /** @type {Map<string, typeof Plugin>} */
8
+ #plugins = new Map()
10
9
  get plugins() {
11
- return this._plugins
10
+ return this.#plugins
12
11
  }
12
+
13
+ constructor() {
14
+ this.#registerDefaults()
15
+ }
16
+
17
+ /**
18
+ * @param {string} id - unique name of the plugin
19
+ * @param {typeof Plugin | { prototype?: unknown, impl: string, taskDefaults: { src: string } }} plugin - class extending Plugin
20
+ */
13
21
  register(id, plugin) {
22
+ /**
23
+ * @param {{prototype?: unknown}} plugin
24
+ * @returns {plugin is typeof Plugin}
25
+ */
26
+ const isNewStylePlugin = plugin => plugin.prototype instanceof Plugin
27
+
14
28
  if (!id || !plugin) {
15
29
  throw new Error(`Invalid parameter passed, build plugin id: ${id}`)
16
30
  }
17
- if (this._plugins.has(id)) {
31
+ if (this.#plugins.has(id)) {
18
32
  throw new Error(`CDS build plugin ${id} already registered`)
19
33
  }
20
- if(!(plugin.prototype instanceof Plugin)) {
34
+ if(!isNewStylePlugin(plugin)) {
21
35
  // with cds-dk version 7 the following registration format was supported:
22
36
  // cds.build.register("cov2ap", { impl: "@cap-js-community/odata-v2-adapter/src/build.js", taskDefaults: { src: "srv" } })
23
37
  throw `The cds build plugin '${id}' is not compatible with this @sap/cds-dk version. Update the npm package '${plugin.impl || id}' to the latest version.`
24
38
  }
25
- DEBUG?.(`Registering build plugin ${id}`)
26
- this._plugins.set(id, plugin)
39
+ DEBUG?.(`registering build plugin ${id}`)
40
+ this.#plugins.set(id, plugin)
27
41
  }
28
42
 
29
- _registerDefaults() {
43
+ #registerDefaults() {
30
44
  this.register('helm', require('./plugins/helm'))
31
45
  }
32
46
  })
@@ -10,7 +10,7 @@ class EdmxBuildPlugin extends FeatureToggleBuildPlugin {
10
10
 
11
11
  // generate edmx for services only that have the odata protocol
12
12
  const serviceNames = cds.reflect(model).services
13
- .filter(service => this._isOdataProtocol(service))
13
+ .filter(service => 'odata' in service.protocols)
14
14
  .map(service => service.name)
15
15
 
16
16
  // new compile impl is throwing error in case no services exist!
@@ -51,16 +51,6 @@ class EdmxBuildPlugin extends FeatureToggleBuildPlugin {
51
51
  return Promise.all(promises)
52
52
  }
53
53
 
54
- _isOdataProtocol(srv) {
55
- let yes = srv._serves_odata; if (yes) return typeof yes === 'function' ? yes.call(srv) : yes // >= cds 7.4.0
56
- let protocols = cds.service.protocols4?.(srv) // >= cds 7.4.0
57
- if (!protocols) { // @sap/cds < 7.3.0
58
- protocols = cds.service.protocols.protocol4(srv)
59
- if (typeof protocols === "string") return protocols.startsWith('odata')
60
- }
61
- return protocols.some(p => p && p.startsWith('odata'))
62
- }
63
-
64
54
  _options4odata() {
65
55
  const o = this.options()
66
56
  o.version = cds.env.odata.version
@@ -1,7 +1,7 @@
1
1
  const path = require('path')
2
2
  const cds = require('../../../cds')
3
3
  const EdmxBuildPlugin = require('../edmxBuildPlugin')
4
- const URL = require('url')
4
+ const { URL } = require('node:url')
5
5
  const { getProperty, relativePaths } = require('../../util')
6
6
  const { OUTPUT_MODE, OUTPUT_MODE_RESULT, BUILD_TASK_FIORI, CDS_CONFIG_PATH_SEP, OUTPUT_MODE_FILESYSTEM } = require('../../constants')
7
7
  const DEBUG = cds.debug('cli|build')
@@ -52,7 +52,7 @@ class FioriBuildPlugin extends EdmxBuildPlugin {
52
52
  appModelGroups.set(appFolder, appModels)
53
53
  }
54
54
 
55
- // ensure edmx is cached as build result
55
+ // ensure edmx is cached as build result
56
56
  const buildOption = this.context.options[OUTPUT_MODE]
57
57
  this.context.options[OUTPUT_MODE] |= OUTPUT_MODE_RESULT
58
58
 
@@ -159,8 +159,8 @@ class FioriBuildPlugin extends EdmxBuildPlugin {
159
159
  }
160
160
 
161
161
  _strippedUrlPath(urlString) {
162
- const url = URL.parse(urlString)
163
- return url.pathname.replace(/^(\/|\\)/, '').replace(/(\/|\\)$/, '') // strip leading and trailing slash or backslash)
162
+ const url = new URL(urlString, 'http://dummy.base') // need dummy base to parse relative URLs correctly
163
+ return url.pathname.replace(/^(\/|\\)/, '').replace(/(\/|\\)$/, '') // strip leading and trailing slash or backslash
164
164
  }
165
165
  }
166
166
 
@@ -44,6 +44,12 @@ class HanaBuildPlugin extends InternalBuildPlugin {
44
44
  wsPaths = await getWorkspacePaths()
45
45
  }
46
46
 
47
+ if (cds.cli.options.mocked) {
48
+ cds.deploy?.include_external_entities_in?.(model)
49
+ } else {
50
+ cds.deploy?.exclude_external_entities_in?.(model)
51
+ }
52
+
47
53
  // the order of 1 and 2 is important
48
54
  // 1. compile
49
55
  const hdiPlugins = await this._compileToHana(model, wsPaths)
@@ -153,7 +159,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
153
159
  if (entry.startsWith(dbSrc)) {
154
160
  return true
155
161
  }
156
- if (fs.statSync(entry).isDirectory()) {
162
+ if (cds.utils.isdir(entry)) {
157
163
  return !/(\/|\\)node_modules(\/|\\)?$/.test(entry) ||
158
164
  (/(\/|\\)node_modules(\/|\\)?$/.test(entry) && this.hasBuildOption(CONTENT_NODE_MODULES, true))
159
165
  }
@@ -179,7 +185,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
179
185
  const regex = RegExp('\\.cds$|\\.csv$|\\.hdbtabledata$')
180
186
 
181
187
  await this.copyNativeContent(src, dest, (entry) => {
182
- if (fs.statSync(entry).isDirectory()) {
188
+ if (cds.utils.isdir(entry)) {
183
189
  return !/(\/|\\)node_modules(\/|\\)?$/.test(entry)
184
190
  }
185
191
  return (!regex.test(entry) && entry !== cds.env.build.outputfile) ||
@@ -191,7 +197,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
191
197
  // subfolders are not supported
192
198
  const allFiles = csvDirs.reduce((acc, csvDir) => {
193
199
  return acc.concat(getFiles(csvDir, (entry) => {
194
- if (fs.statSync(entry).isDirectory()) {
200
+ if (cds.utils.isdir(entry)) {
195
201
  return false
196
202
  }
197
203
  return regexData.test(entry)
@@ -219,7 +225,7 @@ class HanaBuildPlugin extends InternalBuildPlugin {
219
225
  const destSrcDir = path.join(this.task.dest, "src")
220
226
 
221
227
  const allCsvFiles = getFiles(destSrcDir, (entry) => {
222
- if (fs.statSync(entry).isDirectory()) {
228
+ if (cds.utils.isdir(entry)) {
223
229
  return true
224
230
  }
225
231
  if (/\.hdbtabledata$/.test(entry)) {
@@ -243,7 +249,8 @@ class HanaBuildPlugin extends InternalBuildPlugin {
243
249
  const promises = []
244
250
  const options = { ...this.options(), messages: this.messages, dirs: csvDirs, baseDir: this.task.options.compileDest }
245
251
 
246
- const toHdbtabledata = cds.compile.to.hdbtabledata ?? require(path.join(cds.home, 'bin/build/provider/hana/2tabledata')) // cds@6 compatibility
252
+ const toHdbtabledata = cds.compile.to.hdbtabledata
253
+ if (!toHdbtabledata) throw `hdbtabledata plugin not found – make sure to install package '@cap-js/hana'`
247
254
  const tableDataResult = await toHdbtabledata(model, options)
248
255
 
249
256
  for (let [tableData, { file, csvFolder }] of tableDataResult) {