@sap/cds 6.4.0 → 6.5.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 (88) hide show
  1. package/CHANGELOG.md +59 -3
  2. package/apis/cds.d.ts +2 -0
  3. package/apis/cqn.d.ts +14 -3
  4. package/apis/ql.d.ts +12 -8
  5. package/apis/services.d.ts +39 -64
  6. package/apis/test.d.ts +7 -0
  7. package/bin/build/buildTaskEngine.js +9 -12
  8. package/bin/build/buildTaskHandler.js +3 -14
  9. package/bin/build/index.js +8 -2
  10. package/bin/build/provider/buildTaskProviderInternal.js +8 -7
  11. package/bin/build/provider/hana/template/package.json +3 -0
  12. package/bin/build/provider/mtx/resourcesTarBuilder.js +13 -4
  13. package/bin/build/provider/mtx-extension/index.js +41 -38
  14. package/bin/build/util.js +17 -0
  15. package/bin/deploy/to-hana/hdiDeployUtil.js +11 -5
  16. package/bin/serve.js +6 -2
  17. package/common.cds +7 -0
  18. package/lib/auth/index.js +17 -15
  19. package/lib/auth/jwt-auth.js +4 -3
  20. package/lib/compile/for/lean_drafts.js +1 -1
  21. package/lib/compile/minify.js +3 -3
  22. package/lib/core/index.js +1 -0
  23. package/lib/dbs/cds-deploy.js +13 -10
  24. package/lib/env/cds-requires.js +1 -1
  25. package/lib/env/defaults.js +5 -1
  26. package/lib/env/schemas/cds-rc.json +74 -3
  27. package/lib/lazy.js +6 -8
  28. package/lib/log/cds-error.js +2 -2
  29. package/lib/ql/Whereable.js +22 -11
  30. package/lib/ql/cds-ql.js +1 -1
  31. package/lib/req/response.js +8 -3
  32. package/lib/req/user.js +12 -2
  33. package/lib/srv/middlewares/cds-context.js +0 -2
  34. package/lib/srv/middlewares/ctx-auth.js +11 -0
  35. package/lib/srv/middlewares/ctx-model.js +22 -20
  36. package/lib/srv/middlewares/index.js +7 -9
  37. package/lib/srv/protocols/_legacy.js +4 -0
  38. package/lib/srv/protocols/graphql.js +2 -2
  39. package/lib/srv/protocols/index.js +7 -3
  40. package/lib/srv/srv-api.js +1 -0
  41. package/lib/srv/srv-models.js +6 -1
  42. package/lib/utils/cds-utils.js +3 -1
  43. package/lib/utils/data.js +2 -2
  44. package/lib/utils/tar.js +37 -12
  45. package/libx/_runtime/auth/strategies/JWT.js +1 -0
  46. package/libx/_runtime/auth/strategies/ias-auth.js +2 -1
  47. package/libx/_runtime/auth/strategies/mock.js +12 -1
  48. package/libx/_runtime/auth/strategies/xssecUtils.js +7 -8
  49. package/libx/_runtime/auth/strategies/xsuaa.js +1 -0
  50. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -2
  51. package/libx/_runtime/cds-services/services/Service.js +3 -0
  52. package/libx/_runtime/cds-services/services/utils/columns.js +35 -36
  53. package/libx/_runtime/common/code-ext/WorkerReq.js +79 -0
  54. package/libx/_runtime/common/code-ext/config.js +13 -0
  55. package/libx/_runtime/common/code-ext/execute.js +106 -0
  56. package/libx/_runtime/common/code-ext/handlers.js +49 -0
  57. package/libx/_runtime/common/code-ext/worker.js +36 -0
  58. package/libx/_runtime/common/code-ext/workerQuery.js +45 -0
  59. package/libx/_runtime/common/code-ext/workerQueryExecutor.js +33 -0
  60. package/libx/_runtime/common/generic/crud.js +5 -1
  61. package/libx/_runtime/common/generic/paging.js +8 -7
  62. package/libx/_runtime/common/i18n/index.js +1 -1
  63. package/libx/_runtime/common/utils/cqn2cqn4sql.js +47 -11
  64. package/libx/_runtime/common/utils/path.js +5 -25
  65. package/libx/_runtime/common/utils/resolveView.js +2 -0
  66. package/libx/_runtime/common/utils/search2cqn4sql.js +13 -9
  67. package/libx/_runtime/db/expand/expandCQNToJoin.js +2 -1
  68. package/libx/_runtime/db/sql-builder/InsertBuilder.js +5 -1
  69. package/libx/_runtime/db/sql-builder/UpsertBuilder.js +9 -32
  70. package/libx/_runtime/db/sql-builder/annotations.js +6 -3
  71. package/libx/_runtime/db/utils/localized.js +1 -1
  72. package/libx/_runtime/fiori/generic/activate.js +4 -0
  73. package/libx/_runtime/fiori/generic/before.js +8 -1
  74. package/libx/_runtime/fiori/generic/edit.js +5 -0
  75. package/libx/_runtime/fiori/generic/read.js +8 -3
  76. package/libx/_runtime/fiori/lean-draft.js +12 -1
  77. package/libx/_runtime/hana/Service.js +1 -1
  78. package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +5 -5
  79. package/libx/_runtime/hana/execute.js +5 -5
  80. package/libx/_runtime/hana/pool.js +1 -1
  81. package/libx/_runtime/hana/search2cqn4sql.js +51 -51
  82. package/libx/_runtime/sqlite/Service.js +1 -1
  83. package/libx/_runtime/sqlite/customBuilder/CustomUpsertBuilder.js +20 -38
  84. package/libx/odata/afterburner.js +6 -3
  85. package/libx/odata/cqn2odata.js +1 -1
  86. package/libx/rest/middleware/parse.js +26 -4
  87. package/package.json +1 -1
  88. package/server.js +2 -20
