@sap/cds 5.8.2 → 5.9.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 (252) hide show
  1. package/CHANGELOG.md +214 -78
  2. package/app/fiori/preview.js +16 -11
  3. package/app/fiori/routes.js +3 -0
  4. package/app/index.js +1 -1
  5. package/bin/build/buildTaskFactory.js +3 -3
  6. package/bin/build/buildTaskProviderFactory.js +1 -1
  7. package/bin/build/constants.js +1 -1
  8. package/bin/build/provider/buildTaskHandlerEdmx.js +12 -7
  9. package/bin/build/provider/buildTaskHandlerInternal.js +1 -1
  10. package/bin/build/provider/buildTaskProviderInternal.js +8 -2
  11. package/bin/build/provider/hana/2migration.js +27 -24
  12. package/bin/build/provider/hana/index.js +17 -18
  13. package/bin/build/provider/hana/migrationtable.js +9 -10
  14. package/bin/build/provider/java-cf/index.js +4 -5
  15. package/bin/build/provider/node-cf/index.js +99 -6
  16. package/bin/cds.js +20 -17
  17. package/bin/deploy/to-hana/cfUtil.js +16 -19
  18. package/bin/deploy/to-hana/hana.js +7 -24
  19. package/bin/deploy/to-hana/hdiDeployUtil.js +8 -4
  20. package/bin/mtx/in-cds.js +2 -2
  21. package/bin/serve.js +12 -5
  22. package/bin/utils/modules.js +7 -0
  23. package/bin/version.js +56 -3
  24. package/lib/compile/cdsc.js +26 -3
  25. package/lib/compile/etc/_localized.js +36 -25
  26. package/lib/compile/etc/csv.js +8 -8
  27. package/lib/compile/for/drafts.js +9 -0
  28. package/lib/compile/for/java.js +16 -0
  29. package/lib/compile/for/nodejs.js +12 -0
  30. package/lib/compile/for/odata.js +1 -1
  31. package/lib/compile/index.js +3 -0
  32. package/lib/compile/minify.js +16 -2
  33. package/lib/compile/parse.js +2 -2
  34. package/lib/compile/resolve.js +35 -18
  35. package/lib/compile/to/json.js +3 -1
  36. package/lib/compile/to/sql.js +2 -2
  37. package/lib/compile/to/srvinfo.js +4 -2
  38. package/lib/connect/index.js +1 -1
  39. package/lib/core/entities.js +15 -14
  40. package/lib/core/index.js +39 -36
  41. package/lib/core/reflect.js +4 -2
  42. package/lib/deploy.js +114 -127
  43. package/lib/env/defaults.js +1 -0
  44. package/lib/env/index.js +165 -165
  45. package/lib/env/presets.js +1 -0
  46. package/lib/env/requires.js +120 -49
  47. package/lib/index.js +1 -0
  48. package/lib/log/format/kibana.js +2 -2
  49. package/lib/ql/SELECT.js +10 -0
  50. package/lib/ql/parse.js +1 -0
  51. package/lib/req/cds-context.js +4 -1
  52. package/lib/req/context.js +50 -56
  53. package/lib/req/event.js +1 -6
  54. package/lib/req/locale.js +6 -5
  55. package/lib/req/request.js +2 -0
  56. package/lib/req/user.js +7 -5
  57. package/lib/serve/Service-api.js +10 -7
  58. package/lib/serve/Service-dispatch.js +9 -11
  59. package/lib/serve/Service-methods.js +30 -41
  60. package/lib/serve/Transaction.js +10 -7
  61. package/lib/serve/adapters.js +7 -5
  62. package/lib/serve/index.js +24 -12
  63. package/lib/utils/data.js +1 -1
  64. package/lib/utils/index.js +27 -30
  65. package/lib/utils/resources/index.js +101 -0
  66. package/lib/utils/resources/tar.js +71 -0
  67. package/lib/utils/resources/utils.js +11 -0
  68. package/libx/_runtime/audit/Service.js +36 -39
  69. package/libx/_runtime/audit/generic/personal/access.js +3 -4
  70. package/libx/_runtime/audit/generic/personal/modification.js +3 -4
  71. package/libx/_runtime/audit/utils/v2.js +1 -2
  72. package/libx/_runtime/auth/index.js +126 -84
  73. package/libx/_runtime/auth/strategies/JWT.js +12 -19
  74. package/libx/_runtime/auth/strategies/dummy.js +1 -5
  75. package/libx/_runtime/auth/strategies/dwc.js +11 -9
  76. package/libx/_runtime/auth/strategies/mock.js +0 -4
  77. package/libx/_runtime/auth/strategies/{utils/xssec.js → xssecUtils.js} +7 -4
  78. package/libx/_runtime/auth/strategies/xsuaa.js +12 -19
  79. package/libx/_runtime/auth/utils.js +22 -1
  80. package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +104 -98
  81. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +2 -2
  82. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -1
  83. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +13 -0
  84. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/language.js +2 -8
  85. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +4 -29
  86. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +2 -1
  87. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +3 -2
  88. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +2 -2
  89. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +4 -6
  90. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/expandToCQN.js +24 -21
  91. package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/index.js +8 -2
  92. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriHelper.js +1 -1
  93. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/DeserializerFactory.js +2 -0
  94. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/ResourceJsonDeserializer.js +5 -6
  95. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/invocation/DispatcherCommand.js +2 -6
  96. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/utils/UriHelper.js +4 -1
  97. package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -12
  98. package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +33 -9
  99. package/libx/_runtime/cds-services/adapter/odata-v4/utils/dispatcherUtils.js +50 -0
  100. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +2 -2
  101. package/libx/_runtime/cds-services/adapter/odata-v4/utils/request.js +10 -3
  102. package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +9 -11
  103. package/libx/_runtime/cds-services/adapter/rest/RestRequest.js +6 -3
  104. package/libx/_runtime/cds-services/adapter/rest/handlers/operation.js +4 -2
  105. package/libx/_runtime/cds-services/adapter/rest/rest-to-cqn/utils.js +1 -1
  106. package/libx/_runtime/cds-services/adapter/rest/utils/binary.js +1 -1
  107. package/libx/_runtime/cds-services/adapter/rest/utils/key-value-utils.js +2 -3
  108. package/libx/_runtime/cds-services/adapter/rest/utils/parse-url.js +6 -4
  109. package/libx/_runtime/cds-services/adapter/rest/utils/result.js +1 -0
  110. package/libx/_runtime/cds-services/adapter/rest/utils/validation-checks.js +8 -5
  111. package/libx/_runtime/cds-services/services/Service.js +40 -0
  112. package/libx/_runtime/cds-services/services/utils/columns.js +4 -3
  113. package/libx/_runtime/cds-services/services/utils/compareJson.js +4 -4
  114. package/libx/_runtime/cds-services/services/utils/differ.js +3 -3
  115. package/libx/_runtime/cds-services/services/utils/handlerUtils.js +4 -4
  116. package/libx/_runtime/cds-services/services/utils/restrictions.js +78 -0
  117. package/libx/_runtime/cds-services/util/assert.js +20 -14
  118. package/libx/_runtime/cds.js +9 -1
  119. package/libx/_runtime/common/aspects/any.js +5 -0
  120. package/libx/_runtime/common/aspects/entity.js +25 -7
  121. package/libx/_runtime/common/aspects/utils.js +2 -2
  122. package/libx/_runtime/common/composition/data.js +6 -0
  123. package/libx/_runtime/common/composition/insert.js +3 -2
  124. package/libx/_runtime/common/composition/tree.js +4 -10
  125. package/libx/_runtime/common/composition/update.js +4 -4
  126. package/libx/_runtime/common/constants/draft.js +29 -26
  127. package/libx/_runtime/common/error/constants.js +2 -2
  128. package/libx/_runtime/common/error/frontend.js +7 -15
  129. package/libx/_runtime/common/generic/auth/capabilities.js +59 -0
  130. package/libx/_runtime/common/generic/auth/constants.js +20 -0
  131. package/libx/_runtime/common/generic/auth/expand.js +54 -0
  132. package/libx/_runtime/common/generic/auth/index.js +32 -0
  133. package/libx/_runtime/common/generic/auth/insertOnly.js +15 -0
  134. package/libx/_runtime/common/generic/auth/readOnly.js +26 -0
  135. package/libx/_runtime/common/generic/auth/requires.js +34 -0
  136. package/libx/_runtime/common/generic/auth/restrict.js +296 -0
  137. package/libx/_runtime/common/generic/auth/utils.js +213 -0
  138. package/libx/_runtime/common/generic/crud.js +14 -10
  139. package/libx/_runtime/common/generic/etag.js +1 -1
  140. package/libx/_runtime/common/generic/input.js +35 -35
  141. package/libx/_runtime/common/generic/sorting.js +2 -3
  142. package/libx/_runtime/common/generic/temporal.js +2 -2
  143. package/libx/_runtime/common/i18n/index.js +2 -31
  144. package/libx/_runtime/common/i18n/messages.properties +1 -1
  145. package/libx/_runtime/common/toggles/handler.js +21 -0
  146. package/libx/_runtime/common/utils/copy.js +10 -1
  147. package/libx/_runtime/common/utils/cqn2cqn4sql.js +100 -29
  148. package/libx/_runtime/common/utils/csn.js +63 -1
  149. package/libx/_runtime/common/utils/dollar.js +10 -1
  150. package/libx/_runtime/common/utils/draft.js +46 -7
  151. package/libx/_runtime/common/utils/entityFromCqn.js +13 -9
  152. package/libx/_runtime/common/utils/extensibilityUtils.js +18 -0
  153. package/libx/_runtime/common/utils/foreignKeyPropagations.js +88 -104
  154. package/libx/_runtime/common/utils/generateOnCond.js +9 -6
  155. package/libx/_runtime/common/utils/quotingStyles.js +2 -0
  156. package/libx/_runtime/common/utils/resolveStructured.js +25 -9
  157. package/libx/_runtime/common/utils/resolveView.js +4 -1
  158. package/libx/_runtime/common/utils/rewriteAsterisks.js +3 -16
  159. package/libx/_runtime/common/utils/structured.js +33 -37
  160. package/libx/_runtime/common/utils/template.js +17 -8
  161. package/libx/_runtime/common/utils/templateProcessor.js +28 -28
  162. package/libx/_runtime/db/data-conversion/post-processing.js +118 -417
  163. package/libx/_runtime/db/expand/expandCQNToJoin.js +45 -41
  164. package/libx/_runtime/db/expand/rawToExpanded.js +29 -8
  165. package/libx/_runtime/db/generic/index.js +1 -3
  166. package/libx/_runtime/db/generic/input.js +5 -10
  167. package/libx/_runtime/db/generic/rewrite.js +5 -2
  168. package/libx/_runtime/db/generic/structured.js +2 -2
  169. package/libx/_runtime/db/query/delete.js +2 -2
  170. package/libx/_runtime/db/query/insert.js +1 -1
  171. package/libx/_runtime/db/query/update.js +9 -14
  172. package/libx/_runtime/db/sql-builder/CreateBuilder.js +4 -3
  173. package/libx/_runtime/db/sql-builder/InsertBuilder.js +14 -1
  174. package/libx/_runtime/db/sql-builder/SelectBuilder.js +3 -2
  175. package/libx/_runtime/db/sql-builder/dataTypes.js +3 -3
  176. package/libx/_runtime/db/utils/columns.js +3 -3
  177. package/libx/_runtime/db/utils/normalizeTimeData.js +2 -2
  178. package/libx/_runtime/db/utils/propagateForeignKeys.js +6 -2
  179. package/libx/_runtime/extensibility/mps/index.js +5 -0
  180. package/libx/_runtime/extensibility/mps/service.js +111 -0
  181. package/libx/_runtime/extensibility/mps/tar.js +42 -0
  182. package/libx/_runtime/extensibility/mps/utils.js +11 -0
  183. package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformREAD.js +0 -0
  184. package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformRESULT.js +17 -5
  185. package/libx/_runtime/{fiori → extensibility}/uiflex/handler/transformWRITE.js +1 -0
  186. package/libx/_runtime/extensibility/uiflex/index.js +54 -0
  187. package/libx/_runtime/extensibility/uiflex/service.js +276 -0
  188. package/libx/_runtime/{fiori → extensibility}/uiflex/utils.js +22 -7
  189. package/libx/_runtime/fiori/generic/activate.js +2 -2
  190. package/libx/_runtime/fiori/generic/before.js +4 -4
  191. package/libx/_runtime/fiori/generic/new.js +3 -3
  192. package/libx/_runtime/fiori/generic/patch.js +1 -1
  193. package/libx/_runtime/fiori/generic/read.js +58 -66
  194. package/libx/_runtime/fiori/generic/readOverDraft.js +71 -16
  195. package/libx/_runtime/fiori/utils/handler.js +6 -13
  196. package/libx/_runtime/fiori/utils/where.js +6 -5
  197. package/libx/_runtime/hana/Service.js +4 -10
  198. package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +2 -2
  199. package/libx/_runtime/hana/driver.js +2 -2
  200. package/libx/_runtime/hana/execute.js +29 -75
  201. package/libx/_runtime/hana/pool.js +1 -1
  202. package/libx/_runtime/hana/streaming.js +2 -1
  203. package/libx/_runtime/index.js +6 -6
  204. package/libx/_runtime/messaging/AMQPWebhookMessaging.js +5 -21
  205. package/libx/_runtime/messaging/Outbox.js +2 -2
  206. package/libx/_runtime/messaging/common-utils/AMQPClient.js +4 -14
  207. package/libx/_runtime/messaging/common-utils/connections.js +5 -7
  208. package/libx/_runtime/messaging/common-utils/normalizeIncomingMessage.js +30 -0
  209. package/libx/_runtime/messaging/enterprise-messaging-shared.js +2 -1
  210. package/libx/_runtime/messaging/enterprise-messaging-utils/EMManagement.js +36 -30
  211. package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +19 -12
  212. package/libx/_runtime/messaging/enterprise-messaging.js +8 -8
  213. package/libx/_runtime/messaging/file-based.js +5 -5
  214. package/libx/_runtime/messaging/message-queuing.js +14 -12
  215. package/libx/_runtime/messaging/outbox/utils.js +18 -19
  216. package/libx/_runtime/messaging/redis-messaging.js +91 -0
  217. package/libx/_runtime/messaging/service.js +8 -6
  218. package/libx/_runtime/remote/Service.js +44 -8
  219. package/libx/_runtime/remote/utils/client.js +25 -13
  220. package/libx/_runtime/remote/utils/data.js +11 -11
  221. package/libx/_runtime/sqlite/Service.js +6 -9
  222. package/libx/_runtime/sqlite/customBuilder/CustomFunctionBuilder.js +5 -2
  223. package/libx/_runtime/types/api.js +10 -2
  224. package/libx/common/utils/ucsn.js +109 -0
  225. package/libx/gql/resolvers/crud/create.js +6 -1
  226. package/libx/gql/resolvers/crud/delete.js +6 -1
  227. package/libx/gql/resolvers/crud/read.js +6 -1
  228. package/libx/gql/resolvers/crud/update.js +9 -1
  229. package/libx/gql/resolvers/parse/ast2cqn/columns.js +3 -1
  230. package/libx/gql/schema/typeDefMap.js +2 -2
  231. package/libx/odata/afterburner.js +110 -16
  232. package/libx/odata/grammar.pegjs +9 -1
  233. package/libx/odata/parseToCqn.js +39 -0
  234. package/libx/odata/parser.js +1 -1
  235. package/libx/rest/RestAdapter.js +9 -1
  236. package/libx/rest/middleware/input.js +54 -0
  237. package/libx/rest/middleware/operation.js +14 -1
  238. package/libx/rest/middleware/parse.js +11 -7
  239. package/package.json +1 -1
  240. package/server.js +34 -19
  241. package/srv/audit-log.cds +2 -2
  242. package/srv/flex.cds +8 -2
  243. package/srv/flex.js +1 -1
  244. package/srv/mps.cds +23 -0
  245. package/srv/mps.js +1 -0
  246. package/libx/_runtime/auth/strategies/utils/uaa.js +0 -21
  247. package/libx/_runtime/common/generic/auth.js +0 -874
  248. package/libx/_runtime/common/toggles/alpha.js +0 -43
  249. package/libx/_runtime/db/generic/arrayed.js +0 -33
  250. package/libx/_runtime/fiori/uiflex/index.js +0 -35
  251. package/libx/_runtime/fiori/uiflex/service.js +0 -150
  252. package/libx/rest/utils/data.js +0 -60
