@sap/cds-compiler 3.4.4 → 3.5.2
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 -0
- package/README.md +1 -0
- package/bin/cds_update_identifiers.js +5 -5
- package/bin/cdsc.js +12 -12
- package/doc/CHANGELOG_ARCHIVE.md +1 -1
- package/doc/CHANGELOG_BETA.md +9 -1
- package/doc/CHANGELOG_DEPRECATED.md +2 -0
- package/lib/api/main.js +58 -59
- package/lib/api/options.js +4 -2
- package/lib/api/validate.js +2 -2
- package/lib/base/cleanSymbols.js +2 -3
- package/lib/base/dictionaries.js +6 -6
- package/lib/base/error.js +2 -2
- package/lib/base/keywords.js +6 -6
- package/lib/base/location.js +11 -12
- package/lib/base/message-registry.js +124 -28
- package/lib/base/messages.js +247 -179
- package/lib/base/model.js +14 -11
- package/lib/base/node-helpers.js +9 -10
- package/lib/base/optionProcessorHelper.js +138 -129
- package/lib/checks/actionsFunctions.js +5 -5
- package/lib/checks/annotationsOData.js +4 -4
- package/lib/checks/arrayOfs.js +1 -1
- package/lib/checks/cdsPersistence.js +1 -1
- package/lib/checks/checkForTypes.js +3 -3
- package/lib/checks/defaultValues.js +3 -3
- package/lib/checks/elements.js +7 -7
- package/lib/checks/emptyOrOnlyVirtual.js +2 -2
- package/lib/checks/foreignKeys.js +1 -1
- package/lib/checks/invalidTarget.js +4 -4
- package/lib/checks/managedInType.js +1 -1
- package/lib/checks/managedWithoutKeys.js +1 -1
- package/lib/checks/nonexpandableStructured.js +5 -3
- package/lib/checks/nullableKeys.js +1 -1
- package/lib/checks/onConditions.js +5 -6
- package/lib/checks/parameters.js +1 -1
- package/lib/checks/queryNoDbArtifacts.js +2 -2
- package/lib/checks/selectItems.js +4 -4
- package/lib/checks/sql-snippets.js +4 -4
- package/lib/checks/types.js +7 -7
- package/lib/checks/utils.js +4 -4
- package/lib/checks/validator.js +16 -13
- package/lib/compiler/.eslintrc.json +1 -1
- package/lib/compiler/assert-consistency.js +0 -1
- package/lib/compiler/builtins.js +1 -1
- package/lib/compiler/checks.js +73 -15
- package/lib/compiler/define.js +3 -7
- package/lib/compiler/extend.js +212 -32
- package/lib/compiler/finalize-parse-cdl.js +7 -2
- package/lib/compiler/index.js +17 -14
- package/lib/compiler/populate.js +2 -5
- package/lib/compiler/propagator.js +2 -0
- package/lib/compiler/shared.js +23 -12
- package/lib/compiler/tweak-assocs.js +5 -6
- package/lib/compiler/utils.js +6 -0
- package/lib/edm/annotations/genericTranslation.js +553 -319
- package/lib/edm/annotations/preprocessAnnotations.js +39 -35
- package/lib/edm/csn2edm.js +88 -75
- package/lib/edm/edm.js +17 -3
- package/lib/edm/edmAnnoPreprocessor.js +5 -5
- package/lib/edm/edmPreprocessor.js +106 -76
- package/lib/edm/edmUtils.js +41 -2
- package/lib/gen/Dictionary.json +34 -0
- package/lib/gen/language.checksum +1 -1
- package/lib/gen/language.interp +66 -63
- package/lib/gen/language.tokens +81 -81
- package/lib/gen/languageLexer.interp +4 -10
- package/lib/gen/languageLexer.js +854 -869
- package/lib/gen/languageLexer.tokens +79 -81
- package/lib/gen/languageParser.js +14360 -14146
- package/lib/inspect/inspectModelStatistics.js +2 -2
- package/lib/inspect/inspectPropagation.js +6 -6
- package/lib/inspect/inspectUtils.js +2 -2
- package/lib/json/from-csn.js +82 -40
- package/lib/json/to-csn.js +82 -157
- package/lib/language/.eslintrc.json +1 -4
- package/lib/language/genericAntlrParser.js +59 -38
- package/lib/language/language.g4 +1508 -1490
- package/lib/language/multiLineStringParser.js +1 -1
- package/lib/main.js +3 -3
- package/lib/model/csnUtils.js +130 -122
- package/lib/model/revealInternalProperties.js +1 -1
- package/lib/model/sortViews.js +4 -6
- package/lib/modelCompare/utils/filter.js +4 -3
- package/lib/optionProcessor.js +5 -0
- package/lib/render/DuplicateChecker.js +1 -1
- package/lib/render/manageConstraints.js +12 -12
- package/lib/render/toCdl.js +225 -159
- package/lib/render/toHdbcds.js +63 -63
- package/lib/render/toRename.js +5 -5
- package/lib/render/toSql.js +55 -65
- package/lib/render/utils/common.js +20 -37
- package/lib/render/utils/delta.js +3 -3
- package/lib/render/utils/sql.js +22 -6
- package/lib/render/utils/stringEscapes.js +3 -3
- package/lib/transform/db/applyTransformations.js +3 -3
- package/lib/transform/db/assertUnique.js +13 -12
- package/lib/transform/db/associations.js +5 -5
- package/lib/transform/db/cdsPersistence.js +10 -8
- package/lib/transform/db/constraints.js +14 -14
- package/lib/transform/db/expansion.js +20 -22
- package/lib/transform/db/flattening.js +24 -42
- package/lib/transform/db/groupByOrderBy.js +3 -3
- package/lib/transform/db/temporal.js +6 -6
- package/lib/transform/db/transformExists.js +23 -23
- package/lib/transform/db/views.js +16 -16
- package/lib/transform/draft/db.js +10 -10
- package/lib/transform/draft/odata.js +2 -2
- package/lib/transform/forOdataNew.js +12 -40
- package/lib/transform/forRelationalDB.js +17 -7
- package/lib/transform/localized.js +2 -2
- package/lib/transform/odata/toFinalBaseType.js +41 -27
- package/lib/transform/odata/typesExposure.js +106 -62
- package/lib/transform/parseExpr.js +209 -106
- package/lib/transform/transformUtilsNew.js +2 -2
- package/lib/transform/translateAssocsToJoins.js +24 -19
- package/lib/transform/universalCsn/coreComputed.js +10 -10
- package/lib/transform/universalCsn/universalCsnEnricher.js +26 -26
- package/lib/transform/universalCsn/utils.js +3 -3
- package/lib/utils/file.js +5 -5
- package/lib/utils/moduleResolve.js +13 -13
- package/lib/utils/objectUtils.js +6 -6
- package/lib/utils/term.js +5 -2
- package/lib/utils/timetrace.js +51 -24
- package/package.json +5 -7
- package/share/messages/check-proper-type-of.md +1 -1
- package/share/messages/message-explanations.json +1 -1
- package/share/messages/redirected-to-complex.md +4 -4
- package/share/messages/{syntax-expecting-integer.md → syntax-expecting-unsigned-int.md} +7 -4
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,64 @@
|
|
|
7
7
|
Note: `beta` fixes, changes and features are usually not listed in this ChangeLog but [here](doc/CHANGELOG_BETA.md).
|
|
8
8
|
The compiler behavior concerning `beta` features can change at any time without notice.
|
|
9
9
|
|
|
10
|
+
## Version 3.5.2 - 2022-12-20
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- to.sql/hdi/hdbcds: Don't process references in actions, as they have no impact on the database - avoids internal errors
|
|
15
|
+
|
|
16
|
+
## Version 3.5.0 - 2022-12-07
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- grammar: `localized` is now allowed in select items as well, to force the creation of convenience views.
|
|
21
|
+
- to.edm(x):
|
|
22
|
+
+ Validate annotation values of OASIS/SAP vocabulary term definitions against `@Validation.AllowedValues`.
|
|
23
|
+
+ Reveal dangling type references in produced EDM.
|
|
24
|
+
+ `@Capabilities` 'pull up' introduced with [3.3.0](#version-330---2022-09-29) must now be switched
|
|
25
|
+
on with option `odataCapabilitiesPullup`.
|
|
26
|
+
- If option `addTextsLanguageAssoc` is set but ignored by the compiler, an info message is emitted.
|
|
27
|
+
This can happen if, e.g., the `sap.common.Languages` entity is missing.
|
|
28
|
+
- Add OData vocabularies 'Offline' and 'PDF'.
|
|
29
|
+
|
|
30
|
+
### Changed
|
|
31
|
+
|
|
32
|
+
- to.edm(x):
|
|
33
|
+
+ Vocabulary references to `Common` and `Core` are added to the generated EDM by default to allow
|
|
34
|
+
usage of these vocabularies in http messages even if the terms are not being used in the EDM itself.
|
|
35
|
+
+ API representation of enum types as `@Validation.AllowedValues` has been shifted from `for.odata` to
|
|
36
|
+
`to.edm(x)`. This allows to reuse imported enum types in new APIs.
|
|
37
|
+
+ Messages raised from the EDM annotation renderer have been reworked with message id and enhanced message
|
|
38
|
+
position including the annotation under investigation.
|
|
39
|
+
+ `@Validation.AllowedValues` annotation as introduced for enum elements with
|
|
40
|
+
[1.44.2](./doc/CHANGELOG_ARCHIVE.md#version-1442---2020-10-09)
|
|
41
|
+
are now always rendered into the API regardless of `@assert.range`.
|
|
42
|
+
- to.cdl: The input CSN is no longer cloned for client-CSN and parseCdl-CSN,
|
|
43
|
+
as the renderer does not modify it.
|
|
44
|
+
- A new warning is emitted if compositions of anonymous aspects are used with the `Association`
|
|
45
|
+
keyword instead of `Composition`. Replace the former with the latter to fix the warning.
|
|
46
|
+
|
|
47
|
+
### Removed
|
|
48
|
+
|
|
49
|
+
- to.edm(x): 'Empty Schema' warning has been removed.
|
|
50
|
+
|
|
51
|
+
### Fixed
|
|
52
|
+
|
|
53
|
+
- Enums with a structured base type were accidentally not warned about if used in annotation definitions.
|
|
54
|
+
- for.odata/for.hana: Instead of parenthesising tuple expansion with `()`, put
|
|
55
|
+
newly created expression in a `xpr` expression, if the term has more than one expansion.
|
|
56
|
+
- Annotation on indirect or inferred enum values were sometimes lost
|
|
57
|
+
- to.cdl:
|
|
58
|
+
+ Certain keywords of special functions no longer add superfluous parentheses.
|
|
59
|
+
+ Extension rendering now supports type extensions as well as `key` for elements.
|
|
60
|
+
+ Builtins that clashed names with implicit contexts were not rendered with `cds.` prefix.
|
|
61
|
+
+ Unknown artifacts (as can happen in parseCdl-style CSN) are now rendered as `USING` statements.
|
|
62
|
+
+ Type extensions in `csn.extensions` (e.g. for `length`) are now rendered.
|
|
63
|
+
- to.edm(x):
|
|
64
|
+
+ Fix a bug in type exposure when using `@cds.external` complex types.
|
|
65
|
+
+ Don't remove empty `Edm.EntityContainer`.
|
|
66
|
+
+ Aspects with actions outside of services are no longer warned about.
|
|
67
|
+
- for.hana: Fix a foreign key replacement bug during association to join translation.
|
|
10
68
|
|
|
11
69
|
## Version 3.4.4 - 2022-11-25
|
|
12
70
|
|
package/README.md
CHANGED
|
@@ -50,7 +50,7 @@ process.exit(0); // success
|
|
|
50
50
|
|
|
51
51
|
// --------------------------------------------------------
|
|
52
52
|
|
|
53
|
-
function modernizeIdentifierStyle(source, filename) {
|
|
53
|
+
function modernizeIdentifierStyle( source, filename ) {
|
|
54
54
|
const options = { messages: [], attachTokens: true };
|
|
55
55
|
const messageFunctions = createMessageFunctions( options, 'parse', null );
|
|
56
56
|
|
|
@@ -82,7 +82,7 @@ function modernizeIdentifierStyle(source, filename) {
|
|
|
82
82
|
|
|
83
83
|
// -----------------------------------------------
|
|
84
84
|
|
|
85
|
-
function updateIdent(identToken) {
|
|
85
|
+
function updateIdent( identToken ) {
|
|
86
86
|
const newIdentText = toNewIdentStyle(identToken.text);
|
|
87
87
|
|
|
88
88
|
if (!identToken.stop)
|
|
@@ -96,7 +96,7 @@ function modernizeIdentifierStyle(source, filename) {
|
|
|
96
96
|
currentOffset += (newIdentText.length - identToken.text.length);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
function toNewIdentStyle(oldIdentText) {
|
|
99
|
+
function toNewIdentStyle( oldIdentText ) {
|
|
100
100
|
let ident = oldIdentText.slice(1, oldIdentText.length - 1);
|
|
101
101
|
|
|
102
102
|
// There are only two replacement rules we need to check for:
|
|
@@ -116,7 +116,7 @@ function modernizeIdentifierStyle(source, filename) {
|
|
|
116
116
|
* @param {string} replaceWith
|
|
117
117
|
* @return {string}
|
|
118
118
|
*/
|
|
119
|
-
function replaceSliceInSource(source, startIndex, endIndex, replaceWith) {
|
|
119
|
+
function replaceSliceInSource( source, startIndex, endIndex, replaceWith ) {
|
|
120
120
|
return source.substring(0, startIndex) +
|
|
121
121
|
replaceWith +
|
|
122
122
|
source.substring(endIndex);
|
|
@@ -125,7 +125,7 @@ function replaceSliceInSource(source, startIndex, endIndex, replaceWith) {
|
|
|
125
125
|
/**
|
|
126
126
|
* @param {string} msg
|
|
127
127
|
*/
|
|
128
|
-
function exitError(msg) {
|
|
128
|
+
function exitError( msg ) {
|
|
129
129
|
console.error(msg);
|
|
130
130
|
usage();
|
|
131
131
|
process.exit(1);
|
package/bin/cdsc.js
CHANGED
|
@@ -57,7 +57,7 @@ catch (err) {
|
|
|
57
57
|
throw err;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
function remapCmdOptions(options, command) {
|
|
60
|
+
function remapCmdOptions( options, command ) {
|
|
61
61
|
if (!command || !options[command])
|
|
62
62
|
return;
|
|
63
63
|
|
|
@@ -208,7 +208,7 @@ function cdsc_main() {
|
|
|
208
208
|
* @param {CSN.Options} options
|
|
209
209
|
* @param {object} args
|
|
210
210
|
*/
|
|
211
|
-
function validateDirectBackendOption(command, options, args) {
|
|
211
|
+
function validateDirectBackendOption( command, options, args ) {
|
|
212
212
|
if (![ 'toCdl', 'toOdata', 'toHana', 'toCsn', 'toSql' ].includes(command)) {
|
|
213
213
|
displayUsage(`Option '--direct-backend' can't be used with command '${command}'`,
|
|
214
214
|
optionProcessor.helpText, 2);
|
|
@@ -225,7 +225,7 @@ function validateDirectBackendOption(command, options, args) {
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
// Display help text 'helpText' and 'error' (if any), then exit with exit code <code>
|
|
228
|
-
function displayUsage(error, helpText, code) {
|
|
228
|
+
function displayUsage( error, helpText, code ) {
|
|
229
229
|
// Display non-error output (like help) to stdout
|
|
230
230
|
const out = (code === 0 && !error) ? process.stdout : process.stderr;
|
|
231
231
|
// Display help text first, error at the end (more readable, no scrolling)
|
|
@@ -240,7 +240,7 @@ function displayUsage(error, helpText, code) {
|
|
|
240
240
|
}
|
|
241
241
|
|
|
242
242
|
// Executes a command line that has been translated to 'command' (what to do), 'options' (how) and 'args' (which files)
|
|
243
|
-
function executeCommandLine(command, options, args) {
|
|
243
|
+
function executeCommandLine( command, options, args ) {
|
|
244
244
|
const normalizeFilename = options.testMode && process.platform === 'win32';
|
|
245
245
|
const messageLevels = {
|
|
246
246
|
Error: 0, Warning: 1, Info: 2, Debug: 3,
|
|
@@ -428,7 +428,7 @@ function executeCommandLine(command, options, args) {
|
|
|
428
428
|
console.log(explainMessage(args.messageId));
|
|
429
429
|
}
|
|
430
430
|
|
|
431
|
-
function inspect(model) {
|
|
431
|
+
function inspect( model ) {
|
|
432
432
|
const inspectModel = require('../lib/inspect');
|
|
433
433
|
|
|
434
434
|
if (options.statistics) {
|
|
@@ -449,7 +449,7 @@ function executeCommandLine(command, options, args) {
|
|
|
449
449
|
// Display error messages in `err` resulting from a compilation. Also set
|
|
450
450
|
// process.exitCode - process.exit() will force the process to exit as quickly
|
|
451
451
|
// as possible = is problematic, since console.error() might be asynchronous
|
|
452
|
-
function displayErrors(err) {
|
|
452
|
+
function displayErrors( err ) {
|
|
453
453
|
if (err instanceof main.CompilationError) {
|
|
454
454
|
if (options.rawOutput)
|
|
455
455
|
console.error( util.inspect( reveal( err.model, options.rawOutput ), false, null ));
|
|
@@ -531,7 +531,7 @@ function executeCommandLine(command, options, args) {
|
|
|
531
531
|
// or display it to stdout if 'options.out' is '-'.
|
|
532
532
|
// Depending on 'options.rawOutput', the model is either compacted to 'name.json' or
|
|
533
533
|
// written in raw form to '<name>_raw.txt'.
|
|
534
|
-
function displayNamedXsn(xsn, name) {
|
|
534
|
+
function displayNamedXsn( xsn, name ) {
|
|
535
535
|
if (options.rawOutput) {
|
|
536
536
|
writeToFileOrDisplay(options.out, `${name}_raw.txt`, util.inspect(reveal(xsn, options.rawOutput), false, null), true);
|
|
537
537
|
}
|
|
@@ -552,7 +552,7 @@ function executeCommandLine(command, options, args) {
|
|
|
552
552
|
* @param {CSN.Model} csn
|
|
553
553
|
* @param {string} name
|
|
554
554
|
*/
|
|
555
|
-
function displayNamedCsn(csn, name) {
|
|
555
|
+
function displayNamedCsn( csn, name ) {
|
|
556
556
|
if (!csn) // only print CSN if it is set.
|
|
557
557
|
return;
|
|
558
558
|
if (options.internalMsg) {
|
|
@@ -570,7 +570,7 @@ function executeCommandLine(command, options, args) {
|
|
|
570
570
|
// If 'content' is not a string, JSON-stringify it
|
|
571
571
|
// If displaying to stdout, prepend a headline containing 'filename', unless 'omitHeadline' is set.
|
|
572
572
|
// For filenames, illegal characters (slash, backslash, colon) are replaced by '_'.
|
|
573
|
-
function writeToFileOrDisplay(dir, fileName, content, omitHeadline = false) {
|
|
573
|
+
function writeToFileOrDisplay( dir, fileName, content, omitHeadline = false ) {
|
|
574
574
|
if (options.internalMsg)
|
|
575
575
|
return;
|
|
576
576
|
fileName = fileName.replace(/[:/\\]/g, '_');
|
|
@@ -604,7 +604,7 @@ function executeCommandLine(command, options, args) {
|
|
|
604
604
|
}
|
|
605
605
|
}
|
|
606
606
|
|
|
607
|
-
function loadOptionsFromJson(cmdLine) {
|
|
607
|
+
function loadOptionsFromJson( cmdLine ) {
|
|
608
608
|
try {
|
|
609
609
|
let opt = JSON.parse(fs.readFileSync(cmdLine.options.options, 'utf-8'));
|
|
610
610
|
if (opt.cds)
|
|
@@ -620,7 +620,7 @@ function loadOptionsFromJson(cmdLine) {
|
|
|
620
620
|
}
|
|
621
621
|
}
|
|
622
622
|
|
|
623
|
-
function catchErrors(err) {
|
|
623
|
+
function catchErrors( err ) {
|
|
624
624
|
// @ts-ignore
|
|
625
625
|
if (err instanceof Error && err.hasBeenReported)
|
|
626
626
|
return;
|
|
@@ -663,7 +663,7 @@ function parseSeverityOptions({ options }) {
|
|
|
663
663
|
}
|
|
664
664
|
}
|
|
665
665
|
|
|
666
|
-
function parseSeverityOption(list, severity) {
|
|
666
|
+
function parseSeverityOption( list, severity ) {
|
|
667
667
|
const ids = list.split(',');
|
|
668
668
|
for (let id of ids) {
|
|
669
669
|
id = id.trim();
|
package/doc/CHANGELOG_ARCHIVE.md
CHANGED
|
@@ -2870,7 +2870,7 @@ Features
|
|
|
2870
2870
|
|
|
2871
2871
|
Fixes
|
|
2872
2872
|
* Issue an error, if an association element that is defined in a mixin of the
|
|
2873
|
-
same view is explicitly redirected. Up to now this
|
|
2873
|
+
same view is explicitly redirected. Up to now this modeling error was not
|
|
2874
2874
|
recognized and led to the generation of incorrect HANA CDS models.
|
|
2875
2875
|
* We now also allow query entities and their elements to use as type, relaxing
|
|
2876
2876
|
a check introduces with v1.0.26.
|
package/doc/CHANGELOG_BETA.md
CHANGED
|
@@ -8,7 +8,15 @@ Note: `beta` fixes, changes and features are listed in this ChangeLog just for i
|
|
|
8
8
|
The compiler behavior concerning `beta` features can change at any time without notice.
|
|
9
9
|
**Don't use `beta` fixes, changes and features in productive mode.**
|
|
10
10
|
|
|
11
|
-
## Version 3.
|
|
11
|
+
## Version 3.5.0 - 2022-12-07
|
|
12
|
+
|
|
13
|
+
### Added `odataTerms`
|
|
14
|
+
|
|
15
|
+
Allows to introduce and use new `Edm.Term`s in an OData API
|
|
16
|
+
based on CDS annotations. Annotations must be service members,
|
|
17
|
+
they can't be autoexposed.
|
|
18
|
+
|
|
19
|
+
## Version 3.4.0 - 2022-10-26
|
|
12
20
|
|
|
13
21
|
### Added `aspectWithoutElements`
|
|
14
22
|
|
package/lib/api/main.js
CHANGED
|
@@ -27,15 +27,14 @@ const sqlUtils = lazyload('../render/utils/sql');
|
|
|
27
27
|
* @param {CSN.Model} csn SQL transformed model
|
|
28
28
|
* @returns {string} Name with . replaced as _ in some places
|
|
29
29
|
*/
|
|
30
|
-
function getFileName(artifactName, csn) {
|
|
30
|
+
function getFileName( artifactName, csn ) {
|
|
31
31
|
return csnUtils.getResultingName(csn, 'quoted', artifactName);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
const { cloneCsnNonDict } = require('../model/csnUtils');
|
|
35
34
|
const { toHdbcdsSource } = require('../render/toHdbcds');
|
|
36
35
|
const { ModelError } = require('../base/error');
|
|
37
36
|
const { forEach, forEachKey } = require('../utils/objectUtils');
|
|
38
|
-
const { checkRemovedDeprecatedFlags
|
|
37
|
+
const { checkRemovedDeprecatedFlags } = require('../base/model');
|
|
39
38
|
const { csn2edm, csn2edmAll } = require('../edm/csn2edm');
|
|
40
39
|
|
|
41
40
|
const relevantGeneralOptions = [ /* for future generic options */ ];
|
|
@@ -51,8 +50,8 @@ const warnAboutMismatchOdata = [ 'odataVersion' ];
|
|
|
51
50
|
* @param {string[]} relevantOptionNames Option names that are defining characteristics
|
|
52
51
|
* @param {string[]} [optionalOptionNames=[]] Option names that should be attached as a fyi
|
|
53
52
|
*/
|
|
54
|
-
function attachTransformerCharacteristics(csn, transformation, options,
|
|
55
|
-
|
|
53
|
+
function attachTransformerCharacteristics( csn, transformation, options,
|
|
54
|
+
relevantOptionNames, optionalOptionNames = [] ) {
|
|
56
55
|
const relevant = {};
|
|
57
56
|
for (const name of relevantOptionNames ) {
|
|
58
57
|
if (options[name] !== undefined)
|
|
@@ -86,7 +85,7 @@ function attachTransformerCharacteristics(csn, transformation, options,
|
|
|
86
85
|
* @param {string[]} warnAboutMismatch Option names to warn about, but not error on
|
|
87
86
|
* @param {string} module Name of the module that calls this function, e.g. `for.odata`
|
|
88
87
|
*/
|
|
89
|
-
function checkPreTransformedCsn(csn, options, relevantOptionNames, warnAboutMismatch, module) {
|
|
88
|
+
function checkPreTransformedCsn( csn, options, relevantOptionNames, warnAboutMismatch, module ) {
|
|
90
89
|
if (!csn.meta) {
|
|
91
90
|
// Not able to check
|
|
92
91
|
return;
|
|
@@ -94,7 +93,7 @@ function checkPreTransformedCsn(csn, options, relevantOptionNames, warnAboutMism
|
|
|
94
93
|
const { error, warning, throwWithAnyError } = messages.makeMessageFunction(csn, options, module);
|
|
95
94
|
|
|
96
95
|
for (const name of relevantOptionNames ) {
|
|
97
|
-
if (options[name] !== csn.meta.options[name]) {
|
|
96
|
+
if (options[name] !== csn.meta.options?.[name]) {
|
|
98
97
|
error('wrong-pretransformed-csn', null, { prop: name, value: options[name], othervalue: csn.meta.options[name] },
|
|
99
98
|
'Expected pre-processed CSN to have option $(PROP) set to $(VALUE). Found: $(OTHERVALUE)');
|
|
100
99
|
}
|
|
@@ -119,7 +118,7 @@ function checkPreTransformedCsn(csn, options, relevantOptionNames, warnAboutMism
|
|
|
119
118
|
* @param {string} transformation Name of the transformation
|
|
120
119
|
* @returns {boolean} Return true if it is pre-transformed
|
|
121
120
|
*/
|
|
122
|
-
function isPreTransformed(csn, transformation) {
|
|
121
|
+
function isPreTransformed( csn, transformation ) {
|
|
123
122
|
return csn && csn.meta && csn.meta.transformation === transformation;
|
|
124
123
|
}
|
|
125
124
|
|
|
@@ -130,7 +129,7 @@ function isPreTransformed(csn, transformation) {
|
|
|
130
129
|
* @param {object} internalOptions processed options
|
|
131
130
|
* @returns {object} Return an oData-pre-processed CSN
|
|
132
131
|
*/
|
|
133
|
-
function odataInternal(csn, internalOptions) {
|
|
132
|
+
function odataInternal( csn, internalOptions ) {
|
|
134
133
|
const oDataCsn = forOdataNew.transform4odataWithCsn(csn, internalOptions);
|
|
135
134
|
attachTransformerCharacteristics(oDataCsn, 'odata', internalOptions, relevantOdataOptions, warnAboutMismatchOdata);
|
|
136
135
|
return oDataCsn;
|
|
@@ -143,7 +142,7 @@ function odataInternal(csn, internalOptions) {
|
|
|
143
142
|
* @param {ODataOptions} [options={}] Options
|
|
144
143
|
* @returns {oDataCSN} Return an oData-pre-processed CSN
|
|
145
144
|
*/
|
|
146
|
-
function odata(csn, options = {}) {
|
|
145
|
+
function odata( csn, options = {} ) {
|
|
147
146
|
const internalOptions = prepareOptions.for.odata(options);
|
|
148
147
|
return odataInternal(csn, internalOptions);
|
|
149
148
|
}
|
|
@@ -155,9 +154,9 @@ function odata(csn, options = {}) {
|
|
|
155
154
|
* @param {object} [externalOptions={}] Options
|
|
156
155
|
* @returns {object} { model: string, namespace: string }
|
|
157
156
|
*/
|
|
158
|
-
function cdl(csn, externalOptions = {}) {
|
|
157
|
+
function cdl( csn, externalOptions = {} ) {
|
|
159
158
|
const internalOptions = prepareOptions.to.cdl(externalOptions);
|
|
160
|
-
return toCdl.csnToCdl(
|
|
159
|
+
return toCdl.csnToCdl(csn, internalOptions);
|
|
161
160
|
}
|
|
162
161
|
|
|
163
162
|
/**
|
|
@@ -168,7 +167,7 @@ function cdl(csn, externalOptions = {}) {
|
|
|
168
167
|
* @returns {CSN.Model} CSN transformed like to.sql
|
|
169
168
|
* @private
|
|
170
169
|
*/
|
|
171
|
-
function forSql(csn, options = {}) {
|
|
170
|
+
function forSql( csn, options = {} ) {
|
|
172
171
|
const internalOptions = prepareOptions.to.sql(options);
|
|
173
172
|
internalOptions.transformation = 'sql';
|
|
174
173
|
const transformedCsn = forRelationalDB.transformForRelationalDBWithCsn(csn, internalOptions, 'to.sql');
|
|
@@ -183,7 +182,7 @@ function forSql(csn, options = {}) {
|
|
|
183
182
|
* @returns {CSN.Model} CSN transformed like to.hdi
|
|
184
183
|
* @private
|
|
185
184
|
*/
|
|
186
|
-
function forHdi(csn, options = {}) {
|
|
185
|
+
function forHdi( csn, options = {} ) {
|
|
187
186
|
const internalOptions = prepareOptions.to.hdi(options);
|
|
188
187
|
internalOptions.transformation = 'sql';
|
|
189
188
|
const transformedCsn = forRelationalDB.transformForRelationalDBWithCsn(csn, internalOptions, 'to.hdi');
|
|
@@ -198,7 +197,7 @@ function forHdi(csn, options = {}) {
|
|
|
198
197
|
* @returns {CSN.Model} CSN transformed like to.hdbcds
|
|
199
198
|
* @private
|
|
200
199
|
*/
|
|
201
|
-
function forHdbcds(csn, options = {}) {
|
|
200
|
+
function forHdbcds( csn, options = {} ) {
|
|
202
201
|
const internalOptions = prepareOptions.to.hdbcds(options);
|
|
203
202
|
internalOptions.transformation = 'hdbcds';
|
|
204
203
|
|
|
@@ -214,7 +213,7 @@ function forHdbcds(csn, options = {}) {
|
|
|
214
213
|
* @param {SqlOptions} [options={}] Options
|
|
215
214
|
* @returns {SQL[]} Array of SQL statements, tables first, views second
|
|
216
215
|
*/
|
|
217
|
-
function sql(csn, options = {}) {
|
|
216
|
+
function sql( csn, options = {} ) {
|
|
218
217
|
const internalOptions = prepareOptions.to.sql(options);
|
|
219
218
|
internalOptions.transformation = 'sql';
|
|
220
219
|
|
|
@@ -244,7 +243,7 @@ function sql(csn, options = {}) {
|
|
|
244
243
|
* multiple statements concatenated as a multi-line string in case the change e.g.
|
|
245
244
|
* consists of a column drop and add).
|
|
246
245
|
*/
|
|
247
|
-
function mtx(csn, deltaCsn, options = {}) {
|
|
246
|
+
function mtx( csn, deltaCsn, options = {} ) {
|
|
248
247
|
if (!baseModel.isBetaEnabled(options, 'to.mtx'))
|
|
249
248
|
throw new Error('to.mtx is only available with beta flag `to.mtx`');
|
|
250
249
|
|
|
@@ -278,7 +277,7 @@ function mtx(csn, deltaCsn, options = {}) {
|
|
|
278
277
|
* @param {HdiOptions} [options={}] Options
|
|
279
278
|
* @returns {HDIArtifacts} { <filename>:<content>, ...}
|
|
280
279
|
*/
|
|
281
|
-
function hdi(csn, options = {}) {
|
|
280
|
+
function hdi( csn, options = {} ) {
|
|
282
281
|
const internalOptions = prepareOptions.to.hdi(options);
|
|
283
282
|
|
|
284
283
|
// we need the CSN for view sorting
|
|
@@ -334,7 +333,7 @@ function hdi(csn, options = {}) {
|
|
|
334
333
|
* @param {Function} filter Filter for keys not to remap
|
|
335
334
|
* @returns {object} New result structure
|
|
336
335
|
*/
|
|
337
|
-
function remapNames(dict, csn, filter) {
|
|
336
|
+
function remapNames( dict, csn, filter ) {
|
|
338
337
|
const result = Object.create(null);
|
|
339
338
|
|
|
340
339
|
forEach(dict, (key, value) => {
|
|
@@ -354,7 +353,7 @@ function remapNames(dict, csn, filter) {
|
|
|
354
353
|
* @param {Function} filter Filter for keys not to remap
|
|
355
354
|
* @returns {string} Remapped filename
|
|
356
355
|
*/
|
|
357
|
-
function remapName(key, csn, filter = () => true) {
|
|
356
|
+
function remapName( key, csn, filter = () => true ) {
|
|
358
357
|
if (filter(key)) {
|
|
359
358
|
const lastDot = key.lastIndexOf('.');
|
|
360
359
|
const prefix = key.slice(0, lastDot);
|
|
@@ -380,13 +379,10 @@ function remapName(key, csn, filter = () => true) {
|
|
|
380
379
|
* - drops: An array of SQL statements to drop views/tables
|
|
381
380
|
* - createsAndAlters: An array of SQL statements to ALTER/CREATE tables/views
|
|
382
381
|
*/
|
|
383
|
-
function sqlMigration(csn, options, beforeImage) {
|
|
382
|
+
function sqlMigration( csn, options, beforeImage ) {
|
|
384
383
|
const internalOptions = prepareOptions.to.sql(options);
|
|
385
384
|
const { error, throwWithError } = messages.makeMessageFunction(csn, options, 'to.sql.migration');
|
|
386
385
|
|
|
387
|
-
if (!isBetaEnabled(internalOptions, 'sqlMigration'))
|
|
388
|
-
throw new Error('Function `to.sql.migration` requires beta-flag `sqlMigration`');
|
|
389
|
-
|
|
390
386
|
// Prepare after-image.
|
|
391
387
|
const afterImage = forSql(csn, options);
|
|
392
388
|
// Compare both images.
|
|
@@ -399,12 +395,12 @@ function sqlMigration(csn, options, beforeImage) {
|
|
|
399
395
|
Object.entries(diff.deletions).forEach(entry => diffFilterObj.deletion(entry, error));
|
|
400
396
|
}
|
|
401
397
|
|
|
402
|
-
const identifierUtils = sqlUtils.getIdentifierUtils(internalOptions);
|
|
398
|
+
const identifierUtils = sqlUtils.getIdentifierUtils(csn, internalOptions);
|
|
403
399
|
|
|
404
400
|
const drops = {
|
|
405
401
|
creates: {},
|
|
406
402
|
final: Object.entries(diff.deletions).reduce((previous, [ name, artifact ]) => {
|
|
407
|
-
previous[name] = `DROP ${ (artifact.query || artifact.projection) ? 'VIEW' : 'TABLE' } ${ identifierUtils.
|
|
403
|
+
previous[name] = `DROP ${ (artifact.query || artifact.projection) ? 'VIEW' : 'TABLE' } ${ identifierUtils.renderArtifactName(name) };`;
|
|
408
404
|
return previous;
|
|
409
405
|
}, {}),
|
|
410
406
|
};
|
|
@@ -420,7 +416,7 @@ function sqlMigration(csn, options, beforeImage) {
|
|
|
420
416
|
(diffArtifact.query || diffArtifact.projection) &&
|
|
421
417
|
(diffArtifact[modelCompare.isChanged] === true || // we know it changed because we compared two views
|
|
422
418
|
diffArtifact[modelCompare.isChanged] === undefined)) { // if it was removed in the after, then we don't have the flag
|
|
423
|
-
drops.creates[artifactName] = `DROP VIEW ${ identifierUtils.
|
|
419
|
+
drops.creates[artifactName] = `DROP VIEW ${ identifierUtils.renderArtifactName(artifactName) };`;
|
|
424
420
|
} // TODO: What happens with a changed kind -> entity becomes a view?
|
|
425
421
|
else if (diffArtifact &&
|
|
426
422
|
diffArtifact['@cds.persistence.skip'] !== true &&
|
|
@@ -492,7 +488,7 @@ function sqlMigration(csn, options, beforeImage) {
|
|
|
492
488
|
* is known, i.e. for the very first migration step
|
|
493
489
|
* @returns {migration} The migration result
|
|
494
490
|
*/
|
|
495
|
-
function hdiMigration(csn, options, beforeImage) {
|
|
491
|
+
function hdiMigration( csn, options, beforeImage ) {
|
|
496
492
|
const internalOptions = prepareOptions.to.hdi(options);
|
|
497
493
|
|
|
498
494
|
// Prepare after-image.
|
|
@@ -523,7 +519,7 @@ function hdiMigration(csn, options, beforeImage) {
|
|
|
523
519
|
* @param {CSN.Model} afterImage CSN, used to create correct file names in result structure.
|
|
524
520
|
* @returns {object[]} Array of objects, each having: name, suffix and sql
|
|
525
521
|
*/
|
|
526
|
-
function createSqlDefinitions(hdbkinds, afterImage) {
|
|
522
|
+
function createSqlDefinitions( hdbkinds, afterImage ) {
|
|
527
523
|
const result = [];
|
|
528
524
|
forEach(hdbkinds, (kind, artifacts) => {
|
|
529
525
|
const suffix = `.${ kind }`;
|
|
@@ -543,7 +539,7 @@ function createSqlDefinitions(hdbkinds, afterImage) {
|
|
|
543
539
|
* @param {CSN.Model} beforeImage CSN used to create correct file names in result structure.
|
|
544
540
|
* @returns {object[]} Array of objects, each having: name and suffix - only .hdbtable as suffix for now
|
|
545
541
|
*/
|
|
546
|
-
function createSqlDeletions(deletions, beforeImage) {
|
|
542
|
+
function createSqlDeletions( deletions, beforeImage ) {
|
|
547
543
|
const result = [];
|
|
548
544
|
forEach(deletions, name => result.push({ name: getFileName(name, beforeImage), suffix: '.hdbtable' }));
|
|
549
545
|
return result;
|
|
@@ -555,7 +551,7 @@ function createSqlDeletions(deletions, beforeImage) {
|
|
|
555
551
|
* @param {CSN.Model} afterImage CSN used to create correct file names in result structure.
|
|
556
552
|
* @returns {object[]} Array of objects, each having: name, suffix and changeset.
|
|
557
553
|
*/
|
|
558
|
-
function createSqlMigrations(migrations, afterImage) {
|
|
554
|
+
function createSqlMigrations( migrations, afterImage ) {
|
|
559
555
|
const result = [];
|
|
560
556
|
forEach(migrations, (name, changeset) => result.push({ name: getFileName(name, afterImage), suffix: '.hdbmigrationtable', changeset }));
|
|
561
557
|
return result;
|
|
@@ -572,15 +568,13 @@ sql.migration = sqlMigration;
|
|
|
572
568
|
* @param {HdbcdsOptions} [options={}] Options
|
|
573
569
|
* @returns {HDBCDS} { <filename>:<content>, ...}
|
|
574
570
|
*/
|
|
575
|
-
function hdbcds(csn, options = {}) {
|
|
576
|
-
timetrace.timetrace.start('to.hdbcds');
|
|
571
|
+
function hdbcds( csn, options = {} ) {
|
|
577
572
|
const internalOptions = prepareOptions.to.hdbcds(options);
|
|
578
573
|
internalOptions.transformation = 'hdbcds';
|
|
579
574
|
|
|
580
575
|
const hanaCsn = forHdbcds(csn, internalOptions);
|
|
581
576
|
|
|
582
577
|
const result = flattenResultStructure(toHdbcdsSource(hanaCsn, internalOptions));
|
|
583
|
-
timetrace.timetrace.stop();
|
|
584
578
|
return result;
|
|
585
579
|
}
|
|
586
580
|
/**
|
|
@@ -590,7 +584,7 @@ function hdbcds(csn, options = {}) {
|
|
|
590
584
|
* @param {ODataOptions} [options={}] Options
|
|
591
585
|
* @returns {edm} The JSON representation of the service
|
|
592
586
|
*/
|
|
593
|
-
function edm(csn, options = {}) {
|
|
587
|
+
function edm( csn, options = {} ) {
|
|
594
588
|
// If not provided at all, set service to undefined to trigger validation
|
|
595
589
|
const internalOptions = prepareOptions.to.edm(
|
|
596
590
|
// eslint-disable-next-line comma-dangle
|
|
@@ -620,7 +614,7 @@ edm.all = edmall;
|
|
|
620
614
|
* @param {ODataOptions} [options={}] Options
|
|
621
615
|
* @returns {edms} { <service>:<JSON representation>, ...}
|
|
622
616
|
*/
|
|
623
|
-
function edmall(csn, options = {}) {
|
|
617
|
+
function edmall( csn, options = {} ) {
|
|
624
618
|
const internalOptions = prepareOptions.to.edm(options);
|
|
625
619
|
const { error } = messages.makeMessageFunction(csn, internalOptions, 'for.odata');
|
|
626
620
|
|
|
@@ -650,7 +644,7 @@ function edmall(csn, options = {}) {
|
|
|
650
644
|
* @param {ODataOptions} [options={}] Options
|
|
651
645
|
* @returns {edmx} The XML representation of the service
|
|
652
646
|
*/
|
|
653
|
-
function edmx(csn, options = {}) {
|
|
647
|
+
function edmx( csn, options = {} ) {
|
|
654
648
|
// If not provided at all, set service to undefined to trigger validation
|
|
655
649
|
const internalOptions = prepareOptions.to.edmx(
|
|
656
650
|
// eslint-disable-next-line comma-dangle
|
|
@@ -681,7 +675,7 @@ edmx.all = edmxall;
|
|
|
681
675
|
* @param {ODataOptions} [options={}] Options
|
|
682
676
|
* @returns {edmxs} { <service>:<XML representation>, ...}
|
|
683
677
|
*/
|
|
684
|
-
function edmxall(csn, options = {}) {
|
|
678
|
+
function edmxall( csn, options = {} ) {
|
|
685
679
|
const internalOptions = prepareOptions.to.edmx(options);
|
|
686
680
|
|
|
687
681
|
const result = {};
|
|
@@ -713,11 +707,11 @@ function edmxall(csn, options = {}) {
|
|
|
713
707
|
* @param {ODataOptions} options OData / EDMX specific options.
|
|
714
708
|
* @returns {object} Rendered EDMX string for the given service.
|
|
715
709
|
*/
|
|
716
|
-
function preparedCsnToEdmx(csn, service, options) {
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
};
|
|
710
|
+
function preparedCsnToEdmx( csn, service, options ) {
|
|
711
|
+
timetrace.timetrace.start('EDMX rendering');
|
|
712
|
+
const e = csn2edm(csn, service, options)?.toXML('all');
|
|
713
|
+
timetrace.timetrace.stop('EDMX rendering');
|
|
714
|
+
return { edmx: e };
|
|
721
715
|
}
|
|
722
716
|
|
|
723
717
|
/**
|
|
@@ -728,14 +722,13 @@ function preparedCsnToEdmx(csn, service, options) {
|
|
|
728
722
|
* @param {ODataOptions} options OData / EDMX specific options.
|
|
729
723
|
* @returns {object} Dictionary of rendered EDMX strings for each service.
|
|
730
724
|
*/
|
|
731
|
-
function preparedCsnToEdmxAll(csn, options) {
|
|
725
|
+
function preparedCsnToEdmxAll( csn, options ) {
|
|
726
|
+
timetrace.timetrace.start('EDMX all rendering');
|
|
732
727
|
const edmxResult = csn2edmAll(csn, options);
|
|
733
728
|
for (const service in edmxResult)
|
|
734
729
|
edmxResult[service] = edmxResult[service].toXML('all');
|
|
735
|
-
|
|
736
|
-
return {
|
|
737
|
-
edmx: edmxResult,
|
|
738
|
-
};
|
|
730
|
+
timetrace.timetrace.stop('EDMX all rendering');
|
|
731
|
+
return { edmx: edmxResult };
|
|
739
732
|
}
|
|
740
733
|
|
|
741
734
|
/**
|
|
@@ -747,13 +740,13 @@ function preparedCsnToEdmxAll(csn, options) {
|
|
|
747
740
|
* @param {ODataOptions} options OData / EDMX specific options.
|
|
748
741
|
* @returns {object} Rendered EDM JSON object for of the given service.
|
|
749
742
|
*/
|
|
750
|
-
function preparedCsnToEdm(csn, service, options) {
|
|
743
|
+
function preparedCsnToEdm( csn, service, options ) {
|
|
744
|
+
timetrace.timetrace.start('EDM rendering');
|
|
751
745
|
// Override OData version as edm json is always v4
|
|
752
746
|
options.odataVersion = 'v4';
|
|
753
|
-
const e = csn2edm(csn, service, options);
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
};
|
|
747
|
+
const e = csn2edm(csn, service, options)?.toJSON();
|
|
748
|
+
timetrace.timetrace.stop('EDM rendering');
|
|
749
|
+
return { edmj: e };
|
|
757
750
|
}
|
|
758
751
|
|
|
759
752
|
/**
|
|
@@ -764,13 +757,14 @@ function preparedCsnToEdm(csn, service, options) {
|
|
|
764
757
|
* @param {ODataOptions} options OData / EDMX specific options.
|
|
765
758
|
* @returns {object} Dictionary of rendered EDM JSON objects for each service.
|
|
766
759
|
*/
|
|
767
|
-
function preparedCsnToEdmAll(csn, options) {
|
|
760
|
+
function preparedCsnToEdmAll( csn, options ) {
|
|
761
|
+
timetrace.timetrace.start('EDM all rendering');
|
|
768
762
|
// Override OData version as edm json is always v4
|
|
769
763
|
options.odataVersion = 'v4';
|
|
770
764
|
const edmj = csn2edmAll(csn, options);
|
|
771
765
|
for (const service in edmj)
|
|
772
766
|
edmj[service] = edmj[service].toJSON();
|
|
773
|
-
|
|
767
|
+
timetrace.timetrace.stop('EDM all rendering');
|
|
774
768
|
return {
|
|
775
769
|
edmj,
|
|
776
770
|
};
|
|
@@ -785,7 +779,7 @@ function preparedCsnToEdmAll(csn, options) {
|
|
|
785
779
|
* @param {object} toProcess { <type>: { <name>:<content>, ...}, <type>: ...}
|
|
786
780
|
* @returns {object} { <name.type>:<content> }
|
|
787
781
|
*/
|
|
788
|
-
function flattenResultStructure(toProcess) {
|
|
782
|
+
function flattenResultStructure( toProcess ) {
|
|
789
783
|
const result = {};
|
|
790
784
|
forEach(toProcess, (fileType, artifacts) => {
|
|
791
785
|
if (fileType === 'messages')
|
|
@@ -852,9 +846,14 @@ function publishCsnProcessor( processor, _name ) {
|
|
|
852
846
|
checkRemovedDeprecatedFlags( options, messageFunctions );
|
|
853
847
|
}
|
|
854
848
|
checkOutdatedOptions( options );
|
|
855
|
-
|
|
849
|
+
|
|
850
|
+
timetrace.timetrace.start(_name);
|
|
851
|
+
const result = processor( csn, options, ...args );
|
|
852
|
+
timetrace.timetrace.stop(_name);
|
|
853
|
+
return result;
|
|
856
854
|
}
|
|
857
855
|
catch (err) {
|
|
856
|
+
timetrace.timetrace.reset('Exception in backend triggered');
|
|
858
857
|
if (err instanceof messages.CompilationError || options.noRecompile || isPreTransformed(csn, 'odata')) // we cannot recompile a pre-transformed CSN
|
|
859
858
|
throw err;
|
|
860
859
|
|
|
@@ -885,7 +884,7 @@ const oldBackendOptionNames = [ 'toSql', 'toOdata', 'toHana', 'forHana' ];
|
|
|
885
884
|
*
|
|
886
885
|
* @param {CSN.Options} options Backend options
|
|
887
886
|
*/
|
|
888
|
-
function checkOutdatedOptions(options) {
|
|
887
|
+
function checkOutdatedOptions( options ) {
|
|
889
888
|
const { error, throwWithError } = messages.makeMessageFunction(null, options, 'api');
|
|
890
889
|
|
|
891
890
|
// This error has been emitted once, we don't need to emit it again.
|
|
@@ -923,7 +922,7 @@ function checkOutdatedOptions(options) {
|
|
|
923
922
|
* @param {string} moduleName Name of the module to load - like with require
|
|
924
923
|
* @returns {object} A Proxy that handles the on-demand loading
|
|
925
924
|
*/
|
|
926
|
-
function lazyload(moduleName) {
|
|
925
|
+
function lazyload( moduleName ) {
|
|
927
926
|
let module;
|
|
928
927
|
return new Proxy(((...args) => {
|
|
929
928
|
if (!module) // eslint-disable-next-line global-require
|