@sap/cds-dk 7.9.3 → 7.9.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.
package/bin/watch.js CHANGED
@@ -65,7 +65,7 @@ const t = module.exports.codes = {
65
65
  }
66
66
  const extDefaults = 'cds,csn,csv,ts,mjs,cjs,js,json,properties,edmx,xml,env'
67
67
  const ignore = RegExp(
68
- `(node_modules|_out|@types|@cds-models)\\${sep}` +
68
+ `(.git|node_modules|_out|@types|@cds-models)\\${sep}` +
69
69
  `|app(\\${sep}.+)?\\${sep}(` +
70
70
  `(webapp|dist|target)\\${sep}|` +
71
71
  `tsconfig\\.json$|` +
@@ -26,10 +26,8 @@ class BindingResolver {
26
26
 
27
27
  const resolvedBindings = {}
28
28
 
29
- // Serialized because of parallelization issues in the cf CLI,
30
- // see https://github.com/cloudfoundry/cli/issues/2232
31
- // await Promise.all(Object.keys(bindings).map(async name => {
32
- for (const name of Object.keys(bindings)) {
29
+ // run in parallel
30
+ await Promise.all(Object.keys(bindings).map(async name => {
33
31
  const binding = bindings[name]
34
32
  const cacheKey = JSON.stringify(binding)
35
33
  let resolvedBinding
@@ -40,7 +38,7 @@ class BindingResolver {
40
38
  resolvedBinding = cache[cacheKey]
41
39
  }
42
40
  resolvedBindings[name] = resolvedBinding
43
- }
41
+ }));
44
42
  return Object.keys(resolvedBindings).length > 0 ? resolvedBindings : undefined
45
43
  }
46
44
 
package/lib/bind/index.js CHANGED
@@ -32,12 +32,9 @@ async function bind(options) {
32
32
  const onText = { 'cf': 'Cloud Foundry', 'k8s': 'Kubernetes' }[on];
33
33
  if (!options['to-app-services']) logger.log(`Retrieving data from ${bold(onText)}...`);
34
34
 
35
+ // run in parallel
35
36
  const targets = options.to.split(/,/g);
36
- // Serialized because of parallelization issues in the cf CLI,
37
- // see https://github.com/cloudfoundry/cli/issues/2232
38
- // resolvedServices = await Promise.all(targets.map(async target => {
39
- const resolvedServices = [];
40
- for (const target of targets) {
37
+ const resolvedServices = await Promise.all(targets.map(async target => {
41
38
  let binding;
42
39
  if (on === 'k8s') {
43
40
  binding = { type: on, name: target };
@@ -51,8 +48,8 @@ async function bind(options) {
51
48
  resolvedService._target = target;
52
49
  delete resolvedService.credentials;
53
50
  resolvedService.binding.resolved = false;
54
- resolvedServices.push(resolvedService);
55
- }
51
+ return resolvedService;
52
+ }));
56
53
 
57
54
  if (options.kind) {
58
55
  resolvedServices.forEach(service => service.kind = options.kind);
@@ -158,6 +158,9 @@
158
158
  },
159
159
  "txt": {
160
160
  "plugin_name": "com.sap.hana.di.copyonly"
161
+ },
162
+ "hdbeshconfig": {
163
+ "plugin_name": "com.sap.hana.di.eshconfig"
161
164
  }
162
165
  }
163
166
  }
@@ -132,6 +132,9 @@
132
132
  },
133
133
  "txt": {
134
134
  "plugin_name": "com.sap.hana.di.copyonly"
135
+ },
136
+ "hdbeshconfig": {
137
+ "plugin_name": "com.sap.hana.di.eshconfig"
135
138
  }
136
139
  }
137
140
  }
@@ -17,7 +17,7 @@ const { bold, info, warn } = require('../../util/term');
17
17
 
18
18
  const { bind, storeBindings } = require('../../bind');
19
19
 
20
- const DEBUG = cds.debug('deploy');
20
+ const DEBUG = cds.debug('cli');
21
21
 
