@sap/cds-dk 4.4.2 → 4.5.4
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 +60 -0
- package/bin/activate.js +1 -2
- package/bin/deploy/index.js +3 -2
- package/bin/deploy/to-sqlite.js +2 -2
- package/bin/extend.js +2 -4
- package/bin/help.js +1 -1
- package/bin/import.js +105 -23
- package/bin/login.js +7 -8
- package/bin/logout.js +1 -2
- package/bin/repl.js +1 -1
- package/bin/watch.js +30 -11
- 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/common.js +24 -1
- package/lib/import/importapi.js +1 -1
- package/lib/import/index.js +25 -41
- package/lib/import/message.js +10 -6
- package/lib/import/v2parser.js +301 -47
- package/lib/import/v4parser.js +391 -71
- package/lib/init/constants.js +1 -1
- package/lib/init/index.js +15 -10
- package/lib/init/template/data/index.js +38 -46
- package/lib/init/template/hana/index.js +2 -2
- 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/lint/Linter.js +62 -60
- package/lib/lint/generators.js +1 -1
- package/lib/lint/io.js +9 -33
- package/npm-shrinkwrap.json +5179 -10848
- package/package.json +5 -5
package/lib/init/index.js
CHANGED
|
@@ -6,7 +6,7 @@ const term = require('../util/term');
|
|
|
6
6
|
const Spinner = require('./util/spinner');
|
|
7
7
|
|
|
8
8
|
const { OPTIONS_PRIORITY, COMMAND_ADD, COMMAND_INIT,
|
|
9
|
-
OPTION_HANA, OPTION_JAVA, OPTION_MTA, OPTION_MTX, OPTION_NODEJS,
|
|
9
|
+
OPTION_HANA, OPTION_JAVA, OPTION_MTA, OPTION_MTX, OPTION_NODEJS,
|
|
10
10
|
OPTION_PIPELINE, OPTION_SAMPLES, OPTION_CF_MANIFEST, PROJECT_FILES, REGEX_PROJECT_NAME } = require('./constants');
|
|
11
11
|
|
|
12
12
|
module.exports = class CDSGenerator {
|
|
@@ -14,6 +14,8 @@ module.exports = class CDSGenerator {
|
|
|
14
14
|
this.fsUtil = fsUtil || new FsUtil();
|
|
15
15
|
this.logger = logger || defaultLogger;
|
|
16
16
|
|
|
17
|
+
this.cwd = process.cwd();
|
|
18
|
+
|
|
17
19
|
this.uiConfig = [
|
|
18
20
|
{
|
|
19
21
|
title: `Project Name`,
|
|
@@ -23,7 +25,7 @@ module.exports = class CDSGenerator {
|
|
|
23
25
|
validate: async (value) => {
|
|
24
26
|
try {
|
|
25
27
|
await this._validateProjectName(value);
|
|
26
|
-
await this._validateProjectFolder(path.join(
|
|
28
|
+
await this._validateProjectFolder(path.join(this.cwd, value), this.cwd);
|
|
27
29
|
|
|
28
30
|
return true;
|
|
29
31
|
} catch (err) {
|
|
@@ -279,7 +281,7 @@ module.exports = class CDSGenerator {
|
|
|
279
281
|
let tokens = [];
|
|
280
282
|
|
|
281
283
|
if (typeof this.options.add === 'string') {
|
|
282
|
-
tokens = this.options.add.split(
|
|
284
|
+
tokens = this.options.add.split(/[,\s+]/g);
|
|
283
285
|
|
|
284
286
|
} else if (Array.isArray(this.options.add)) {
|
|
285
287
|
tokens = this.options.add
|
|
@@ -310,15 +312,18 @@ module.exports = class CDSGenerator {
|
|
|
310
312
|
this.options.add.add(OPTION_NODEJS);
|
|
311
313
|
}
|
|
312
314
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
315
|
+
this._checkAdditionalOptions();
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
_checkAdditionalOptions() {
|
|
319
|
+
for (const [key] of Object.entries(this.options)) {
|
|
320
|
+
const keySplit = key.split(/:/);
|
|
321
|
+
if (keySplit.length === 2) {
|
|
322
|
+
if (!this.options.add.has(keySplit[0])) {
|
|
323
|
+
this.logger.warn(`ignoring option ${key} since ${keySplit[0]} is not part of specified feature list: ${Array.from(this.options.add).join(', ')}`);
|
|
324
|
+
}
|
|
319
325
|
}
|
|
320
326
|
}
|
|
321
|
-
|
|
322
327
|
}
|
|
323
328
|
|
|
324
329
|
async _validateOptions() {
|
|
@@ -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
|
}
|
|
@@ -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/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");
|
|
@@ -72,7 +70,7 @@ class Linter {
|
|
|
72
70
|
*/
|
|
73
71
|
async lint(args, options) {
|
|
74
72
|
this.eslintCmdOpts = this._sanitizeUserOpts(options);
|
|
75
|
-
this.eslintCmdFileExpr = args
|
|
73
|
+
this.eslintCmdFileExpr = args.length ? args : ['.']
|
|
76
74
|
if (this.eslintCmdOpts.help) {
|
|
77
75
|
this._printHelp();
|
|
78
76
|
} else {
|
|
@@ -97,16 +95,10 @@ class Linter {
|
|
|
97
95
|
// Limit to CDS file extensions
|
|
98
96
|
this._addExtensions();
|
|
99
97
|
// Run ESLint with collected options
|
|
100
|
-
let result = "";
|
|
101
98
|
try {
|
|
102
|
-
|
|
99
|
+
await this._runEslint();
|
|
103
100
|
} catch (err) {
|
|
104
|
-
|
|
105
|
-
console.log(err.stdout);
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
if (result.stdout) {
|
|
109
|
-
console.log(result.stdout);
|
|
101
|
+
term.error(err);
|
|
110
102
|
}
|
|
111
103
|
}
|
|
112
104
|
}
|
|
@@ -171,66 +163,76 @@ class Linter {
|
|
|
171
163
|
async _runEslint(dryRun = false) {
|
|
172
164
|
const eslintCmdOpts = [];
|
|
173
165
|
// Collect cmd line options
|
|
174
|
-
|
|
175
|
-
let
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
} else {
|
|
179
|
-
if (value) {
|
|
166
|
+
try {
|
|
167
|
+
for (let key in this.eslintCmdOpts) {
|
|
168
|
+
let value = this.eslintCmdOpts[key];
|
|
169
|
+
if (this.flags.includes(`--${key}`)) {
|
|
180
170
|
eslintCmdOpts.push(`--${key}`);
|
|
181
|
-
|
|
182
|
-
if (
|
|
183
|
-
eslintCmdOpts.push(
|
|
184
|
-
//
|
|
185
|
-
|
|
186
|
-
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)) {
|
|
187
176
|
eslintCmdOpts.push(`"${value}"`);
|
|
177
|
+
// Paths are quoted according on os
|
|
188
178
|
} else {
|
|
189
|
-
|
|
179
|
+
if (IS_WIN) {
|
|
180
|
+
eslintCmdOpts.push(`"${value}"`);
|
|
181
|
+
} else {
|
|
182
|
+
eslintCmdOpts.push(value);
|
|
183
|
+
}
|
|
190
184
|
}
|
|
191
185
|
}
|
|
192
186
|
}
|
|
193
187
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
const fileExtensions = getFileExtensions();
|
|
197
|
-
eslintCmdOpts.push("--ignore-pattern");
|
|
198
|
-
let ignorePattern = "*.*";
|
|
199
|
-
if (IS_WIN) {
|
|
200
|
-
ignorePattern = `"${ignorePattern}"`;
|
|
201
|
-
}
|
|
202
|
-
eslintCmdOpts.push(ignorePattern);
|
|
203
|
-
fileExtensions.forEach((ext) => {
|
|
188
|
+
// Only lint file extensions prescribed by plugin
|
|
189
|
+
const fileExtensions = getFileExtensions();
|
|
204
190
|
eslintCmdOpts.push("--ignore-pattern");
|
|
205
|
-
ignorePattern =
|
|
191
|
+
let ignorePattern = "*.*";
|
|
206
192
|
if (IS_WIN) {
|
|
207
193
|
ignorePattern = `"${ignorePattern}"`;
|
|
194
|
+
} else {
|
|
195
|
+
ignorePattern = `'${ignorePattern}'`;
|
|
208
196
|
}
|
|
209
197
|
eslintCmdOpts.push(ignorePattern);
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
console.log(
|
|
218
|
-
`Linting:\n ${term.info(
|
|
219
|
-
`${this.eslintCmdShort} ${eslintCmdOpts.join(" ")} ${input}`
|
|
220
|
-
)}`
|
|
221
|
-
);
|
|
222
|
-
}
|
|
223
|
-
if (!dryRun) {
|
|
224
|
-
return execAsync(
|
|
225
|
-
`${this.eslintCmd} ${eslintCmdOpts.join(" ")} ${input}`,
|
|
226
|
-
{
|
|
227
|
-
cwd: process.cwd(),
|
|
228
|
-
shell: IS_WIN,
|
|
229
|
-
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}'`;
|
|
230
205
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
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);
|
|
234
236
|
}
|
|
235
237
|
}
|
|
236
238
|
|
|
@@ -305,7 +307,7 @@ class Linter {
|
|
|
305
307
|
this.esllintCmdOpts = io.mergeWithUserOpts(
|
|
306
308
|
this.eslintCmdOpts,
|
|
307
309
|
"rule",
|
|
308
|
-
`${rule}
|
|
310
|
+
`${rule}:${rules[rule]}`
|
|
309
311
|
);
|
|
310
312
|
}
|
|
311
313
|
});
|
package/lib/lint/generators.js
CHANGED
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);
|