@sap/cds 6.0.2 → 6.1.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.
- package/CHANGELOG.md +153 -19
- package/apis/cds.d.ts +11 -7
- package/apis/log.d.ts +48 -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 +13 -32
- package/bin/build/provider/buildTaskHandlerInternal.js +56 -4
- package/bin/build/provider/buildTaskProviderInternal.js +22 -14
- package/bin/build/provider/hana/index.js +8 -7
- 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 +64 -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/build/util.js +6 -4
- package/bin/deploy/to-hana/cfUtil.js +7 -2
- package/bin/deploy/to-hana/hana.js +6 -3
- package/bin/serve.js +8 -13
- 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} +8 -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 +605 -0
- package/lib/index.js +20 -17
- package/lib/log/{errors.js → cds-error.js} +1 -1
- package/lib/log/{index.js → cds-log.js} +0 -0
- package/lib/ql/SELECT.js +1 -1
- package/lib/ql/{index.js → cds-ql.js} +0 -0
- package/lib/req/cds-context.js +1 -1
- package/lib/req/context.js +35 -7
- 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 +2 -3
- package/lib/{serve/Service-api.js → srv/srv-api.js} +14 -6
- package/lib/{serve/Service-dispatch.js → srv/srv-dispatch.js} +3 -2
- 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 +206 -0
- package/lib/{serve/Transaction.js → srv/srv-tx.js} +6 -1
- package/lib/utils/{tests.js → cds-test.js} +2 -2
- package/lib/utils/cds-utils.js +146 -0
- package/lib/utils/index.js +2 -136
- package/lib/utils/jest.js +43 -0
- package/lib/utils/resources/index.js +14 -24
- package/lib/utils/resources/tar.js +18 -41
- package/libx/_runtime/auth/index.js +13 -10
- package/libx/_runtime/cds-services/adapter/odata-v4/OData.js +9 -20
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +1 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/action.js +19 -7
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +8 -11
- 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 +2 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +8 -10
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +38 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/handlerUtils.js +2 -6
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +8 -5
- 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/constants/events.js +1 -3
- package/libx/_runtime/common/i18n/messages.properties +2 -1
- package/libx/_runtime/common/perf/index.js +10 -15
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +0 -1
- package/libx/_runtime/common/utils/entityFromCqn.js +8 -5
- 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/generic/input.js +4 -0
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +37 -18
- package/libx/_runtime/extensibility/activate.js +47 -47
- package/libx/_runtime/extensibility/add.js +19 -13
- package/libx/_runtime/extensibility/addExtension.js +17 -13
- package/libx/_runtime/extensibility/defaults.js +25 -30
- 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 +78 -21
- package/libx/_runtime/extensibility/service.js +29 -12
- package/libx/_runtime/extensibility/token.js +56 -0
- package/libx/_runtime/extensibility/validation.js +6 -9
- package/libx/_runtime/fiori/generic/activate.js +0 -4
- package/libx/_runtime/fiori/generic/edit.js +1 -9
- package/libx/_runtime/fiori/generic/new.js +3 -28
- package/libx/_runtime/fiori/generic/patch.js +6 -7
- package/libx/_runtime/fiori/generic/prepare.js +11 -18
- package/libx/_runtime/fiori/generic/read.js +11 -1
- package/libx/_runtime/fiori/utils/handler.js +0 -17
- 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/AMQPWebhookMessaging.js +18 -19
- package/libx/_runtime/messaging/file-based.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/client.js +6 -2
- package/libx/_runtime/remote/utils/data.js +5 -0
- package/libx/_runtime/sqlite/Service.js +0 -1
- package/libx/odata/afterburner.js +79 -2
- package/libx/odata/cqn2odata.js +9 -7
- package/libx/odata/grammar.pegjs +161 -77
- 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 +1 -2
- 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
|
@@ -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 || 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
|
+
|
|
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,136 +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
|
-
/** @type <T>(o,p,v:T) => T */
|
|
135
|
-
const $set = (o,p,v) => { Object.defineProperty(o,p,{value:v}); return v }
|
|
136
|
-
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,36 +1,26 @@
|
|
|
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
|
|
9
|
+
const packTarArchive = async (files, root, flat = false) => {
|
|
10
|
+
if (typeof files === 'string') return await packArchiveCLI(files)
|
|
11
|
+
|
|
12
12
|
let tgzBuffer, temp
|
|
13
|
-
|
|
14
13
|
try {
|
|
15
|
-
temp = await fs.promises.mkdtemp(`${TEMP_DIR}${path.sep}tar-`)
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
files = files_
|
|
24
|
-
root = temp
|
|
14
|
+
temp = await fs.promises.mkdtemp(`${TEMP_DIR}${path.sep}tar-`)
|
|
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
26
|
await (fs.promises.rm || fs.promises.rmdir)(temp, { recursive: true, force: true })
|
|
@@ -40,13 +30,13 @@ const packTarArchive = async (files, root, flat = false, cli = true) => {
|
|
|
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
41
|
if (await exists(temp)) await (fs.promises.rm || fs.promises.rmdir)(temp, { recursive: true, force: true })
|
|
52
42
|
}
|
|
@@ -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 || fs.promises.rmdir)(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
|
}
|
|
@@ -57,7 +57,7 @@ const _log = (req, challenges) => {
|
|
|
57
57
|
LOG.debug(`User "${req.user.id}" request URL`, req.url, '\n', ...challengesLog)
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
const
|
|
60
|
+
const cap_auth_callback = (req, res, next, internalError, user, challenges) => {
|
|
61
61
|
// An internal error occurs during the authentication process
|
|
62
62
|
if (internalError) {
|
|
63
63
|
// REVISIT: What to do? Security log?
|
|
@@ -83,7 +83,7 @@ const _authCallback = (req, res, next, internalError, user, challenges) => {
|
|
|
83
83
|
|
|
84
84
|
const _mountCustomAuth = (srv, app, config) => {
|
|
85
85
|
const impl = cds.resolve(config.impl)
|
|
86
|
-
app.use(
|
|
86
|
+
app.use(_require(impl))
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
const _mountMockAuth = (srv, app, strategy, config) => {
|
|
@@ -92,12 +92,12 @@ const _mountMockAuth = (srv, app, strategy, config) => {
|
|
|
92
92
|
? new (require('./strategies/dummy'))()
|
|
93
93
|
: new (require('./strategies/mock'))(config, `mock_${srv.name}`)
|
|
94
94
|
|
|
95
|
-
app.use(
|
|
95
|
+
app.use(function cap_auth(req, res, next) {
|
|
96
96
|
let user, challenge
|
|
97
97
|
impl.success = arg => (user = arg)
|
|
98
98
|
impl.fail = arg => (challenge = arg)
|
|
99
99
|
impl.authenticate(req)
|
|
100
|
-
|
|
100
|
+
cap_auth_callback(req, res, next, undefined, user, [challenge])
|
|
101
101
|
})
|
|
102
102
|
}
|
|
103
103
|
|
|
@@ -119,10 +119,10 @@ const _mountPassportAuth = (srv, app, strategy, config) => {
|
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
// authenticate
|
|
122
|
-
app.use(
|
|
123
|
-
app.use(
|
|
122
|
+
app.use(passport.initialize())
|
|
123
|
+
app.use((req, res, next) => {
|
|
124
124
|
const options = { session: false, failWithError: true }
|
|
125
|
-
const callback =
|
|
125
|
+
const callback = cap_auth_callback.bind(undefined, req, res, next)
|
|
126
126
|
passport.authenticate(strategy === 'jwt' ? 'JWT' : strategy, options, callback)(req, res, next)
|
|
127
127
|
})
|
|
128
128
|
}
|
|
@@ -131,7 +131,9 @@ const _mountPassportAuth = (srv, app, strategy, config) => {
|
|
|
131
131
|
* export authentication middleware
|
|
132
132
|
*/
|
|
133
133
|
// eslint-disable-next-line complexity
|
|
134
|
-
module.exports = (srv,
|
|
134
|
+
module.exports = (srv, options = srv.options) => {
|
|
135
|
+
const handlers = [],
|
|
136
|
+
app = { use: h => handlers.push(h) }
|
|
135
137
|
// NOTE: options.auth is not an official API
|
|
136
138
|
let config = 'auth' in options ? options.auth : cds.env.requires.auth
|
|
137
139
|
if (!config) {
|
|
@@ -147,7 +149,7 @@ module.exports = (srv, app, options) => {
|
|
|
147
149
|
LOG._warn && LOG.warn(`No authentication configured. This is not recommended in production.`)
|
|
148
150
|
}
|
|
149
151
|
// no auth wanted > return
|
|
150
|
-
return
|
|
152
|
+
return handlers
|
|
151
153
|
}
|
|
152
154
|
|
|
153
155
|
// cds.env.requires.auth = { kind: 'xsuaa-auth' } was briefly documented on capire -> also support
|
|
@@ -181,11 +183,12 @@ module.exports = (srv, app, options) => {
|
|
|
181
183
|
(process.env.NODE_ENV === 'production' && config.credentials && config.restrict_all_services)
|
|
182
184
|
) {
|
|
183
185
|
if (!logged) LOG._debug && LOG.debug(`Enforcing authenticated users for all services`)
|
|
184
|
-
app.use(
|
|
186
|
+
app.use(_enforce_authenticated_user)
|
|
185
187
|
}
|
|
186
188
|
|
|
187
189
|
// so we don't log the same stuff multiple times
|
|
188
190
|
logged = true
|
|
191
|
+
return handlers
|
|
189
192
|
}
|
|
190
193
|
|
|
191
194
|
const _strategy4 = config => {
|
|
@@ -107,8 +107,7 @@ class OData {
|
|
|
107
107
|
constructor(edm, csn, options = {}) {
|
|
108
108
|
this._validateEdm(edm)
|
|
109
109
|
this._options = options
|
|
110
|
-
this.
|
|
111
|
-
this._createOdataService(edm)
|
|
110
|
+
this._createOdataService(edm, csn)
|
|
112
111
|
}
|
|
113
112
|
|
|
114
113
|
_validateEdm(edm) {
|
|
@@ -118,7 +117,7 @@ class OData {
|
|
|
118
117
|
}
|
|
119
118
|
}
|
|
120
119
|
|
|
121
|
-
_createOdataService(edm) {
|
|
120
|
+
_createOdataService(edm, csn) {
|
|
122
121
|
const ServiceFactory = require('./okra/odata-server').ServiceFactory
|
|
123
122
|
|
|
124
123
|
// skip okra's validation in production or implicitly for w4 and x4
|
|
@@ -133,7 +132,7 @@ class OData {
|
|
|
133
132
|
effective.odata.proxies ||
|
|
134
133
|
effective.odata.xrefs
|
|
135
134
|
|
|
136
|
-
this._odataService = ServiceFactory.createService(edm, _config(edm,
|
|
135
|
+
this._odataService = ServiceFactory.createService(edm, _config(edm, csn, this._options)).trust(isTrusted)
|
|
137
136
|
|
|
138
137
|
// will be added to express app like app.use('/base/path/', service) and odata-v4 wants app.use('/', service) if basePath is set
|
|
139
138
|
this._odataService.setBasePath('/')
|
|
@@ -162,10 +161,10 @@ class OData {
|
|
|
162
161
|
const txs = (data.txs = data.txs || {})
|
|
163
162
|
const {
|
|
164
163
|
req: { user },
|
|
165
|
-
req
|
|
164
|
+
req,
|
|
165
|
+
res
|
|
166
166
|
} = data
|
|
167
|
-
|
|
168
|
-
const tx = (txs[odataContext.id] = cdsService.tx({ user, req, _model: cdsService.model }))
|
|
167
|
+
const tx = (txs[odataContext.id] = cdsService.tx({ user, req, res }))
|
|
169
168
|
cds.context = tx.context
|
|
170
169
|
// for collecting results and errors
|
|
171
170
|
data.results = data.results || {}
|
|
@@ -182,19 +181,8 @@ class OData {
|
|
|
182
181
|
if (errors) {
|
|
183
182
|
// rollback without errors to not trigger srv.on('error') with array
|
|
184
183
|
await tx.rollback()
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
const failedRequests = {}
|
|
188
|
-
|
|
189
|
-
for (const e of errors) {
|
|
190
|
-
const { error: err, req } = e
|
|
191
|
-
for (const each of cdsService._handlers._error) each.handler.call(cdsService, err, req)
|
|
192
|
-
const requestId = req._.odataReq.getOdataRequestId()
|
|
193
|
-
const { error, statusCode } = normalizeError(err, req)
|
|
194
|
-
failedRequests[requestId] = Object.assign(error, { statusCode })
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
done(new Error(`Atomicity group "${odataContext.id}" failed`), { failedRequests })
|
|
184
|
+
|
|
185
|
+
done()
|
|
198
186
|
return
|
|
199
187
|
}
|
|
200
188
|
|
|
@@ -225,6 +213,7 @@ class OData {
|
|
|
225
213
|
this._odataService.use(DATA_DELETE_HANDLER, _delete(cdsService))
|
|
226
214
|
|
|
227
215
|
this._odataService.use(ACTION_EXECUTE_HANDLER, _action(cdsService))
|
|
216
|
+
return this
|
|
228
217
|
}
|
|
229
218
|
|
|
230
219
|
/**
|
|
@@ -163,12 +163,9 @@ class ODataRequest extends cds.Request {
|
|
|
163
163
|
*/
|
|
164
164
|
const { user } = req
|
|
165
165
|
|
|
166
|
-
// REVISIT: _model should not be necessary
|
|
167
|
-
const _model = service.model
|
|
168
|
-
|
|
169
166
|
// REVISIT: public API for query options (express style req.query already in use)?
|
|
170
167
|
const _queryOptions = odataReq.getQueryOptions()
|
|
171
|
-
super({ event, target, data, query, user, method, headers, req, res,
|
|
168
|
+
super({ event, target, data, query, user, method, headers, req, res, _queryOptions })
|
|
172
169
|
}
|
|
173
170
|
|
|
174
171
|
/*
|