22
22
  module.exports = new class HanaDeployer {
23
23
 
@@ -5,7 +5,7 @@ module.exports = {
5
5
  COMMAND_ADD: 'add',
6
6
 
7
7
  JAVA_LTS_VERSIONS: [17, 21],
8
- MAVEN_ARCHETYPE_VERSION: '2.9.0',
8
+ MAVEN_ARCHETYPE_VERSION: '2.10.1',
9
9
 
10
10
  OPTIONS: Object.freeze({
11
11
  JAVA: 'java',
package/lib/init/index.js CHANGED
@@ -245,6 +245,8 @@ module.exports = class CDSGenerator {
245
245
  templates.set(plugin, template)
246
246
  const dependencies = await template.requires()
247
247
  dependencies?.forEach(d => plugins.add(d))
248
+ } else {
249
+ throw 'cannot run plugin \'' + plugin + '\'' + (DEBUG ? 'Does not satisfy the canRun() function:\n ' + template.canRun : '')
248
250
  }
249
251
  }
250
252
  }
@@ -131,6 +131,9 @@
131
131
  },
132
132
  "txt": {
133
133
  "plugin_name": "com.sap.hana.di.copyonly"
134
+ },
135
+ "hdbeshconfig": {
136
+ "plugin_name": "com.sap.hana.di.eshconfig"
134
137
  }
135
138
  }
136
139
  }
package/lib/util/cf.js CHANGED
@@ -1,18 +1,18 @@
1
- // eslint-disable-next-line no-console
2
-
3
1
  const cp = require('child_process');
4
2
  const fsp = require('fs').promises;
5
3
  const os = require('os');
6
4
  const path = require('path');
7
5
  const util = require('util');
8
6
 
7
+ const axios = require('axios');
8
+
9
9
  const IS_WIN = os.platform() === 'win32';
10
10
  const execAsync = util.promisify(cp.exec);
11
11
 
12
12
  const cds = require('../cds')
13
13
 
14
- const LOG = cds.log ? cds.log('deploy') : console;
15
- const DEBUG = cds.debug('deploy');
14
+ const LOG = cds.log ? cds.log('cli') : console;
15
+ const DEBUG = cds.debug('cli');
16
16
 
17
17
  const { bold, warn } = require('./term');
18
18
 
@@ -27,6 +27,7 @@ const OPERATION_STATE_FAILED = 'failed';
27
27
  const OPERATION_STATE_SUCCEEDED = 'succeeded';
28
28
 
29
29
  const CF_CLIENT_MINIMUM_VERSION = 8;
30
+ const ENCODED_COMMA = encodeURIComponent(',');
30
31
 
31
32
  module.exports = new class CfUtil {
32
33
  spaceInfo;
@@ -56,47 +57,46 @@ module.exports = new class CfUtil {
56
57
  err.stderr = err.stderr?.trim();
57
58
  throw err;
58
59
  } finally {
59
- // eslint-disable-next-line no-console
60
60
  DEBUG && console.timeEnd(cmdLine);
61
61
  }
62
62
  }
63
63
 