package/lib/deploy.js CHANGED
@@ -1,6 +1,6 @@
1
- const cds = require('./index'), { local } = cds.utils
1
+ const cds = require('./index'), { local, inspect } = cds.utils
2
2
  const DEBUG = cds.debug('deploy')
3
- let LOG
3
+ /* eslint-disable no-console */
4
4
 
5
5
  /**
6
6
  * Implementation of `cds.deploy` common to all databases.
@@ -11,8 +11,8 @@ let LOG
11
11
  exports = module.exports = function cds_deploy (model,options) { return {
12
12
 
13
13
  /** @param {cds.Service} db */
14
- async to (db, o=options||{}) { // NOSONAR
15
- LOG = cds.log('deploy')
14
+ async to (db, o = options || cds.options || {}) {
15
+ const LOG = o.silent || !cds.log('deploy')._info ? ()=>{} : console.log
16
16
 
17
17
  if (model && !model.definitions) {
18
18
  model = await cds.load (model) .then (cds.minify)
@@ -31,25 +31,22 @@ exports = module.exports = function cds_deploy (model,options) { return {
31
31
  if (!cds.db) cds.db = cds.services.db = db
32
32
  if (!db.model) db.model = model
33
33
 
34
- if (o.ddl !== false) {
35
- const any = await db.deploy (model,o) //> CREATE TABLE, ...
36
- if (!any) return
37
- }
34
+ // create tables & views...
35
+ const any = await exports.create (db,model,o)
36
+ if (!any) return db
38
37
 
39
38
  // fill in initial data...
40
- const SILENT = o.silent || !LOG._info
41
- await init_from_code (db,model,SILENT)
42
- await init_from_csv (db,model,SILENT)
43
- await init_from_json (db,model,SILENT)
44
-
45
- const {credentials} = db.options, file = credentials && (credentials.database || credentials.url)
46
- if (!SILENT) {
47
- if (file !== ':memory:') console.log (`/> successfully deployed to ./${file}\n`)
48
- else console.log (`/> successfully deployed to sqlite in-memory db\n`)
49
- }
50
-
39
+ await exports.init (db,model, file => LOG(
40
+ `\x1b[2m > init from ${local(file)} \x1b[0m`
41
+ ))
42
+
43
+ // done
44
+ const {credentials:c} = db.options, file = c && (c.database || c.url)
45
+ if (file !== ':memory:') LOG (`/> successfully deployed to ./${file}\n`)
46
+ else LOG (`/> successfully deployed to sqlite in-memory db\n`)
51
47
  return db
52
48
  },
49
+
53
50
  // continue to support cds.deploy() as well...
54
51
  then(n,e) { return this.to (cds.db||'db') .then (n,e) },
55
52
  catch(e) { return this.to (cds.db||'db') .catch (e) },
@@ -57,9 +54,10 @@ exports = module.exports = function cds_deploy (model,options) { return {
57
54
 
58
55
 
59
56
 
60
-
61
- const { fs, path, isdir, isfile, read } = cds.utils
57
+ const { fs, path, read } = cds.utils
62
58
  const { readdir } = fs.promises
59
+ const isdir = (..._) => fs.isdir(path.join(..._))
60
+ const isfile = (..._) => fs.isfile(path.join(..._))
63
61
 
64
62
  exports.include_external_entities_in = function (model) {
65
63
  if (model._mocked) return model; else Object.defineProperty(model,'_mocked',{value:true})
@@ -101,125 +99,114 @@ exports.exclude_external_entities_in = function (csn) { // NOSONAR
101
99
  }
102
100
 
103
101
 
104
- function init_from_code (db, csn, SILENT) {
105
-
106
- if (!csn.$sources) return
107
- const folders = new Set([ path.resolve(cds.root,'db'), ...csn.$sources.map (path.dirname)])
108
- const inits = []
109
-
110
- for (let each of folders) {
111
- let file;
112
- if (process.env.CDS_TYPESCRIPT === 'true') file = isfile (path.resolve(each,'init.ts'));
113
- if (!file) file = isfile (path.resolve(each,'init.js'));
114
- if (!file) continue
115
- SILENT || console.log (` > initializing database from ${local(file)}`) // eslint-disable-line
116
- let init = require(file); if (!init) continue
117
- if (!init.then && typeof init === 'function') inits.push (init(db))
118
- else inits.push (init)
119
- }
120
-
121
- return Promise.all (inits)
102
+ exports.create = async function (db, csn=db.model, o) {
103
+ if (!db.deploy || o.lean) {
104
+ const creates = cds.compile.to.sql (csn,o); if (!creates || creates.length === 0) return
105
+ const drops = creates.map (each => {
106
+ let [, kind, entity] = each.match(/^CREATE (TABLE|VIEW) "?([^\s"(]+)/im) || []
107
+ return `DROP ${kind} IF EXISTS ${entity};`
108
+ }).reverse()
109
+ if (o.dry) {
110
+ console.log(); for (let each of drops) console.log(each)
111
+ console.log(); for (let each of creates) console.log(each,'\n')
112
+ return
113
+ } else await db.tx (async tx => {
114
+ await tx.run(drops)
115
+ await tx.run(creates)
116
+ return true
117
+ })
118
+ } else return db.deploy (csn,o)
122
119
  }
123
120
 
124
- function init_from_csv (db, csn, SILENT) {
125
- return init_from_ (['data','csv'], _csvs, db, csn, SILENT, (entity, src) => {
126
- let [ cols, ...rows ] = cds.parse.csv (src)
127
- return rows && rows[0] && INSERT.into (entity) .columns (cols) .rows (rows)
128
- });
129
121
 
130
- function _csvs (filename,_,allFiles) {
131
- if (filename[0] === '-' || !filename.endsWith ('.csv')) return false
132
- if (prefer_translated_texts(filename, allFiles)) return false
133
- return true
122
+ exports.init = (db, csn=db.model, log=()=>{}) => db.tx (async tx => {
123
+ cds.context = tx //> registers tx as root transaction
124
+ const resources = await exports.resources(csn), inits=[], err = new Error
125
+ for (let [file,e] of Object.entries(resources)) {
126
+ if (e === '*') { // init.js/ts
127
+ const x = require(file); if (!x) continue
128
+ log (file)
129
+ inits.push (!x.then && typeof x === 'function' ? x(db) : x)
130
+ } else { // from .csv or .json
131
+ const INSERT_into = _from_csv_or_json [path.extname(file)]
132
+ const src = await read(file,'utf8'); if (!src) continue
133
+ const q = INSERT_into (e,src); if (!q) continue
134
+ log (file,e)
135
+ inits.push (tx.run(q) .catch (e => { throw Object.assign (e,{
136
+ message: 'in cds.deploy(): ' + e.message +'\n'+ inspect(q),
137
+ })}))
138
+ }
134
139
  }
135
- }
136
-
137
- function init_from_json (db, csn, SILENT) {
138
- return init_from_ (['data'], _jsons, db, csn, SILENT, (entity, src) => {
139
- let json = JSON.parse (src)
140
- return json[0] && INSERT.into (entity) .entries (json)
141
- });
142
-
143
- function _jsons (filename,_,allFiles) {
144
- if (filename[0] === '-' || !filename.endsWith ('.json')) return false
145
- if (prefer_translated_texts(filename, allFiles)) return false
146
- return true
140
+ await Promise.all (inits)
141
+ })
142
+
143
+
144
+ exports.resources = async function (csn) {
145
+ if (!csn || !csn.definitions) csn = await cds.load (csn||'*') .then (cds.minify)
146
+ const folders = await exports.resources.folders(csn)
147
+ const found={}, ts = process.env.CDS_TYPESCRIPT
148
+ for (let folder of folders) {
149
+ // fetching init.js files
150
+ const init_js = ts && isfile(folder,'init.ts') || isfile(folder,'init.js')
151
+ if (init_js) found[init_js] = '*'
152
+ // fetching .csv and .json files
153
+ for (let each of ['data','csv']) {
154
+ const subdir = isdir(folder,each); if (!subdir) continue
155
+ const files = await readdir (subdir)
156
+ for (let fx of files) {
157
+ if (fx[0] === '-') continue
158
+ const ext = path.extname(fx); if (ext in _from_csv_or_json) {
159
+ const f = fx.slice(0,-ext.length)
160
+ if (/[._]texts$/.test(f) && files.some(g => g.startsWith(f+'_'))) {
161
+ // ignores 'Books_texts.csv/json' if there is any 'Books_texts_LANG.csv/json'
162
+ DEBUG && DEBUG (`ignoring '${fx}' in favor of translated ones`); continue
163
+ }
164
+ const e = _entity4(f,csn); if (_skip(e)) continue
165
+ found[path.join(subdir,fx)] = e.name
166
+ }
167
+ }
168
+ }
147
169
  }
170
+ return found
148
171
  }
149
172
 
150
- /**
151
- * ignores 'Books_texts.csv/json' if there is any 'Books_texts_LANG.csv/json'
152
- */
153
- function prefer_translated_texts (file, all) {
154
- if (/[._]texts\.(json|csv)$/.test (file)) {
155
- const pattern = new RegExp('^'+ path.basename(file) +'_')
156
- const translated = all.filter (f => pattern.test(f))
157
- if (translated.length > 0) {
158
- DEBUG && DEBUG (`ignoring '${file}' in favor of [${translated}]`) // eslint-disable-line
159
- return true
160
- }
161
- }
173
+
174
+ exports.resources.folders = async function (csn) {
175
+ if (!csn || !csn.definitions) csn = await cds.load (csn||'*') .then (cds.minify)
176
+ const folders = new Set (csn.$sources.map (path.dirname) .filter (f => f !== cds.home))
177
+ if (cds.env.folders.db) folders.add (path.resolve(cds.root, cds.env.folders.db))
178
+ if (cds.env.features.test_data) folders.add (path.resolve(cds.root,'test/'))
179
+ return folders
162
180
  }
163
181
 
164
- async function init_from_ (locations, filter, db, csn, SILENT, INSERT_into) { // NOSONAR
165
182
 
166
- const folders = new Set
167
- let roots = Object.values(cds.env.folders); if (cds.env.features.test_data) roots.push('test/')
168
- for (let root of roots) {
169
- for (let data of locations) {
170
- let each = path.resolve(root,data)
171
- if (isdir (each)) folders.add(each)
183
+ const _entity4 = (file,csn) => {
184
+ const name = file.replace(/-/g,'.')
185
+ const entity = csn.definitions [name]
186
+ if (!entity) {
187
+ if (/(.+)[._]texts_?/.test(name)) { // 'Books.texts', 'Books.texts_de'
188
+ const base = csn.definitions [RegExp.$1]
189
+ return base && _entity4 (base.elements.texts.target,csn)
172
190
  }
191
+ else return DEBUG && DEBUG (`warning: ${name} not in model`)
173
192
  }
174
- if (csn.$sources) for (let model of csn.$sources) {
175
- for (let data of locations) {
176
- let each = path.resolve(model,'..',data)
177
- if (isdir (each)) folders.add(each)
178
- }
193
+ // We also support insert into simple views if they have no projection
194
+ const p = entity.query && entity.query.SELECT || entity.projection
195
+ if (p && !p.columns && p.from.ref && p.from.ref.length === 1) {
196
+ if (csn.definitions [p.from.ref[0]]) return entity
179
197
  }
198
+ return entity.name ? entity : { name, __proto__:entity }
199
+ }
180
200
 
181
- if (folders.size === 0) return
182
-
183
- const {local} = cds.utils, inits = [], err = new Error
184
- await db.tx (async tx => {
185
- for (let folder of folders) {
186
- const files = await readdir (folder)
187
- for (let each of files.filter (filter)) {
188
- let name = each.replace(/-/g,'.').slice(0, -path.extname(each).length)
189
- let entity = _entity4 (name)
190
- if (!entity) { DEBUG && DEBUG (`warning: ${name} not in model`); continue }
191
- if (entity['@cds.persistence.skip'] === true) continue
192
- const file = path.join(folder,each)
193
- const src = await read (file,'utf8'); if (!src) continue
194
- const q = INSERT_into (entity,src)
195
- if (!q) { DEBUG && DEBUG (`skipping empty ${local(file)}`); continue }
196
- SILENT || console.log (`\x1b[2m > filling ${entity.name} from ${local(file)} \x1b[0m`) // eslint-disable-line
197
- inits.push (tx.run(q).catch(e=>{ const ex = new Error
198
- e.stack = e.message +'\n'+ require('util').inspect(q) + err.stack.slice(5)
199
- .replace (/deploy\.js:\d+:/, ex.stack.slice(5).match(/deploy\.js:\d+:/)[0])
200
- throw e
201
- }))
202
- }
203
- }
204
- await Promise.all(inits)
205
- })
206
-
207
- function _entity4 (name) {
208
- let entity = csn.definitions [name]
209
- if (!entity) {
210
- if (/(.+)[._]texts_?/.test (name)) { // 'Books.texts', 'Books.texts_de'
211
- const base = csn.definitions [RegExp.$1]
212
- return base && _entity4 (base.elements.texts.target)
213
- }
214
- else return
215
- }
216
- // We also support insert into simple views if they have no projection
217
- const p = entity.query && entity.query.SELECT || entity.projection
218
- if (p && !p.columns && p.from.ref && p.from.ref.length === 1) {
219
- if (csn.definitions [p.from.ref[0]]) return entity
220
- }
221
- return entity.name ? entity : { name, __proto__:entity }
222
- }
201
+ const INSERT_from_csv = (entity, csv) => {
202
+ let [ cols, ...rows ] = cds.parse.csv (csv)
203
+ if (rows.length > 0) return INSERT.into (entity) .columns (cols) .rows (rows)
204
+ }
223
205
 
206
+ const INSERT_from_json = (entity, json) => {
207
+ let records = JSON.parse (json)
208
+ if (records.length > 0) return INSERT.into (entity) .entries (records)
224
209
  }
225
- /* eslint no-console: off */
210
+
211
+ const _from_csv_or_json = { '.json': INSERT_from_json, '.csv': INSERT_from_csv, }
212
+ const _skip = e => !e || e['@cds.persistence.skip'] === true
@@ -6,6 +6,7 @@ module.exports = {
6
6
  requires: require('./requires'),
7
7
 
8
8
  features: {
9
+ folders: 'fts/*', // where to find feature toggles -> switch on by default when released
9
10
  cls: major > 12 || major == 12 && minor >= 18,
10
11
  live_reload: !production,
11
12
  fiori_preview: !production,