@sap/cds-dk 4.5.3 → 4.6.3
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 +56 -0
- package/bin/bind.js +124 -8
- package/bin/cds-ts.js +1 -1
- package/bin/cds.js +1 -0
- package/bin/compile/index.js +2 -1
- package/bin/env.js +50 -9
- package/bin/help.js +1 -0
- package/bin/import.js +34 -14
- package/bin/repl.js +6 -2
- package/bin/watch.js +59 -14
- package/lib/bind/bindingResolver.js +138 -0
- package/lib/bind/cfKeyProvider.js +353 -0
- package/lib/bind/userCdsrcJsonStorageProvider.js +144 -0
- package/lib/client/activate.js +3 -9
- package/lib/client/auth_manager.js +4 -4
- package/lib/client/extend.js +4 -9
- package/lib/client/settings_manager.js +6 -5
- package/lib/import/common.js +10 -1
- package/lib/import/importapi.js +4 -3
- package/lib/import/index.js +34 -5
- package/lib/import/message.js +1 -0
- package/lib/import/utils/MetadataConverter.js +25 -4
- package/lib/import/utils/MetadataConverterFactory.js +1 -2
- package/lib/import/utils/MultiMap.js +26 -0
- package/lib/import/v2parser.js +137 -16
- package/lib/import/v4parser.js +212 -172
- package/lib/init/constants.js +1 -1
- package/lib/init/template/data/index.js +11 -1
- package/lib/init/template/hana/index.js +16 -20
- package/lib/init/template/lint/files/.eslint/rules/no-entity-moo.js +36 -52
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/rule.test.js +15 -0
- package/lib/init/template/lint/index.js +19 -17
- package/lib/init/template/mta/files/mta.yaml.hbs +0 -7
- package/lib/init/template/mta/projectReader.js +1 -3
- package/lib/init/template/mtx/files/xs-security.json.hbs +3 -1
- package/lib/init/template/mtx/package/dependencies.package.json +1 -1
- package/lib/init/template/nodejs/files/.gitignore.hbs +1 -0
- package/lib/init/template/samples/index.js +1 -1
- package/lib/init/template/templateBase.js +10 -41
- package/lib/init/util/commandUtil.js +5 -0
- package/lib/lint/Linter.js +19 -28
- package/lib/lint/generators.js +5 -4
- package/lib/lint/io.js +76 -51
- package/lib/util/term.js +2 -0
- package/lib/watch/node-watch.js +38 -19
- package/npm-shrinkwrap.json +1435 -1946
- package/package.json +3 -3
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/test.js +0 -10
|
@@ -13,8 +13,6 @@ const { nullLogger } = require('../../util/logger');
|
|
|
13
13
|
module.exports = class HanaTemplate extends TemplateBase {
|
|
14
14
|
constructor(projectPath, generator) {
|
|
15
15
|
super(projectPath, generator, __dirname);
|
|
16
|
-
|
|
17
|
-
this.env = null;
|
|
18
16
|
}
|
|
19
17
|
|
|
20
18
|
async checkEnabled() {
|
|
@@ -22,11 +20,11 @@ module.exports = class HanaTemplate extends TemplateBase {
|
|
|
22
20
|
return true;
|
|
23
21
|
}
|
|
24
22
|
|
|
25
|
-
|
|
23
|
+
const env = await this.getEnv();
|
|
26
24
|
|
|
27
|
-
const hdiConfigPath = path.join(this.projectPath,
|
|
25
|
+
const hdiConfigPath = path.join(this.projectPath, env.folders.db, 'src/.hdiconfig');
|
|
28
26
|
if (await this.fsUtil.pathExists(hdiConfigPath)) {
|
|
29
|
-
const configFilePath = path.join(
|
|
27
|
+
const configFilePath = path.join(env.folders.db, 'src/.hdiconfig');
|
|
30
28
|
throw new Error(`Database config file ${configFilePath} already exists. Use --force to overwrite.`);
|
|
31
29
|
}
|
|
32
30
|
|
|
@@ -34,22 +32,20 @@ module.exports = class HanaTemplate extends TemplateBase {
|
|
|
34
32
|
}
|
|
35
33
|
|
|
36
34
|
// read env from project
|
|
37
|
-
async getEnv(
|
|
35
|
+
async getEnv() {
|
|
38
36
|
const cdsEnvVar = process.env.CDS_ENV;
|
|
39
37
|
process.env.CDS_ENV = 'production'
|
|
40
|
-
let env
|
|
41
38
|
try {
|
|
42
|
-
|
|
39
|
+
return await super.getEnv();
|
|
43
40
|
} finally {
|
|
44
41
|
cdsEnvVar ? process.env.CDS_ENV = cdsEnvVar : delete process.env.CDS_ENV
|
|
45
42
|
}
|
|
46
|
-
return env
|
|
47
43
|
}
|
|
48
44
|
|
|
49
45
|
async run() {
|
|
50
|
-
|
|
46
|
+
const env = await this.getEnv();
|
|
51
47
|
|
|
52
|
-
await this.templateUtil.copyFiles('common', path.join(this.projectPath,
|
|
48
|
+
await this.templateUtil.copyFiles('common', path.join(this.projectPath, env.folders.db), {
|
|
53
49
|
projectName: this.projectName
|
|
54
50
|
}, this.options.force);
|
|
55
51
|
|
|
@@ -57,13 +53,13 @@ module.exports = class HanaTemplate extends TemplateBase {
|
|
|
57
53
|
const projectType = await this.getProjectType();
|
|
58
54
|
switch (projectType) {
|
|
59
55
|
case PROJECT_TYPE.java:
|
|
60
|
-
await this.templateUtil.copyFiles('java', path.join(this.projectPath,
|
|
56
|
+
await this.templateUtil.copyFiles('java', path.join(this.projectPath, env.folders.db), {}, this.options.force);
|
|
61
57
|
await this._updatePomXml();
|
|
62
|
-
await this._updateCdsrcJson(cdsrcJsonPath,
|
|
58
|
+
await this._updateCdsrcJson(cdsrcJsonPath, env.folders.db, env);
|
|
63
59
|
break;
|
|
64
60
|
|
|
65
61
|
case PROJECT_TYPE.nodejs:
|
|
66
|
-
await this._updatePackageJson(path.join(this.projectPath, 'package.json'),
|
|
62
|
+
await this._updatePackageJson(path.join(this.projectPath, 'package.json'), env.folders.db, env);
|
|
67
63
|
break;
|
|
68
64
|
|
|
69
65
|
default: break;
|
|
@@ -87,7 +83,7 @@ module.exports = class HanaTemplate extends TemplateBase {
|
|
|
87
83
|
}
|
|
88
84
|
}
|
|
89
85
|
|
|
90
|
-
async _updatePackageJson(packageJsonPath, modelName) { //NOSONAR
|
|
86
|
+
async _updatePackageJson(packageJsonPath, modelName, env) { //NOSONAR
|
|
91
87
|
modelName = path.basename(modelName);
|
|
92
88
|
|
|
93
89
|
if (!await this.fsUtil.pathExists(packageJsonPath)) {
|
|
@@ -109,7 +105,7 @@ module.exports = class HanaTemplate extends TemplateBase {
|
|
|
109
105
|
changed = true
|
|
110
106
|
}
|
|
111
107
|
|
|
112
|
-
if (!this._isUsingHana(modelName)) {
|
|
108
|
+
if (!this._isUsingHana(modelName, env)) {
|
|
113
109
|
packageJson.cds = packageJson.cds || {};
|
|
114
110
|
packageJson.cds.requires = packageJson.cds.requires || {};
|
|
115
111
|
packageJson.cds.requires[modelName] = packageJson.cds.requires[modelName] || {};
|
|
@@ -130,7 +126,7 @@ module.exports = class HanaTemplate extends TemplateBase {
|
|
|
130
126
|
}
|
|
131
127
|
}
|
|
132
128
|
|
|
133
|
-
async _updateCdsrcJson(cdsrcJsonPath, modelName) {
|
|
129
|
+
async _updateCdsrcJson(cdsrcJsonPath, modelName, env) {
|
|
134
130
|
modelName = path.basename(modelName);
|
|
135
131
|
|
|
136
132
|
let changed;
|
|
@@ -143,7 +139,7 @@ module.exports = class HanaTemplate extends TemplateBase {
|
|
|
143
139
|
|
|
144
140
|
this.logger.isDebug && this.logger.debug(`_updateCdsrcJson before: ${JSON.stringify(cdsrcJson, null, 2)}`);
|
|
145
141
|
|
|
146
|
-
if (!this._isUsingHana(modelName)) {
|
|
142
|
+
if (!this._isUsingHana(modelName, env)) {
|
|
147
143
|
cdsrcJson.requires = cdsrcJson.requires || {};
|
|
148
144
|
cdsrcJson.requires[modelName] = cdsrcJson.requires[modelName] || {};
|
|
149
145
|
cdsrcJson.requires[modelName].kind = KIND_SQL;
|
|
@@ -161,7 +157,7 @@ module.exports = class HanaTemplate extends TemplateBase {
|
|
|
161
157
|
}
|
|
162
158
|
}
|
|
163
159
|
|
|
164
|
-
_isUsingHana(db) {
|
|
165
|
-
return
|
|
160
|
+
_isUsingHana(db, env) {
|
|
161
|
+
return env.get(`requires.${db}.kind`) === KIND_HANA || env.get(`requires.${db}.dialect`) === KIND_HANA || env.get(`requires.${db}.use`) === KIND_HANA;
|
|
166
162
|
}
|
|
167
163
|
}
|
|
@@ -1,56 +1,40 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
module.exports = cdsLint.createRule(
|
|
4
|
-
// Rule meta data
|
|
5
|
-
{
|
|
1
|
+
module.exports = require("@sap/eslint-plugin-cds/lib/api").createRule({
|
|
2
|
+
meta: {
|
|
6
3
|
docs: {
|
|
7
|
-
description: `Demonstrates how to implement a model validation check.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
4
|
+
description: `Demonstrates how to implement a model validation check.
|
|
5
|
+
|
|
6
|
+
__________________-_______
|
|
7
|
+
< Entity 'Moo' not allowed! >
|
|
8
|
+
--------------------------
|
|
9
|
+
\ ^__^
|
|
10
|
+
\ (oo)\_______
|
|
11
|
+
(__)\ )\/\
|
|
12
|
+
||----w |
|
|
13
|
+
|| ||`,
|
|
14
|
+
version: "1.0.0",
|
|
18
15
|
},
|
|
19
16
|
fixable: "code",
|
|
20
|
-
type: "problem",
|
|
21
|
-
version: "1.0.0",
|
|
22
17
|
},
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const fix = (fixer) => {
|
|
47
|
-
const rangeEnd = sourcecode.getIndexFromLoc({line: loc.end.line, column: loc.end.column});
|
|
48
|
-
return fixer.insertTextAfterRange([0, rangeEnd], "n");
|
|
49
|
-
};
|
|
50
|
-
report.push({ message: "Entity 'Moo' not allowed!", loc, fix, file: d.$location.file });
|
|
51
|
-
}
|
|
52
|
-
});
|
|
53
|
-
return report;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
);
|
|
18
|
+
create: function (context) {
|
|
19
|
+
const m = context.cds.model;
|
|
20
|
+
m.forall("entity", (d) => {
|
|
21
|
+
const entityName = d.name.split(".").pop();
|
|
22
|
+
if (entityName === "Moo") {
|
|
23
|
+
const loc = context.cds.getLocation(entityName, d);
|
|
24
|
+
const fix = (fixer) => {
|
|
25
|
+
const rangeEnd = context.sourcecode.getIndexFromLoc({
|
|
26
|
+
line: loc.end.line,
|
|
27
|
+
column: loc.end.column,
|
|
28
|
+
});
|
|
29
|
+
return fixer.insertTextAfterRange([0, rangeEnd], "n");
|
|
30
|
+
};
|
|
31
|
+
context.report({
|
|
32
|
+
message: "Entity 'Moo' not allowed!",
|
|
33
|
+
loc,
|
|
34
|
+
fix,
|
|
35
|
+
file: d.$location.file,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
})
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const { runRuleTester } = require("@sap/eslint-plugin-cds/lib/api");
|
|
2
|
+
|
|
3
|
+
runRuleTester({
|
|
4
|
+
root: __dirname,
|
|
5
|
+
filename: "schema.cds",
|
|
6
|
+
errors: [
|
|
7
|
+
{
|
|
8
|
+
message: "Entity 'Moo' not allowed!",
|
|
9
|
+
line: 2,
|
|
10
|
+
column: 8,
|
|
11
|
+
endLine: 2,
|
|
12
|
+
endColumn: 11,
|
|
13
|
+
},
|
|
14
|
+
],
|
|
15
|
+
});
|
|
@@ -24,6 +24,7 @@ module.exports = class LintTemplate extends TemplateBase {
|
|
|
24
24
|
this.lintType = "local";
|
|
25
25
|
this.customRuleExample = false;
|
|
26
26
|
this.missingNpmDependencies = { names: [], msgs: [] };
|
|
27
|
+
this.isTest = false;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
async checkEnabled() {
|
|
@@ -41,17 +42,16 @@ module.exports = class LintTemplate extends TemplateBase {
|
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
async run() {
|
|
44
|
-
const cdsdkPath = path.join(__dirname, "../../../..");
|
|
45
|
-
const globalPath = path.join(cdsdkPath, "../..");
|
|
46
|
-
|
|
47
45
|
// Require ESLint v>=7.0.0
|
|
48
|
-
this.
|
|
46
|
+
if (!this.isTest) {
|
|
47
|
+
this._checkEslint();
|
|
48
|
+
}
|
|
49
49
|
|
|
50
50
|
// To enable custom lint rules ('lint' or 'lint:dev')
|
|
51
51
|
if (this.lintType === "local") {
|
|
52
52
|
// Require local ESLint plugin installation and corresponding config
|
|
53
53
|
this._checkEslintPlugin();
|
|
54
|
-
this._addEslintPluginConfig();
|
|
54
|
+
await this._addEslintPluginConfig();
|
|
55
55
|
// Include custom lint sample rule and test ('lint:dev')
|
|
56
56
|
if (this.customRuleExample) {
|
|
57
57
|
// Generate custom lint rules dirs
|
|
@@ -66,15 +66,16 @@ module.exports = class LintTemplate extends TemplateBase {
|
|
|
66
66
|
// Generate custom lint rules docs
|
|
67
67
|
await generators.genDocs(this.projectPath);
|
|
68
68
|
}
|
|
69
|
+
|
|
70
|
+
// Generate VS Code extension settings
|
|
71
|
+
await io.sanitizeVscodeSettings(
|
|
72
|
+
this.projectPath,
|
|
73
|
+
path.join(this.projectPath, ".vscode/settings.json"),
|
|
74
|
+
this.lintType,
|
|
75
|
+
this.customRuleExample
|
|
76
|
+
);
|
|
69
77
|
}
|
|
70
78
|
|
|
71
|
-
// Generate VS Code extension settings
|
|
72
|
-
await io.sanitizeVscodeSettings(
|
|
73
|
-
this.projectPath,
|
|
74
|
-
path.join(this.projectPath, ".vscode/settings.json"),
|
|
75
|
-
this.lintType,
|
|
76
|
-
this.customRuleExample
|
|
77
|
-
);
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
async finalize() {
|
|
@@ -101,15 +102,15 @@ module.exports = class LintTemplate extends TemplateBase {
|
|
|
101
102
|
this.logger.log("\n");
|
|
102
103
|
}
|
|
103
104
|
});
|
|
104
|
-
|
|
105
105
|
this._promptInstallDependencies(task);
|
|
106
106
|
}
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
|
+
|
|
109
110
|
}
|
|
110
111
|
|
|
111
|
-
_checkEslint(
|
|
112
|
-
const eslintCmd = checks.resolveEslint(this.projectPath,
|
|
112
|
+
_checkEslint() {
|
|
113
|
+
const eslintCmd = checks.resolveEslint(this.projectPath, '');
|
|
113
114
|
if (!eslintCmd) {
|
|
114
115
|
this.missingNpmDependencies["names"].push("eslint");
|
|
115
116
|
this.missingNpmDependencies["msgs"].push("ESLint v>=7.0.0");
|
|
@@ -144,9 +145,10 @@ module.exports = class LintTemplate extends TemplateBase {
|
|
|
144
145
|
|
|
145
146
|
async _addEslintPluginConfig() {
|
|
146
147
|
let configPath = getConfigPath(this.projectPath, this.logger);
|
|
147
|
-
if (configPath) {
|
|
148
|
-
|
|
148
|
+
if (!configPath) {
|
|
149
|
+
configPath = path.join(this.projectPath, ".eslintrc");
|
|
149
150
|
}
|
|
151
|
+
await io.sanitizeEslintConfig(configPath, this.customRuleExample, this.logger);
|
|
150
152
|
return;
|
|
151
153
|
}
|
|
152
154
|
|
|
@@ -38,7 +38,6 @@ modules:
|
|
|
38
38
|
{{#cap.isJava}}
|
|
39
39
|
{{#cap.isMultitenant}}
|
|
40
40
|
properties:
|
|
41
|
-
SAP_JWT_TRUST_ACL: [{"clientid":"*","identityzone":"sap-provisioning"}] # Trust between server and SaaS Manager
|
|
42
41
|
SPRING_PROFILES_ACTIVE: cloud
|
|
43
42
|
{{/cap.isMultitenant}}
|
|
44
43
|
{{^cap.isMultitenant}}
|
|
@@ -50,12 +49,6 @@ modules:
|
|
|
50
49
|
commands: [ mvn clean package ]
|
|
51
50
|
build-result: "target/*-exec.[wj]ar"
|
|
52
51
|
{{/cap.isJava}}
|
|
53
|
-
{{#cap.isNodejs}}
|
|
54
|
-
{{#cap.isMultitenant}}
|
|
55
|
-
properties:
|
|
56
|
-
SAP_JWT_TRUST_ACL: [{"clientid":"*","identityzone":"sap-provisioning"}] # Trust between server and SaaS Manager
|
|
57
|
-
{{/cap.isMultitenant}}
|
|
58
|
-
{{/cap.isNodejs}}
|
|
59
52
|
{{#cap.hasRequires}}
|
|
60
53
|
requires:
|
|
61
54
|
{{#cap.isJava}}
|
|
@@ -22,13 +22,11 @@ module.exports = class ProjectReader {
|
|
|
22
22
|
async getEnv(profile = 'production') {
|
|
23
23
|
const cdsEnvVar = process.env.CDS_ENV
|
|
24
24
|
process.env.CDS_ENV = profile
|
|
25
|
-
let env
|
|
26
25
|
try {
|
|
27
|
-
|
|
26
|
+
return await this.template.getEnv();
|
|
28
27
|
} finally {
|
|
29
28
|
cdsEnvVar ? process.env.CDS_ENV = cdsEnvVar : delete process.env.CDS_ENV
|
|
30
29
|
}
|
|
31
|
-
return env
|
|
32
30
|
}
|
|
33
31
|
|
|
34
32
|
get fsUtil() {
|
|
@@ -58,7 +58,7 @@ module.exports = class SamplesTemplate extends TemplateBase {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
async _addNodejsSamples() {
|
|
61
|
-
const folders = (await this.getEnv(
|
|
61
|
+
const folders = (await this.getEnv()).folders;
|
|
62
62
|
const dbFolder = path.join(this.projectPath, folders.db);
|
|
63
63
|
await this.templateUtil.copyFiles('nodejs/db', dbFolder, {}, this.options.force);
|
|
64
64
|
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
-
const
|
|
2
|
+
const Config = require('@sap/cds/lib/env');
|
|
3
3
|
|
|
4
4
|
const TemplateUtil = require('../util/templateUtil');
|
|
5
|
-
const commandUtil = require('../util/commandUtil');
|
|
6
|
-
const { nullLogger } = require('../util/logger');
|
|
7
5
|
|
|
8
|
-
const {
|
|
6
|
+
const { PROJECT_TYPE } = require('../constants');
|
|
9
7
|
|
|
10
8
|
|
|
11
9
|
module.exports = class TemplateBase {
|
|
@@ -43,49 +41,20 @@ module.exports = class TemplateBase {
|
|
|
43
41
|
return true;
|
|
44
42
|
}
|
|
45
43
|
|
|
46
|
-
getCdsModulePath() {
|
|
47
|
-
return path.join(__dirname, '../../../bin/cds.js');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
44
|
/**
|
|
51
45
|
* calls cds env and caches result
|
|
52
46
|
* @param {boolean} force, ignore cached value
|
|
53
47
|
* @returns {object} the current cds env
|
|
54
48
|
*/
|
|
55
|
-
async getEnv(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
projectPath = this.cwd;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const logger = (this.logger.isDebug ? this.logger : nullLogger);
|
|
65
|
-
|
|
66
|
-
let modPath = this.getCdsModulePath();
|
|
67
|
-
if (IS_WIN) {
|
|
68
|
-
modPath = `"${modPath}"`;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
let envJsonOutput = await commandUtil.spawnCommand('node', [modPath, 'env', 'json'], {
|
|
72
|
-
cwd: projectPath,
|
|
73
|
-
env: process.env
|
|
74
|
-
}, logger, true);
|
|
75
|
-
|
|
76
|
-
if (envJsonOutput) {
|
|
77
|
-
// cheap check to see if json is valid
|
|
78
|
-
if (envJsonOutput.indexOf('":') < 0) {
|
|
79
|
-
// eslint-disable-next-line no-control-regex
|
|
80
|
-
envJsonOutput = envJsonOutput.replace(/'/g, '"').replace(/\s(\w+):\s/g, ' "$1": ').replace(/\x1b\[\w+m/g, '');
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
this.env = JSON.parse(envJsonOutput);
|
|
84
|
-
// env has additional getters and setters
|
|
85
|
-
Object.setPrototypeOf(this.env, cds.env.__proto__);
|
|
86
|
-
}
|
|
49
|
+
async getEnv() {
|
|
50
|
+
let projectPath;
|
|
51
|
+
if (await this.fsUtil.pathExists(this.projectPath)) {
|
|
52
|
+
projectPath = this.projectPath;
|
|
53
|
+
} else {
|
|
54
|
+
projectPath = this.cwd;
|
|
87
55
|
}
|
|
88
|
-
|
|
56
|
+
|
|
57
|
+
return Config.for('cds', projectPath);
|
|
89
58
|
}
|
|
90
59
|
|
|
91
60
|
/**
|
|
@@ -50,12 +50,17 @@ class CommandUtil {
|
|
|
50
50
|
resolve(stdLogBuffer.getResult());
|
|
51
51
|
} else {
|
|
52
52
|
const errorLog = errLogBuffer.getResult();
|
|
53
|
+
|
|
53
54
|
const error = new Error(`${cmd} ${args.join(' ')} failed with code ${code}, ${errorLog}`)
|
|
54
55
|
// add code ENOENT on Win if command not found
|
|
55
56
|
if (IS_WIN && errorLog.includes(cmd) && /not recognized/i.exec(errorLog)) {
|
|
56
57
|
error.code = 'ENOENT';
|
|
57
58
|
error.path = cmd;
|
|
58
59
|
}
|
|
60
|
+
|
|
61
|
+
error.errLog = errorLog;
|
|
62
|
+
error.stdLog = stdLogBuffer.getResult();
|
|
63
|
+
|
|
59
64
|
reject(error);
|
|
60
65
|
}
|
|
61
66
|
});
|
package/lib/lint/Linter.js
CHANGED
|
@@ -14,6 +14,8 @@ const {
|
|
|
14
14
|
} = require("@sap/eslint-plugin-cds/lib/api");
|
|
15
15
|
|
|
16
16
|
const IS_WIN = os.platform() === "win32";
|
|
17
|
+
const ALLOWED_FILE_EXTENSIONS = getFileExtensions();
|
|
18
|
+
|
|
17
19
|
class Linter {
|
|
18
20
|
constructor() {
|
|
19
21
|
this.eslintCmd = "";
|
|
@@ -21,6 +23,7 @@ class Linter {
|
|
|
21
23
|
this.eslintCmdOpts = {};
|
|
22
24
|
this.eslintCmdOptsIndex = 0;
|
|
23
25
|
this.eslintCmdFileExpr = "";
|
|
26
|
+
this.formatter = false;
|
|
24
27
|
this.isFile = false;
|
|
25
28
|
this.help = "";
|
|
26
29
|
this.debug = "";
|
|
@@ -75,7 +78,7 @@ class Linter {
|
|
|
75
78
|
this._printHelp();
|
|
76
79
|
} else {
|
|
77
80
|
// Determine if case "local" or "global" and resolve plugin accordingly
|
|
78
|
-
this._getConfigFileAndSetProjectPath(args);
|
|
81
|
+
await this._getConfigFileAndSetProjectPath(args);
|
|
79
82
|
|
|
80
83
|
if (this.lintType === "local") {
|
|
81
84
|
await this._addRulePaths();
|
|
@@ -88,7 +91,7 @@ class Linter {
|
|
|
88
91
|
"rules"
|
|
89
92
|
);
|
|
90
93
|
if (overwriteRules) {
|
|
91
|
-
this._overwriteRuleSeverities();
|
|
94
|
+
await this._overwriteRuleSeverities();
|
|
92
95
|
}
|
|
93
96
|
}
|
|
94
97
|
|
|
@@ -138,25 +141,14 @@ class Linter {
|
|
|
138
141
|
|
|
139
142
|
_addExtensions() {
|
|
140
143
|
// Add CDS file extensions to lint
|
|
144
|
+
const extensions = ALLOWED_FILE_EXTENSIONS.map((ext) => ext.replace('*.', '.'));
|
|
141
145
|
this.eslintCmdOpts = io.mergeWithUserOpts(
|
|
142
146
|
this.eslintCmdOpts,
|
|
143
147
|
"ext",
|
|
144
|
-
|
|
145
|
-
);
|
|
146
|
-
// Add custom CDS formatter
|
|
147
|
-
const formatterPath = this.pluginPath.replace(
|
|
148
|
-
"index.js",
|
|
149
|
-
"../api/formatter.js"
|
|
150
|
-
);
|
|
151
|
-
this.eslintCmdOpts = io.mergeWithUserOpts(
|
|
152
|
-
this.eslintCmdOpts,
|
|
153
|
-
"format",
|
|
154
|
-
path.relative(".", formatterPath)
|
|
148
|
+
extensions.join(',')
|
|
155
149
|
);
|
|
156
150
|
// Enable colored output
|
|
157
|
-
|
|
158
|
-
this.eslintCmdOpts = io.mergeWithUserOpts(this.eslintCmdOpts, "color");
|
|
159
|
-
}
|
|
151
|
+
this.eslintCmdOpts = io.mergeWithUserOpts(this.eslintCmdOpts, "color");
|
|
160
152
|
return;
|
|
161
153
|
}
|
|
162
154
|
|
|
@@ -186,7 +178,6 @@ class Linter {
|
|
|
186
178
|
}
|
|
187
179
|
}
|
|
188
180
|
// Only lint file extensions prescribed by plugin
|
|
189
|
-
const fileExtensions = getFileExtensions();
|
|
190
181
|
eslintCmdOpts.push("--ignore-pattern");
|
|
191
182
|
let ignorePattern = "*.*";
|
|
192
183
|
if (IS_WIN) {
|
|
@@ -195,7 +186,7 @@ class Linter {
|
|
|
195
186
|
ignorePattern = `'${ignorePattern}'`;
|
|
196
187
|
}
|
|
197
188
|
eslintCmdOpts.push(ignorePattern);
|
|
198
|
-
|
|
189
|
+
ALLOWED_FILE_EXTENSIONS.forEach((ext) => {
|
|
199
190
|
eslintCmdOpts.push("--ignore-pattern");
|
|
200
191
|
ignorePattern = `!${ext}`;
|
|
201
192
|
if (IS_WIN) {
|
|
@@ -212,18 +203,18 @@ class Linter {
|
|
|
212
203
|
} else {
|
|
213
204
|
input = `'${this.eslintCmdFileExpr.join("' '")}'`;
|
|
214
205
|
}
|
|
215
|
-
const eslintCmdSplit = this.eslintCmd.split(" ");
|
|
216
|
-
this.eslintCmd = eslintCmdSplit[0];
|
|
217
|
-
eslintCmdOpts.unshift(eslintCmdSplit[1]);
|
|
218
|
-
eslintCmdOpts.push(input);
|
|
219
206
|
// Run ESLint with given cmd line options
|
|
207
|
+
// - Show 'eslint' instead of actual eslint cmd ('node .../.eslint.js')
|
|
208
|
+
// - Remove debug flag for printed cmd line
|
|
220
209
|
if (this.eslintCmdOpts.debug) {
|
|
210
|
+
eslintCmdOpts.splice(eslintCmdOpts.indexOf('--debug'), 1);
|
|
221
211
|
console.log(
|
|
222
|
-
`Linting:\n ${term.info(
|
|
212
|
+
`Linting:\n ${term.info(`eslint ${eslintCmdOpts.concat(input).join(' ')}`)}\n`
|
|
223
213
|
);
|
|
214
|
+
eslintCmdOpts.push('--debug');
|
|
224
215
|
}
|
|
225
216
|
if (!dryRun) {
|
|
226
|
-
return commandUtil.spawnCommand(this.eslintCmd, eslintCmdOpts, {
|
|
217
|
+
return commandUtil.spawnCommand(this.eslintCmd, eslintCmdOpts.concat(input), {
|
|
227
218
|
cwd: process.cwd(),
|
|
228
219
|
shell: true,
|
|
229
220
|
stdio: process.env.NODE_ENV === 'test' ? 'pipe' : 'inherit',
|
|
@@ -245,7 +236,7 @@ class Linter {
|
|
|
245
236
|
return;
|
|
246
237
|
}
|
|
247
238
|
|
|
248
|
-
_getConfigFileAndSetProjectPath(args) {
|
|
239
|
+
async _getConfigFileAndSetProjectPath(args) {
|
|
249
240
|
let input;
|
|
250
241
|
// Only resolve the first input argument
|
|
251
242
|
//
|
|
@@ -269,7 +260,7 @@ class Linter {
|
|
|
269
260
|
this.configPath = this.configGlobalPath;
|
|
270
261
|
this.lintType === "global";
|
|
271
262
|
} else {
|
|
272
|
-
this.configContents = io.readEslintConfig(this.configPath);
|
|
263
|
+
this.configContents = await io.readEslintConfig(this.configPath);
|
|
273
264
|
if (this.configContents) {
|
|
274
265
|
if ("extends" in this.configContents) {
|
|
275
266
|
this.extendsPlugin = checks.hasEslintConfigContent(
|
|
@@ -295,8 +286,8 @@ class Linter {
|
|
|
295
286
|
return;
|
|
296
287
|
}
|
|
297
288
|
|
|
298
|
-
_overwriteRuleSeverities() {
|
|
299
|
-
let configContents = io.readEslintConfig(this.configPath) || {};
|
|
289
|
+
async _overwriteRuleSeverities() {
|
|
290
|
+
let configContents = (await io.readEslintConfig(this.configPath)) || {};
|
|
300
291
|
let rules = configContents.rules;
|
|
301
292
|
// Allow recommended plugin rules in cds-dk to be overwritten
|
|
302
293
|
// by user by adding rule to cmd line (because of precedence)
|
package/lib/lint/generators.js
CHANGED
|
@@ -3,6 +3,7 @@ const os = require("os");
|
|
|
3
3
|
const cp = require("child_process");
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const { mkdirp } = require("@sap/cds/lib/utils");
|
|
6
|
+
const term = require("../util/term");
|
|
6
7
|
|
|
7
8
|
const IS_WIN = os.platform() === "win32";
|
|
8
9
|
|
|
@@ -35,12 +36,12 @@ module.exports = {
|
|
|
35
36
|
let cdslintCmd = eslintOpts[0].replace("eslint", "*cds lint*");
|
|
36
37
|
eslintOpts[0] = `
|
|
37
38
|
# SYNOPSIS
|
|
38
|
-
|
|
39
|
+
|
|
39
40
|
${cdslintCmd} [beta]
|
|
40
|
-
|
|
41
|
+
|
|
41
42
|
Runs environment checks and/or checks the specified models
|
|
42
43
|
based on the ESLint framework
|
|
43
|
-
|
|
44
|
+
|
|
44
45
|
# OPTIONS`;
|
|
45
46
|
return `${eslintOpts.join("\n ")}\n`;
|
|
46
47
|
},
|
|
@@ -97,7 +98,7 @@ module.exports = {
|
|
|
97
98
|
},
|
|
98
99
|
|
|
99
100
|
/**
|
|
100
|
-
* Generates custom rules documentation for user
|
|
101
|
+
* Generates custom rules documentation for user
|
|
101
102
|
* according to contents of rules files
|
|
102
103
|
* @param {*} projectPath
|
|
103
104
|
*/
|