@sap/cds 9.3.1 → 9.4.3

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 (80) hide show
  1. package/CHANGELOG.md +63 -3
  2. package/_i18n/i18n_vi.properties +113 -0
  3. package/_i18n/messages.properties +106 -17
  4. package/_i18n/messages_ar.properties +194 -0
  5. package/_i18n/messages_bg.properties +194 -0
  6. package/_i18n/messages_cs.properties +194 -0
  7. package/_i18n/messages_da.properties +194 -0
  8. package/_i18n/messages_de.properties +194 -0
  9. package/_i18n/messages_el.properties +194 -0
  10. package/_i18n/messages_en.properties +194 -0
  11. package/_i18n/messages_en_US_saptrc.properties +194 -0
  12. package/_i18n/messages_es.properties +194 -0
  13. package/_i18n/messages_es_MX.properties +194 -0
  14. package/_i18n/messages_fi.properties +194 -0
  15. package/_i18n/messages_fr.properties +194 -0
  16. package/_i18n/messages_he.properties +194 -0
  17. package/_i18n/messages_hr.properties +194 -0
  18. package/_i18n/messages_hu.properties +194 -0
  19. package/_i18n/messages_it.properties +194 -0
  20. package/_i18n/messages_ja.properties +194 -0
  21. package/_i18n/messages_kk.properties +194 -0
  22. package/_i18n/messages_ko.properties +194 -0
  23. package/_i18n/messages_ms.properties +194 -0
  24. package/_i18n/messages_nl.properties +194 -0
  25. package/_i18n/messages_no.properties +194 -0
  26. package/_i18n/messages_pl.properties +194 -0
  27. package/_i18n/messages_pt.properties +194 -0
  28. package/_i18n/messages_ro.properties +194 -0
  29. package/_i18n/messages_ru.properties +194 -0
  30. package/_i18n/messages_sh.properties +194 -0
  31. package/_i18n/messages_sk.properties +194 -0
  32. package/_i18n/messages_sl.properties +194 -0
  33. package/_i18n/messages_sv.properties +194 -0
  34. package/_i18n/messages_th.properties +194 -0
  35. package/_i18n/messages_tr.properties +194 -0
  36. package/_i18n/messages_uk.properties +194 -0
  37. package/_i18n/messages_vi.properties +194 -0
  38. package/_i18n/messages_zh_CN.properties +194 -0
  39. package/_i18n/messages_zh_TW.properties +194 -0
  40. package/bin/serve.js +9 -1
  41. package/common.cds +9 -1
  42. package/lib/compile/cds-compile.js +1 -0
  43. package/lib/compile/etc/properties.js +1 -0
  44. package/lib/compile/for/flows.js +70 -4
  45. package/lib/compile/for/nodejs.js +1 -1
  46. package/lib/compile/minify.js +84 -56
  47. package/lib/compile/to/csn.js +2 -0
  48. package/lib/compile/to/yaml.js +1 -1
  49. package/lib/env/cds-requires.js +3 -0
  50. package/lib/i18n/bundles.js +8 -1
  51. package/lib/i18n/files.js +5 -1
  52. package/lib/i18n/index.js +1 -5
  53. package/lib/i18n/localize.js +4 -2
  54. package/lib/index.js +1 -1
  55. package/lib/ql/SELECT.js +16 -19
  56. package/lib/req/validate.js +10 -5
  57. package/lib/srv/bindings.js +1 -1
  58. package/lib/srv/cds-serve.js +1 -1
  59. package/lib/srv/middlewares/auth/ias-auth.js +3 -2
  60. package/lib/srv/middlewares/auth/jwt-auth.js +3 -2
  61. package/lib/srv/middlewares/errors.js +2 -1
  62. package/lib/srv/protocols/hcql.js +8 -6
  63. package/lib/srv/srv-dispatch.js +4 -8
  64. package/lib/srv/srv-handlers.js +28 -1
  65. package/lib/utils/colors.js +54 -49
  66. package/libx/_runtime/common/generic/flows.js +79 -12
  67. package/libx/_runtime/common/generic/input.js +12 -2
  68. package/libx/_runtime/fiori/lean-draft.js +10 -2
  69. package/libx/_runtime/messaging/common-utils/connections.js +31 -18
  70. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +2 -2
  71. package/libx/_runtime/messaging/redis-messaging.js +1 -1
  72. package/libx/_runtime/ucl/Service.js +5 -5
  73. package/libx/http/body-parser.js +10 -1
  74. package/libx/odata/ODataAdapter.js +10 -7
  75. package/libx/odata/middleware/error.js +3 -0
  76. package/libx/odata/parse/afterburner.js +13 -16
  77. package/libx/odata/parse/multipartToJson.js +3 -1
  78. package/libx/rest/middleware/parse.js +1 -1
  79. package/package.json +2 -2
  80. package/server.js +1 -1