64
64
  async cfRequest(urlPath, queryObj, bodyObj) {
65
- if (queryObj) {
66
- const entries = Object.entries(queryObj);
67
- const queryStr = entries.map(([key, value]) => {
68
- if (Array.isArray(value)) {
69
- value = value.join(',');
70
- }
71
- // commas cause problems in cf curl when not double encoded
72
- // value = value.replace(/,/g, encodeURIComponent(','));
73
- return `${key}=${encodeURIComponent(value)}`;
74
- }).join('&');
65
+ const url = this.spaceInfo.apiEndpoint + urlPath;
75
66
 
76
- urlPath = urlPath + `?${queryStr}`;
77
- }
67
+ const options = {
68
+ headers: { 'Authorization': this.spaceInfo.token }
69
+ };
78
70
 
79
- // cf curl PATH [-iv] [-X METHOD] [-H HEADER]... [-d DATA] [--output FILE]
80
- const args = ['curl', urlPath];
81
- if (bodyObj) {
82
- args.push('-d');
83
- args.push(JSON.stringify(bodyObj)); // cfRun uses spawn so no special handling for quotes on cli required
84
- }
85
-
86
- const result = await this.cfRun(...args);
87
- let response = {};
88
- if (result.stdout) {
89
- response = JSON.parse(result.stdout);
90
- } else if (result.stderr) {
91
- response = { errors: [{ title: result.stderr }] };
71
+ if (queryObj && Object.keys(queryObj).length > 0) {
72
+ const params = {};
73
+ for (const [k, v] of Object.entries(queryObj)) {
74
+ // cf rest API does not accept comma in query parameters
75
+ params[k] = v.replaceAll(',', ENCODED_COMMA);
76
+ }
77
+ options.params = params;
92
78
  }
93
79
 
94
- if (response.errors) {
95
- const errorMessage = response.errors.map((entry) => `${entry.title || ''}: ${entry.detail || ''} (${entry.code || ''})`).join('\n');
96
- throw new Error(errorMessage);
80
+ try {
81
+ let response;
82
+ if (bodyObj) {
83
+ response = (await axios.post(url, bodyObj, options));
84
+ } else {
85
+ response = (await axios.get(url, options));
86
+ }
87
+ if (DEBUG) {
88
+ options.headers.Authorization = 'bearer <token>';
89
+ LOG.debug(`POST ${url}\n${JSON.stringify(options, null, 4)}\n${JSON.stringify(response.data, null, 4)}`);
90
+ }
91
+ return response.data;
92
+ } catch (err) {
93
+ if (err instanceof axios.AxiosError) {
94
+ if (err.response?.data?.errors[0]) {
95
+ throw JSON.stringify(err.response.data.errors[0], null, 4);
96
+ }
97
+ throw err.message;
98
+ }
97
99
  }
98
-
99
- return response;
100
100
  }
101
101
 
102
102
  _extract(string, pattern, errorMsg) {
@@ -104,7 +104,7 @@ module.exports = new class CfUtil {
104
104
  if (match?.[1]) {
105
105
  return match[1];
106
106
  }
107
- throw new Error(errorMsg);
107
+ throw errorMsg;
108
108
  }
109
109
 
110
110
  async _getCfTargetFromConfigFile() {
@@ -147,8 +147,10 @@ module.exports = new class CfUtil {
147
147
 
148
148
  async getCfTarget() {
149
149
  await this._checkCliVersion();
150
- await this._getCfAuthorization();
151
- return await this._getCfTargetFromConfigFile() || await this._getCfTargetFromCli();
150
+ const token = await this._getCfAuthorization();
151
+ const target = await this._getCfTargetFromConfigFile() || await this._getCfTargetFromCli();
152
+ target.token = token;
153
+ return target;
152
154
  }
153
155
 
154
156
  async _checkCliVersion() {
@@ -167,22 +169,26 @@ Deployment will stop in the near future for Cloud Foundry client versions < ${CF
167
169
  LOG.debug('getting space info');
168
170
 
169
171
  const target = await this.getCfTarget();
170
-
172
+ this.spaceInfo = target;
171
173
  const { org, space } = target;
172
- const orgs = await this.cfRequest(`/v3/organizations`, { names: org });
174
+ const orgs = await this.cfRequest('/v3/organizations', { names: org });
173
175
  if (!orgs?.resources?.length) {
174
- throw new Error(`CF org ${bold(org)} not found!`);
176
+ throw `CF org ${bold(org)} not found!`;
175
177
  }
176
178
 
177
179
  const orgGuid = orgs.resources[0].guid;
178
- const spaces = await this.cfRequest(`/v3/spaces`, { names: space, organization_guids: orgGuid });
180
+ const spaces = await this.cfRequest('/v3/spaces', { names: space, organization_guids: orgGuid });
179
181
  if (!spaces?.resources?.length) {
180
- throw new Error(`CF space ${bold(space)} not found in org ${bold(org)}!`);
182
+ throw `CF space ${bold(space)} not found in org ${bold(org)}!`;
181
183
  }
182
184
 
183
185
  const spaceGuid = spaces.resources[0].guid;
184
186
 
185
- this.spaceInfo = Object.assign({}, target, { orgGuid, spaceGuid });
187
+ this.spaceInfo = {
188
+ ...target,
189
+ orgGuid,
190
+ spaceGuid
191
+ }
186
192
  }
187
193
 
188
194
  return this.spaceInfo;
@@ -228,7 +234,10 @@ Deployment will stop in the near future for Cloud Foundry client versions < ${CF
228
234
  return serviceInstance;
229
235
 
230
236
  case OPERATION_STATE_FAILED:
231
- throw new Error(`The returned service reported state '${OPERATION_STATE_FAILED}'.\n${JSON.stringify(serviceInstance, null, 4)}`);
237
+ if (!DEBUG && serviceInstance?.last_operation?.description) {
238
+ throw serviceInstance.last_operation.description;
239
+ }
240
+ throw `The returned service reported state '${OPERATION_STATE_FAILED}'.\n${JSON.stringify(serviceInstance, null, 4)}`;
232
241
 
233
242
  default:
234
243
  console.error(`Unsupported server response state '${serviceInstance?.last_operation?.state}'. Waiting for next response.`);
@@ -236,7 +245,7 @@ Deployment will stop in the near future for Cloud Foundry client versions < ${CF
236
245
  }
237
246
  }
238
247
 
239
- throw new Error(`Timeout occurred while getting service ${bold(serviceName)}`);
248
+ throw `Timeout occurred while getting service ${bold(serviceName)}`;
240
249
  }
241
250
 
242
251
 
@@ -260,7 +269,7 @@ Deployment will stop in the near future for Cloud Foundry client versions < ${CF
260
269
  });
261
270
 
262
271
  if (!servicePlan?.resources?.length) {
263
- throw new Error(`No service plans found`);
272
+ throw `No service plans found for ${planName} in service offering ${serviceOfferingName}.`;
264
273
  }
265
274
 
266
275
  const body = {
@@ -287,7 +296,7 @@ Deployment will stop in the near future for Cloud Foundry client versions < ${CF
287
296
 
288
297
  const postResult = await this.cfRequest('/v3/service_instances', undefined, body);
289
298
  if (postResult?.errors) {
290
- throw new Error(postResult.errors[0].detail);
299
+ throw postResult.errors[0].detail;
291
300
  }
292
301
 
293
302
  const newService = await this.getService(serviceName, false);
@@ -295,7 +304,7 @@ Deployment will stop in the near future for Cloud Foundry client versions < ${CF
295
304
  return newService;
296
305
  }
297
306
 
298
- throw new Error(`Could not create service ${bold(serviceName)}`);
307
+ throw `Could not create service ${bold(serviceName)}`;
299
308
  }
300
309
 
301
310
  async _getServiceKey(serviceInstance, serviceKeyName, showMessage = true) {
@@ -322,7 +331,10 @@ Deployment will stop in the near future for Cloud Foundry client versions < ${CF
322
331
  }
323
332
 
324
333
  case OPERATION_STATE_FAILED:
325
- throw new Error(`The returned binding reported state '${OPERATION_STATE_FAILED}'.\n${JSON.stringify(binding, null, 4)}`);
334
+ if (!DEBUG && binding?.last_operation?.description) {
335
+ throw binding.last_operation.description;
336
+ }
337
+ throw `The returned binding reported state '${OPERATION_STATE_FAILED}'.\n${JSON.stringify(binding, null, 4)}`;
326
338
 
327
339
  default:
328
340
  console.error(`Unsupported server response state '${binding?.last_operation?.state}'. Waiting for next response.`);
@@ -330,7 +342,7 @@ Deployment will stop in the near future for Cloud Foundry client versions < ${CF
330
342
  }
331
343
  }
332
344
 
333
- throw new Error(`Timeout occurred while getting service key ${bold(serviceKeyName)}`);
345
+ throw `Timeout occurred while getting service key ${bold(serviceKeyName)}`;
334
346
  }
335
347
 
336
348
  async getOrCreateServiceKey(serviceInstance, serviceKeyName, parameters, { silent = false, create = true } = {}) {
@@ -357,7 +369,7 @@ Deployment will stop in the near future for Cloud Foundry client versions < ${CF
357
369
 
358
370
  const postResult = await this.cfRequest('/v3/service_credential_bindings', undefined, body);
359
371
  if (postResult?.errors) {
360
- throw new Error(postResult.errors[0].detail);
372
+ throw postResult.errors[0].detail;
361
373
  }
362
374
 
363
375
  const newServiceKey = await this._getServiceKey(serviceInstance, serviceKeyName, false);
@@ -365,6 +377,6 @@ Deployment will stop in the near future for Cloud Foundry client versions < ${CF
365
377
  return newServiceKey;
366
378
  }
367
379
 
368
- throw new Error(`Could not create service key ${bold(serviceKeyName)}`);
380
+ throw `Could not create service key ${bold(serviceKeyName)}`;
369
381
  }
370
- }
382
+ }
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@sap/cds-dk",
3
- "version": "7.9.3",
3
+ "version": "7.9.5",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@sap/cds-dk",
9
- "version": "7.9.3",
9
+ "version": "7.9.5",
10
10
  "license": "SEE LICENSE IN LICENSE",
11
11
  "dependencies": {
12
12
  "@sap/cds": "^7",
@@ -53,7 +53,7 @@
53
53
  }
54
54
  },
55
55
  "node_modules/@eslint-community/regexpp": {
56
- "version": "4.10.1",
56
+ "version": "4.11.0",
57
57
  "license": "MIT",
58
58
  "engines": {
59
59
  "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
@@ -208,7 +208,7 @@
208
208
  }
209
209
  },
210
210
  "node_modules/@sap/cds": {
211
- "version": "7.9.2",
211
+ "version": "7.9.3",
212
212
  "license": "SEE LICENSE IN LICENSE",
213
213
  "dependencies": {
214
214
  "@cap-js/cds-types": "<1",
@@ -240,15 +240,15 @@
240
240
  }
241
241
  },
242
242
  "node_modules/@sap/cds-fiori": {
243
- "version": "1.2.3",
243
+ "version": "1.2.7",
244
244
  "license": "SEE LICENSE IN LICENSE",
245
245
  "peerDependencies": {
246
- "@sap/cds": ">=7.1",
246
+ "@sap/cds": ">=7.6",
247
247
  "express": ">=4"
248
248
  }
249
249
  },
250
250
  "node_modules/@sap/cds-foss": {
251
- "version": "5.0.0",
251
+ "version": "5.0.1",
252
252
  "license": "See LICENSE in LICENSE",
253
253
  "dependencies": {
254
254
  "big.js": "^6.1.1",
@@ -261,7 +261,7 @@
261
261
  }
262
262
  },
263
263
  "node_modules/@sap/cds-mtxs": {
264
- "version": "1.18.1",
264
+ "version": "1.18.2",
265
265
  "license": "SEE LICENSE IN LICENSE",
266
266
  "dependencies": {
267
267
  "@sap/hdi-deploy": "^4",
@@ -273,10 +273,10 @@
273
273
  }
274
274
  },
275
275
  "node_modules/@sap/eslint-plugin-cds": {
276
- "version": "3.0.3",
276
+ "version": "3.0.4",
277
277
  "license": "See LICENSE file",
278
278
  "dependencies": {
279
- "@sap/cds": ">=5.6.0",
279
+ "@sap/cds": ">=7",
280
280
  "semver": "^7.3.4"
281
281
  },
282
282
  "engines": {
@@ -396,7 +396,7 @@
396
396
  }
397
397
  },
398
398
  "node_modules/acorn": {
399
- "version": "8.11.3",
399
+ "version": "8.12.1",
400
400
  "license": "MIT",
401
401
  "bin": {
402
402
  "acorn": "bin/acorn"
@@ -1175,7 +1175,7 @@
1175
1175
  }
1176
1176
  },
1177
1177
  "node_modules/esquery": {
1178
- "version": "1.5.0",
1178
+ "version": "1.6.0",
1179
1179
  "license": "BSD-3-Clause",
1180
1180
  "dependencies": {
1181
1181
  "estraverse": "^5.1.0"
@@ -2214,7 +2214,7 @@
2214
2214
  "license": "MIT"
2215
2215
  },
2216
2216
  "node_modules/node-abi": {
2217
- "version": "3.63.0",
2217
+ "version": "3.65.0",
2218
2218
  "license": "MIT",
2219
2219
  "optional": true,
2220
2220
  "dependencies": {
@@ -2301,8 +2301,11 @@
2301
2301
  }
2302
2302
  },
2303
2303
  "node_modules/object-inspect": {
2304
- "version": "1.13.1",
2304
+ "version": "1.13.2",
2305
2305
  "license": "MIT",
2306
+ "engines": {
2307
+ "node": ">= 0.4"
2308
+ },
2306
2309
  "funding": {
2307
2310
  "url": "https://github.com/sponsors/ljharb"
2308
2311
  }
@@ -3136,7 +3139,7 @@
3136
3139
  }
3137
3140
  },
3138
3141
  "node_modules/uglify-js": {
3139
- "version": "3.17.4",
3142
+ "version": "3.18.0",
3140
3143
  "license": "BSD-2-Clause",
3141
3144
  "optional": true,
3142
3145
  "bin": {
@@ -3244,7 +3247,7 @@
3244
3247
  "license": "ISC"
3245
3248
  },
3246
3249
  "node_modules/ws": {
3247
- "version": "8.17.0",
3250
+ "version": "8.18.0",
3248
3251
  "license": "MIT",
3249
3252
  "engines": {
3250
3253
  "node": ">=10.0.0"
@@ -3280,7 +3283,7 @@
3280
3283
  }
3281
3284
  },
3282
3285
  "node_modules/yaml": {
3283
- "version": "2.4.3",
3286
+ "version": "2.4.5",
3284
3287
  "license": "ISC",
3285
3288
  "bin": {
3286
3289
  "yaml": "bin.mjs"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sap/cds-dk",
3
- "version": "7.9.3",
3
+ "version": "7.9.5",
4
4
  "description": "Command line client and development toolkit for the SAP Cloud Application Programming Model",
5
5
  "homepage": "https://cap.cloud.sap/",
6
6
  "keywords": [