@sap/cds 6.0.3 → 6.1.1

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 (131) hide show
  1. package/CHANGELOG.md +165 -18
  2. package/apis/cds.d.ts +11 -7
  3. package/apis/log.d.ts +46 -0
  4. package/apis/ql.d.ts +72 -15
  5. package/bin/build/buildTaskHandler.js +5 -2
  6. package/bin/build/constants.js +4 -1
  7. package/bin/build/provider/buildTaskHandlerEdmx.js +11 -39
  8. package/bin/build/provider/buildTaskHandlerFeatureToggles.js +14 -34
  9. package/bin/build/provider/buildTaskHandlerInternal.js +56 -4
  10. package/bin/build/provider/buildTaskProviderInternal.js +22 -14
  11. package/bin/build/provider/hana/index.js +12 -9
  12. package/bin/build/provider/java/index.js +18 -8
  13. package/bin/build/provider/mtx/index.js +7 -4
  14. package/bin/build/provider/mtx/resourcesTarBuilder.js +60 -35
  15. package/bin/build/provider/mtx-extension/index.js +57 -0
  16. package/bin/build/provider/mtx-sidecar/index.js +46 -18
  17. package/bin/build/provider/nodejs/index.js +34 -13
  18. package/bin/deploy/to-hana/cfUtil.js +7 -2
  19. package/bin/deploy/to-hana/hana.js +20 -25
  20. package/bin/deploy/to-hana/hdiDeployUtil.js +13 -2
  21. package/bin/serve.js +7 -4
  22. package/lib/compile/{index.js → cds-compile.js} +0 -0
  23. package/lib/compile/extend.js +15 -5
  24. package/lib/compile/minify.js +1 -15
  25. package/lib/compile/parse.js +1 -1
  26. package/lib/compile/resolve.js +2 -2
  27. package/lib/compile/to/srvinfo.js +6 -4
  28. package/lib/{deploy.js → dbs/cds-deploy.js} +9 -8
  29. package/lib/env/{index.js → cds-env.js} +1 -17
  30. package/lib/env/{requires.js → cds-requires.js} +24 -3
  31. package/lib/env/defaults.js +7 -1
  32. package/lib/env/schemas/cds-package.json +11 -0
  33. package/lib/env/schemas/cds-rc.json +614 -0
  34. package/lib/index.js +19 -16
  35. package/lib/log/{errors.js → cds-error.js} +1 -1
  36. package/lib/log/{index.js → cds-log.js} +0 -0
  37. package/lib/ql/Query.js +9 -3
  38. package/lib/ql/SELECT.js +2 -2
  39. package/lib/ql/{index.js → cds-ql.js} +0 -9
  40. package/lib/req/context.js +49 -17
  41. package/lib/req/locale.js +5 -1
  42. package/lib/{serve → srv}/adapters.js +23 -19
  43. package/lib/{connect → srv}/bindings.js +0 -0
  44. package/lib/{connect/index.js → srv/cds-connect.js} +1 -1
  45. package/lib/{serve/index.js → srv/cds-serve.js} +1 -1
  46. package/lib/{serve → srv}/factory.js +1 -1
  47. package/lib/{serve/Service-api.js → srv/srv-api.js} +22 -6
  48. package/lib/{serve/Service-dispatch.js → srv/srv-dispatch.js} +13 -8
  49. package/lib/{serve/Service-handlers.js → srv/srv-handlers.js} +10 -0
  50. package/lib/{serve/Service-methods.js → srv/srv-methods.js} +10 -8
  51. package/lib/srv/srv-models.js +207 -0
  52. package/lib/{serve/Transaction.js → srv/srv-tx.js} +57 -40
  53. package/lib/utils/{tests.js → cds-test.js} +2 -2
  54. package/lib/utils/cds-utils.js +146 -0
  55. package/lib/utils/index.js +2 -145
  56. package/lib/utils/jest.js +43 -0
  57. package/lib/utils/resources/index.js +15 -25
  58. package/lib/utils/resources/tar.js +18 -41
  59. package/libx/_runtime/auth/index.js +14 -11
  60. package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +7 -19
  61. package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -4
  62. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -4
  63. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -4
  64. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +1 -4
  65. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +2 -2
  66. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +6 -19
  67. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +1 -4
  68. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +1 -1
  69. package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +1 -4
  70. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/PrimitiveValueDecoder.js +0 -2
  71. package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/DeserializerFactory.js +3 -1
  72. package/libx/_runtime/cds-services/adapter/odata-v4/to.js +38 -4
  73. package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +1 -3
  74. package/libx/_runtime/cds-services/services/utils/differ.js +4 -0
  75. package/libx/_runtime/cds-services/util/errors.js +1 -29
  76. package/libx/_runtime/common/i18n/messages.properties +2 -1
  77. package/libx/_runtime/common/perf/index.js +10 -15
  78. package/libx/_runtime/common/utils/binary.js +3 -4
  79. package/libx/_runtime/common/utils/cqn2cqn4sql.js +0 -1
  80. package/libx/_runtime/common/utils/entityFromCqn.js +8 -5
  81. package/libx/_runtime/common/utils/resolveView.js +1 -1
  82. package/libx/_runtime/common/utils/template.js +1 -1
  83. package/libx/_runtime/db/Service.js +2 -14
  84. package/libx/_runtime/db/expand/expandCQNToJoin.js +28 -25
  85. package/libx/_runtime/db/expand/rawToExpanded.js +7 -6
  86. package/libx/_runtime/db/generic/input.js +8 -1
  87. package/libx/_runtime/db/sql-builder/SelectBuilder.js +37 -18
  88. package/libx/_runtime/extensibility/activate.js +47 -47
  89. package/libx/_runtime/extensibility/add.js +22 -13
  90. package/libx/_runtime/extensibility/addExtension.js +17 -13
  91. package/libx/_runtime/extensibility/defaults.js +25 -30
  92. package/libx/_runtime/extensibility/handler/transformREAD.js +20 -18
  93. package/libx/_runtime/extensibility/linter/allowlist_checker.js +373 -0
  94. package/libx/_runtime/extensibility/linter/annotations_checker.js +113 -0
  95. package/libx/_runtime/extensibility/linter/checker_base.js +20 -0
  96. package/libx/_runtime/extensibility/linter/namespace_checker.js +180 -0
  97. package/libx/_runtime/extensibility/linter.js +32 -0
  98. package/libx/_runtime/extensibility/push.js +77 -20
  99. package/libx/_runtime/extensibility/service.js +29 -12
  100. package/libx/_runtime/extensibility/token.js +56 -0
  101. package/libx/_runtime/extensibility/utils.js +8 -6
  102. package/libx/_runtime/extensibility/validation.js +6 -9
  103. package/libx/_runtime/fiori/generic/new.js +0 -11
  104. package/libx/_runtime/hana/Service.js +0 -1
  105. package/libx/_runtime/hana/conversion.js +12 -1
  106. package/libx/_runtime/hana/customBuilder/CustomFunctionBuilder.js +4 -3
  107. package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +5 -0
  108. package/libx/_runtime/hana/pool.js +6 -10
  109. package/libx/_runtime/hana/search2Contains.js +0 -5
  110. package/libx/_runtime/hana/search2cqn4sql.js +1 -0
  111. package/libx/_runtime/messaging/outbox/utils.js +1 -1
  112. package/libx/_runtime/messaging/service.js +11 -6
  113. package/libx/_runtime/remote/utils/data.js +5 -0
  114. package/libx/_runtime/sqlite/Service.js +7 -6
  115. package/libx/_runtime/sqlite/execute.js +41 -28
  116. package/libx/odata/afterburner.js +79 -2
  117. package/libx/odata/cqn2odata.js +9 -7
  118. package/libx/odata/grammar.pegjs +157 -76
  119. package/libx/odata/index.js +9 -3
  120. package/libx/odata/parser.js +1 -1
  121. package/libx/odata/utils.js +39 -5
  122. package/libx/rest/RestAdapter.js +3 -7
  123. package/libx/rest/middleware/delete.js +4 -5
  124. package/libx/rest/middleware/parse.js +3 -2
  125. package/package.json +3 -3
  126. package/server.js +1 -1
  127. package/srv/extensibility-service.cds +6 -3
  128. package/srv/model-provider.cds +3 -1
  129. package/srv/model-provider.js +84 -104
  130. package/srv/mtx.js +7 -1
  131. package/libx/_runtime/cds-services/adapter/odata-v4/Dispatcher.js +0 -240