@@ -0,0 +1,194 @@
1
+ # Input Validation
2
+
3
+ #XMSG: Enter a value between 0 and 100. // Implementation still provides 3 values
4
+ ASSERT_RANGE=\u8F93\u5165\u4E00\u4E2A\u4ECB\u4E8E {1} \u548C {2} \u4E4B\u95F4\u7684\u503C\u3002
5
+ #XMSG: Enter a valuematching the pattern /^abc/.
6
+ ASSERT_FORMAT=\u8F93\u5165\u4E00\u4E2A\u7B26\u5408\u6A21\u5F0F {1} \u7684\u503C\u3002
7
+ #XMSG: Enter one of the allowed values: High,Medium,Low. // Implementation still provides 2 values
8
+ ASSERT_ENUM=\u8F93\u5165\u5176\u4E2D\u4E00\u4E2A\u5141\u8BB8\u7684\u503C\uFF1A{1}\u3002
9
+ #XMSG: Provide the missing value. // Error text displayed on a field, in case a mandatory value is not set.
10
+ ASSERT_MANDATORY=\u63D0\u4F9B\u7F3A\u5C11\u7684\u503C\u3002
11
+ #XMSG: Target with this key doesn't exist.
12
+ ASSERT_TARGET=\u5177\u6709\u6B64\u952E\u503C\u7684\u76EE\u6807\u4E0D\u5B58\u5728\u3002
13
+
14
+ # Aggregating Error
15
+
16
+ #XMSG
17
+ MULTIPLE_ERRORS=\u51FA\u73B0\u591A\u4E2A\u9519\u8BEF\uFF0C\u8BF7\u53C2\u9605\u4E0B\u9762\u7684\u8BE6\u7EC6\u4FE1\u606F\u3002
18
+
19
+ # Input format
20
+
21
+ #NOTR
22
+ ASSERT_VALID_ELEMENT=Element is not valid
23
+ #NOTR
24
+ ASSERT_DATA_TYPE=Value {0} is not a valid {1}
25
+ #NOTR
26
+ ASSERT_ARRAY=Value must be an array
27
+
28
+ # Status Codes
29
+
30
+ #NOTR
31
+ 400=Bad Request
32
+ #NOTR
33
+ 401=Unauthorized
34
+ #NOTR
35
+ 403=Forbidden
36
+ #NOTR
37
+ 404=Not Found
38
+ #NOTR
39
+ 405=Method Not Allowed
40
+ #NOTR
41
+ 406=Not Acceptable
42
+ #NOTR
43
+ 407=Proxy Authentication Required
44
+ #NOTR
45
+ 408=Request Timeout
46
+ #NOTR
47
+ 409=Conflict
48
+ #NOTR
49
+ 410=Gone
50
+ #NOTR
51
+ 411=Length Required
52
+ #NOTR
53
+ 412=Precondition Failed
54
+ #NOTR
55
+ 413=Payload Too Large
56
+ #NOTR
57
+ 414=URI Too Long
58
+ #NOTR
59
+ 415=Unsupported Media Type
60
+ #NOTR
61
+ 416=Range Not Satisfiable
62
+ #NOTR
63
+ 417=Expectation Failed
64
+ #NOTR
65
+ 422=Unprocessable Content
66
+ #NOTR
67
+ 424=Failed Dependency
68
+ #NOTR
69
+ 428=Precondition Required
70
+ #NOTR
71
+ 429=Too Many Requests
72
+ #NOTR
73
+ 431=Request Header Fields Too Large
74
+ #NOTR
75
+ 451=Unavailable For Legal Reasons
76
+ #NOTR
77
+ 500=Internal Server Error
78
+ #NOTR
79
+ 501=The server does not support the functionality required to fulfill the request
80
+ #NOTR
81
+ 502=Bad Gateway
82
+ #NOTR
83
+ 503=Service Unavailable
84
+ #NOTR
85
+ 504=Gateway Timeout
86
+
87
+ # fragments
88
+
89
+ #NOTR
90
+ ENTITY=entity
91
+ #NOTR
92
+ TYPE=type
93
+ #NOTR
94
+ FUNCTION=function
95
+ #NOTR
96
+ ACTION=action
97
+
98
+ # db
99
+
100
+ #NOTR
101
+ NO_DATABASE_CONNECTION=No database connection
102
+ #NOTR
103
+ ENTITY_ALREADY_EXISTS=Entity already exists
104
+ #NOTR
105
+ ENTITY_LOCKED=Entity locked
106
+ #NOTR
107
+ UNIQUE_CONSTRAINT_VIOLATION=Unique constraint violation
108
+ #NOTR
109
+ FK_CONSTRAINT_VIOLATION=Foreign key constraint violation
110
+
111
+ # remote
112
+
113
+ #NOTR
114
+ INVALID_CONTENT_TYPE_ONLY_JSON=Invalid content type. Only "application/json" is supported.
115
+
116
+ # access control
117
+
118
+ #NOTR
119
+ INSERTABLE=insertable
120
+ #NOTR
121
+ READABLE=readable
122
+ #NOTR
123
+ UPDATABLE=updatable
124
+ #NOTR
125
+ DELETABLE=deletable
126
+ #NOTR
127
+ ENTITY_IS_INSERT_ONLY=Entity "{0}" is insert-only
128
+ #NOTR
129
+ ENTITY_IS_READ_ONLY=Entity "{0}" is read-only
130
+ #NOTR
131
+ ENTITY_IS_NOT_CRUD=Entity "{0}" is not {1}
132
+ #NOTR
133
+ ENTITY_IS_NOT_CRUD_VIA_NAVIGATION=Entity "{0}" is not {1} via navigation "{2}"
134
+ #NOTR
135
+ ENTITY_IS_AUTOEXPOSED=Entity "{0}" is not explicitly exposed as part of the service
136
+ #NOTR
137
+ ENTITY_IS_AUTOEXPOSE_READONLY=Entity "{0}" is explicitly exposed as readonly
138
+ #NOTR
139
+ EXPAND_IS_RESTRICTED=Navigation property "{0}" is not allowed for expand operation
140
+
141
+ # rest protocol adapter
142
+
143
+ #NOTR
144
+ INVALID_RESOURCE="{0}" is not a valid resource
145
+ #NOTR
146
+ INVALID_PARAMETER="{0}" is not a valid parameter
147
+ #NOTR
148
+ INVALID_PARAMETER_VALUE_TYPE=Parameter value for "{0}" must be of type "{1}"
149
+ #NOTR
150
+ INVALID_OPERATION_FOR_ENTITY=Entity "{0}" has no {1} "{2}"
151
+ #NOTR
152
+ NO_MATCHING_RESOURCE=The server has not found a resource matching the requested URI
153
+ #NOTR
154
+ INVALID_POST=POST is only allowed on resource collections and actions
155
+ #NOTR
156
+ INVALID_PUT=PUT is only allowed on a specific resource
157
+ #NOTR
158
+ INVALID_PATCH=PATCH is only allowed on a specific resource
159
+ #NOTR
160
+ INVALID_DELETE=DELETE is only supported on a specific resource
161
+ #NOTR
162
+ CRUD_VIA_NAVIGATION_NOT_SUPPORTED=CRUD via navigations is not yet supported
163
+
164
+ # OData protocol adapter
165
+
166
+ #NOTR
167
+ BATCH_TOO_MANY_REQ=Batch request contains too many requests
168
+
169
+ # draft
170
+
171
+ #NOTR
172
+ DRAFT_LOCKED_BY_ANOTHER_USER=The entity is locked by user "{0}"
173
+ #NOTR
174
+ DRAFT_ALREADY_EXISTS=A draft for this entity already exists
175
+ #NOTR
176
+ DRAFT_NOT_EXISTING=No draft for this entity exists
177
+ #NOTR
178
+ DRAFT_MODIFICATION_ONLY_VIA_ROOT=A draft-enabled entity can only be modified via its root entity
179
+ #NOTR
180
+ ACTIVE_MODIFICATION_VIA_DRAFT=Active entities cannot be modified via draft request
181
+ #NOTR
182
+ DRAFT_ACTIVE_DELETE_FORBIDDEN_DRAFT_EXISTS=Entity cannot be deleted because a draft exists
183
+
184
+ # singleton
185
+
186
+ #NOTR
187
+ SINGLETON_NOT_NULLABLE=The singleton entity is not nullable
188
+
189
+ # flows
190
+
191
+ #XMSG: Action "acceptTravel" requires "travelStatus" to be "Open".
192
+ INVALID_FLOW_TRANSITION_SINGLE=\u64CD\u4F5C "{0}" \u8981\u6C42 "{1}" \u5FC5\u987B\u4E3A "{2}"\u3002
193
+ #XMSG: Action "cancelTravel" requires "travelStatus" to be one of the following values: Open,Accepted.
194
+ INVALID_FLOW_TRANSITION_MULTI=\u64CD\u4F5C "{0}" \u8981\u6C42 "{1}" \u5FC5\u987B\u4E3A\u4EE5\u4E0B\u503C\u4E4B\u4E00\uFF1A{2}\u3002
@@ -0,0 +1,194 @@
1
+ # Input Validation
2
+
3
+ #XMSG: Enter a value between 0 and 100. // Implementation still provides 3 values
4
+ ASSERT_RANGE=\u8ACB\u8F38\u5165\u4ECB\u65BC {1} \u5230 {2} \u4E4B\u9593\u7684\u503C\u3002
5
+ #XMSG: Enter a valuematching the pattern /^abc/.
6
+ ASSERT_FORMAT=\u8ACB\u8F38\u5165\u7B26\u5408\u6A21\u5F0F {1} \u7684\u503C\u3002
7
+ #XMSG: Enter one of the allowed values: High,Medium,Low. // Implementation still provides 2 values
8
+ ASSERT_ENUM=\u8ACB\u8F38\u5165\u5176\u4E2D\u4E00\u500B\u5141\u8A31\u7684\u503C\uFF1A{1}\u3002
9
+ #XMSG: Provide the missing value. // Error text displayed on a field, in case a mandatory value is not set.
10
+ ASSERT_MANDATORY=\u8ACB\u63D0\u4F9B\u7F3A\u5C11\u7684\u503C\u3002
11
+ #XMSG: Target with this key doesn't exist.
12
+ ASSERT_TARGET=\u542B\u6709\u6B64\u9375\u503C\u7684\u76EE\u6A19\u4E0D\u5B58\u5728\u3002
13
+
14
+ # Aggregating Error
15
+
16
+ #XMSG
17
+ MULTIPLE_ERRORS=\u767C\u751F\u591A\u500B\u932F\u8AA4\uFF0C\u8ACB\u67E5\u770B\u4E0B\u65B9\u8A73\u7D30\u8CC7\u6599\u3002
18
+
19
+ # Input format
20
+
21
+ #NOTR
22
+ ASSERT_VALID_ELEMENT=Element is not valid
23
+ #NOTR
24
+ ASSERT_DATA_TYPE=Value {0} is not a valid {1}
25
+ #NOTR
26
+ ASSERT_ARRAY=Value must be an array
27
+
28
+ # Status Codes
29
+
30
+ #NOTR
31
+ 400=Bad Request
32
+ #NOTR
33
+ 401=Unauthorized
34
+ #NOTR
35
+ 403=Forbidden
36
+ #NOTR
37
+ 404=Not Found
38
+ #NOTR
39
+ 405=Method Not Allowed
40
+ #NOTR
41
+ 406=Not Acceptable
42
+ #NOTR
43
+ 407=Proxy Authentication Required
44
+ #NOTR
45
+ 408=Request Timeout
46
+ #NOTR
47
+ 409=Conflict
48
+ #NOTR
49
+ 410=Gone
50
+ #NOTR
51
+ 411=Length Required
52
+ #NOTR
53
+ 412=Precondition Failed
54
+ #NOTR
55
+ 413=Payload Too Large
56
+ #NOTR
57
+ 414=URI Too Long
58
+ #NOTR
59
+ 415=Unsupported Media Type
60
+ #NOTR
61
+ 416=Range Not Satisfiable
62
+ #NOTR
63
+ 417=Expectation Failed
64
+ #NOTR
65
+ 422=Unprocessable Content
66
+ #NOTR
67
+ 424=Failed Dependency
68
+ #NOTR
69
+ 428=Precondition Required
70
+ #NOTR
71
+ 429=Too Many Requests
72
+ #NOTR
73
+ 431=Request Header Fields Too Large
74
+ #NOTR
75
+ 451=Unavailable For Legal Reasons
76
+ #NOTR
77
+ 500=Internal Server Error
78
+ #NOTR
79
+ 501=The server does not support the functionality required to fulfill the request
80
+ #NOTR
81
+ 502=Bad Gateway
82
+ #NOTR
83
+ 503=Service Unavailable
84
+ #NOTR
85
+ 504=Gateway Timeout
86
+
87
+ # fragments
88
+
89
+ #NOTR
90
+ ENTITY=entity
91
+ #NOTR
92
+ TYPE=type
93
+ #NOTR
94
+ FUNCTION=function
95
+ #NOTR
96
+ ACTION=action
97
+
98
+ # db
99
+
100
+ #NOTR
101
+ NO_DATABASE_CONNECTION=No database connection
102
+ #NOTR
103
+ ENTITY_ALREADY_EXISTS=Entity already exists
104
+ #NOTR
105
+ ENTITY_LOCKED=Entity locked
106
+ #NOTR
107
+ UNIQUE_CONSTRAINT_VIOLATION=Unique constraint violation
108
+ #NOTR
109
+ FK_CONSTRAINT_VIOLATION=Foreign key constraint violation
110
+
111
+ # remote
112
+
113
+ #NOTR
114
+ INVALID_CONTENT_TYPE_ONLY_JSON=Invalid content type. Only "application/json" is supported.
115
+
116
+ # access control
117
+
118
+ #NOTR
119
+ INSERTABLE=insertable
120
+ #NOTR
121
+ READABLE=readable
122
+ #NOTR
123
+ UPDATABLE=updatable
124
+ #NOTR
125
+ DELETABLE=deletable
126
+ #NOTR
127
+ ENTITY_IS_INSERT_ONLY=Entity "{0}" is insert-only
128
+ #NOTR
129
+ ENTITY_IS_READ_ONLY=Entity "{0}" is read-only
130
+ #NOTR
131
+ ENTITY_IS_NOT_CRUD=Entity "{0}" is not {1}
132
+ #NOTR
133
+ ENTITY_IS_NOT_CRUD_VIA_NAVIGATION=Entity "{0}" is not {1} via navigation "{2}"
134
+ #NOTR
135
+ ENTITY_IS_AUTOEXPOSED=Entity "{0}" is not explicitly exposed as part of the service
136
+ #NOTR
137
+ ENTITY_IS_AUTOEXPOSE_READONLY=Entity "{0}" is explicitly exposed as readonly
138
+ #NOTR
139
+ EXPAND_IS_RESTRICTED=Navigation property "{0}" is not allowed for expand operation
140
+
141
+ # rest protocol adapter
142
+
143
+ #NOTR
144
+ INVALID_RESOURCE="{0}" is not a valid resource
145
+ #NOTR
146
+ INVALID_PARAMETER="{0}" is not a valid parameter
147
+ #NOTR
148
+ INVALID_PARAMETER_VALUE_TYPE=Parameter value for "{0}" must be of type "{1}"
149
+ #NOTR
150
+ INVALID_OPERATION_FOR_ENTITY=Entity "{0}" has no {1} "{2}"
151
+ #NOTR
152
+ NO_MATCHING_RESOURCE=The server has not found a resource matching the requested URI
153
+ #NOTR
154
+ INVALID_POST=POST is only allowed on resource collections and actions
155
+ #NOTR
156
+ INVALID_PUT=PUT is only allowed on a specific resource
157
+ #NOTR
158
+ INVALID_PATCH=PATCH is only allowed on a specific resource
159
+ #NOTR
160
+ INVALID_DELETE=DELETE is only supported on a specific resource
161
+ #NOTR
162
+ CRUD_VIA_NAVIGATION_NOT_SUPPORTED=CRUD via navigations is not yet supported
163
+
164
+ # OData protocol adapter
165
+
166
+ #NOTR
167
+ BATCH_TOO_MANY_REQ=Batch request contains too many requests
168
+
169
+ # draft
170
+
171
+ #NOTR
172
+ DRAFT_LOCKED_BY_ANOTHER_USER=The entity is locked by user "{0}"
173
+ #NOTR
174
+ DRAFT_ALREADY_EXISTS=A draft for this entity already exists
175
+ #NOTR
176
+ DRAFT_NOT_EXISTING=No draft for this entity exists
177
+ #NOTR
178
+ DRAFT_MODIFICATION_ONLY_VIA_ROOT=A draft-enabled entity can only be modified via its root entity
179
+ #NOTR
180
+ ACTIVE_MODIFICATION_VIA_DRAFT=Active entities cannot be modified via draft request
181
+ #NOTR
182
+ DRAFT_ACTIVE_DELETE_FORBIDDEN_DRAFT_EXISTS=Entity cannot be deleted because a draft exists
183
+
184
+ # singleton
185
+
186
+ #NOTR
187
+ SINGLETON_NOT_NULLABLE=The singleton entity is not nullable
188
+
189
+ # flows
190
+
191
+ #XMSG: Action "acceptTravel" requires "travelStatus" to be "Open".
192
+ INVALID_FLOW_TRANSITION_SINGLE=\u52D5\u4F5C "{0}" \u9700\u8981 "{1}" \u662F "{2}"\u3002
193
+ #XMSG: Action "cancelTravel" requires "travelStatus" to be one of the following values: Open,Accepted.
194
+ INVALID_FLOW_TRANSITION_MULTI=\u52D5\u4F5C "{0}" \u9700\u8981 "{1}" \u662F\u4E0B\u5217\u5176\u4E2D\u4E00\u500B\u503C\uFF1A{2}\u3002
package/bin/serve.js CHANGED
@@ -8,7 +8,7 @@ module.exports = exports = Object.assign ( serve, {
8
8
  '--project', '--projects',
9
9
  '--in-memory', '--in-memory?',
10
10
  '--mocked', '--with-mocks', '--with-bindings', '--resolve-bindings',
11
- '--watch',
11
+ '--watch', '--with-mtx',
12
12
  ],
13
13
  shortcuts: [ '-s', undefined, '-2', '-a', '-w', undefined, undefined, '-p' ],
14
14
  help: `
@@ -75,6 +75,10 @@ module.exports = exports = Object.assign ( serve, {
75
75
  You can use *cds watch* as shortcut, which is equivalent to:
76
76
  *cds serve --with-mocks --in-memory? --watch --project ...*
77
77
 
78
+ *--with-mtx*
79
+
80
+ A shortcut for _--profile with-mtx_ to enable MTX features.
81
+
78
82
  *--workers* <number> | true
79
83
 
80
84
  Spawns <number> of worker processes in a cluster to handle incoming requests.
@@ -168,6 +172,10 @@ async function serve (all=[], o={}) {
168
172
  // let plugins know about the CLI
169
173
  cds.cli = { command: 'serve', argv: all, options: o }
170
174
 
175
+ // Enable mtx features also in dev mode, if asked to
176
+ if (o['with-mtx'])
177
+ process.env.CDS_ENV = process.env.CDS_ENV ? process.env.CDS_ENV + ',with-mtx' : 'with-mtx'
178
+
171
179
  // Ensure loading plugins before calling cds.env!
172
180
  await cds.plugins
173
181
 
package/common.cds CHANGED
@@ -96,6 +96,15 @@ context sap.common {
96
96
  aspect TextsAspect {
97
97
  key locale: Locale;
98
98
  }
99
+
100
+ aspect FlowHistory {
101
+ transitions_ : Composition of many {
102
+ key timestamp : managed:createdAt;
103
+ user : managed:createdBy;
104
+ status : String;
105
+ comment : String;
106
+ }
107
+ }
99
108
  }
100
109
 
101
110
 
@@ -130,7 +139,6 @@ aspect temporal {
130
139
  validTo : Timestamp @cds.valid.to;
131
140
  }
132
141
 
133
-
134
142
  /**
135
143
  * Canonical user ID
136
144
  */
@@ -7,6 +7,7 @@ const compile = module.exports = Object.assign (cds_compile, {
7
7
  get java(){ return super.java = require('./for/java') }
8
8
  get nodejs() { return super.nodejs = require('./for/nodejs') }
9
9
  get lean_drafts() { return super.lean_drafts = require('./for/lean_drafts') }
10
+ get flows() { return super.flows = require('./for/flows') }
10
11
  get odata() { return super.odata = require('./for/odata') }
11
12
  get sql() { return super.sql = require('./for/sql') }
12
13
  },
@@ -40,4 +40,5 @@ function string4 (raw) {
40
40
  return raw
41
41
  .replace(/''/g,"'") .replace(/^"(.*)"$/,"$1") .replace(/^'(.*)'$/,"$1")
42
42
  .replace(/\\u[\dA-F]{4}/gi, (match) => String.fromCharCode(parseInt(match.replace(/\\u/g, ''), 16)))
43
+ .replace(/\\(.)/g, (_, seq) => ({ n: '\n', r: '\r', t: '\t', f: '\f' }[seq] ?? seq))
43
44
  }
@@ -8,17 +8,20 @@ const TO = '@to'
8
8
  // backwards compat
9
9
  const FLOW_FROM = '@flow.from'
10
10
  const FLOW_TO = '@flow.to'
11
+ const FLOW_PREVIOUS = '$flow.previous'
11
12
 
12
13
  const getFrom = action => {
13
14
  let from = action[FROM] ?? action[FLOW_FROM]
14
- from = Array.isArray(from) ? from : [from]
15
- return from.map(f => f['#'] ?? f['='] ?? f)
15
+ return Array.isArray(from) ? from : [from]
16
16
  }
17
17
 
18
18
  function addOperationAvailableToActions(actions, statusEnum, statusElementName) {
19
19
  for (const action of Object.values(actions)) {
20
20
  const fromList = getFrom(action)
21
- const conditions = fromList.map(from => `$self.${statusElementName} = '${statusEnum[from].val ?? from}'`)
21
+ const conditions = fromList.map(from => {
22
+ const value = from['#'] ? (statusEnum[from['#']]?.val ?? from['#']) : from
23
+ return `$self.${statusElementName} = ${typeof value === 'string' ? `'${value}'` : value}`
24
+ })
22
25
  const condition = `(${conditions.join(' OR ')})`
23
26
  const parsedXpr = cds.parse.expr(condition)
24
27
  action['@Core.OperationAvailable'] ??= {
@@ -99,4 +102,67 @@ function enhanceCSNwithFlowAnnotations4FE(csn) {
99
102
  }
100
103
  }
101
104
 
102
- module.exports = { enhanceCSNwithFlowAnnotations4FE, getFrom }
105
+ module.exports = function cds_compile_for_flows(csn) {
106
+ let flowHistory
107
+
108
+ for (const name in csn.definitions) {
109
+ const def = csn.definitions[name]
110
+
111
+ if (!def.kind || def.kind !== 'entity' || !def.actions || def.elements?.transitions_) continue
112
+
113
+ let history
114
+ if (cds.env.features.history_for_flows === 'all') {
115
+ for (const each in def.elements) {
116
+ if (def.elements[each]['@flow.status']) {
117
+ history = true
118
+ break
119
+ }
120
+ }
121
+ } else {
122
+ for (const each in def.actions) {
123
+ const action = def.actions[each]
124
+ if (action && (action[TO]?.['='] === FLOW_PREVIOUS || action[FLOW_TO]?.['='] === FLOW_PREVIOUS)) {
125
+ history = true
126
+ break
127
+ }
128
+ }
129
+ }
130
+ if (!history) continue
131
+
132
+ flowHistory ??= csn.definitions['sap.common.FlowHistory']
133
+ if (!flowHistory) cds.error('Cannot find definition sap.common.FlowHistory')
134
+
135
+ const { elements: aspectElements } = flowHistory.elements.transitions_.targetAspect
136
+
137
+ def.includes ??= []
138
+ def.includes.push('sap.common.FlowHistory')
139
+ def.elements.transitions_ = JSON.parse(`{
140
+ "type": "cds.Composition",
141
+ "cardinality": { "max": "*" },
142
+ "targetAspect": { "elements": ${JSON.stringify(aspectElements)} },
143
+ "target": "${name}.transitions_",
144
+ "on": [{ "ref": ["transitions_", "up_"] }, "=", { "ref": ["$self"] }]
145
+ }`)
146
+
147
+ const def_keys = Object.keys(def.elements)
148
+ .filter(k => def.elements[k].key)
149
+ .map(k => ({ ref: [k] }))
150
+ csn.definitions[`${name}.transitions_`] = JSON.parse(`{
151
+ "kind": "entity",
152
+ "elements": {
153
+ "up_": {
154
+ "key": true,
155
+ "type": "cds.Association",
156
+ "cardinality": { "min": 1, "max": 1 },
157
+ "target": "${name}",
158
+ "keys": ${JSON.stringify(def_keys)},
159
+ "notNull": true
160
+ },
161
+ ${JSON.stringify(aspectElements).slice(1, -1)}
162
+ }
163
+ }`)
164
+ }
165
+ }
166
+
167
+ module.exports.enhanceCSNwithFlowAnnotations4FE = enhanceCSNwithFlowAnnotations4FE
168
+ module.exports.getFrom = getFrom
@@ -8,7 +8,7 @@ function _compile_for_nodejs (csn, o) {
8
8
  let dsn = cds.compile.for.odata(min, o) //> creates a partial copy -> avoid any cds.linked() before
9
9
  dsn = unfold_csn(dsn)
10
10
  dsn = cds.linked(dsn)
11
- cds.compile.for.lean_drafts(dsn, o)
11
+ cds.compile.for.lean_drafts(dsn)
12
12
 
13
13
  // @Common.Text → @cds.search
14
14
  text_to_search: for (const name in dsn.definitions) {