package/CHANGELOG.md CHANGED
@@ -4,6 +4,60 @@
4
4
  - The format is based on [Keep a Changelog](http://keepachangelog.com/).
5
5
  - This project adheres to [Semantic Versioning](http://semver.org/).
6
6
 
7
+ ## Version 6.5.0 - 2023-01-27
8
+
9
+ ### Added
10
+
11
+ - New aspect `sap.common.TextsAspect` in common.cds
12
+ - New syntax for collection bound entities
13
+
14
+ ### Changed
15
+
16
+ - Successive calls to `SELECT.where()` wraps existing clause in brackets if it contains `or`. E.g.
17
+ ```js
18
+ SELECT.from `X` .where `x` .or `y` .where `z`
19
+ //> SELECT from X where (x or y) and z`
20
+ ```
21
+ - `cds build` for HANA now adds an `engines.node` version to the generated `db/package.json`. This will help in the future when runtime environments change their default to some version higher than the one supported by `@sap/hdi-deploy`.
22
+ - `cds build` checks the consistency of built-in models for java projects. An error is logged if some model files could not successfully be resolved indicating that a required npm module might be missing.
23
+ - Status code of draft actions are set in respective handler instead of protocol adapter
24
+ - `cds deploy --dry` no longer loads the `sqlite3` module by mistake. This fixes a regression when building Java projects. As a side effect a file with the name `undefined` was created in the project root folder.
25
+ - Internal representation of pseudo roles `internal-user` and `system-user`
26
+
27
+ ### Fixed
28
+
29
+ - Resolve i18n folders from the root directory
30
+ - Types for `cds.test`
31
+ - Types for `srv.send`
32
+ - Optimized Search: Search queries for localized entities will now use default values, if no localized data is found in the corresponding localized tables on SAP HANA. Correct aliasing by search queries with navigation.
33
+ - Resolution of `type of` references during minify in bootstrap
34
+ - Generation of odata-v2 URL in case of select=* in `urlify()`
35
+ - Build resets changed `cds.env` and `cds.root` when finished
36
+ - Expand error when using infix filters
37
+ - CDS configuration schema validation for `@sap/cds-mtxs`
38
+ - Typings for QL API
39
+ - Return types of asynchronous service API
40
+
41
+ ## Version 6.4.1 - 2022-01-16
42
+
43
+ ### Fixed
44
+
45
+ - `cds build` correctly creates a `resources.tgz` file for MTXS projects on Windows
46
+ - `cds.deploy` for HANA now doesn't try to search for a globally installed `@sap/hdi-deploy` if there's no `npm` installed, e.g. on a Node.js server without `npm`
47
+ - Signature for `cds.ql.UPSERT`
48
+ - Signature for `<srv>.delete().where()`
49
+ - Signature for `SELECT.alias`
50
+ - `UPSERT` requests for SQLite if only keys are provided
51
+ - `cds.test` doesn't log database resets with `autoReset` enabled any more
52
+ - The `cds.deploy` output for HANA is now correctly formatted in Kibana
53
+ - SAP HANA stored procedures containing implicit selects
54
+ - Shorthand configuration for `graphql` in `cds.env.protocols`
55
+ - If `cds.env.protocols` is set, `cds.requires.middlewares` is automatically turned on
56
+ - `cds.context` middleware is split to initial handling of request correlation and user propagation
57
+ - fix view resolving and managed data for UPSERT
58
+ - `cds.linked` supports polymorphic self links like in: `action foo( self: [many] $self, ...)`
59
+ - Error with `@odata.draft.enabled` and `@restrict`
60
+
7
61
  ## Version 6.4.0 - 2022-12-15
8
62
 
9
63
  ### Added
@@ -14,11 +68,12 @@
14
68
  - `persistent-outbox`: Support for parallel processing with option `parallel: true` as well as pluggable processor functions through `service.outbox.process` (beta)
15
69
  - `cds version` now also lists packages with `@cap-js/` prefix from dependencies
16
70
  - `cds.context.http` is now available for webhook-based requests
17
- - `cds build` for HANA migration tables now only saves model entities annotated with `@cds.persistence.journal` as `last-dev` version.
71
+ - `cds build` for SAP HANA migration tables now only saves model entities annotated with `@cds.persistence.journal` as `last-dev` version.
18
72
  - `cds deploy` now uses the `VCAP_SERVICES` environment variable (if set), and skips `cf` operations in this case
19
73
 
20
74
  ### Changed
21
75
 
76
+ - Added several missing signatures in CQN types that are now in accordance with the current documentation.
22
77
  - `.columns(…)` of both `cql.SELECT` and `cql.INSERT` give improved code completion when paired when appropriate type definitions are present
23
78
  - Status code of error messages caused by empty `not null` fields is changed from `400` to `500` on database layer. Note, that as result the error message `Value is required` in production will be replaced by `Internal server error` in the HTTP response.
24
79
  - Underscores in environment variables can now be escaped by two `__` to set keys in `cds.env`. For example, use `CDS_FEATURES_WITH__MOCKS=...` to set `features.with_mocks`. Note that previously, this ended up as `features: { with_: { mocks:... }}`, so in rare cases, it might yield unexpected results.
@@ -49,6 +104,7 @@
49
104
  - Quoting of keys typed as `cds.String` in error targets. Error targets are a relative resource path to correlate error
50
105
  messages with the corresponding text input filed in the UI in an OData HTTP error response body for errors, warnings,
51
106
  and info messages. For example:
107
+ - Error with `GET` on `actions`
52
108
 
53
109
  ```diff
54
110
  HTTP/1.1 400 Bad Request
@@ -69,8 +125,8 @@ Content-Length: 145
69
125
  ```
70
126
 
71
127
  - Application crash if batched Uri uses invalid percent encoding
72
- - `cds build` for HANA no longer produces `hdbtabledata` for csv files that refer to non-existing entities. This can be the case for imported content packages that bring csv files for entities that are not used in the application model.
73
- - `cds build` for HANA now gives precedence for csv files from application layer. This is important for imported content packages that bring csv files that shall be overwritten in the application layer.
128
+ - `cds build` for SAP HANA no longer produces `hdbtabledata` for csv files that refer to non-existing entities. This can be the case for imported content packages that bring csv files for entities that are not used in the application model.
129
+ - `cds build` for SAP HANA now gives precedence for csv files from application layer. This is important for imported content packages that bring csv files that shall be overwritten in the application layer.
74
130
  - `cds build` for Java no longer adds the service `cds.xt.MTXServices` to the application model.
75
131
  - `cds build` no longer fails when creating large resource TAR archives for MTXS projects.
76
132
 
package/apis/cds.d.ts CHANGED
@@ -16,6 +16,7 @@ declare global {
16
16
  // these provide the functionality from SELECT, INSERT, etc in the global facade
17
17
  const SELECT: typeof cds.ql.SELECT
18
18
  const INSERT: typeof cds.ql.INSERT
19
+ const UPSERT: typeof cds.ql.UPSERT
19
20
  const UPDATE: typeof cds.ql.UPDATE
20
21
  const DELETE: typeof cds.ql.DELETE
21
22
  const CREATE: typeof cds.ql.CREATE
@@ -24,6 +25,7 @@ declare global {
24
25
  // and these allow us to use them as type too, i.e. `const q: SELECT<Book> = ...`
25
26
  type SELECT<T> = ql.SELECT<T>
26
27
  type INSERT<T> = ql.INSERT<T>
28
+ type UPSERT<T> = ql.UPSERT<T>
27
29
  type UPDATE<T> = ql.UPDATE<T>
28
30
  type DELETE<T> = ql.DELETE<T>
29
31
  type CREATE<T> = ql.CREATE<T>
package/apis/cqn.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ import { entity } from "./csn"
2
+
1
3
  export type Query = SELECT | INSERT | UPDATE | DELETE | CREATE | DROP | UPSERT
2
4
  export type ParsedExpr = expr & { _:string }
3
5
 
@@ -5,6 +7,7 @@ export type SELECT = {SELECT:{
5
7
  distinct?: true
6
8
  one? : boolean
7
9
  from : source
10
+ mixin?: {[key:string]: expr}
8
11
  columns? : column_expr[]
9
12
  excluding? : string[]
10
13
  where? : predicate
@@ -12,18 +15,23 @@ export type SELECT = {SELECT:{
12
15
  groupBy? : expr[]
13
16
  orderBy? : ordering_term[]
14
17
  limit?: { rows:val, offset:val }
18
+ forUpdate?: { wait: number }
19
+ forShareLock?: { wait: number }
20
+ search?: _xpr
21
+ count?: boolean
15
22
  }}
16
23
 
17
24
  export type INSERT = {INSERT:{
18
- into : name
25
+ into : name | ref
19
26
  entries : any[]
20
27
  columns : string[]
21
28
  values : any[]
22
29
  rows : any[]
30
+ as : SELECT
23
31
  }}
24
32
 
25
33
  export type UPSERT = {UPSERT:{
26
- into : name
34
+ into : name | ref
27
35
  entries : any[]
28
36
  columns : string[]
29
37
  values : any[]
@@ -42,11 +50,14 @@ export type DELETE = {DELETE:{
42
50
  }}
43
51
 
44
52
  export type CREATE = {CREATE:{
45
- entity : name
53
+ entity : entity | name
54
+ as: SELECT
46
55
  }}
47
56
 
48
57
  export type DROP = {DROP:{
49
58
  entity : name
59
+ table: ref
60
+ view: ref
50
61
  }}
51
62
 
52
63
  type name = string
package/apis/ql.d.ts CHANGED
@@ -95,6 +95,8 @@ declare class QL<T> {
95
95
  SELECT : StaticSELECT<T>
96
96
  INSERT : typeof INSERT
97
97
  & ((...entries:object[]) => INSERT<any>) & ((entries:object[]) => INSERT<any>)
98
+ UPSERT: typeof UPSERT
99
+ & ((...entries:object[]) => UPSERT<any>) & ((entries:object[]) => UPSERT<any>)
98
100
  UPDATE : typeof UPDATE
99
101
  & typeof UPDATE.entity
100
102
  DELETE : typeof DELETE
@@ -137,6 +139,8 @@ export class SELECT<T> extends ConstructedQuery {
137
139
  & ((rows : number, offset? : number) => this)
138
140
  forShareLock () : this
139
141
  forUpdate ({wait}? : {wait?: number}) : this
142
+ alias (as: string) : this
143
+
140
144
 
141
145
  // Not yet public
142
146
  // fullJoin (other: string, as: string) : this
@@ -148,7 +152,7 @@ export class SELECT<T> extends ConstructedQuery {
148
152
  // & ((...expr : string[]) => this)
149
153
  // & ((predicate:object) => this)
150
154
 
151
- SELECT : CQN.SELECT
155
+ SELECT : CQN.SELECT["SELECT"]
152
156
  }
153
157
 
154
158
 
@@ -205,7 +209,7 @@ export class INSERT<T> extends ConstructedQuery {
205
209
  columns (...col: string[]) : this
206
210
  values (... val: any[]) : this
207
211
  rows (... row: any[]) : this
208
- INSERT : CQN.INSERT
212
+ INSERT : CQN.INSERT["INSERT"]
209
213
  }
210
214
 
211
215
 
@@ -225,7 +229,7 @@ export class UPSERT<T> extends ConstructedQuery {
225
229
  columns (...col: string[]) : this
226
230
  values (... val: any[]) : this
227
231
  rows (... row: any[]) : this
228
- UPSERT : CQN.UPSERT
232
+ UPSERT : CQN.UPSERT["UPSERT"]
229
233
  }
230
234
 
231
235
 
@@ -239,7 +243,7 @@ export class DELETE<T> extends ConstructedQuery {
239
243
  where (...expr : any[]) : this
240
244
  and (predicate:object) : this
241
245
  and (...expr : any[]) : this
242
- DELETE : CQN.DELETE
246
+ DELETE : CQN.DELETE["DELETE"]
243
247
  }
244
248
 
245
249
  export class UPDATE<T> extends ConstructedQuery {
@@ -260,15 +264,15 @@ export class UPDATE<T> extends ConstructedQuery {
260
264
  where (...expr : any[]) : this
261
265
  and (predicate:object) : this
262
266
  and (...expr : any[]) : this
263
- UPDATE : CQN.UPDATE
267
+ UPDATE : CQN.UPDATE["UPDATE"]
264
268
  }
265
269
 
266
270
  export class CREATE<T> extends ConstructedQuery {
267
271
  static entity (entity : Definition | string) : CREATE<any>
268
- CREATE : CQN.CREATE
272
+ CREATE : CQN.CREATE["CREATE"]
269
273
  }
270
274
 
271
275
  export class DROP<T> extends ConstructedQuery {
272
276
  static entity (entity : Definition | string) : DROP<any>
273
- DROP : CQN.DROP
274
- }
277
+ DROP : CQN.DROP["DROP"]
278
+ }
@@ -1,4 +1,4 @@
1
- import { SELECT, INSERT, UPDATE, DELETE, Query, ConstructedQuery } from './ql'
1
+ import { SELECT, INSERT, UPDATE, DELETE, Query, ConstructedQuery, UPSERT } from './ql'
2
2
  import { Projection, Proxy, Awaitable } from './ql'
3
3
  import { ArrayConstructable } from './internal/inference'
4
4
  import { LinkedModel, Definition, Definitions } from './reflect'
@@ -33,33 +33,27 @@ export class QueryAPI {
33
33
  /**
34
34
  * @see [docs](https://cap.cloud.sap/docs/node.js/services#srv-run)
35
35
  */
36
- update: {
37
- <T extends ArrayConstructable<any>>(entity: T, key?: any): UPDATE<T>
38
- <T>(entity: Definition | string, key?: any): UPDATE<T>
36
+ upsert: {
37
+ <T extends ArrayConstructable<any>>(data: T): UPSERT<T>
38
+ <T>(data: object | object[]): UPSERT<T>
39
39
  }
40
40
 
41
41
  /**
42
42
  * @see [docs](https://cap.cloud.sap/docs/node.js/services#srv-run)
43
43
  */
44
- // as delete is the only one of the CRUD methods from QueryAPI
45
- // that is extended in Service, we have to add the second signature down there
46
- // (TS error 2425)
47
- delete<T>(entity: Definition | string, key?: any): DELETE<T>
48
-
49
- /**
50
- * @see [docs](https://cap.cloud.sap/docs/node.js/services#srv-run)
51
- */
52
- run(query: ConstructedQuery | ConstructedQuery[]): Promise<ResultSet | any>
44
+ update: {
45
+ <T extends ArrayConstructable<any>>(entity: T, key?: any): UPDATE<T>
46
+ <T>(entity: Definition | string, key?: any): UPDATE<T>
47
+ }
53
48
 
54
49
  /**
55
50
  * @see [docs](https://cap.cloud.sap/docs/node.js/services#srv-run)
56
51
  */
57
- run(query: Query): Promise<ResultSet | any>
58
-
59
- /**
60
- * @see [docs](https://cap.cloud.sap/docs/node.js/services#srv-run-sql)
61
- */
62
- run(query: string, args?: any[] | object): Promise<ResultSet | any>
52
+ run: {
53
+ (query: ConstructedQuery | ConstructedQuery[]): Promise<ResultSet | any>
54
+ (query: Query): Promise<ResultSet | any>
55
+ (query: string, args?: any[] | object): Promise<ResultSet | any>
56
+ }
63
57
 
64
58
  /**
65
59
  * @see [docs](https://cap.cloud.sap/docs/node.js/services#srv-run)
@@ -69,17 +63,15 @@ export class QueryAPI {
69
63
  /**
70
64
  * @see [docs](https://cap.cloud.sap/docs/node.js/services#srv-stream)
71
65
  */
72
- stream(column: string): {
73
- from(entity: Definition | string): {
74
- where(filter: any): ReadableStream
66
+ stream: {
67
+ (column: string): {
68
+ from(entity: Definition | string): {
69
+ where(filter: any): ReadableStream
70
+ }
75
71
  }
72
+ (query: Query): Promise<ReadableStream>
76
73
  }
77
74
 
78
- /**
79
- * @see [docs](https://cap.cloud.sap/docs/node.js/services#srv-stream)
80
- */
81
- stream(query: Query): Promise<ReadableStream>
82
-
83
75
  /**
84
76
  * Starts or joins a transaction
85
77
  * @see [docs](https://cap.cloud.sap/docs/node.js/services#srv-tx)
@@ -148,68 +140,51 @@ export class Service extends QueryAPI {
148
140
  * Constructs and emits an asynchronous event.
149
141
  * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srv-emit)
150
142
  */
151
- emit(details: { event: Events; data?: object; headers?: object }): Promise<this>
152
-
153
- /**
154
- * Constructs and emits an asynchronous event.
155
- * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srv-emit)
156
- */
157
- emit(event: Events, data?: object, headers?: object): Promise<this>
143
+ emit: {
144
+ <T = any>(details: { event: Events; data?: object; headers?: object }): Promise<T>
145
+ <T = any>(event: Events, data?: object, headers?: object): Promise<T>
146
+ }
158
147
 
159
148
  /**
160
149
  * Constructs and sends a synchronous request.
161
150
  * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srvsend--method-path-data-headers--results-)
162
151
  */
163
- send(event: Events, path: string, data?: object, headers?: object): Promise<this>
164
-
165
- /**
166
- * Constructs and sends a synchronous request.
167
- * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srvsend---method-path--query--event-data-headers---results-)
168
- */
169
- send(details: { event: Events; data?: object; headers?: object }): Promise<this>
170
-
171
- /**
172
- * Constructs and sends a synchronous request.
173
- * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srvsend---method-path--query--event-data-headers---results-)
174
- */
175
- send(details: { query: ConstructedQuery; data?: object; headers?: object }): Promise<this>
176
-
177
- /**
178
- * Constructs and sends a synchronous request.
179
- * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srvsend---method-path--query--event-data-headers---results-)
180
- */
181
- send(details: { method: Event; path: string; data?: object; headers?: object }): Promise<this>
152
+ send: {
153
+ <T = any>(event: Events, path: string, data?: object, headers?: object): Promise<T>
154
+ <T = any>(event: Events, data?: object, headers?: object): Promise<T>
155
+ <T = any>(details: { event: Events; data?: object; headers?: object }): Promise<T>
156
+ <T = any>(details: { query: ConstructedQuery; data?: object; headers?: object }): Promise<T>
157
+ <T = any>(details: { method: Event; path: string; data?: object; headers?: object }): Promise<T>
158
+ }
182
159
 
183
160
  /**
184
161
  * Constructs and sends a GET request.
185
162
  * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srv-send)
186
163
  */
187
- get(entityOrPath: Target, data?: object): Promise<this>
164
+ get<T = any>(entityOrPath: Target, data?: object): Promise<T>
188
165
  /**
189
166
  * Constructs and sends a POST request.
190
167
  * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srv-send)
191
168
  */
192
- post(entityOrPath: Target, data?: object): Promise<this>
169
+ post<T = any>(entityOrPath: Target, data?: object): Promise<T>
193
170
  /**
194
171
  * Constructs and sends a PUT request.
195
172
  * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srv-send)
196
173
  */
197
- put(entityOrPath: Target, data?: object): Promise<this>
174
+ put<T = any>(entityOrPath: Target, data?: object): Promise<T>
198
175
  /**
199
176
  * Constructs and sends a PATCH request.
200
177
  * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srv-send)
201
178
  */
202
- patch(entityOrPath: Target, data?: object): Promise<this>
179
+ patch<T = any>(entityOrPath: Target, data?: object): Promise<T>
203
180
  /**
204
181
  * Constructs and sends a DELETE request.
205
- * @see [capire docs](https://cap.cloud.sap/docs/node.js/services#srv-send)
206
182
  */
207
- delete(entityOrPath: Target, data?: object): Promise<this>
208
- /**
209
- * @see [docs](https://cap.cloud.sap/docs/node.js/services#srv-run)
210
- */
211
- delete<T extends ArrayConstructable<any>>(entity: T, key?: any): DELETE<T>
212
- delete<T>(entity: Definition | string, key?: any): DELETE<T>
183
+ delete: {
184
+ (entityOrPath: Target, data?: object): DELETE<T>
185
+ <T extends ArrayConstructable<any>>(entity: T, key?: any): DELETE<T>
186
+ <T>(entity: Definition | string, key?: any): DELETE<T>
187
+ }
213
188
 
214
189
  // The central method to dispatch events
215
190
  dispatch(msg: EventMessage): Promise<any>
package/apis/test.d.ts CHANGED
@@ -57,5 +57,12 @@ declare class Test extends Axios {
57
57
  export = cds
58
58
 
59
59
  declare class cds {
60
+ /**
61
+ * @see [capire docs](https://cap.cloud.sap/docs/node.js/cds-test?q=cds.test#run)
62
+ */
60
63
  test(projectDir: string): Test;
64
+ /**
65
+ * @see [capire docs](https://cap.cloud.sap/docs/node.js/cds-test?q=cds.test#run-2)
66
+ */
67
+ test(command: string, ...args: string[]): Test;
61
68
  }
@@ -2,7 +2,7 @@ const fs = require('fs')
2
2
  const path = require('path')
3
3
  const cds = require('./cds'), { log } = cds.exec
4
4
  const { sortMessagesSeverityAware, deduplicateMessages, CompilationError } = require('@sap/cds-compiler')
5
- const { relativePaths, BuildError, BuildMessage, resolveRequiredSapModels, hasJavaNature } = require('./util')
5
+ const { relativePaths, BuildError, BuildMessage, resolveRequiredSapModels } = require('./util')
6
6
  const { OUTPUT_MODE_DEFAULT, SEVERITIES, LOG_LEVELS, LOG_MODULE_NAMES, CDS_MODEL_EXCLUDE_LIST } = require('./constants')
7
7
  const BuildTaskProviderFactory = require('./buildTaskProviderFactory')
8
8
  const BuildTaskHandlerInternal = require('./provider/buildTaskHandlerInternal')
@@ -41,16 +41,13 @@ class BuildTaskEngine {
41
41
  buildOptions.target = path.resolve(buildOptions.root, cds.env.build.target)
42
42
  }
43
43
 
44
- // Java projects don't have node modules installed on project root level
45
- if (!hasJavaNature([buildOptions.root])) {
46
- // validate required @sap namespace models - log only
47
- const { unresolved, missing } = BuildTaskEngine._resolveRequiredSapServices(tasks)
48
- if (unresolved.length > 0) {
49
- messages.push(new BuildMessage(`Required CDS service models [${unresolved.join(', ')}] cannot be resolved. Make sure to install the missing npm modules.`))
50
- }
51
- if (missing.length > 0) {
52
- messages.push(new BuildMessage(`Required CDS service models [${missing.join(', ')}] are missing in custom build tasks. Make sure to add the missing models.`))
53
- }
44
+ // validate required @sap namespace models - log only
45
+ const { unresolved, missing } = BuildTaskEngine._resolveRequiredSapServices(tasks)
46
+ if (unresolved.length > 0) {
47
+ messages.push(new BuildMessage(`Required CDS service models [${unresolved.join(', ')}] cannot be resolved. Make sure to install the missing npm modules.`))
48
+ }
49
+ if (missing.length > 0) {
50
+ messages.push(new BuildMessage(`Required CDS service models [${missing.join(', ')}] are missing in custom build tasks. Make sure to add the missing models.`))
54
51
  }
55
52
 
56
53
  // create build task handlers
@@ -337,7 +334,7 @@ class BuildTaskEngine {
337
334
  }
338
335
 
339
336
  /**
340
- * Returns a sorted and flatend list of all messages extracted from the given errors.
337
+ * Returns a sorted and flattened list of all messages extracted from the given errors.
341
338
  * @param {Array<Error>} errors
342
339
  */
343
340
  static _getErrorMessages(errors) {
@@ -3,7 +3,7 @@ const fs = require('fs').promises
3
3
  const cds = require('./cds')
4
4
 
5
5
  const { BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_DEFAULT, OUTPUT_MODE_RESULT_ONLY, SEVERITY_INFO, SEVERITY_WARNING, SEVERITY_ERROR, OVERRIDE_METHOD_MSG } = require('./constants')
6
- const { hasOptionValue, getProperty, relativePaths, BuildMessage } = require('./util')
6
+ const { hasOptionValue, getProperty, relativePaths, copy, BuildMessage } = require('./util')
7
7
 
8
8
  /**
9
9
  * The build task handler creates the build output for a dedicated build task. It is uniquely identified
@@ -157,7 +157,7 @@ class BuildTaskHandler {
157
157
  if (fs.cp) { // Node.js >= 16.7
158
158
  return fs.cp(src, dest, { recursive: true })
159
159
  }
160
- return this._copy(src, dest)
160
+ return copy(src, dest)
161
161
  }
162
162
  return dest
163
163
  }
@@ -184,7 +184,7 @@ class BuildTaskHandler {
184
184
  async model() {
185
185
  const files = this._resolveModel()
186
186
  if (!files || files.length === 0) {
187
- this._logger.log("no model found, skip build")
187
+ this._logger.log("no CDS model found")
188
188
  return null
189
189
  }
190
190
  this._logger._debug && this._logger.debug(`model: ${relativePaths(this._buildOptions.root, files).join(", ")}`)
@@ -237,16 +237,5 @@ class BuildTaskHandler {
237
237
  }
238
238
  return getProperty(this._buildOptions, qualifiedName)
239
239
  }
240
-
241
- // Asynchronously copies the entire content from src to dest.
242
- async _copy(src, dest) {
243
- if ((await fs.stat(src)).isDirectory()) {
244
- const entries = await fs.readdir(src)
245
- return Promise.all(entries.map(async each => this._copy(path.join(src, each), path.join(dest, each))))
246
- } else {
247
- await fs.mkdir(path.dirname(dest), { recursive: true })
248
- return fs.copyFile(src, dest)
249
- }
250
- }
251
240
  }
252
241
  module.exports = BuildTaskHandler
@@ -13,7 +13,7 @@ module.exports = Object.assign(build,
13
13
  /**
14
14
  * New modular build.
15
15
  *
16
- * @param {object} options - commmand options as defined by build command.
16
+ * @param {object} options - command options as defined by build command.
17
17
  */
18
18
  async function build(options = {}) {
19
19
  const projectPath = path.resolve(options.project || '.')
@@ -22,6 +22,7 @@ async function build(options = {}) {
22
22
  }
23
23
 
24
24
  const cds = require('./cds')
25
+ const cdsEnv = cds.env, cdsRoot = cds.root
25
26
  if (projectPath !== process.cwd()) {
26
27
  const env = cds.env.for('cds', projectPath);
27
28
  cds.env = env // REVISIT: not good / fragile
@@ -31,17 +32,22 @@ async function build(options = {}) {
31
32
  const buildOptions = _mergeCliOptions({ root: projectPath }, options)
32
33
  const buildTaskFactory = new BuildTaskFactory(logger)
33
34
  const buildTaskEngine = new BuildTaskEngine(logger)
35
+ let buildResult
34
36
 
35
37
  try {
36
38
  const tasks = await buildTaskFactory.getTasks(buildOptions)
37
- return buildTaskEngine.processTasks(tasks, buildOptions)
39
+ buildResult = await buildTaskEngine.processTasks(tasks, buildOptions)
38
40
  } catch (e) {
39
41
  // cds CLI layer logs if invoked from CLI
40
42
  if (!buildOptions.cli) {
41
43
  buildTaskEngine._logMessages(buildOptions, [e])
42
44
  }
43
45
  throw e
46
+ } finally {
47
+ cds.root = cdsRoot
48
+ cds.env = cdsEnv
44
49
  }
50
+ return buildResult
45
51
  }
46
52
 
47
53
  function _mergeCliOptions(buildOptions, options) {
@@ -191,6 +191,14 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
191
191
  }
192
192
  this.logger.debug("determining mtx version of nodejs project")
193
193
 
194
+ // preserve order of creation
195
+ if (BuildTaskProviderInternal._isMtxExtension()) {
196
+ this.logger.debug("Streamlined MTX extension app")
197
+ return {
198
+ for: BUILD_TASK_MTX_EXTENSION
199
+ }
200
+ }
201
+
194
202
  if (isStreamlinedMtx()) {
195
203
  if (cds.env.requires["cds.xt.ModelProviderService"]?.kind === "rest") { // "cds.xt.ModelProviderService": "from-sidecar"
196
204
  this.logger.debug("Nodejs Streamlined MTX app with sidecar")
@@ -220,13 +228,6 @@ class BuildTaskProviderInternal extends BuildTaskProvider {
220
228
  }
221
229
  }
222
230
 
223
- if (BuildTaskProviderInternal._isMtxExtension()) {
224
- this.logger.debug("Streamlined MTX extension app")
225
- return {
226
- for: BUILD_TASK_MTX_EXTENSION
227
- }
228
- }
229
-
230
231
  if (cds.env.requires.multitenancy) {
231
232
  this.logger.debug("Nodejs Classic MTX app without sidecar")
232
233
  return {
@@ -3,6 +3,9 @@
3
3
  "dependencies": {
4
4
  "@sap/hdi-deploy": "^4"
5
5
  },
6
+ "engines": {
7
+ "node": "^14 || ^16 || ^18"
8
+ },
6
9
  "scripts": {
7
10
  "start": "node node_modules/@sap/hdi-deploy/deploy.js"
8
11
  }
@@ -21,12 +21,21 @@ class ResourcesTarBuilder {
21
21
  this.handler.pushMessage("No deployment resources found - skip resources.tgz", WARNING)
22
22
  return
23
23
  }
24
- await this.writeTarFile(resources, root, path.join(dest, DEFAULT_TAR_NAME))
24
+ await this.writeTarFile(path.join(dest, DEFAULT_TAR_NAME), root, resources)
25
25
  }
26
26
 
27
- async writeTarFile(resources, root, tarFile) {
27
+ /**
28
+ * Creates a TAR file at the given absolute tarPath. An optional resources list holds the files and folders
29
+ * that will be added to the TAR. Paths are relative to the passed root directory. If omitted, the entire
30
+ * root directory contents will be added.
31
+ * @param {*} tarFile Absolute TAR file name.
32
+ * @param {*} root The root directory the passed resources are relative to.
33
+ * @param {*} resources Optional list of absolute or relative resource paths - relative to the given root directory.
34
+ * If omitted all resources contained in the root directory are added to the TAR file.
35
+ */
36
+ async writeTarFile(tarFile, root, resources) {
28
37
  const { tar } = require('../../../../lib').utils
29
- await tar.czfd(tarFile, root, resources) // REVISIT: tar.czfd was created for this case only -> it ensures the target's dir exists
38
+ await tar.czfd(tarFile, root, resources)
30
39
  this.handler.pushFile(tarFile)
31
40
  }
32
41
 
@@ -37,7 +46,7 @@ class ResourcesTarBuilder {
37
46
  if (root) {
38
47
  resources = this._getHanaResources(root)
39
48
  } else {
40
- root = path.join(this.handler.buildOptions.root, cds.env.folders.db)
49
+ root = this.handler.buildOptions.root
41
50
  resources = await this._getSqliteResources(model)
42
51
  }
43
52
  return { root, resources }