@sap/cds-dk 4.3.3 → 4.5.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 +62 -1
- package/bin/activate.js +1 -2
- package/bin/deploy/index.js +1 -1
- package/bin/deploy/to-sqlite.js +2 -2
- package/bin/extend.js +2 -4
- package/bin/help.js +1 -1
- package/bin/login.js +7 -8
- package/bin/logout.js +1 -2
- package/bin/repl.js +1 -1
- package/bin/watch.js +12 -8
- package/lib/client/activate.js +243 -0
- package/lib/client/auth_manager.js +115 -0
- package/lib/client/base_command.js +55 -0
- package/lib/client/extend.js +179 -0
- package/lib/client/helper/cf_helper.js +186 -0
- package/lib/client/helper/dependency_helper.js +26 -0
- package/lib/client/helper/env_helper.js +4 -0
- package/lib/client/helper/fs_helper.js +83 -0
- package/lib/client/helper/logging.js +37 -0
- package/lib/client/helper/question.js +50 -0
- package/lib/client/helper/string_helper.js +53 -0
- package/lib/client/helper/url_helper.js +17 -0
- package/lib/client/index.js +14 -0
- package/lib/client/params.js +435 -0
- package/lib/client/settings_manager.js +526 -0
- package/lib/import/index.js +17 -38
- package/lib/import/message.js +6 -7
- package/lib/import/v2parser.js +340 -64
- package/lib/import/v4parser.js +346 -59
- package/lib/init/constants.js +1 -1
- package/lib/init/index.js +13 -10
- package/lib/init/template/data/index.js +38 -46
- package/lib/init/template/hana/index.js +2 -2
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/fixed/schema.cds +4 -0
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/invalid/schema.cds +4 -0
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/test.js +10 -0
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo/valid/schema.cds +6 -0
- package/lib/init/template/lint/index.js +8 -6
- package/lib/init/template/mta/projectReader.js +8 -5
- package/lib/init/template/nodejs/files/.vscode/extensions.json +1 -1
- package/lib/init/template/nodejs/index.js +1 -8
- package/lib/init/util/logger.js +1 -1
- package/lib/lint/Linter.js +82 -65
- package/lib/lint/io.js +9 -33
- package/npm-shrinkwrap.json +6327 -11301
- package/package.json +6 -7
- package/lib/init/template/lint/files/.eslint/tests/no-entity-moo.test.js +0 -34
|
@@ -25,14 +25,20 @@ module.exports = class DataTemplate extends TemplateBase {
|
|
|
25
25
|
const logger = this.logger;
|
|
26
26
|
|
|
27
27
|
cds.root = this.projectPath;
|
|
28
|
-
let csn = await cds.compile.to.csn(
|
|
29
|
-
|
|
28
|
+
let csn = await cds.compile.to.csn(cds.env.roots); // normal CSN
|
|
29
|
+
|
|
30
|
+
// Also include 'external' entities w/ cds.persistence.skip (similar to 'mocked' option of serve).
|
|
31
|
+
// Could be too much sometimes, but don't want to bother users w/ a separate option for this.
|
|
32
|
+
cds.deploy.include_external_entities_in(csn)
|
|
33
|
+
|
|
34
|
+
csn = cds.compile.for.sql(csn, { names:env.sql.names, messages:[] }) // CSN w/ persistence information
|
|
30
35
|
csn = cds.reflect(csn); // reflected model (adds additional helper functions)
|
|
31
36
|
|
|
32
37
|
csn.all('entity')
|
|
33
38
|
.filter(prefixedWith)
|
|
34
|
-
.filter (
|
|
35
|
-
.
|
|
39
|
+
.filter (e => !e.query) // exclude entities with queries (projection on, select from ...)
|
|
40
|
+
.filter (e => e.name !== 'DRAFT.DraftAdministrativeData' && !e.name.endsWith('.drafts')) // exclude draft stuff
|
|
41
|
+
.forEach(e => processEntity(e, dest, this.projectPath, csn, force, logger));
|
|
36
42
|
}
|
|
37
43
|
|
|
38
44
|
}
|
|
@@ -44,15 +50,15 @@ function processEntity (entity, dest, projectPath, csn, force, logger) {
|
|
|
44
50
|
dataFileName = `${entity.name}.csv`;
|
|
45
51
|
}
|
|
46
52
|
else {
|
|
47
|
-
const entityName = entity.name.replace(namespace +
|
|
53
|
+
const entityName = entity.name.replace(namespace + '.', '');
|
|
48
54
|
dataFileName = `${namespace}-${entityName}.csv`;
|
|
49
55
|
}
|
|
50
56
|
|
|
51
|
-
if (entity.name.endsWith(
|
|
57
|
+
if (entity.name.endsWith('.texts')) {
|
|
52
58
|
// handle '.texts' entities (for localized elements) differently:
|
|
53
59
|
// if there is already file exist with '_texts' (old cds versions) - overwrite this one (when --force is used)
|
|
54
60
|
// otherwise use the new '.texts' format
|
|
55
|
-
const dataFileNameOldFormat = dataFileName.replace(
|
|
61
|
+
const dataFileNameOldFormat = dataFileName.replace('.texts.csv','_texts.csv');
|
|
56
62
|
const dataFilePathOldFormat = join(dest, dataFileNameOldFormat);
|
|
57
63
|
if (fs.existsSync(dataFilePathOldFormat)) {
|
|
58
64
|
createDataFile(true, dataFilePathOldFormat, dest, projectPath, force, entity, logger);
|
|
@@ -68,62 +74,48 @@ function getDefaultTargetFolder (env, projectPath) {
|
|
|
68
74
|
const dbFolder = env.folders.db;
|
|
69
75
|
// csv files should be located in the 'db/data' folder unless a 'db/csv' folder already exists
|
|
70
76
|
let mockDataFolder;
|
|
71
|
-
if (fs.existsSync(join(projectPath, dbFolder,
|
|
72
|
-
mockDataFolder =
|
|
77
|
+
if (fs.existsSync(join(projectPath, dbFolder, 'csv'))) {
|
|
78
|
+
mockDataFolder = 'csv';
|
|
73
79
|
} else {
|
|
74
|
-
mockDataFolder =
|
|
80
|
+
mockDataFolder = 'data';
|
|
75
81
|
}
|
|
76
82
|
return join(dbFolder, mockDataFolder);
|
|
77
83
|
}
|
|
78
84
|
|
|
79
85
|
|
|
80
86
|
function createDataFile (isFileExists, dataFilePath, dest, projectPath, force, entity, logger) {
|
|
87
|
+
let relFilePath = dataFilePath;
|
|
88
|
+
if (dataFilePath.indexOf(projectPath) == 0) {
|
|
89
|
+
// use relative path in log (for readability), only when data files are added within the project
|
|
90
|
+
// (potentially can be located anywhere using the --out parameter)
|
|
91
|
+
relFilePath = relative(projectPath, dataFilePath);
|
|
92
|
+
}
|
|
81
93
|
if (isFileExists && !force) {
|
|
82
|
-
|
|
83
|
-
if (dataFilePath.indexOf(projectPath) == 0) {
|
|
84
|
-
// use relative path in log (for readability), only when data files are added within the project
|
|
85
|
-
// (potentially can be located anywhere using the --out parameter)
|
|
86
|
-
loggedDataFilePath = relative(projectPath, dataFilePath);
|
|
87
|
-
}
|
|
88
|
-
logger.log(`file ${loggedDataFilePath} already exists with no '--force' option - skip add data for entity ${entity.name}`);
|
|
94
|
+
logger.log(`Skipping ${relFilePath}`);
|
|
89
95
|
}
|
|
90
96
|
else {
|
|
91
|
-
// continue only if file not already exists, or
|
|
97
|
+
// continue only if file not already exists, or '--force' option provided
|
|
92
98
|
const dataFileContent = prepareDataFileContent(entity);
|
|
93
|
-
if (
|
|
94
|
-
fs.mkdirSync(dest, {recursive: true})
|
|
99
|
+
if (dataFileContent && dataFileContent.length) {
|
|
100
|
+
if (!fs.existsSync(dest)) fs.mkdirSync(dest, {recursive: true})
|
|
101
|
+
fs.writeFileSync(dataFilePath, dataFileContent);
|
|
102
|
+
isFileExists ? logger.log(`Overwriting `+relFilePath) : logger.log(`Creating `+relFilePath)
|
|
95
103
|
}
|
|
96
|
-
fs.writeFileSync(dataFilePath, dataFileContent);
|
|
97
104
|
}
|
|
98
105
|
}
|
|
99
106
|
|
|
100
107
|
function prepareDataFileContent (entity) {
|
|
101
|
-
const persistenceKeyNames = Object.values(entity.keys)
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
const persistenceNames = Object.values(entity.elements)
|
|
108
|
+
const persistenceKeyNames = Object.values(entity.keys||[]).map(element => element['@cds.persistence.name']);
|
|
109
|
+
return Object.values(entity.elements)
|
|
105
110
|
.filter(element => !(element instanceof cds.Association)) // exclude associations+compositions
|
|
106
|
-
.
|
|
107
|
-
.
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
content += `${name}`;
|
|
115
|
-
isFirst = false;
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
content += `;${name}`;
|
|
119
|
-
}
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
persistenceNames.forEach(name => {
|
|
123
|
-
content += `;${name}`;
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
return content;
|
|
111
|
+
.filter(element => !!element['@cds.persistence.name']) // exclude no-persistence elements, e.g. virtual ones
|
|
112
|
+
.map (element => element['@cds.persistence.name'])
|
|
113
|
+
.sort((e1, e2) => { // sort with keys first
|
|
114
|
+
if (persistenceKeyNames.includes(e1) && !persistenceKeyNames.includes(e2)) return -1
|
|
115
|
+
if (!persistenceKeyNames.includes(e1) && persistenceKeyNames.includes(e2)) return 1
|
|
116
|
+
return 0 // preserve original order otherwise
|
|
117
|
+
})
|
|
118
|
+
.join(';')
|
|
127
119
|
}
|
|
128
120
|
|
|
129
121
|
// Logic is taken from cds-compile
|
|
@@ -161,7 +161,7 @@ module.exports = class HanaTemplate extends TemplateBase {
|
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
_isUsingHana(
|
|
165
|
-
return this.env.get(`requires.${
|
|
164
|
+
_isUsingHana(db) {
|
|
165
|
+
return this.env.get(`requires.${db}.kind`) === KIND_HANA || this.env.get(`requires.${db}.dialect`) === KIND_HANA || this.env.get(`requires.${db}.use`) === KIND_HANA;
|
|
166
166
|
}
|
|
167
167
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const path = require("path");
|
|
2
|
+
const rule = require("../../rules/no-entity-moo");
|
|
3
|
+
const { runRuleTester } = require("@sap/eslint-plugin-cds/lib/api");
|
|
4
|
+
|
|
5
|
+
runRuleTester({
|
|
6
|
+
root: path.resolve(__dirname),
|
|
7
|
+
rule,
|
|
8
|
+
filename: 'schema.cds',
|
|
9
|
+
errors: [{ message: "Entity 'Moo' not allowed!" }],
|
|
10
|
+
});
|
|
@@ -52,26 +52,28 @@ module.exports = class LintTemplate extends TemplateBase {
|
|
|
52
52
|
// Require local ESLint plugin installation and corresponding config
|
|
53
53
|
this._checkEslintPlugin();
|
|
54
54
|
this._addEslintPluginConfig();
|
|
55
|
-
// Generate custom lint rules dirs
|
|
56
|
-
await this._generateEslintDirs();
|
|
57
55
|
// Include custom lint sample rule and test ('lint:dev')
|
|
58
56
|
if (this.customRuleExample) {
|
|
57
|
+
// Generate custom lint rules dirs
|
|
58
|
+
await this._generateEslintDirs();
|
|
59
|
+
|
|
59
60
|
if (!fs.existsSync(".eslint/rules/no-entity-moo.js")) {
|
|
60
61
|
await this._copyFromTemplate(".eslint/rules", this.rulesPath);
|
|
61
62
|
}
|
|
62
63
|
if (!fs.existsSync(".eslint/tests/no-entity-moo.test.js")) {
|
|
63
64
|
await this._copyFromTemplate(".eslint/tests", this.testsPath);
|
|
64
65
|
}
|
|
66
|
+
// Generate custom lint rules docs
|
|
67
|
+
await generators.genDocs(this.projectPath);
|
|
65
68
|
}
|
|
66
|
-
// Generate custom lint rules docs
|
|
67
|
-
await generators.genDocs(this.projectPath);
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
// Generate VS Code extension settings
|
|
71
72
|
await io.sanitizeVscodeSettings(
|
|
72
73
|
this.projectPath,
|
|
73
74
|
path.join(this.projectPath, ".vscode/settings.json"),
|
|
74
|
-
this.lintType
|
|
75
|
+
this.lintType,
|
|
76
|
+
this.customRuleExample
|
|
75
77
|
);
|
|
76
78
|
}
|
|
77
79
|
|
|
@@ -96,7 +98,7 @@ module.exports = class LintTemplate extends TemplateBase {
|
|
|
96
98
|
this.missingNpmDependencies["msgs"].forEach((msg, i) => {
|
|
97
99
|
this.logger.log(`(${i + 1}) ${msg}`);
|
|
98
100
|
if (i === this.missingNpmDependencies["msgs"].length - 1) {
|
|
99
|
-
this.logger.log(
|
|
101
|
+
this.logger.log("\n");
|
|
100
102
|
}
|
|
101
103
|
});
|
|
102
104
|
|
|
@@ -331,7 +331,10 @@ module.exports = class ProjectReader {
|
|
|
331
331
|
|
|
332
332
|
_hasHanaServiceBinding(env) {
|
|
333
333
|
const kind = ProjectReader._getProperty(env, 'requires.db.kind')
|
|
334
|
-
return kind === 'hana' ||
|
|
334
|
+
return kind === 'hana' || kind === 'sql' && (
|
|
335
|
+
ProjectReader._getProperty(env, 'requires.db.dialect') === 'hana' ||
|
|
336
|
+
ProjectReader._getProperty(env, 'requires.db.use') === 'hana'
|
|
337
|
+
)
|
|
335
338
|
}
|
|
336
339
|
|
|
337
340
|
_getReqResource(key, reqEntry, capDescriptor) {
|
|
@@ -359,7 +362,7 @@ module.exports = class ProjectReader {
|
|
|
359
362
|
switch (reqEntry.kind) {
|
|
360
363
|
case 'sql':
|
|
361
364
|
case 'hana':
|
|
362
|
-
if (reqEntry.kind === 'sql' && reqEntry.use !== 'hana') {
|
|
365
|
+
if (reqEntry.kind === 'sql' && reqEntry.dialect !== 'hana' && reqEntry.use !== 'hana') {
|
|
363
366
|
break
|
|
364
367
|
}
|
|
365
368
|
// use different service name to avoid conflicts when switching from single tenant to multitenant
|
|
@@ -394,12 +397,12 @@ module.exports = class ProjectReader {
|
|
|
394
397
|
}
|
|
395
398
|
|
|
396
399
|
/**
|
|
397
|
-
* Parse a given string containing xml
|
|
400
|
+
* Parse a given string containing xml
|
|
398
401
|
* used to remove the _text object from converted json i.e. from xml-js.
|
|
399
402
|
* example : converted json has "groupId":[{"_text":["customer"]}]
|
|
400
403
|
* and after removing textAttributes (using this function): "groupId":["customer"]
|
|
401
404
|
* @param xml string to parse
|
|
402
|
-
* @returns parsed json object
|
|
405
|
+
* @returns parsed json object
|
|
403
406
|
*/
|
|
404
407
|
async _parseXml(pomXmlPath) {
|
|
405
408
|
const xmljs = require('xml-js');
|
|
@@ -426,7 +429,7 @@ module.exports = class ProjectReader {
|
|
|
426
429
|
}
|
|
427
430
|
}
|
|
428
431
|
|
|
429
|
-
/*
|
|
432
|
+
/*
|
|
430
433
|
Remove the _text attributes and convert value it into array
|
|
431
434
|
input : "groupId":[{"_text":["customer"]}]
|
|
432
435
|
output: "groupId":["customer"]
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
// List of extensions which should be recommended for users of this workspace.
|
|
6
6
|
"recommendations": [
|
|
7
|
-
|
|
7
|
+
"SAPSE.vscode-cds",
|
|
8
8
|
"dbaeumer.vscode-eslint",
|
|
9
9
|
"esbenp.prettier-vscode",
|
|
10
10
|
"mechatroner.rainbow-csv",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
|
|
3
3
|
const TemplateBase = require('../templateBase');
|
|
4
|
-
const { COMMAND_ADD, OPTION_JAVA,
|
|
4
|
+
const { COMMAND_ADD, OPTION_JAVA, OPTION_NODEJS, URLS } = require('../../constants');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
module.exports = class NodeJSTemplate extends TemplateBase {
|
|
@@ -18,13 +18,6 @@ module.exports = class NodeJSTemplate extends TemplateBase {
|
|
|
18
18
|
throw new Error(`Only one runtime per project is supported. Specify either ${OPTION_JAVA} or ${OPTION_NODEJS}.`);
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
if (this.options[OPTION_JAVA_PACKAGE]) {
|
|
22
|
-
this.logger.warn(`Specified Java package will be ignored since project type is not Java. Use --add java to create project type Java.`);
|
|
23
|
-
}
|
|
24
|
-
if (this.options[OPTION_JAVA_MVN]) {
|
|
25
|
-
this.logger.warn(`Specified Maven parameters will be ignored since project type is not Java. Use --add java to create project type Java.`);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
21
|
return true;
|
|
29
22
|
}
|
|
30
23
|
|
package/lib/init/util/logger.js
CHANGED
package/lib/lint/Linter.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
const os = require("os");
|
|
2
2
|
const fs = require("fs");
|
|
3
|
-
const
|
|
4
|
-
const util = require("util");
|
|
5
|
-
const execAsync = util.promisify(cp.exec);
|
|
3
|
+
const commandUtil = require("../init/util/commandUtil");
|
|
6
4
|
const path = require("path");
|
|
7
5
|
const glob = require("glob");
|
|
8
6
|
const term = require("../util/term");
|
|
@@ -23,6 +21,7 @@ class Linter {
|
|
|
23
21
|
this.eslintCmdOpts = {};
|
|
24
22
|
this.eslintCmdOptsIndex = 0;
|
|
25
23
|
this.eslintCmdFileExpr = "";
|
|
24
|
+
this.isFile = false;
|
|
26
25
|
this.help = "";
|
|
27
26
|
this.debug = "";
|
|
28
27
|
this.flags = [];
|
|
@@ -71,7 +70,7 @@ class Linter {
|
|
|
71
70
|
*/
|
|
72
71
|
async lint(args, options) {
|
|
73
72
|
this.eslintCmdOpts = this._sanitizeUserOpts(options);
|
|
74
|
-
this.eslintCmdFileExpr = args
|
|
73
|
+
this.eslintCmdFileExpr = args.length ? args : ['.']
|
|
75
74
|
if (this.eslintCmdOpts.help) {
|
|
76
75
|
this._printHelp();
|
|
77
76
|
} else {
|
|
@@ -96,16 +95,10 @@ class Linter {
|
|
|
96
95
|
// Limit to CDS file extensions
|
|
97
96
|
this._addExtensions();
|
|
98
97
|
// Run ESLint with collected options
|
|
99
|
-
let result = "";
|
|
100
98
|
try {
|
|
101
|
-
|
|
99
|
+
await this._runEslint();
|
|
102
100
|
} catch (err) {
|
|
103
|
-
|
|
104
|
-
console.log(err.stdout);
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
if (result.stdout) {
|
|
108
|
-
console.log(result.stdout);
|
|
101
|
+
term.error(err);
|
|
109
102
|
}
|
|
110
103
|
}
|
|
111
104
|
}
|
|
@@ -150,10 +143,6 @@ class Linter {
|
|
|
150
143
|
"ext",
|
|
151
144
|
".cds,.csn"
|
|
152
145
|
);
|
|
153
|
-
// Enable colored output
|
|
154
|
-
if (process.stdout.isTTY) {
|
|
155
|
-
this.eslintCmdOpts = io.mergeWithUserOpts(this.eslintCmdOpts, "color");
|
|
156
|
-
}
|
|
157
146
|
// Add custom CDS formatter
|
|
158
147
|
const formatterPath = this.pluginPath.replace(
|
|
159
148
|
"index.js",
|
|
@@ -164,72 +153,86 @@ class Linter {
|
|
|
164
153
|
"format",
|
|
165
154
|
path.relative(".", formatterPath)
|
|
166
155
|
);
|
|
156
|
+
// Enable colored output
|
|
157
|
+
if (process.stdout.isTTY) {
|
|
158
|
+
this.eslintCmdOpts = io.mergeWithUserOpts(this.eslintCmdOpts, "color");
|
|
159
|
+
}
|
|
167
160
|
return;
|
|
168
161
|
}
|
|
169
162
|
|
|
170
163
|
async _runEslint(dryRun = false) {
|
|
171
164
|
const eslintCmdOpts = [];
|
|
172
165
|
// Collect cmd line options
|
|
173
|
-
|
|
174
|
-
let
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
} else {
|
|
178
|
-
if (value) {
|
|
166
|
+
try {
|
|
167
|
+
for (let key in this.eslintCmdOpts) {
|
|
168
|
+
let value = this.eslintCmdOpts[key];
|
|
169
|
+
if (this.flags.includes(`--${key}`)) {
|
|
179
170
|
eslintCmdOpts.push(`--${key}`);
|
|
180
|
-
|
|
181
|
-
if (
|
|
182
|
-
eslintCmdOpts.push(
|
|
183
|
-
//
|
|
184
|
-
|
|
185
|
-
if (IS_WIN) {
|
|
171
|
+
} else {
|
|
172
|
+
if (value) {
|
|
173
|
+
eslintCmdOpts.push(`--${key}`);
|
|
174
|
+
// Always quote args which are not paths
|
|
175
|
+
if (!fs.existsSync(value)) {
|
|
186
176
|
eslintCmdOpts.push(`"${value}"`);
|
|
177
|
+
// Paths are quoted according on os
|
|
187
178
|
} else {
|
|
188
|
-
|
|
179
|
+
if (IS_WIN) {
|
|
180
|
+
eslintCmdOpts.push(`"${value}"`);
|
|
181
|
+
} else {
|
|
182
|
+
eslintCmdOpts.push(value);
|
|
183
|
+
}
|
|
189
184
|
}
|
|
190
185
|
}
|
|
191
186
|
}
|
|
192
187
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
const fileExtensions = getFileExtensions();
|
|
196
|
-
eslintCmdOpts.push("--ignore-pattern");
|
|
197
|
-
let ignorePattern = "*.*";
|
|
198
|
-
if (IS_WIN) {
|
|
199
|
-
ignorePattern = `"${ignorePattern}"`;
|
|
200
|
-
}
|
|
201
|
-
eslintCmdOpts.push(ignorePattern);
|
|
202
|
-
fileExtensions.forEach((ext) => {
|
|
188
|
+
// Only lint file extensions prescribed by plugin
|
|
189
|
+
const fileExtensions = getFileExtensions();
|
|
203
190
|
eslintCmdOpts.push("--ignore-pattern");
|
|
204
|
-
ignorePattern =
|
|
191
|
+
let ignorePattern = "*.*";
|
|
205
192
|
if (IS_WIN) {
|
|
206
193
|
ignorePattern = `"${ignorePattern}"`;
|
|
194
|
+
} else {
|
|
195
|
+
ignorePattern = `'${ignorePattern}'`;
|
|
207
196
|
}
|
|
208
197
|
eslintCmdOpts.push(ignorePattern);
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
console.log(
|
|
217
|
-
`Linting:\n ${term.info(
|
|
218
|
-
`${this.eslintCmdShort} ${eslintCmdOpts.join(" ")} ${input}`
|
|
219
|
-
)}`
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
if (!dryRun) {
|
|
223
|
-
return execAsync(
|
|
224
|
-
`${this.eslintCmd} ${eslintCmdOpts.join(" ")} ${input}`,
|
|
225
|
-
{
|
|
226
|
-
cwd: process.cwd(),
|
|
227
|
-
shell: IS_WIN,
|
|
228
|
-
stdio: "inherit",
|
|
198
|
+
fileExtensions.forEach((ext) => {
|
|
199
|
+
eslintCmdOpts.push("--ignore-pattern");
|
|
200
|
+
ignorePattern = `!${ext}`;
|
|
201
|
+
if (IS_WIN) {
|
|
202
|
+
ignorePattern = `"${ignorePattern}"`;
|
|
203
|
+
} else {
|
|
204
|
+
ignorePattern = `'${ignorePattern}'`;
|
|
229
205
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
206
|
+
eslintCmdOpts.push(ignorePattern);
|
|
207
|
+
});
|
|
208
|
+
let input = "";
|
|
209
|
+
if (IS_WIN) {
|
|
210
|
+
// Braucht es diese unterscheidung wirklich? Unterstützt Windows nicht auch single quotes?
|
|
211
|
+
input = `"${this.eslintCmdFileExpr.join('" "')}"`;
|
|
212
|
+
} else {
|
|
213
|
+
input = `'${this.eslintCmdFileExpr.join("' '")}'`;
|
|
214
|
+
}
|
|
215
|
+
const eslintCmdSplit = this.eslintCmd.split(" ");
|
|
216
|
+
this.eslintCmd = eslintCmdSplit[0];
|
|
217
|
+
eslintCmdOpts.unshift(eslintCmdSplit[1]);
|
|
218
|
+
eslintCmdOpts.push(input);
|
|
219
|
+
// Run ESLint with given cmd line options
|
|
220
|
+
if (this.eslintCmdOpts.debug) {
|
|
221
|
+
console.log(
|
|
222
|
+
`Linting:\n ${term.info(`${this.eslintCmd} ${eslintCmdOpts.join(' ')}`)}`
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
if (!dryRun) {
|
|
226
|
+
return commandUtil.spawnCommand(this.eslintCmd, eslintCmdOpts, {
|
|
227
|
+
cwd: process.cwd(),
|
|
228
|
+
shell: true,
|
|
229
|
+
stdio: process.env.NODE_ENV === 'test' ? 'pipe' : 'inherit',
|
|
230
|
+
});
|
|
231
|
+
} else {
|
|
232
|
+
return Promise.resolve("");
|
|
233
|
+
}
|
|
234
|
+
} catch (err) {
|
|
235
|
+
return Promise.resolve(err);
|
|
233
236
|
}
|
|
234
237
|
}
|
|
235
238
|
|
|
@@ -244,8 +247,22 @@ class Linter {
|
|
|
244
247
|
|
|
245
248
|
_getConfigFileAndSetProjectPath(args) {
|
|
246
249
|
let input;
|
|
250
|
+
// Only resolve the first input argument
|
|
251
|
+
//
|
|
247
252
|
if (args.length > 0) {
|
|
248
|
-
|
|
253
|
+
let stats;
|
|
254
|
+
try {
|
|
255
|
+
stats = fs.statSync(args[0]);
|
|
256
|
+
} catch (err) {
|
|
257
|
+
// Do nothing
|
|
258
|
+
}
|
|
259
|
+
if (
|
|
260
|
+
args[0] === "." ||
|
|
261
|
+
(stats && (stats.isFile() || stats.isDirectory()))
|
|
262
|
+
) {
|
|
263
|
+
this.isFile = true;
|
|
264
|
+
}
|
|
265
|
+
input = glob.sync(args[0])[0];
|
|
249
266
|
}
|
|
250
267
|
this.configPath = getConfigPath(input);
|
|
251
268
|
if (!this.configPath) {
|
|
@@ -290,7 +307,7 @@ class Linter {
|
|
|
290
307
|
this.esllintCmdOpts = io.mergeWithUserOpts(
|
|
291
308
|
this.eslintCmdOpts,
|
|
292
309
|
"rule",
|
|
293
|
-
`${rule}
|
|
310
|
+
`${rule}:${rules[rule]}`
|
|
294
311
|
);
|
|
295
312
|
}
|
|
296
313
|
});
|
package/lib/lint/io.js
CHANGED
|
@@ -172,10 +172,10 @@ module.exports = {
|
|
|
172
172
|
* (3) "Global" case adds configFile and removes rulePaths
|
|
173
173
|
* @param {*} settingsPath VS Code settings file
|
|
174
174
|
*/
|
|
175
|
-
async sanitizeVscodeSettings(projectPath, settingsPath, lintType) {
|
|
175
|
+
async sanitizeVscodeSettings(projectPath, settingsPath, lintType, customRuleExample = false) {
|
|
176
176
|
let settings = (await this.readVscodeSettings(settingsPath)) || {};
|
|
177
177
|
const lintFileTypes = ["cds", "csn"];
|
|
178
|
-
const rulePaths = [path.join(
|
|
178
|
+
const rulePaths = [path.join(".eslint/rules")];
|
|
179
179
|
const configFile = path.join(__dirname, ".eslintrc.js");
|
|
180
180
|
|
|
181
181
|
function _addArrayOrString(array) {
|
|
@@ -194,42 +194,18 @@ module.exports = {
|
|
|
194
194
|
settings["eslint.validate"] = lintFileTypes;
|
|
195
195
|
}
|
|
196
196
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
if (
|
|
200
|
-
delete settings["eslint.runtime"];
|
|
201
|
-
}
|
|
202
|
-
if (settings["eslint.nodePath"]) {
|
|
203
|
-
delete settings["eslint.nodePath"];
|
|
204
|
-
}
|
|
205
|
-
if (settings["eslint.options"]) {
|
|
206
|
-
if (settings["eslint.options"]["configFile"]) {
|
|
207
|
-
delete settings["eslint.options"]["configFile"];
|
|
208
|
-
}
|
|
197
|
+
if (lintType === "local") {
|
|
198
|
+
if (settings["eslint.options"]) {
|
|
199
|
+
if (customRuleExample) {
|
|
209
200
|
settings["eslint.options"]["rulePaths"] = rulePaths;
|
|
210
|
-
} else {
|
|
211
|
-
settings["eslint.options"] = {
|
|
212
|
-
rulePaths: rulePaths,
|
|
213
|
-
};
|
|
214
201
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
settings["eslint.runtime"] = "node";
|
|
218
|
-
settings["eslint.nodePath"] = path.join(__dirname, "../../node_modules");
|
|
219
|
-
if (settings["eslint.options"]) {
|
|
220
|
-
if (settings["eslint.options"]["rulePaths"]) {
|
|
221
|
-
delete settings["eslint.options"]["rulePaths"];
|
|
222
|
-
}
|
|
223
|
-
settings["eslint.options"]["configFile"] =
|
|
224
|
-
_addArrayOrString(configFile);
|
|
225
|
-
} else {
|
|
202
|
+
} else {
|
|
203
|
+
if (customRuleExample) {
|
|
226
204
|
settings["eslint.options"] = {
|
|
227
|
-
|
|
205
|
+
rulePaths: rulePaths,
|
|
228
206
|
};
|
|
229
207
|
}
|
|
230
|
-
|
|
231
|
-
default:
|
|
232
|
-
break;
|
|
208
|
+
}
|
|
233
209
|
}
|
|
234
210
|
|
|
235
211
|
await this.writeVscodeSettings(settings, settingsPath);
|