@@ -1,42 +1,47 @@
1
1
  const cds = require('../index'), { cds_tx_protection } = cds.env.features
2
2
  const EventContext = require('../req/context')
3
- class RootContext extends EventContext {}
3
+ class RootContext extends EventContext {
4
+ static for(_) {
5
+ if (_ instanceof EventContext) return _
6
+ else return super.for(_,'as root')
7
+ }
8
+ }
9
+ class NestedContext extends EventContext {
10
+ static for(_) {
11
+ if (_ instanceof EventContext) return _
12
+ else return super.for(_)
13
+ }
14
+ }
15
+
4
16
 
5
17
  /**
6
18
  * This is the implementation of the `srv.tx(req)` method. It constructs
7
19
  * a new Transaction as a derivate of the `srv` (i.e. {__proto__:srv})
8
- * @returns { Transaction & import('./Service-api') }
20
+ * @returns { Transaction & import('./srv-api') }
9
21
  * @param { EventContext } ctx
10
22
  */
11
- module.exports = function tx (ctx,fn) { const srv = this
23
+ function srv_tx (ctx,fn) { const srv = this
12
24
 
13
25
  if (srv.context) return srv // srv.tx().tx() -> idempotent
26
+ if (!ctx) return RootTransaction.for (srv)
27
+
28
+ // Creating root or nested txes for existing contexts
29
+ if (ctx instanceof EventContext) {
30
+ if (ctx.tx) return NestedTransaction.for (srv, ctx)
31
+ else return RootTransaction.for (srv, ctx)
32
+ }
14
33
 
15
34
  // Last arg may be a function -> srv.tx (tx => { ... })
16
35
  if (typeof ctx === 'function') [ ctx, fn ] = [ undefined, ctx ]
17
36
  if (typeof fn === 'function') {
18
- const tx = srv.tx(ctx), fx = ()=> Promise.resolve(fn(tx)).then(tx.commit,tx.rollback)
19
- const gc = cds.context, _has_tx = gc && gc.tx && !gc.tx._done
20
- return _has_tx ? fx() : cds._context.run(tx,fx)
21
- }
22
-
23
- if (ctx) {
24
- if (ctx.context) ctx = ctx.context
25
-
26
- // REVISIT: This is for compatibility with former srv.tx(req) usages
27
- if (ctx instanceof EventContext) {
28
- if (ctx.tx) return NestedTransaction.for (srv, ctx)
29
- else return RootTransaction.for (srv, ctx)
30
- }
31
-
32
- // REVISIT: This is for compatibility with AFC only
33
- if (ctx._txed_before) return NestedTransaction.for (srv, ctx._txed_before)
34
- else Object.defineProperty(ctx, '_txed_before', { value: ctx = RootContext.for(ctx) })
35
- return RootTransaction.for (srv, ctx)
37
+ const tx = RootTransaction.for (srv, ctx)
38
+ return cds._context.run (tx, ()=> Promise.resolve(fn(tx)) .then (tx.commit, tx.rollback))
36
39
  }
37
40
 
38
- // `ctx` is a plain context object or undefined
39
- return RootTransaction.for (srv, RootContext.for(ctx))
41
+ // REVISIT: following is for compatibility with AFC only -> we should get rid of that
42
+ if (ctx._txed_before) return NestedTransaction.for (srv, ctx._txed_before)
43
+ else Object.defineProperty (ctx, '_txed_before', { value: ctx = RootContext.for(ctx) })
44
+ return RootTransaction.for (srv, ctx)
40
45
  }
41
46
 
42
47
 
@@ -45,19 +50,23 @@ class Transaction {
45
50
  /**
46
51
  * Returns an already started tx for given srv, or creates a new instance
47
52
  */
48
- static for (srv,root) {
49
- let txs = root.transactions
50
- if (!txs) Object.defineProperty(root, 'transactions', {value: txs = new Map})
53
+ static for (srv, ctx) {
54
+ const txs = ctx.context.transactions || ctx.context._set ('transactions', new Map)
55
+ if (srv._real_srv) srv = srv._real_srv // REVISIT: srv._real_srv is a dirty hack for current Okra Adapters
51
56
  let tx = txs.get (srv)
52
- if (!tx) txs.set (srv, tx = new this (srv,root))
57
+ if (!tx) txs.set (srv, tx = new this (srv,ctx))
53
58
  return tx
54
59
  }
55
60
 
56
- constructor (srv,root) {
57
- const tx = { __proto__:srv, context:root }
61
+ constructor (srv, ctx) {
62
+ const tx = { __proto__:srv, _kind: new.target.name, context: ctx }
58
63
  const proto = new.target.prototype
59
64
  tx.commit = proto.commit.bind(tx)
60
65
  tx.rollback = proto.rollback.bind(tx)
66
+ if (srv.isExtensible) {
67
+ const m = cds.context?.model
68
+ if (m) tx.model = m
69
+ }
61
70
  return _init(tx)
62
71
  }
63
72
 
@@ -102,11 +111,12 @@ class Transaction {
102
111
  class RootTransaction extends Transaction {
103
112
 
104
113
  /**
105
- * Register the new transaction with the root context.
106
- * @param {EventContext} root
114
+ * Register the new transaction with the given context.
115
+ * @param {EventContext} ctx
107
116
  */
108
- static for (srv,root) {
109
- return root.tx = super.for (srv,root)
117
+ static for (srv, ctx) {
118
+ ctx = RootContext.for (ctx?.tx?._done ? {} : ctx)
119
+ return ctx.tx = super.for (srv, ctx)
110
120
  }
111
121
 
112
122
  /**
@@ -148,16 +158,21 @@ class RootTransaction extends Transaction {
148
158
 
149
159
  class NestedTransaction extends Transaction {
150
160
 
161
+ static for (srv,ctx) {
162
+ ctx = NestedContext.for (ctx)
163
+ return super.for (srv, ctx)
164
+ }
165
+
151
166
  /**
152
- * Registers event listeners with the root context, to commit or rollback
167
+ * Registers event listeners with the given context, to commit or rollback
153
168
  * when the root tx is about to commit or rollback.
154
- * @param {import ('../req/context')} root
169
+ * @param {EventContext} ctx
155
170
  */
156
- constructor (srv,root) {
157
- super (srv,root)
158
- root.before ('succeeded', ()=> this.commit())
159
- root.before ('failed', ()=> this.rollback())
160
- if ('end' in srv) root.once ('done', ()=> srv.end())
171
+ constructor (srv,ctx) {
172
+ super (srv,ctx)
173
+ ctx.before ('succeeded', ()=> this.commit())
174
+ ctx.before ('failed', ()=> this.rollback())
175
+ if ('end' in srv) ctx.once ('done', ()=> srv.end())
161
176
  }
162
177
 
163
178
  }
@@ -188,3 +203,5 @@ const _begin = async function (req) {
188
203
  delete this.dispatch
189
204
  return this.dispatch (req)
190
205
  }
206
+
207
+ module.exports = srv_tx
@@ -25,7 +25,7 @@ class Test extends require('./axios') {
25
25
  this.server = server
26
26
  this.url = url
27
27
  })
28
- try { return cds.exec (cmd, ...args, '--port','0') }
28
+ try { return cds.exec (cmd, ...args, ...(args.includes('--port') ? [] : ['--port', '0'])) }
29
29
  catch (e) { if (is_mocha) console.error(e) } // eslint-disable-line no-console
30
30
  })
31
31
 
@@ -97,7 +97,7 @@ function support_jest_and_mocha() {
97
97
  }
98
98
  after(()=>{
99
99
  delete global.cds
100
- for (let k in require.cache) delete require.cache[k]
100
+ for (let k in require.cache) delete require.cache[k] // REVISIT: Whay are we doing that?
101
101
  })
102
102
  } else if (is_jest) { // it's jest
103
103
  global.before = (msg,fn) => global.beforeAll(fn||msg)
@@ -0,0 +1,146 @@
1
+ const cwd = process.env._original_cwd || process.cwd()
2
+ const path = require ('path'), { dirname, extname, join, resolve, relative } = path
3
+ const fs = require('fs')
4
+ const cds = require('../index')
5
+
6
+ const all = module.exports = exports = { ...fs,
7
+ get inspect() { return $set (this, 'inspect', require('util').inspect) },
8
+ get uuid() { return $set (this, 'uuid', require('@sap/cds-foss').uuid) },
9
+ }
10
+
11
+ exports.fs = all
12
+ exports.path = path
13
+
14
+ exports.local = (file) => relative(cwd,file)
15
+
16
+ exports.readdir = async function (x) {
17
+ const d = resolve (cds.root,x)
18
+ return fs.promises.readdir(d)
19
+ }
20
+
21
+ exports.stat = async function (x) {
22
+ const d = resolve (cds.root,x)
23
+ return fs.promises.stat(d)
24
+ }
25
+
26
+ exports.exists = function exists (x) {
27
+ if (x) {
28
+ const y = resolve (cds.root,x)
29
+ return fs.existsSync(y)
30
+ }
31
+ }
32
+
33
+ exports.isdir = function isdir (x) {
34
+ if (x) try {
35
+ const y = resolve (cds.root,x)
36
+ const ls = fs.lstatSync(y)
37
+ if (ls.isDirectory()) return y
38
+ if (ls.isSymbolicLink()) return isdir (join (dirname(y), fs.readlinkSync(y)))
39
+ } catch(e){/* ignore */}
40
+ }
41
+
42
+ exports.isfile = function isfile (x) {
43
+ if (x) try {
44
+ const y = resolve (cds.root,x)
45
+ const ls = fs.lstatSync(y)
46
+ if (ls.isFile()) return y
47
+ if (ls.isSymbolicLink()) return isfile (join (dirname(y), fs.readlinkSync(y)))
48
+ } catch(e){/* ignore */}
49
+ }
50
+
51
+ exports.read = async function read (file, _encoding) {
52
+ const f = resolve (cds.root,file)
53
+ const src = await fs.promises.readFile (f, _encoding !== 'json' && _encoding || 'utf8')
54
+ return _encoding === 'json' || !_encoding && f.endsWith('.json') ? JSON.parse(src) : src
55
+ }
56
+
57
+ exports.write = function write (file, data, o) {
58
+ if (arguments.length === 1) return {to:(...path) => write(join(...path),file)}
59
+ if (typeof data === 'object' && !Buffer.isBuffer(data))
60
+ data = JSON.stringify(data, null, ' '.repeat(o && o.spaces))
61
+ const f = resolve (cds.root,file)
62
+ return mkdirp (dirname(f)).then (()=> fs.promises.writeFile (f,data,o))
63
+ }
64
+
65
+ exports.mkdirp = async function (...path) {
66
+ const d = resolve (cds.root,...path)
67
+ await fs.promises.mkdir (d,{recursive:true})
68
+ return d
69
+ }
70
+
71
+ exports.rmdir = (...path) => {
72
+ const d = resolve (cds.root,...path)
73
+ return fs.promises.rm (d, {recursive:true})
74
+ }
75
+
76
+ exports.rimraf = (...path) => {
77
+ const d = resolve (cds.root,...path)
78
+ return fs.promises.rm (d, {recursive:true,force:true})
79
+ }
80
+
81
+ exports.rm = async function rm (x) {
82
+ const y = resolve (cds.root,x)
83
+ return fs.promises.rm(y)
84
+ }
85
+
86
+ exports.copy = async function copy (x,y) {
87
+ const src = resolve (cds.root,x)
88
+ const dst = resolve (cds.root,y)
89
+ if (fs.promises.cp) return fs.promises.cp (src,dst,{recursive:true})
90
+ await mkdirp (dirname(dst))
91
+ if (isdir(src)) {
92
+ const entries = await fs.promises.readdir(src)
93
+ return Promise.all (entries.map (async each => {
94
+ const e = join (src,each)
95
+ const f = join (dst,each)
96
+ return copy (e,f)
97
+ }))
98
+ } else {
99
+ return fs.promises.copyFile (src,dst)
100
+ }
101
+ }
102
+
103
+ exports.find = function find (base, patterns='*', filter=()=>true) {
104
+ const files=[]; base = resolve (cds.root,base)
105
+ if (typeof patterns === 'string') patterns = patterns.split(',')
106
+ if (typeof filter === 'string') filter = this[filter]
107
+ patterns.forEach (pattern => {
108
+ const star = pattern.indexOf('*')
109
+ if (star >= 0) {
110
+ const head = pattern.slice(0,star).replace(/[^/\\]*$/,'')
111
+ const dir = join (base,head)
112
+ try {
113
+ const ls = fs.lstatSync(dir)
114
+ if (ls.isDirectory()) {
115
+ const [,suffix,tail] = /([^/\\]*)?(?:.(.*))?/.exec (pattern.slice(star+1))
116
+ const prefix = pattern.slice(head.length,star)
117
+ let entries = fs.readdirSync(dir) //.filter (_filter)
118
+ if (prefix) entries = entries.filter (e => e.startsWith(prefix)); if (!entries.length) return
119
+ if (suffix) entries = entries.filter (e => e.endsWith(suffix)); if (!entries.length) return
120
+ let paths = entries.map (e=>join(dir,e))
121
+ if (filter) paths = paths.filter (filter); if (!paths.length) return
122
+ if (tail) for (let _files of paths.map (e=>find (e,tail,filter))) files.push (..._files)
123
+ else files.push (...paths)
124
+ }
125
+ } catch(e) {/* ignore */}
126
+ } else {
127
+ const file = join (base, pattern)
128
+ if (fs.existsSync(file)) files.push (file)
129
+ }
130
+ })
131
+ return files
132
+ }
133
+
134
+
135
+ // internal utility to load a file through ESM or CommonJs. TODO find a better place.
136
+ const { pathToFileURL } = require('url')
137
+ exports._import = async function(filePath) {
138
+ return typeof jest !== 'undefined' || extname(filePath) === '.ts' // ts-node w/ ESM not working (cap/issues#11980)
139
+ ? require(filePath)
140
+ : import (pathToFileURL(filePath).href) // must use a file: URL, esp. on Windows for C:\... paths
141
+ }
142
+
143
+
144
+ /** @type <T>(o,p,v:T) => T */
145
+ const $set = (o,p,v) => { Object.defineProperty(o,p,{value:v}); return v }
146
+ const { mkdirp, isdir } = exports
@@ -1,145 +1,2 @@
1
- const cwd = process.env._original_cwd || process.cwd()
2
- const path = require ('path'), { dirname, extname, join, resolve, sep, relative } = path
3
- const fs = require('fs')
4
- const cds = require('../index')
5
-
6
- const all = module.exports = exports = { ...fs,
7
- get inspect() { return $set (this, 'inspect', require('util').inspect) },
8
- get uuid() { return $set (this, 'uuid', require('@sap/cds-foss').uuid) },
9
- }
10
-
11
- exports.fs = all
12
- exports.path = path
13
-
14
- exports.local = (file) => relative(cwd,file)
15
-
16
- exports.readdir = async function (x) {
17
- const d = resolve (cds.root,x)
18
- return fs.promises.readdir(d)
19
- }
20
-
21
- exports.stat = async function (x) {
22
- const d = resolve (cds.root,x)
23
- return fs.promises.stat(d)
24
- }
25
-
26
- exports.exists = function exists (x) {
27
- if (x) {
28
- const y = resolve (cds.root,x)
29
- return fs.existsSync(y)
30
- }
31
- }
32
-
33
- exports.isdir = function isdir (x) {
34
- if (x) try {
35
- const y = resolve (cds.root,x)
36
- const ls = fs.lstatSync(y)
37
- if (ls.isDirectory()) return y
38
- if (ls.isSymbolicLink()) return isdir (join (dirname(y), fs.readlinkSync(y)))
39
- } catch(e){/* ignore */}
40
- }
41
-
42
- exports.isfile = function isfile (x) {
43
- if (x) try {
44
- const y = resolve (cds.root,x)
45
- const ls = fs.lstatSync(y)
46
- if (ls.isFile()) return y
47
- if (ls.isSymbolicLink()) return isfile (join (dirname(y), fs.readlinkSync(y)))
48
- } catch(e){/* ignore */}
49
- }
50
-
51
- exports.read = async function read (file, _encoding) {
52
- const f = resolve (cds.root,file)
53
- const src = await fs.promises.readFile (f, _encoding !== 'json' && _encoding || 'utf8')
54
- return _encoding === 'json' || !_encoding && f.endsWith('.json') ? JSON.parse(src) : src
55
- }
56
-
57
- exports.write = function write (file, data, o) {
58
- if (arguments.length === 1) return {to:(...path) => write(join(...path),file)}
59
- if (typeof data === 'object' && !Buffer.isBuffer(data))
60
- data = JSON.stringify(data, null, ' '.repeat(o && o.spaces))
61
- const f = resolve (cds.root,file)
62
- return mkdirp (dirname(f)).then (()=> fs.promises.writeFile (f,data,o))
63
- }
64
-
65
- exports.mkdirp = async function (...path) {
66
- const d = resolve (cds.root,...path)
67
- await fs.promises.mkdir (d,{recursive:true})
68
- return d
69
- }
70
-
71
- exports.rmdir = (...path) => {
72
- const d = resolve (cds.root,...path)
73
- return (fs.promises.rm || fs.promises.rmdir) (d, {recursive:true})
74
- }
75
-
76
- exports.rimraf = (...path) => {
77
- const d = resolve (cds.root,...path)
78
- return (fs.promises.rm || fs.promises.rmdir) (d, {recursive:true,force:true})
79
- }
80
-
81
- exports.rm = async function rm (x) {
82
- const y = resolve (cds.root,x)
83
- return (fs.promises.rm || fs.promises.unlink)(y)
84
- }
85
-
86
- exports.copy = async function copy (x,y) {
87
- const src = resolve (cds.root,x)
88
- const dst = resolve (cds.root,y)
89
- if (fs.promises.cp) return fs.promises.cp (src,dst,{recursive:true})
90
- await mkdirp (dirname(dst))
91
- if (isdir(src)) {
92
- const entries = await fs.promises.readdir(src)
93
- return Promise.all (entries.map (async each => {
94
- const e = join (src,each)
95
- const f = join (dst,each)
96
- return copy (e,f)
97
- }))
98
- } else {
99
- return fs.promises.copyFile (src,dst)
100
- }
101
- }
102
-
103
- exports.find = function find (base, patterns='*', filter=()=>true) {
104
- const files=[]; base = resolve (cds.root,base)
105
- if (typeof patterns === 'string') patterns = patterns.split(',')
106
- if (typeof filter === 'string') filter = this[filter]
107
- patterns.forEach (pattern => {
108
- const star = pattern.indexOf('*')
109
- if (star >= 0) {
110
- const head = pattern.slice(0,star).replace(/[^/\\]*$/,'')
111
- const dir = join (base,head)
112
- try {
113
- const ls = fs.lstatSync(dir)
114
- if (ls.isDirectory()) {
115
- const [,suffix,tail] = /([^/\\]*)?(?:.(.*))?/.exec (pattern.slice(star+1))
116
- const prefix = pattern.slice(head.length,star)
117
- let entries = fs.readdirSync(dir) //.filter (_filter)
118
- if (prefix) entries = entries.filter (e => e.startsWith(prefix)); if (!entries.length) return
119
- if (suffix) entries = entries.filter (e => e.endsWith(suffix)); if (!entries.length) return
120
- let paths = entries.map (e=>join(dir,e))
121
- if (filter) paths = paths.filter (filter); if (!paths.length) return
122
- if (tail) for (let _files of paths.map (e=>find (e,tail,filter))) files.push (..._files)
123
- else files.push (...paths)
124
- }
125
- } catch(e) {/* ignore */}
126
- } else {
127
- const file = join (base, pattern)
128
- if (fs.existsSync(file)) files.push (file)
129
- }
130
- })
131
- return files
132
- }
133
-
134
- // internal utility to load a file through ESM or CommonJs. TODO find a better place.
135
- const { pathToFileURL } = require('url')
136
- exports._import = async function(filePath) {
137
- return typeof jest !== 'undefined' || extname(filePath) === '.ts' // ts-node w/ ESM not working (cap/issues#11980)
138
- ? require(filePath)
139
- : import (pathToFileURL(filePath).href) // on Windows, must use a file: URL for ESM import
140
- }
141
-
142
-
143
- /** @type <T>(o,p,v:T) => T */
144
- const $set = (o,p,v) => { Object.defineProperty(o,p,{value:v}); return v }
145
- const { mkdirp, isdir } = exports
1
+ // for compatibility with old releases of cds-lint
2
+ module.exports = require('./cds-utils')
@@ -0,0 +1,43 @@
1
+ let vm = require('vm')
2
+ if (!vm.__caching__) {
3
+ vm.__caching__ = true
4
+ const scriptCache = {}
5
+ vm._Script = vm._Script || vm.Script
6
+ class CachedScript extends vm._Script {
7
+ constructor(src, options) {
8
+ const cached = scriptCache[options.filename]
9
+ if (cached) {
10
+ return cached
11
+ }
12
+ super(src, options)
13
+ // Assume that .test.js files are only loaded once
14
+ if (!options.filename.endsWith('.test.js')) {
15
+ scriptCache[options.filename] = this
16
+ }
17
+ }
18
+ }
19
+
20
+ vm.Script = CachedScript
21
+ }
22
+ vm = undefined
23
+
24
+ let asyncHooks = require('async_hooks')
25
+ if (!asyncHooks._AsyncLocalStorage) {
26
+ asyncHooks._AsyncLocalStorage = asyncHooks.AsyncLocalStorage
27
+ class TmpAsyncLocalStorage extends asyncHooks._AsyncLocalStorage {
28
+ disable() {
29
+ if (this._timer) clearTimeout(this._timer)
30
+ return super.disable()
31
+ }
32
+
33
+ _enable() {
34
+ if (this._timer) clearTimeout(this._timer)
35
+ this._timer = setTimeout(() => this.disable(), 60 * 1000)
36
+ this._timer.unref()
37
+ return super._enable()
38
+ }
39
+ }
40
+
41
+ asyncHooks.AsyncLocalStorage = TmpAsyncLocalStorage
42
+ }
43
+ asyncHooks = null
@@ -1,54 +1,44 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
3
 
4
- const cds = require('../../../libx/_runtime/cds')
5
- const { packArchive, packArchiveCLI, unpackArchive, unpackArchiveCLI } = require('./tar')
4
+ const { packArchiveCLI, unpackArchiveCLI } = require('./tar')
6
5
  const { exists } = require('./utils')
7
6
 
8
- // use tar command line interface
9
7
  const TEMP_DIR = fs.realpathSync(require('os').tmpdir())
10
8
 
11
- const packTarArchive = async (files, root, flat = false, cli = true) => {
12
- let tgzBuffer, temp
9
+ const packTarArchive = async (files, root, flat = false) => {
10
+ if (typeof files === 'string') return await packArchiveCLI(files)
13
11
 
12
+ let tgzBuffer, temp
14
13
  try {
15
14
  temp = await fs.promises.mkdtemp(`${TEMP_DIR}${path.sep}tar-`)
16
- if (flat) {
17
- const files_ = []
18
- for (const file of files) {
19
- const destination = path.join(temp, path.basename(file))
20
- await fs.promises.copyFile(file, destination)
21
- files_.push(destination)
22
- }
23
- files = files_
24
- root = temp
15
+ for (const file of files) {
16
+ const fname = flat ? path.basename(file) : path.relative(root, file)
17
+ const destination = path.join(temp, fname)
18
+ const dirname = path.dirname(destination)
19
+ if (!await exists(dirname)) await fs.promises.mkdir(dirname, { recursive: true })
20
+ await fs.promises.copyFile(file, destination)
25
21
  }
26
22
 
27
- const relativeFiles = files.map(file => path.relative(root, file))
28
- if (cli) {
29
- const output = path.relative(root, path.join(temp, `${cds.utils.uuid()}.tgz`))
30
- tgzBuffer = await packArchiveCLI(relativeFiles, root, output)
31
- } else {
32
- tgzBuffer = await packArchive(relativeFiles, root)
33
- }
23
+ tgzBuffer = await packArchiveCLI(temp)
34
24
  } finally {
35
25
  if (await exists(temp)) {
36
- await (fs.promises.rm || fs.promises.rmdir)(temp, { recursive: true, force: true })
26
+ await fs.promises.rm(temp, { recursive: true, force: true })
37
27
  }
38
28
  }
39
29
 
40
30
  return tgzBuffer
41
31
  }
42
32
 
43
- const unpackTarArchive = async (buffer, folder, cli = true) => {
33
+ const unpackTarArchive = async (buffer, folder) => {
44
34
  const temp = await fs.promises.mkdtemp(`${TEMP_DIR}${path.sep}tar-`)
45
35
  const tgz = path.join(temp, 'resources.tgz')
46
36
  await fs.promises.writeFile(tgz, Buffer.from(buffer), 'binary')
47
37
 
48
38
  try {
49
- cli ? await unpackArchiveCLI(tgz, folder) : await unpackArchive(tgz, folder)
39
+ await unpackArchiveCLI(tgz, folder)
50
40
  } finally {
51
- if (await exists(temp)) await (fs.promises.rm || fs.promises.rmdir)(temp, { recursive: true, force: true })
41
+ if (await exists(temp)) await fs.promises.rm(temp, { recursive: true, force: true })
52
42
  }
53
43
  }
54
44
 
@@ -1,21 +1,13 @@
1
1
  const fs = require('fs')
2
2
  const path = require('path')
3
3
  const exec = require('child_process').exec
4
+ const cds = require('../../../libx/_runtime/cds')
5
+ const { exists } = require('./utils')
4
6
 
5
- const _createArchive = (files, root) => {
6
- const tar = require('tar')
7
- return tar.c(
8
- {
9
- gzip: true,
10
- preservePaths: false,
11
- cwd: root
12
- },
13
- files
14
- )
15
- }
7
+ const TEMP_DIR = fs.realpathSync(require('os').tmpdir())
16
8
 
17
- const _createArchiveCLI = (files, root, output) => {
18
- const cmd = 'cd ' + root + ' && tar -czf ' + output + ' ' + files.join(' ')
9
+ const _createArchiveCLI = (root, output) => {
10
+ const cmd = 'tar -zcvf ' + output + ' -C ' + root + ' .'
19
11
 
20
12
  return new Promise((resolve, reject) => {
21
13
  exec(cmd, err => {
@@ -25,32 +17,19 @@ const _createArchiveCLI = (files, root, output) => {
25
17
  })
26
18
  }
27
19
 
28
- const packArchive = (files, root) => {
29
- _createArchive(files, root)
30
- const stream = _createArchive(files, root)
31
- return new Promise((resolve, reject) => {
32
- const chunks = []
33
- stream.on('data', data => chunks.push(data))
34
- stream.on('error', error => reject(error))
35
- stream.on('end', () => {
36
- resolve(Buffer.concat(chunks))
37
- })
38
- })
39
- }
40
-
41
- const packArchiveCLI = async (files, root, output) => {
42
- await _createArchiveCLI(files, root, output)
43
-
44
- return fs.promises.readFile(path.join(root, output))
45
- }
46
-
47
- const unpackArchive = async (tgz, folder) => {
48
- const tar = require('tar')
49
- await tar.x({
50
- file: tgz,
51
- gzip: true,
52
- C: folder
53
- })
20
+ const packArchiveCLI = async (root) => {
21
+ const temp = await fs.promises.mkdtemp(`${TEMP_DIR}${path.sep}tar-`)
22
+ const output = path.join(temp, `${cds.utils.uuid()}.tgz`)
23
+ try {
24
+ await _createArchiveCLI(root, output)
25
+
26
+ return fs.promises.readFile(output)
27
+ }
28
+ finally {
29
+ if (await exists(temp)) {
30
+ await fs.promises.rm(temp, { recursive: true, force: true })
31
+ }
32
+ }
54
33
  }
55
34
 
56
35
  const unpackArchiveCLI = async (tgz, folder) => {
@@ -65,8 +44,6 @@ const unpackArchiveCLI = async (tgz, folder) => {
65
44
  }
66
45
 
67
46
  module.exports = {
68
- packArchive,
69
47
  packArchiveCLI,
70
- unpackArchive,
71
48
  unpackArchiveCLI
72
49
  }