@sap/cds 6.8.4 → 7.0.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 +58 -5
- 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 +1 -1
- 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 +1 -1
- 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/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/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/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,171 +0,0 @@
|
|
|
1
|
-
const path = require('path')
|
|
2
|
-
const cds = require('../../cds')
|
|
3
|
-
const BuildTaskHandlerEdmx = require('../buildTaskHandlerEdmx')
|
|
4
|
-
const URL = require('url')
|
|
5
|
-
const { getProperty, isOldJavaStack, relativePaths } = require('../../util')
|
|
6
|
-
|
|
7
|
-
const { ODATA_VERSION_V2, BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY, BUILD_TASK_FIORI, BUILD_TASK_JAVA_CF, CDS_CONFIG_PATH_SEP, BUILD_TASK_JAVA } = require('../../constants')
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* With cds 4 service metadata for the UI service binding is no longer created by default.
|
|
11
|
-
* For SAP Web IDE Full-Stack compatibility a corresponding metadata.xml is still generated.
|
|
12
|
-
* Though, 'fiori' build tasks can still be configured for UI5 mockserver usage - see https://github.wdf.sap.corp/cap/issues/issues/8673
|
|
13
|
-
*/
|
|
14
|
-
class FioriAppModuleBuilder extends BuildTaskHandlerEdmx {
|
|
15
|
-
async prepare() {
|
|
16
|
-
this.buildOptions.for[BUILD_TASK_FIORI] = this.buildOptions.for[BUILD_TASK_FIORI] || {}
|
|
17
|
-
|
|
18
|
-
// cache for later use across multiple FioriAppModuleBuilder instances
|
|
19
|
-
const fioriBuildOptions = getProperty(this.buildOptions.for, BUILD_TASK_FIORI)
|
|
20
|
-
fioriBuildOptions.appModel = new Map()
|
|
21
|
-
fioriBuildOptions.appEdmx = new Map()
|
|
22
|
-
|
|
23
|
-
// group tasks that have a common application root folder
|
|
24
|
-
const appTaskGroups = new Map()
|
|
25
|
-
this.buildOptions.tasks.forEach(task => {
|
|
26
|
-
if (task.for === BUILD_TASK_FIORI) {
|
|
27
|
-
const appFolder = path.relative(this.buildOptions.root, task.src).split(CDS_CONFIG_PATH_SEP)[0]
|
|
28
|
-
appTaskGroups.has(appFolder) ? appTaskGroups.get(appFolder).push(task) : appTaskGroups.set(appFolder, [task])
|
|
29
|
-
}
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
// merge all model references to resolve the model later on
|
|
33
|
-
const appModelGroups = new Map()
|
|
34
|
-
for (let [appFolder, appTaskGroup] of appTaskGroups.entries()) {
|
|
35
|
-
const appModels = new Set()
|
|
36
|
-
appTaskGroup.forEach(task => {
|
|
37
|
-
if (Array.isArray(task.options.model)) {
|
|
38
|
-
task.options.model.forEach(model => appModels.add(model))
|
|
39
|
-
}
|
|
40
|
-
})
|
|
41
|
-
appModelGroups.set(appFolder, appModels)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const originFioriBuildOption = fioriBuildOptions[BUILD_OPTION_OUTPUT_MODE]
|
|
45
|
-
fioriBuildOptions[BUILD_OPTION_OUTPUT_MODE] = OUTPUT_MODE_RESULT_ONLY
|
|
46
|
-
|
|
47
|
-
try {
|
|
48
|
-
const edmxOptions = { version: cds.env.odata?.version }
|
|
49
|
-
|
|
50
|
-
if (edmxOptions.version !== ODATA_VERSION_V2) {
|
|
51
|
-
const javaTask = this.buildOptions.tasks.find(task => task.for === BUILD_TASK_JAVA_CF || task.for === BUILD_TASK_JAVA)
|
|
52
|
-
|
|
53
|
-
if (javaTask
|
|
54
|
-
&& await isOldJavaStack([javaTask.src, this.buildOptions.root])
|
|
55
|
-
&& !cds.env.for("cds", this.buildOptions.root, false).odata?.version) {
|
|
56
|
-
|
|
57
|
-
// old java stack
|
|
58
|
-
// default is now v4 and not v2 anymore, so overwrite with v2 if using default
|
|
59
|
-
this.logger.debug("Fiori task is forcing OData v2 for building though the default is v4.")
|
|
60
|
-
edmxOptions.version = ODATA_VERSION_V2
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
for (let [appFolder, appModelGroup] of appModelGroups.entries()) {
|
|
65
|
-
this.logger.debug(`building module [${appFolder}] using [${this.constructor.name}]`)
|
|
66
|
-
const modelPaths = cds.resolve(Array.from(appModelGroup.values()), this.buildOptions)
|
|
67
|
-
if (!modelPaths || modelPaths.length === 0) {
|
|
68
|
-
continue
|
|
69
|
-
}
|
|
70
|
-
this.logger._debug && this.logger.debug(`model: ${relativePaths(this.buildOptions.root, modelPaths).join(", ")}`)
|
|
71
|
-
|
|
72
|
-
//cache model per fiori app root folder
|
|
73
|
-
const options = this.options()
|
|
74
|
-
const model = await cds.load(modelPaths, options)
|
|
75
|
-
fioriBuildOptions.appModel.set(appFolder, model)
|
|
76
|
-
|
|
77
|
-
await this.compileToEdmx(model, null, edmxOptions)
|
|
78
|
-
|
|
79
|
-
// cache edmx per fiori app root folder
|
|
80
|
-
fioriBuildOptions.appEdmx.set(appFolder, this._result.edmx)
|
|
81
|
-
}
|
|
82
|
-
} finally {
|
|
83
|
-
fioriBuildOptions[BUILD_OPTION_OUTPUT_MODE] = originFioriBuildOption
|
|
84
|
-
}
|
|
85
|
-
return false
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* This version only creates a odata representation for the 'mainService' data source
|
|
90
|
-
* as defined by the fiori wizard - everything else is currently not supported.
|
|
91
|
-
* Therefore errors are only logged, the build does not fail in case a service
|
|
92
|
-
* cannot be resolved based on the defined service URI
|
|
93
|
-
*/
|
|
94
|
-
async build() {
|
|
95
|
-
const model = await this.model()
|
|
96
|
-
if (!model) {
|
|
97
|
-
return
|
|
98
|
-
}
|
|
99
|
-
await this._writeEdmxToWebapp(this.task.src, this.task.dest)
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
async _writeEdmxToWebapp(src, dest) {
|
|
103
|
-
const manifestPath = path.join(src, 'webapp', 'manifest.json')
|
|
104
|
-
let manifest
|
|
105
|
-
|
|
106
|
-
try {
|
|
107
|
-
manifest = require(manifestPath)
|
|
108
|
-
} catch (error) {
|
|
109
|
-
this.logger.log(`UI module does not contain a manifest.json [${relativePaths(this.buildOptions.root, manifestPath)}], skipping build`)
|
|
110
|
-
return
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const mainService = getProperty(manifest, ['sap.app', 'dataSources', 'mainService'])
|
|
114
|
-
if (!mainService) {
|
|
115
|
-
// no mainService defined - not supported
|
|
116
|
-
this.logger._debug && this.logger.debug(`UI module does not have a datasource [mainService], [${relativePaths(this.buildOptions.root, manifestPath)}], skipping build`)
|
|
117
|
-
return
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
const localUri = getProperty(mainService, ['settings', 'localUri'])
|
|
121
|
-
const uri = mainService.uri
|
|
122
|
-
|
|
123
|
-
if (!localUri || !uri) {
|
|
124
|
-
this.logger._debug && this.logger.warn(`local uri setting missing for data source [mainService], [${relativePaths(this.buildOptions.root, manifestPath)}]`)
|
|
125
|
-
return
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const appFolder = path.relative(this.buildOptions.root, src).split(CDS_CONFIG_PATH_SEP)[0]
|
|
129
|
-
const model = this.getBuildOption("appModel").get(appFolder)
|
|
130
|
-
if (!model) {
|
|
131
|
-
this.logger.error(`failed to load model for service uri ${uri}, data source [mainService]`)
|
|
132
|
-
return
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const edmx = this._getEdmxForUri(model, appFolder, uri)
|
|
136
|
-
if (!edmx) {
|
|
137
|
-
this.logger.error(`failed to resolve service definition for service uri ${uri}, data source [mainService]`)
|
|
138
|
-
return
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
if (!this.hasBuildOption(BUILD_OPTION_OUTPUT_MODE, OUTPUT_MODE_RESULT_ONLY)) {
|
|
142
|
-
const edmxPath = path.resolve(path.join(dest, 'webapp'), this._strippedUrlPath(localUri))
|
|
143
|
-
return this.write(edmx).to(edmxPath)
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
_getEdmxForUri(model, appFolder, uri) {
|
|
148
|
-
const uriSegments = this._strippedUrlPath(uri).split('/')
|
|
149
|
-
|
|
150
|
-
// one segment of the URI has to match a service name
|
|
151
|
-
// NOTE: assumption is that the service definition can be resolved - either by
|
|
152
|
-
// - defining corresponding using statement in annotations model or
|
|
153
|
-
// - adding the service module folder to the model option
|
|
154
|
-
let service = cds.reflect(model).find(service => uriSegments.find(segment => service.name === segment))
|
|
155
|
-
|
|
156
|
-
if (service) {
|
|
157
|
-
const allServices = this.getBuildOption("appEdmx").get(appFolder)
|
|
158
|
-
if (allServices) {
|
|
159
|
-
return allServices.get(service.name + ".xml")
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
return null
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
_strippedUrlPath(urlString) {
|
|
166
|
-
const url = URL.parse(urlString)
|
|
167
|
-
return url.pathname.replace(/^(\/|\\)/, '').replace(/(\/|\\)$/, '') // strip leading and trailing slash or backslash)
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
module.exports = FioriAppModuleBuilder
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
const path = require('path')
|
|
2
|
-
const parser = require('./migrationtable')
|
|
3
|
-
const { BuildError, hasOptionValue } = require('../../util')
|
|
4
|
-
const { LOG_MODULE_NAMES } = require('../../constants')
|
|
5
|
-
const cds = require('../../cds'), { compiler: cdsc } = cds
|
|
6
|
-
const cdscVersion = `-- generated by cds-compiler version ${cdsc.version()}`
|
|
7
|
-
const { getArtifactCdsPersistenceName } = cdsc
|
|
8
|
-
let logger = cds.log(LOG_MODULE_NAMES)
|
|
9
|
-
const ANNO_PERSISTENCE_JOURNAL = '@cds.persistence.journal'
|
|
10
|
-
|
|
11
|
-
module.exports = async (model, lastDevVersion, srcPath, options = {}) => {
|
|
12
|
-
if (options.logger) {
|
|
13
|
-
logger = options.logger
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const journalFileNames = _getJournalFileNames(model)
|
|
17
|
-
const { definitions, deletions, migrations, afterImage } = _toHdiMigration(model, lastDevVersion, journalFileNames, options)
|
|
18
|
-
const definitionResult = []
|
|
19
|
-
|
|
20
|
-
for (const { name, suffix, sql } of definitions) {
|
|
21
|
-
let definitionEntry = { name, suffix, content: sql }
|
|
22
|
-
|
|
23
|
-
if (suffix === '.hdbtable') {
|
|
24
|
-
if (journalFileNames.has(name)) {
|
|
25
|
-
const migration = migrations.find(migration => migration.name === name)
|
|
26
|
-
definitionEntry = await _2migrationtable(srcPath, migration || _emptyMigration(name), sql)
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
if (definitionEntry) {
|
|
30
|
-
definitionResult.push(definitionEntry)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return { definitions: definitionResult, deletions, afterImage: _filterJournalArtifacts(afterImage) }
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function _toHdiMigration(model, lastDevVersion, journalFileNames, options) {
|
|
37
|
-
const result = cdsc.to.hdi.migration(cds.minify(model), options, lastDevVersion);
|
|
38
|
-
if (logger._debug) {
|
|
39
|
-
logger.debug('cdsc.to.hdi.migration returned')
|
|
40
|
-
for (const { name, suffix, sql } of result.definitions) {
|
|
41
|
-
if (suffix === '.hdbtable' || suffix === '.hdbmigrationtable') {
|
|
42
|
-
if (journalFileNames.has(name)) {
|
|
43
|
-
const migration = result.migrations.find(migration => migration.name === name)
|
|
44
|
-
logger.debug(`
|
|
45
|
-
File ${name + '.hdbmigrationtable'} - ${migration ? migration.changeset.length : 0} new changes
|
|
46
|
-
${sql}
|
|
47
|
-
${migration ? migration.changeset.map(change => change.sql).join('\n') : 'Empty changeset'}
|
|
48
|
-
`)
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return result
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Returns an object providing access to the .hdbmigrationtable file content and its corresponding filename.
|
|
58
|
-
*
|
|
59
|
-
* @param {String} srcPath Fully qualified path of the directory containing .hdbmigrationtable files
|
|
60
|
-
* @param {String} migration the migration descriptor
|
|
61
|
-
* @param {String} tableSql SQL TABLE definition
|
|
62
|
-
* @returns {Object} Providing access to 'content' and 'fileName'.
|
|
63
|
-
*/
|
|
64
|
-
async function _2migrationtable(srcPath, migration, tableSql) {
|
|
65
|
-
let migrationTableModel = null
|
|
66
|
-
const file = path.join(srcPath, migration.name + migration.suffix)
|
|
67
|
-
try {
|
|
68
|
-
migrationTableModel = await parser.read(file)
|
|
69
|
-
} catch (e) {
|
|
70
|
-
// abort build in order to ensure consistent afterImage model state / hdbmigrationtable file state
|
|
71
|
-
throw new BuildError(`${path.relative(process.cwd(), file)}: ${e.message}`)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (migrationTableModel) {
|
|
75
|
-
// adding new changeset if change exist, ignore otherwise
|
|
76
|
-
const migrationEntry = _getNewMigrationEntry(migration.changeset, migrationTableModel.versionNumber)
|
|
77
|
-
if (migrationEntry) {
|
|
78
|
-
const versionNumber = migrationTableModel.versionNumber + 1
|
|
79
|
-
const migrationCount = migrationTableModel.migrations.entries.length
|
|
80
|
-
const migrations = `${migrationEntry.content}${migrationCount > 0 ? '\n' : ''}${migrationTableModel.migrations.toString()}${migrationCount > 0 ? '\n' : ''}`
|
|
81
|
-
return {
|
|
82
|
-
name: migration.name,
|
|
83
|
-
suffix: migration.suffix,
|
|
84
|
-
content: `== version=${versionNumber}\n${tableSql}\n\n${migrations}`,
|
|
85
|
-
changed: true,
|
|
86
|
-
dropColumns: migrationEntry.dropColumns
|
|
87
|
-
}
|
|
88
|
-
} else {
|
|
89
|
-
// existing migration file version
|
|
90
|
-
return { name: migration.name, suffix: migration.suffix, content: migrationTableModel.toString(), changed: false }
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
// initial migration file version
|
|
94
|
-
return { name: migration.name, suffix: migration.suffix, content: `== version=1\n${tableSql}\n`, changed: true }
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
function _getNewMigrationEntry(changeset, currentVersion) {
|
|
98
|
-
if (changeset && changeset.length > 0) {
|
|
99
|
-
const dropColumns = changeset.some(e => e.drop)
|
|
100
|
-
const manualChange = changeset.some(e => !e.sql)
|
|
101
|
-
const enableDrop = cds.env.hana?.journal?.['enable-drop']
|
|
102
|
-
const content = changeset.reduce((acc, e) => {
|
|
103
|
-
if (!acc) {
|
|
104
|
-
acc = `== migration=${currentVersion + 1}\n`
|
|
105
|
-
acc += `${cdscVersion}\n`
|
|
106
|
-
|
|
107
|
-
if (dropColumns && enableDrop !== true) {
|
|
108
|
-
acc += `>>>>> Manual resolution required - DROP statements causing data loss are disabled by default.
|
|
109
|
-
>>>>> You may either:
|
|
110
|
-
>>>>> uncomment statements to allow incompatible changes, or
|
|
111
|
-
>>>>> refactor statements, e.g. replace DROP/ADD by single RENAME statement
|
|
112
|
-
>>>>> After manual resolution delete all lines starting with >>>>>\n`
|
|
113
|
-
} else if (manualChange) {
|
|
114
|
-
acc += `>>>>> Manual resolution required - insert ALTER statement(s) as described below.
|
|
115
|
-
>>>>> After manual resolution delete all lines starting with >>>>>\n`
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
if (e.sql) {
|
|
119
|
-
if (e.drop && enableDrop !== true) {
|
|
120
|
-
acc += `${e.sql.replace(/^/gm, '-- ')}\n`;
|
|
121
|
-
} else {
|
|
122
|
-
acc += `${e.sql}\n`
|
|
123
|
-
}
|
|
124
|
-
} else {
|
|
125
|
-
acc +=
|
|
126
|
-
`>>>>> Insert ALTER statement for: ${e.description}\n`
|
|
127
|
-
}
|
|
128
|
-
return acc
|
|
129
|
-
}, null)
|
|
130
|
-
return { dropColumns, content }
|
|
131
|
-
}
|
|
132
|
-
return null
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function _emptyMigration(name) {
|
|
136
|
-
return { name, suffix: ".hdbmigrationtable", changeset: [] }
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
function _getJournalFileNames(model) {
|
|
140
|
-
const journalNames = new Set(cds.reflect(model).all(item => {
|
|
141
|
-
if (item.kind === 'entity' && item[ANNO_PERSISTENCE_JOURNAL] === true) {
|
|
142
|
-
if (item['@cds.persistence.skip'] === true || item['@cds.persistence.exists'] === true) {
|
|
143
|
-
logger.warn(`[hdbmigrationtable] annotation @cds.persistence.journal skipped for entity '${item.name}' as persistence exists`)
|
|
144
|
-
}
|
|
145
|
-
return true
|
|
146
|
-
}
|
|
147
|
-
return false
|
|
148
|
-
}).map(entity => getArtifactCdsPersistenceName(entity.name, 'quoted', model, 'hana')))
|
|
149
|
-
|
|
150
|
-
logger._debug && logger.debug(`\n[hdbmigrationtable] found ${journalNames.size} model entities annotated with '@cds.persistence.journal`)
|
|
151
|
-
logger._debug && logger.debug(`[hdbmigrationtable] ${[...journalNames].join(', ')}\n`)
|
|
152
|
-
|
|
153
|
-
return journalNames
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
// delete all entities that are not relevant
|
|
157
|
-
function _filterJournalArtifacts(csn) {
|
|
158
|
-
if (!csn) {
|
|
159
|
-
return
|
|
160
|
-
}
|
|
161
|
-
const dict = csn.definitions
|
|
162
|
-
for (const name in dict) {
|
|
163
|
-
if (!_isPersistedAsJournalTable(dict[name])) {
|
|
164
|
-
delete dict[name]
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
// mark CSN as modified by cds build
|
|
168
|
-
csn.meta.build = `CDS Build v${cds.version}`
|
|
169
|
-
return csn;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// see cds-compiler/lib/model/csnUtils.js#isPersistedAsTable
|
|
173
|
-
function _isPersistedAsJournalTable(artifact) {
|
|
174
|
-
return artifact.kind === 'entity' && hasOptionValue(artifact['@cds.persistence.journal'], true) &&
|
|
175
|
-
!artifact.abstract &&
|
|
176
|
-
!hasOptionValue(artifact['@cds.persistence.skip'], true) &&
|
|
177
|
-
!hasOptionValue(artifact['@cds.persistence.exists'], true) &&
|
|
178
|
-
(!artifact.query && !artifact.projection || hasOptionValue(artifact['@cds.persistence.table'], true))
|
|
179
|
-
}
|