@sap/cds 6.8.4 → 7.0.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 +66 -4
- package/README.md +0 -1
- package/bin/cds-serve.js +50 -3
- package/bin/deploy/to-hana.js +1 -0
- package/bin/serve.js +16 -20
- package/lib/auth/basic-auth.js +6 -4
- package/lib/auth/index.js +4 -3
- package/lib/auth/jwt-auth.js +2 -5
- package/lib/compile/cds-compile.js +34 -89
- package/lib/compile/cdsc.js +11 -0
- package/lib/compile/etc/properties.js +2 -2
- package/lib/compile/for/lean_drafts.js +36 -69
- package/lib/compile/for/nodejs.js +2 -1
- package/lib/compile/load.js +3 -3
- package/lib/compile/minify.js +2 -0
- package/lib/compile/to/csn.js +74 -0
- package/{bin/build/provider/hana/2tabledata.js → lib/compile/to/hdbtabledata.js} +4 -6
- package/lib/compile/to/json.js +1 -1
- package/lib/compile/to/sql.js +8 -6
- package/lib/dbs/cds-deploy.js +174 -114
- package/lib/env/cds-env.js +64 -79
- package/lib/env/cds-requires.js +11 -28
- package/lib/env/defaults.js +13 -3
- package/lib/env/plugins.js +1 -12
- package/lib/env/presets.js +25 -21
- package/lib/index.js +121 -147
- package/lib/{core/reflect.js → linked/models.js} +2 -2
- package/lib/{core/infer.js → linked/queries.js} +2 -0
- package/lib/{core/index.js → linked/types.js} +2 -1
- package/lib/log/cds-error.js +13 -7
- package/lib/log/format/cf.js +1 -1
- package/lib/plugins.js +49 -0
- package/lib/ql/Query.js +0 -9
- package/lib/ql/STREAM.js +0 -1
- package/lib/req/context.js +2 -7
- package/lib/req/request.js +6 -2
- package/lib/req/response.js +23 -10
- package/lib/srv/middlewares/ctx-model.js +2 -2
- package/lib/srv/middlewares/errors.js +1 -1
- package/lib/srv/protocols/_legacy.js +1 -0
- package/lib/srv/protocols/graphql.js +7 -16
- package/lib/srv/protocols/index.js +59 -45
- package/lib/srv/protocols/odata-v2-proxy.js +2 -70
- package/lib/srv/protocols/odata-v4.js +9 -4
- package/lib/srv/srv-api.js +9 -3
- package/lib/srv/srv-dispatch.js +12 -9
- package/lib/srv/srv-models.js +4 -21
- package/lib/srv/srv-tx.js +15 -12
- package/lib/utils/cds-test.js +14 -9
- package/lib/utils/cds-utils.js +2 -12
- package/lib/utils/check-version.js +17 -0
- package/{bin/build → lib/utils}/csv-reader.js +23 -24
- package/libx/_runtime/auth/index.js +27 -23
- package/libx/_runtime/cds-services/adapter/odata-v4/ODataRequest.js +15 -72
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/create.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +0 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/read.js +33 -63
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/request.js +14 -18
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/update.js +15 -5
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/ExpressionToCQN.js +5 -4
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/readToCQN.js +37 -40
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/updateToCQN.js +7 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/odata-to-cqn/utils.js +101 -38
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/errors/AbstractError.js +5 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/uri/UriTokenizer.js +5 -8
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-commons/utils/ValueConverter.js +2 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/deserializer/ResourceJsonDeserializer.js +9 -8
- package/libx/_runtime/cds-services/adapter/odata-v4/to.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +15 -11
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/readAfterWrite.js +4 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/result.js +5 -2
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/stream.js +1 -123
- package/libx/_runtime/cds-services/services/Service.js +79 -107
- package/libx/_runtime/cds-services/services/utils/columns.js +23 -19
- package/libx/_runtime/cds-services/services/utils/compareJson.js +11 -1
- package/libx/_runtime/cds-services/services/utils/differ.js +7 -2
- package/libx/_runtime/cds-services/util/assert.js +65 -2
- package/libx/_runtime/common/composition/data.js +1 -0
- package/libx/_runtime/common/generic/auth/expand.js +1 -1
- package/libx/_runtime/common/generic/auth/restrict.js +5 -10
- package/libx/_runtime/common/generic/auth/restrictions.js +40 -0
- package/libx/_runtime/common/generic/auth/utils.js +1 -2
- package/libx/_runtime/common/generic/crud.js +32 -16
- package/libx/_runtime/common/generic/etag.js +133 -104
- package/libx/_runtime/common/generic/input.js +6 -21
- package/libx/_runtime/common/generic/put.js +1 -1
- package/libx/_runtime/common/generic/stream.js +52 -0
- package/libx/_runtime/common/generic/temporal.js +25 -8
- package/libx/_runtime/common/i18n/messages.properties +0 -2
- package/libx/_runtime/common/utils/cqn.js +1 -1
- package/libx/_runtime/common/utils/cqn2cqn4sql.js +5 -2
- package/libx/_runtime/common/utils/csn.js +0 -51
- package/libx/_runtime/common/utils/etag.js +30 -0
- package/libx/_runtime/common/utils/keys.js +1 -1
- package/libx/_runtime/common/utils/normalizeTimestamp.js +25 -0
- package/libx/_runtime/common/utils/path.js +1 -1
- package/libx/_runtime/common/utils/resolveView.js +2 -1
- package/libx/_runtime/common/utils/rewriteAsterisks.js +6 -4
- package/libx/_runtime/common/utils/search2cqn4sql.js +12 -16
- package/libx/_runtime/common/utils/stream.js +140 -0
- package/libx/_runtime/common/utils/streamProp.js +29 -12
- package/libx/_runtime/common/utils/templateProcessorPathSerializer.js +0 -2
- package/libx/_runtime/db/generic/index.js +0 -2
- package/libx/_runtime/db/query/delete.js +2 -2
- package/libx/_runtime/db/query/insert.js +2 -2
- package/libx/_runtime/db/query/read.js +2 -2
- package/libx/_runtime/db/query/run.js +2 -2
- package/libx/_runtime/db/query/update.js +2 -2
- package/libx/_runtime/db/sql-builder/BaseBuilder.js +0 -6
- package/libx/_runtime/db/sql-builder/ExpressionBuilder.js +23 -12
- package/libx/_runtime/db/sql-builder/FunctionBuilder.js +18 -6
- package/libx/_runtime/db/sql-builder/InsertBuilder.js +1 -0
- package/libx/_runtime/db/sql-builder/SelectBuilder.js +3 -7
- package/libx/_runtime/db/sql-builder/UpsertBuilder.js +1 -0
- package/libx/_runtime/db/utils/normalizeTimeData.js +7 -3
- package/libx/_runtime/fiori/draft.js +2 -0
- package/libx/_runtime/fiori/generic/activate.js +8 -9
- package/libx/_runtime/fiori/generic/before.js +30 -20
- package/libx/_runtime/fiori/generic/cancel.js +5 -3
- package/libx/_runtime/fiori/generic/delete.js +5 -3
- package/libx/_runtime/fiori/generic/edit.js +7 -7
- package/libx/_runtime/fiori/generic/index.js +10 -16
- package/libx/_runtime/fiori/generic/new.js +5 -3
- package/libx/_runtime/fiori/generic/patch.js +11 -8
- package/libx/_runtime/fiori/generic/prepare.js +13 -6
- package/libx/_runtime/fiori/generic/read.js +12 -6
- package/libx/_runtime/fiori/lean-draft.js +207 -152
- package/libx/_runtime/fiori/utils/delete.js +10 -5
- package/libx/_runtime/fiori/utils/req.js +17 -5
- package/libx/_runtime/fiori/utils/stream.js +36 -0
- package/libx/_runtime/hana/Service.js +12 -9
- package/libx/_runtime/hana/conversion.js +10 -15
- package/libx/_runtime/hana/driver.js +2 -0
- package/libx/_runtime/hana/execute.js +28 -6
- package/libx/_runtime/hana/pool.js +36 -122
- package/libx/_runtime/hana/search2cqn4sql.js +34 -36
- package/libx/_runtime/messaging/enterprise-messaging-utils/getTenantInfo.js +2 -6
- package/libx/_runtime/messaging/enterprise-messaging-utils/registerEndpoints.js +3 -1
- package/libx/_runtime/messaging/enterprise-messaging.js +10 -58
- package/libx/_runtime/messaging/outbox/utils.js +1 -1
- package/libx/_runtime/remote/Service.js +20 -1
- package/libx/_runtime/remote/utils/client.js +3 -5
- package/libx/_runtime/sqlite/Service.js +4 -6
- package/libx/_runtime/sqlite/conversion.js +3 -13
- package/libx/_runtime/sqlite/customBuilder/CustomFunctionBuilder.js +9 -6
- package/libx/_runtime/sqlite/customBuilder/CustomUpsertBuilder.js +6 -1
- package/libx/_runtime/sqlite/execute.js +5 -16
- package/libx/odata/afterburner.js +22 -6
- package/libx/odata/grammar.pegjs +6 -1
- package/libx/odata/parser.js +1 -1
- package/libx/rest/RestAdapter.js +16 -9
- package/libx/rest/RestRequest.js +1 -1
- package/libx/rest/middleware/input.js +2 -1
- package/libx/rest/middleware/operation.js +1 -0
- package/libx/rest/middleware/parse.js +3 -2
- package/libx/rest/middleware/payload.js +9 -8
- package/libx/rest/middleware/read.js +1 -0
- package/package.json +9 -16
- package/server.js +1 -1
- package/app/fiori/preview.js +0 -270
- package/app/fiori/routes.js +0 -59
- package/bin/build/buildTaskEngine.js +0 -360
- package/bin/build/buildTaskFactory.js +0 -283
- package/bin/build/buildTaskHandler.js +0 -241
- package/bin/build/buildTaskProvider.js +0 -22
- package/bin/build/buildTaskProviderFactory.js +0 -175
- package/bin/build/cds.js +0 -5
- package/bin/build/constants.js +0 -66
- package/bin/build/index.js +0 -58
- package/bin/build/provider/buildTaskHandlerEdmx.js +0 -82
- package/bin/build/provider/buildTaskHandlerFeatureToggles.js +0 -131
- package/bin/build/provider/buildTaskHandlerInternal.js +0 -254
- package/bin/build/provider/buildTaskProviderInternal.js +0 -383
- package/bin/build/provider/fiori/index.js +0 -171
- package/bin/build/provider/hana/2migration.js +0 -179
- package/bin/build/provider/hana/index.js +0 -505
- package/bin/build/provider/hana/migrationtable.js +0 -472
- package/bin/build/provider/hana/template/.hdiconfig-haas +0 -163
- package/bin/build/provider/hana/template/.hdiconfig-hanacloud +0 -137
- package/bin/build/provider/hana/template/.hdinamespace +0 -4
- package/bin/build/provider/hana/template/package.json +0 -12
- package/bin/build/provider/hana/template/undeploy.json +0 -5
- package/bin/build/provider/java/index.js +0 -111
- package/bin/build/provider/java-cf/index.js +0 -1
- package/bin/build/provider/mtx/index.js +0 -268
- package/bin/build/provider/mtx/resourcesTarBuilder.js +0 -95
- package/bin/build/provider/mtx-extension/index.js +0 -131
- package/bin/build/provider/mtx-sidecar/index.js +0 -137
- package/bin/build/provider/node-cf/index.js +0 -1
- package/bin/build/provider/nodejs/index.js +0 -192
- package/bin/build/util.js +0 -299
- package/bin/cds.js +0 -125
- package/bin/deploy/to-hana/cfUtil.js +0 -355
- package/bin/deploy/to-hana/gitUtil.js +0 -57
- package/bin/deploy/to-hana/hana.js +0 -306
- package/bin/deploy/to-hana/hdiDeployUtil.js +0 -153
- package/bin/deploy/to-hana/index.js +0 -16
- package/bin/deploy/to-hana/mtaUtil.js +0 -170
- package/bin/mtx/in-cds.js +0 -17
- package/bin/plugins.js +0 -32
- package/bin/run.js +0 -24
- package/bin/utils/log.js +0 -24
- package/bin/version.js +0 -178
- package/libx/_runtime/audit/Service.js +0 -222
- package/libx/_runtime/audit/generic/personal/access.js +0 -61
- package/libx/_runtime/audit/generic/personal/index.js +0 -56
- package/libx/_runtime/audit/generic/personal/modification.js +0 -132
- package/libx/_runtime/audit/generic/personal/utils.js +0 -186
- package/libx/_runtime/audit/utils/log.js +0 -23
- package/libx/_runtime/audit/utils/v2.js +0 -176
- package/libx/_runtime/db/data-conversion/timestamp.js +0 -9
- package/libx/_runtime/db/generic/integrity.js +0 -455
- package/srv/audit-log.cds +0 -87
- package/srv/mtx.cds +0 -2
- package/srv/mtx.js +0 -8
- /package/lib/{core → linked}/classes.js +0 -0
- /package/lib/{core → linked}/entities.js +0 -0
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
const path = require('path')
|
|
2
|
-
const fs = require('fs')
|
|
3
|
-
const cds = require('../../cds')
|
|
4
|
-
|
|
5
|
-
const BuildTaskHandlerInternal = require('../buildTaskHandlerInternal')
|
|
6
|
-
const { FOLDER_GEN, EXTENSION_POINT_VALIDATION } = require('../../constants')
|
|
7
|
-
const ResourcesTarBuilder = require('../mtx/resourcesTarBuilder')
|
|
8
|
-
const { BuildError, BuildMessage } = require('../../util')
|
|
9
|
-
|
|
10
|
-
class MtxExtensionModuleBuilder extends BuildTaskHandlerInternal {
|
|
11
|
-
init() {
|
|
12
|
-
super.init()
|
|
13
|
-
if (this.buildOptions.root === this.buildOptions.target) {
|
|
14
|
-
this.task.dest = path.join(this.task.dest, FOLDER_GEN)
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async build() {
|
|
19
|
-
const { src, dest } = this.task
|
|
20
|
-
const destExt = path.join(dest, 'ext')
|
|
21
|
-
// check existence of appPackage folder only
|
|
22
|
-
// REVISIT: cds.resolve will fail as no index.csn file exists in this folder for the extension migration use case
|
|
23
|
-
// a compilation error is thrown anyhow if any base model refs cannot be resolved
|
|
24
|
-
const appPackageFolder = this._getAppPackageFolder()
|
|
25
|
-
if (!fs.existsSync(path.join(src, appPackageFolder))) {
|
|
26
|
-
throw new BuildError(`The SaaS application base model '${appPackageFolder}' is missing. Have you run the 'cds pull' command?`)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
// full compile of the extension using base model - ensuring consistency
|
|
30
|
-
const model = await this.model()
|
|
31
|
-
|
|
32
|
-
if (model) {
|
|
33
|
-
// extension CSN using parsed format
|
|
34
|
-
const options = { ...this.options(), flavor: 'parsed' }
|
|
35
|
-
const extModel = await cds.load(this._resolveExtensionFiles(model), options)
|
|
36
|
-
if (extModel.requires) {
|
|
37
|
-
extModel.requires.length = 0
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (!this.hasBuildOption(EXTENSION_POINT_VALIDATION, false)) {
|
|
41
|
-
this._lintExtModel(extModel, model) // throws error in case of linting errors
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
await this.compileToJson(extModel, path.join(destExt, 'extension.csn'))
|
|
45
|
-
|
|
46
|
-
await this.collectLanguageBundles(extModel, path.join(destExt, 'i18n'))
|
|
47
|
-
|
|
48
|
-
const files = Object.keys(await cds.deploy.resources(model))
|
|
49
|
-
if (files.length > 0) {
|
|
50
|
-
const dataDest = path.join(destExt, 'data')
|
|
51
|
-
await Promise.all(
|
|
52
|
-
files
|
|
53
|
-
.filter(file => /\.csv$/.test(file))
|
|
54
|
-
.map(csv => {
|
|
55
|
-
return this.copy(csv).to(path.join(dataDest, path.basename(csv)))
|
|
56
|
-
})
|
|
57
|
-
)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
const packageJson = path.join(src, 'package.json')
|
|
62
|
-
if (!fs.existsSync(packageJson)) {
|
|
63
|
-
throw new BuildError(`package.json file not found in ${src}`)
|
|
64
|
-
}
|
|
65
|
-
await this.copy(packageJson).to(path.join(destExt, 'package.json'))
|
|
66
|
-
|
|
67
|
-
// copy handlers
|
|
68
|
-
const folders = [path.join(src, cds.env.folders.srv, 'handlers')]
|
|
69
|
-
await this.copyNativeContent(src, destExt, res => {
|
|
70
|
-
if (fs.statSync(res).isDirectory()) {
|
|
71
|
-
return folders.some(folder => folder.startsWith(res))
|
|
72
|
-
}
|
|
73
|
-
if (folders.includes(path.dirname(res)) && /\.js$/.test(res)) {
|
|
74
|
-
return true
|
|
75
|
-
}
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
// add all resources contained in 'gen/ext' folder
|
|
79
|
-
await new ResourcesTarBuilder(this).writeTarFile(path.join(this.task.dest, 'extension.tgz'), destExt)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
_resolveExtensionFiles(model) {
|
|
83
|
-
const node_modules = path.join(this.task.src, 'node_modules')
|
|
84
|
-
const paths = model['$sources'].reduce((acc, file) => {
|
|
85
|
-
if (file.startsWith(this.task.src) && !file.startsWith(node_modules)) {
|
|
86
|
-
acc.push(file)
|
|
87
|
-
}
|
|
88
|
-
return acc
|
|
89
|
-
}, [])
|
|
90
|
-
|
|
91
|
-
return paths
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
_lintExtModel(extModel, model) {
|
|
95
|
-
const linter = this._linter()
|
|
96
|
-
if (!linter) {
|
|
97
|
-
return
|
|
98
|
-
}
|
|
99
|
-
const env = cds.env.for('cds', path.join(this.task.src, this._getAppPackageFolder()))
|
|
100
|
-
this.logger._debug && this.logger.debug(`Saas extension point restrictions:\n${env.requires?.['cds.xt.ExtensibilityService']}`)
|
|
101
|
-
|
|
102
|
-
const messages = linter.lint(extModel, model, env)
|
|
103
|
-
if (messages.length) {
|
|
104
|
-
// REVISIT: lint messages can be passed as is with cds-mtxs version >= 1.7
|
|
105
|
-
throw new BuildError('SaaS extension point restrictions violated. Check the concrete restrictions defined by the SaaS app provider.',
|
|
106
|
-
messages.map(f => new BuildMessage(f.message, f.severity, f.location || f.element?.$location)))
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
_linter() {
|
|
111
|
-
let linter
|
|
112
|
-
try {
|
|
113
|
-
// Make sure cds-mtxs APIs are loaded
|
|
114
|
-
linter = require('@sap/cds-mtxs').xt?.linter // eslint-disable-line cds/no-missing-dependencies
|
|
115
|
-
if (!linter) {
|
|
116
|
-
this.pushMessage('MTXS linter cannot be loaded. Update of @sap/cds-dk and @sap/cds-mtxs modules required? Skipping extension model lint step.')
|
|
117
|
-
return null // too old mtxs
|
|
118
|
-
}
|
|
119
|
-
} catch (e) {
|
|
120
|
-
if (e.code !== 'MODULE_NOT_FOUND') throw e
|
|
121
|
-
this.pushMessage('MTXS linter cannot be loaded, @sap/cds-mtxs not installed. Skipping extension model lint step.')
|
|
122
|
-
}
|
|
123
|
-
return linter
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
_getAppPackageFolder() {
|
|
127
|
-
return path.join('node_modules', cds.env.extends || '_base');
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
module.exports = MtxExtensionModuleBuilder
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
const path = require('path')
|
|
2
|
-
const cds = require('../../cds')
|
|
3
|
-
const fs = require('fs')
|
|
4
|
-
const { FOLDER_GEN, DEFAULT_CSN_FILE_NAME } = require('../../constants')
|
|
5
|
-
const NodeCfModuleBuilder = require('../nodejs')
|
|
6
|
-
const ResourcesTarProvider = require('../mtx/resourcesTarBuilder')
|
|
7
|
-
const { INFO, ERROR } = NodeCfModuleBuilder
|
|
8
|
-
const { relativePaths, BuildError, resolveRequiredSapModels } = require('../../util')
|
|
9
|
-
|
|
10
|
-
const DEFAULT_MAIN_FOLDER = "_main"
|
|
11
|
-
|
|
12
|
-
class MtxSidecarModuleBuilder extends NodeCfModuleBuilder {
|
|
13
|
-
get priority() {
|
|
14
|
-
// should be scheduled after 'hana' build tasks are finished
|
|
15
|
-
return NodeCfModuleBuilder.PRIORITY_MIN_VALUE
|
|
16
|
-
}
|
|
17
|
-
init() {
|
|
18
|
-
super.init()
|
|
19
|
-
if (this.buildOptions.root === this.buildOptions.target) {
|
|
20
|
-
this.task.dest = path.join(this.task.dest, FOLDER_GEN)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Builds the mtx sidecar app consisting of:
|
|
26
|
-
* - nodejs app model defined by the required sidecar services
|
|
27
|
-
* - main app model defined by the build task's model options including feature models and resources TAR
|
|
28
|
-
*
|
|
29
|
-
* build.target=".": 'dest' -> 'model-provider/gen'
|
|
30
|
-
* build.target="gen": 'dest' -> 'gen/model-provider'
|
|
31
|
-
*/
|
|
32
|
-
async build() {
|
|
33
|
-
// nodejs app parts have to be built using sidecar env
|
|
34
|
-
const sidecarEnv = cds.env.for("cds", this.task.src)
|
|
35
|
-
// build main application
|
|
36
|
-
await this._buildMainApp(sidecarEnv)
|
|
37
|
-
// build node application
|
|
38
|
-
await this._buildNodeApp(sidecarEnv)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Builds the mtx sidecar nodejs app parts.
|
|
43
|
-
* @param {object} sidecarEnv cds env based on the sidecar dir
|
|
44
|
-
*/
|
|
45
|
-
async _buildNodeApp(sidecarEnv) {
|
|
46
|
-
const destSidecar = this.task.dest
|
|
47
|
-
const destSidecarSrc = path.join(destSidecar, cds.env.folders.srv)
|
|
48
|
-
const i18nFolder = cds.env.i18n.folders?.[0] || 'i18n'
|
|
49
|
-
const model = this._compileSidecarSync(sidecarEnv)
|
|
50
|
-
await this.compileToJson(model, path.join(destSidecarSrc, DEFAULT_CSN_FILE_NAME))
|
|
51
|
-
|
|
52
|
-
await this.collectLanguageBundles(model, path.join(destSidecarSrc, i18nFolder))
|
|
53
|
-
await this.copyProjectRootContent(this.task.src, destSidecar)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Builds the main app parts containing base model CSN with feature CSNs and resources TAR.
|
|
58
|
-
* @param {object} sidecarEnv cds env based on the sidecar dir
|
|
59
|
-
*/
|
|
60
|
-
async _buildMainApp(sidecarEnv) {
|
|
61
|
-
let main = sidecarEnv.requires['cds.xt.ModelProviderService']?.root
|
|
62
|
-
if (!main) {
|
|
63
|
-
throw new BuildError(`Invalid MTX sidecar configuration. Make sure that the profile 'mtx-sidecar' is configured and an up-to-date version of @sap/cds-mtxs is installed.`)
|
|
64
|
-
}
|
|
65
|
-
const profiles = cds.env.profiles || []
|
|
66
|
-
|
|
67
|
-
if (!profiles.includes("production") && !profiles.includes("prod")) {
|
|
68
|
-
main = DEFAULT_MAIN_FOLDER
|
|
69
|
-
// root should represent the production use case and not development
|
|
70
|
-
this.pushMessage(`MTX sidecar build results are created in folder '${main}'. Enable 'production' or 'prod' profile if the folder is configured differently.`, INFO)
|
|
71
|
-
}
|
|
72
|
-
const destRoot = this.task.dest
|
|
73
|
-
const destMain = path.join(destRoot, main)
|
|
74
|
-
const destMainSrv = path.join(destMain, cds.env.folders.srv)
|
|
75
|
-
const csn = await this.model()
|
|
76
|
-
if (!csn) {
|
|
77
|
-
return
|
|
78
|
-
}
|
|
79
|
-
const { dictionary, sources } = await this.compileAll(csn, destMainSrv, destMain)
|
|
80
|
-
await this.collectAllLanguageBundles(dictionary, sources, destMainSrv, destMain)
|
|
81
|
-
|
|
82
|
-
// create resources TAR
|
|
83
|
-
// resources are determined based on available database build task, SQLite as fallback
|
|
84
|
-
await new ResourcesTarProvider(this).createTar(destMain, csn)
|
|
85
|
-
|
|
86
|
-
// copy package.json and .cdsrc.json from project root
|
|
87
|
-
await this._copyMainConfigFiles(cds.root, destMain)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Synchronous compilation using the sidecar context.
|
|
92
|
-
* @param {object} sidecarEnv cds env based on the sidecar dir
|
|
93
|
-
* @returns the compiled mtx sidecar CSN
|
|
94
|
-
*/
|
|
95
|
-
_compileSidecarSync(sidecarEnv) {
|
|
96
|
-
const env = cds.env
|
|
97
|
-
try {
|
|
98
|
-
cds.root = this.task.src
|
|
99
|
-
cds.env = sidecarEnv
|
|
100
|
-
const modelPaths = cds.resolve('*', false)
|
|
101
|
-
const modelFilePaths = cds.resolve(modelPaths)
|
|
102
|
-
|
|
103
|
-
if (!modelFilePaths || modelFilePaths.length === 0) {
|
|
104
|
-
throw new BuildError("No CDS models found in MTX sidecar. Make sure up-to-date versions of the required npm modules are installed.")
|
|
105
|
-
}
|
|
106
|
-
this._logger._debug && this._logger.debug(`sidecar model: ${relativePaths(this.buildOptions.root, modelFilePaths).join(", ")}`)
|
|
107
|
-
|
|
108
|
-
// check whether all models belonging to the @sap namespace can be resolved
|
|
109
|
-
const unresolved = resolveRequiredSapModels(modelPaths)
|
|
110
|
-
if (unresolved.length > 0) {
|
|
111
|
-
// log error, but don't fail
|
|
112
|
-
throw new BuildError(`CDS models [${unresolved.join(', ')}] required by MTX sidecar cannot be resolved. Make sure up-to-date versions of the corresponding npm modules are installed.`, ERROR)
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// synchronous compilation
|
|
116
|
-
return cds.load(modelFilePaths, { sync: true, ...this.options() })
|
|
117
|
-
} finally {
|
|
118
|
-
// restore project scope
|
|
119
|
-
cds.root = this.buildOptions.root
|
|
120
|
-
cds.env = env
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async _copyMainConfigFiles(src, dest) {
|
|
125
|
-
const packageJson = path.join(src, 'package.json')
|
|
126
|
-
const cdsrcJson = path.join(src, '.cdsrc.json')
|
|
127
|
-
const promises = []
|
|
128
|
-
if (fs.existsSync(packageJson)) {
|
|
129
|
-
promises.push(this.copy(packageJson).to(path.join(dest, 'package.json')))
|
|
130
|
-
}
|
|
131
|
-
if (fs.existsSync(cdsrcJson)) {
|
|
132
|
-
promises.push(this.copy(cdsrcJson).to(path.join(dest, '.cdsrc.json')))
|
|
133
|
-
}
|
|
134
|
-
return promises
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
module.exports = MtxSidecarModuleBuilder
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
module.exports = require('../nodejs')
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
const fs = require('fs')
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const cds = require('../../cds')
|
|
4
|
-
const BuildTaskHandlerEdmx = require('../buildTaskHandlerEdmx')
|
|
5
|
-
const { BuildError } = require('../../util')
|
|
6
|
-
const { BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY, ODATA_VERSION_V2, FOLDER_GEN, BUILD_NODEJS_EDMX_GENERATION, EDMX_GENERATION,
|
|
7
|
-
SKIP_PACKAGE_JSON_GENERATION, CONTENT_EDMX, CONTENT_PACKAGE_JSON, CONTENT_PACKAGELOCK_JSON, CONTENT_NPMRC, CONTENT_CDSRC_JSON,
|
|
8
|
-
CONTENT_ENV, CONTENT_DEFAULT_ENV_JSON } = require('../../constants')
|
|
9
|
-
const { WARNING } = BuildTaskHandlerEdmx
|
|
10
|
-
|
|
11
|
-
class NodejsModuleBuilder extends BuildTaskHandlerEdmx {
|
|
12
|
-
init() {
|
|
13
|
-
super.init()
|
|
14
|
-
// set unified option values in order to ease access later on
|
|
15
|
-
// default value true
|
|
16
|
-
this.task.options[CONTENT_PACKAGE_JSON] = !this.hasBuildOption(CONTENT_PACKAGE_JSON, false) && !this.hasBuildOption(SKIP_PACKAGE_JSON_GENERATION, true) ? true : false
|
|
17
|
-
this.task.options[CONTENT_PACKAGELOCK_JSON] = !this.hasBuildOption(CONTENT_PACKAGELOCK_JSON, false) ? true : false
|
|
18
|
-
this.task.options[CONTENT_NPMRC] = !this.hasBuildOption(CONTENT_NPMRC, false) ? true : false
|
|
19
|
-
this.task.options[CONTENT_CDSRC_JSON] = !this.hasBuildOption(CONTENT_CDSRC_JSON, false) ? true : false
|
|
20
|
-
|
|
21
|
-
// default value false
|
|
22
|
-
this.task.options[CONTENT_EDMX] = this.hasBuildOption(CONTENT_EDMX, true) || this.hasCdsEnvOption(BUILD_NODEJS_EDMX_GENERATION, true) || this.hasBuildOption(EDMX_GENERATION, true) ? true : false
|
|
23
|
-
this.task.options[CONTENT_ENV] = this.hasBuildOption(CONTENT_ENV, true) ? true : false
|
|
24
|
-
this.task.options[CONTENT_DEFAULT_ENV_JSON] = this.hasBuildOption(CONTENT_DEFAULT_ENV_JSON, true) ? true : false
|
|
25
|
-
|
|
26
|
-
if (this.task.options.compileDest) {
|
|
27
|
-
throw new BuildError("Option not supported - compileDest")
|
|
28
|
-
}
|
|
29
|
-
// fallback if src has been defined as '.'
|
|
30
|
-
this.destSrv = this.isStagingBuild() ? path.resolve(this.task.dest, cds.env.folders.srv) : path.join(this.task.dest, FOLDER_GEN)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
options() {
|
|
34
|
-
const options = super.options()
|
|
35
|
-
if (cds.env.requires.extensibility || cds.env.requires.toggles) {
|
|
36
|
-
options.flavor = 'xtended'
|
|
37
|
-
}
|
|
38
|
-
return options
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async build() {
|
|
42
|
-
const destSrv = this.isStagingBuild() ? this.destSrv : path.resolve(this.destSrv, cds.env.folders.srv)
|
|
43
|
-
const destRoot = this.isStagingBuild() ? this.task.dest : this.destSrv
|
|
44
|
-
|
|
45
|
-
if (cds.env.odata?.version === ODATA_VERSION_V2) {
|
|
46
|
-
// log warning as nodejs is only supporting odata version V4
|
|
47
|
-
this.pushMessage("OData v2 is not supported by node runtime. Make sure to define OData v2 in cds configuration.", WARNING)
|
|
48
|
-
}
|
|
49
|
-
// by default model contains all features
|
|
50
|
-
const model = await this.model()
|
|
51
|
-
if (!model) {
|
|
52
|
-
return this._result
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
const { dictionary, sources } = await this.compileAll(model, destSrv, destRoot)
|
|
56
|
-
|
|
57
|
-
// collect and write language bundles into single i18n.json file
|
|
58
|
-
await this.collectAllLanguageBundles(dictionary, sources, destSrv, destRoot)
|
|
59
|
-
|
|
60
|
-
if (this.hasBuildOption(CONTENT_EDMX, true)) {
|
|
61
|
-
const m = await cds.load(sources.base, super.options()) // REVISIT: Quick hack to get inferred model as expected by cds.compile.to.edmx()
|
|
62
|
-
await this.compileToEdmx(m, this.destSrv)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (this.isStagingBuild() && !this.hasBuildOption(BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY)) {
|
|
66
|
-
const srcSrv = this.task.src === this.buildOptions.root ? path.resolve(this.task.src, cds.env.folders.srv) : this.task.src
|
|
67
|
-
await this._copyNativeContent(this.buildOptions.root, srcSrv, destRoot, destSrv)
|
|
68
|
-
await this._fixCapireSamplesDeps(destRoot)
|
|
69
|
-
}
|
|
70
|
-
return this._result
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// REVISIT: fix for capire samples - needs to be reworked
|
|
74
|
-
// Instead of adding relative paths we may better delete the entire entry as relative paths
|
|
75
|
-
// cannot be resolved in cloud deployments anyway.
|
|
76
|
-
// Support for HANA native artifacts defined in sub-modules required
|
|
77
|
-
async _fixCapireSamplesDeps(dest) {
|
|
78
|
-
const packageJson = path.join(dest, 'package.json')
|
|
79
|
-
try {
|
|
80
|
-
const content = require(packageJson)
|
|
81
|
-
const { dependencies } = content
|
|
82
|
-
let changed
|
|
83
|
-
for (let dependency in dependencies) {
|
|
84
|
-
if (dependency.startsWith('@capire/')) {
|
|
85
|
-
dependencies[dependency] = path.relative(dest, path.dirname(require.resolve(dependency + '/package.json')))
|
|
86
|
-
changed = true
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (changed) {
|
|
90
|
-
return this.write(JSON.stringify(content, null, ' ')).to(packageJson)
|
|
91
|
-
}
|
|
92
|
-
} catch (e) {/*ignore*/ }
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
async clean() {
|
|
96
|
-
// staging build content is deleted by BuildTaskEngine
|
|
97
|
-
if (this.buildOptions.target === this.buildOptions.root) {
|
|
98
|
-
// delete the entire 'task.dest' folder otherwise, for details see #constructor
|
|
99
|
-
// - the value of the folder 'src' has been appended to the origin 'task.dest' dir
|
|
100
|
-
this.logger._debug && this.logger.debug(`Deleting build target folder ${this.destSrv}`)
|
|
101
|
-
await fs.promises.rm(this.isStagingBuild() ? this.task.dest : this.destSrv, { force: true, recursive: true })
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
async _copyNativeContent(srcRoot, srcSrv, destRoot, destSrv) {
|
|
106
|
-
// project/srv/** -> 'gen/srv/srv/**'
|
|
107
|
-
const filesFilter = await this._copySrvContent(srcSrv, destRoot, destSrv)
|
|
108
|
-
|
|
109
|
-
// project/* -> 'gen/srv/*'
|
|
110
|
-
await this.copyProjectRootContent(srcRoot, destRoot, (entry) => !filesFilter.includes(path.basename(entry)))
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Copy files for nodejs staging builds from the given <em>src</em>' folder (e.g. 'project/srv') to either <em>destRoot</em> (e.g. 'project/gen/srv')
|
|
115
|
-
* or <em>destSrv</em> (e.g. 'project/gen/srv/srv') folders according to the file semantics.
|
|
116
|
-
* Files with project semantics like 'package.json' or '.npmrc' file are copied to <em>destRoot</em> while others like '.js' service handlers
|
|
117
|
-
* are copied to <em>destSrv</em>.
|
|
118
|
-
* @param {*} src
|
|
119
|
-
* @param {*} destRoot - folder name representing the app root folder (e.g. gen/srv)
|
|
120
|
-
* @param {*} destSrv - folder name representing the app sub-folder (e.g. gen/srv/srv)
|
|
121
|
-
* @returns the list of files that have been copied
|
|
122
|
-
*/
|
|
123
|
-
async _copySrvContent(src, destRoot, destSrv) {
|
|
124
|
-
const srvRootBlockList = RegExp('package\\.json$|package-lock\\.json$|\\.npmrc$|\\.cdsrc\\.json$')
|
|
125
|
-
const srvBlockList = RegExp('\\.cds$|csn\\.json$|\\.csn$|manifest\\.y.?ml$|\\.env($|\\..*$)|default-env\\.json$')
|
|
126
|
-
const srvRootFileNames = []
|
|
127
|
-
|
|
128
|
-
// 1. copy all files to 'destSrv' except those contained in the blocklist (including node_modules)
|
|
129
|
-
// project/srv -> 'gen/srv/srv'
|
|
130
|
-
await super.copyNativeContent(src, destSrv, (entry) => {
|
|
131
|
-
if (fs.statSync(entry).isDirectory()) {
|
|
132
|
-
// TODO shall not copy language bundles - return !/(\/|\\)(node_modules|_i18n)(\/|\\)?$/.test(entry)
|
|
133
|
-
return !/(\/|\\)node_modules(\/|\\)?$/.test(entry)
|
|
134
|
-
}
|
|
135
|
-
// make sure the file exists on srv root level - see https://github.tools.sap/cap/issues/issues/12077
|
|
136
|
-
if (srvRootBlockList.test(entry) && path.dirname(entry) === src) {
|
|
137
|
-
srvRootFileNames.push(path.basename(entry))
|
|
138
|
-
return false
|
|
139
|
-
}
|
|
140
|
-
return !srvBlockList.test(entry)
|
|
141
|
-
})
|
|
142
|
-
|
|
143
|
-
// 2. copy dedicated files like package.json, .npmrc to 'destRoot'
|
|
144
|
-
// project/srv -> 'gen/srv'
|
|
145
|
-
let srvAllowList = "package\\.json$" // always copy package.json, modify only if CONTENT_PACKAGE_JSON is true
|
|
146
|
-
srvAllowList += this.hasBuildOption(CONTENT_PACKAGELOCK_JSON, true) ? "|package-lock\\.json$" : ""
|
|
147
|
-
srvAllowList += this.hasBuildOption(CONTENT_NPMRC, true) ? "|\\.npmrc$" : ""
|
|
148
|
-
srvAllowList += this.hasBuildOption(CONTENT_CDSRC_JSON, true) ? "|\\.cdsrc\\.json$" : ""
|
|
149
|
-
srvAllowList += this.hasBuildOption(CONTENT_ENV, true) ? "|\\.env($|\\..*$)" : ""
|
|
150
|
-
srvAllowList += this.hasBuildOption(CONTENT_DEFAULT_ENV_JSON, true) ? "|default-env\\.json$" : ""
|
|
151
|
-
srvAllowList = new RegExp(srvAllowList)
|
|
152
|
-
await Promise.all(srvRootFileNames.map(fileName => {
|
|
153
|
-
if (srvAllowList.test(fileName)) {
|
|
154
|
-
return this.copy(path.join(src, fileName)).to(path.join(destRoot, fileName))
|
|
155
|
-
}
|
|
156
|
-
}))
|
|
157
|
-
|
|
158
|
-
return srvRootFileNames
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Copy dedicated files (files with project semantics like package.json, .npmrc, .cdsrc, etc.)
|
|
163
|
-
* from the given <em>src</em> folder (e.g. 'project') into the given <em>dest</em> folder (e.g. 'project/gen/srv')
|
|
164
|
-
* @param {*} src
|
|
165
|
-
* @param {*} dest
|
|
166
|
-
* @param {*} filter - copy file if filter function returns true
|
|
167
|
-
*/
|
|
168
|
-
async copyProjectRootContent(src, dest, filter) {
|
|
169
|
-
let { folders = ['i18n'] } = cds.env.i18n
|
|
170
|
-
folders.push('handlers')
|
|
171
|
-
folders = folders.map(folder => path.join(src, folder))
|
|
172
|
-
let srvAllowList = "package\\.json$" // always copy package.json, modify only if CONTENT_PACKAGE_JSON is true
|
|
173
|
-
srvAllowList += this.hasBuildOption(CONTENT_PACKAGELOCK_JSON, true) ? "|package-lock\\.json$" : ""
|
|
174
|
-
srvAllowList += this.hasBuildOption(CONTENT_NPMRC, true) ? "|\\.npmrc$" : ""
|
|
175
|
-
srvAllowList += this.hasBuildOption(CONTENT_CDSRC_JSON, true) ? "|\\.cdsrc\\.json$" : ""
|
|
176
|
-
srvAllowList += this.hasBuildOption(CONTENT_ENV, true) ? "|\\.env($|\\..*$)" : ""
|
|
177
|
-
srvAllowList += this.hasBuildOption(CONTENT_DEFAULT_ENV_JSON, true) ? "|default-env\\.json$" : ""
|
|
178
|
-
srvAllowList = new RegExp(srvAllowList)
|
|
179
|
-
|
|
180
|
-
await super.copyNativeContent(src, dest, (entry) => {
|
|
181
|
-
if (fs.statSync(entry).isDirectory()) {
|
|
182
|
-
return folders.some(folder => entry.startsWith(folder))
|
|
183
|
-
}
|
|
184
|
-
if (/\.js$|\.properties$/.test(entry)) {
|
|
185
|
-
return true
|
|
186
|
-
}
|
|
187
|
-
return srvAllowList.test(entry) && (!filter || filter.call(this, entry))
|
|
188
|
-
})
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
module.exports = NodejsModuleBuilder
|