@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.
- package/CHANGELOG.md +165 -18
- package/apis/cds.d.ts +11 -7
- package/apis/log.d.ts +46 -0
- package/apis/ql.d.ts +72 -15
- package/bin/build/buildTaskHandler.js +5 -2
- package/bin/build/constants.js +4 -1
- package/bin/build/provider/buildTaskHandlerEdmx.js +11 -39
- package/bin/build/provider/buildTaskHandlerFeatureToggles.js +14 -34
- package/bin/build/provider/buildTaskHandlerInternal.js +56 -4
- package/bin/build/provider/buildTaskProviderInternal.js +22 -14
- package/bin/build/provider/hana/index.js +12 -9
- package/bin/build/provider/java/index.js +18 -8
- package/bin/build/provider/mtx/index.js +7 -4
- package/bin/build/provider/mtx/resourcesTarBuilder.js +60 -35
- package/bin/build/provider/mtx-extension/index.js +57 -0
- package/bin/build/provider/mtx-sidecar/index.js +46 -18
- package/bin/build/provider/nodejs/index.js +34 -13
- package/bin/deploy/to-hana/cfUtil.js +7 -2
- package/bin/deploy/to-hana/hana.js +20 -25
- package/bin/deploy/to-hana/hdiDeployUtil.js +13 -2
- package/bin/serve.js +7 -4
- package/lib/compile/{index.js → cds-compile.js} +0 -0
- package/lib/compile/extend.js +15 -5
- package/lib/compile/minify.js +1 -15
- package/lib/compile/parse.js +1 -1
- package/lib/compile/resolve.js +2 -2
- package/lib/compile/to/srvinfo.js +6 -4
- package/lib/{deploy.js → dbs/cds-deploy.js} +9 -8
- package/lib/env/{index.js → cds-env.js} +1 -17
- package/lib/env/{requires.js → cds-requires.js} +24 -3
- package/lib/env/defaults.js +7 -1
- package/lib/env/schemas/cds-package.json +11 -0
- package/lib/env/schemas/cds-rc.json +614 -0
- package/lib/index.js +19 -16
- package/lib/log/{errors.js → cds-error.js} +1 -1
- package/lib/log/{index.js → cds-log.js} +0 -0
- package/lib/ql/Query.js +9 -3
- package/lib/ql/SELECT.js +2 -2
- package/lib/ql/{index.js → cds-ql.js} +0 -9
- package/lib/req/context.js +49 -17
- package/lib/req/locale.js +5 -1
- package/lib/{serve → srv}/adapters.js +23 -19
- package/lib/{connect → srv}/bindings.js +0 -0
- package/lib/{connect/index.js → srv/cds-connect.js} +1 -1
- package/lib/{serve/index.js → srv/cds-serve.js} +1 -1
- package/lib/{serve → srv}/factory.js +1 -1
- package/lib/{serve/Service-api.js → srv/srv-api.js} +22 -6
- package/lib/{serve/Service-dispatch.js → srv/srv-dispatch.js} +13 -8
- package/lib/{serve/Service-handlers.js → srv/srv-handlers.js} +10 -0
- package/lib/{serve/Service-methods.js → srv/srv-methods.js} +10 -8
- package/lib/srv/srv-models.js +207 -0
- package/lib/{serve/Transaction.js → srv/srv-tx.js} +57 -40
- package/lib/utils/{tests.js → cds-test.js} +2 -2
- package/lib/utils/cds-utils.js +146 -0
- package/lib/utils/index.js +2 -145
- package/lib/utils/jest.js +43 -0
- package/lib/utils/resources/index.js +15 -25
- package/lib/utils/resources/tar.js +18 -41
- package/libx/_runtime/auth/index.js +14 -11
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +7 -19
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/delete.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +6 -19
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/PrimitiveValueDecoder.js +0 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/DeserializerFactory.js +3 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +38 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +1 -3
- package/libx/_runtime/cds-services/services/utils/differ.js +4 -0
- package/libx/_runtime/cds-services/util/errors.js +1 -29
- package/libx/_runtime/common/i18n/messages.properties +2 -1
- package/libx/_runtime/common/perf/index.js +10 -15
- package/libx/_runtime/common/utils/binary.js +3 -4
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +0 -1
- package/libx/_runtime/common/utils/entityFromCqn.js +8 -5
- package/libx/_runtime/common/utils/resolveView.js +1 -1
- package/libx/_runtime/common/utils/template.js +1 -1
- package/libx/_runtime/db/Service.js +2 -14
- package/libx/_runtime/db/expand/expandCQNToJoin.js +28 -25
- package/libx/_runtime/db/expand/rawToExpanded.js +7 -6
- package/libx/_runtime/db/generic/input.js +8 -1
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +37 -18
- package/libx/_runtime/extensibility/activate.js +47 -47
- package/libx/_runtime/extensibility/add.js +22 -13
- package/libx/_runtime/extensibility/addExtension.js +17 -13
- package/libx/_runtime/extensibility/defaults.js +25 -30
- package/libx/_runtime/extensibility/handler/transformREAD.js +20 -18
- package/libx/_runtime/extensibility/linter/allowlist_checker.js +373 -0
- package/libx/_runtime/extensibility/linter/annotations_checker.js +113 -0
- package/libx/_runtime/extensibility/linter/checker_base.js +20 -0
- package/libx/_runtime/extensibility/linter/namespace_checker.js +180 -0
- package/libx/_runtime/extensibility/linter.js +32 -0
- package/libx/_runtime/extensibility/push.js +77 -20
- package/libx/_runtime/extensibility/service.js +29 -12
- package/libx/_runtime/extensibility/token.js +56 -0
- package/libx/_runtime/extensibility/utils.js +8 -6
- package/libx/_runtime/extensibility/validation.js +6 -9
- package/libx/_runtime/fiori/generic/new.js +0 -11
- package/libx/_runtime/hana/Service.js +0 -1
- package/libx/_runtime/hana/conversion.js +12 -1
- package/libx/_runtime/hana/customBuilder/CustomFunctionBuilder.js +4 -3
- package/libx/_runtime/hana/customBuilder/CustomSelectBuilder.js +5 -0
- package/libx/_runtime/hana/pool.js +6 -10
- package/libx/_runtime/hana/search2Contains.js +0 -5
- package/libx/_runtime/hana/search2cqn4sql.js +1 -0
- package/libx/_runtime/messaging/outbox/utils.js +1 -1
- package/libx/_runtime/messaging/service.js +11 -6
- package/libx/_runtime/remote/utils/data.js +5 -0
- package/libx/_runtime/sqlite/Service.js +7 -6
- package/libx/_runtime/sqlite/execute.js +41 -28
- package/libx/odata/afterburner.js +79 -2
- package/libx/odata/cqn2odata.js +9 -7
- package/libx/odata/grammar.pegjs +157 -76
- package/libx/odata/index.js +9 -3
- package/libx/odata/parser.js +1 -1
- package/libx/odata/utils.js +39 -5
- package/libx/rest/RestAdapter.js +3 -7
- package/libx/rest/middleware/delete.js +4 -5
- package/libx/rest/middleware/parse.js +3 -2
- package/package.json +3 -3
- package/server.js +1 -1
- package/srv/extensibility-service.cds +6 -3
- package/srv/model-provider.cds +3 -1
- package/srv/model-provider.js +84 -104
- package/srv/mtx.js +7 -1
- 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('./
|
|
20
|
+
* @returns { Transaction & import('./srv-api') }
|
|
9
21
|
* @param { EventContext } ctx
|
|
10
22
|
*/
|
|
11
|
-
|
|
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 =
|
|
19
|
-
|
|
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
|
-
//
|
|
39
|
-
return
|
|
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,
|
|
49
|
-
|
|
50
|
-
if (
|
|
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,
|
|
57
|
+
if (!tx) txs.set (srv, tx = new this (srv,ctx))
|
|
53
58
|
return tx
|
|
54
59
|
}
|
|
55
60
|
|
|
56
|
-
constructor (srv,
|
|
57
|
-
const tx = { __proto__:srv, context:
|
|
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
|
|
106
|
-
* @param {EventContext}
|
|
114
|
+
* Register the new transaction with the given context.
|
|
115
|
+
* @param {EventContext} ctx
|
|
107
116
|
*/
|
|
108
|
-
static for (srv,
|
|
109
|
-
|
|
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
|
|
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 {
|
|
169
|
+
* @param {EventContext} ctx
|
|
155
170
|
*/
|
|
156
|
-
constructor (srv,
|
|
157
|
-
super (srv,
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if ('end' in srv)
|
|
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
|
package/lib/utils/index.js
CHANGED
|
@@ -1,145 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
|
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
|
|
12
|
-
|
|
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
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
39
|
+
await unpackArchiveCLI(tgz, folder)
|
|
50
40
|
} finally {
|
|
51
|
-
if (await exists(temp)) await
|
|
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
|
|
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 = (
|
|
18
|
-
const cmd = '
|
|
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
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
}
|