1 | /**
|
2 | * @fileoverview Helper to locate and load configuration files.
|
3 | * @author Nicholas C. Zakas
|
4 | */
|
5 |
|
6 | ;
|
7 |
|
8 | //------------------------------------------------------------------------------
|
9 | // Requirements
|
10 | //------------------------------------------------------------------------------
|
11 |
|
12 | const fs = require("fs"),
|
13 | path = require("path"),
|
14 | stringify = require("json-stable-stringify-without-jsonify");
|
15 |
|
16 | const debug = require("debug")("eslint:config-file");
|
17 |
|
18 | //------------------------------------------------------------------------------
|
19 | // Helpers
|
20 | //------------------------------------------------------------------------------
|
21 |
|
22 | /**
|
23 | * Determines sort order for object keys for json-stable-stringify
|
24 | *
|
25 | * see: https://github.com/samn/json-stable-stringify#cmp
|
26 | * @param {Object} a The first comparison object ({key: akey, value: avalue})
|
27 | * @param {Object} b The second comparison object ({key: bkey, value: bvalue})
|
28 | * @returns {number} 1 or -1, used in stringify cmp method
|
29 | */
|
30 | function sortByKey(a, b) {
|
31 | return a.key > b.key ? 1 : -1;
|
32 | }
|
33 |
|
34 | //------------------------------------------------------------------------------
|
35 | // Private
|
36 | //------------------------------------------------------------------------------
|
37 |
|
38 | /**
|
39 | * Writes a configuration file in JSON format.
|
40 | * @param {Object} config The configuration object to write.
|
41 | * @param {string} filePath The filename to write to.
|
42 | * @returns {void}
|
43 | * @private
|
44 | */
|
45 | function writeJSONConfigFile(config, filePath) {
|
46 | debug(`Writing JSON config file: ${filePath}`);
|
47 |
|
48 | const content = stringify(config, { cmp: sortByKey, space: 4 });
|
49 |
|
50 | fs.writeFileSync(filePath, content, "utf8");
|
51 | }
|
52 |
|
53 | /**
|
54 | * Writes a configuration file in YAML format.
|
55 | * @param {Object} config The configuration object to write.
|
56 | * @param {string} filePath The filename to write to.
|
57 | * @returns {void}
|
58 | * @private
|
59 | */
|
60 | function writeYAMLConfigFile(config, filePath) {
|
61 | debug(`Writing YAML config file: ${filePath}`);
|
62 |
|
63 | // lazy load YAML to improve performance when not used
|
64 | const yaml = require("js-yaml");
|
65 |
|
66 | const content = yaml.safeDump(config, { sortKeys: true });
|
67 |
|
68 | fs.writeFileSync(filePath, content, "utf8");
|
69 | }
|
70 |
|
71 | /**
|
72 | * Writes a configuration file in JavaScript format.
|
73 | * @param {Object} config The configuration object to write.
|
74 | * @param {string} filePath The filename to write to.
|
75 | * @throws {Error} If an error occurs linting the config file contents.
|
76 | * @returns {void}
|
77 | * @private
|
78 | */
|
79 | function writeJSConfigFile(config, filePath) {
|
80 | debug(`Writing JS config file: ${filePath}`);
|
81 |
|
82 | let contentToWrite;
|
83 | const stringifiedContent = `module.exports = ${stringify(config, { cmp: sortByKey, space: 4 })};`;
|
84 |
|
85 | try {
|
86 | const { CLIEngine } = require("../cli-engine");
|
87 | const linter = new CLIEngine({
|
88 | baseConfig: config,
|
89 | fix: true,
|
90 | useEslintrc: false
|
91 | });
|
92 | const report = linter.executeOnText(stringifiedContent);
|
93 |
|
94 | contentToWrite = report.results[0].output || stringifiedContent;
|
95 | } catch (e) {
|
96 | debug("Error linting JavaScript config file, writing unlinted version");
|
97 | const errorMessage = e.message;
|
98 |
|
99 | contentToWrite = stringifiedContent;
|
100 | e.message = "An error occurred while generating your JavaScript config file. ";
|
101 | e.message += "A config file was still generated, but the config file itself may not follow your linting rules.";
|
102 | e.message += `\nError: ${errorMessage}`;
|
103 | throw e;
|
104 | } finally {
|
105 | fs.writeFileSync(filePath, contentToWrite, "utf8");
|
106 | }
|
107 | }
|
108 |
|
109 | /**
|
110 | * Writes a configuration file.
|
111 | * @param {Object} config The configuration object to write.
|
112 | * @param {string} filePath The filename to write to.
|
113 | * @returns {void}
|
114 | * @throws {Error} When an unknown file type is specified.
|
115 | * @private
|
116 | */
|
117 | function write(config, filePath) {
|
118 | switch (path.extname(filePath)) {
|
119 | case ".js":
|
120 | writeJSConfigFile(config, filePath);
|
121 | break;
|
122 |
|
123 | case ".json":
|
124 | writeJSONConfigFile(config, filePath);
|
125 | break;
|
126 |
|
127 | case ".yaml":
|
128 | case ".yml":
|
129 | writeYAMLConfigFile(config, filePath);
|
130 | break;
|
131 |
|
132 | default:
|
133 | throw new Error("Can't write to unknown file type.");
|
134 | }
|
135 | }
|
136 |
|
137 | //------------------------------------------------------------------------------
|
138 | // Public Interface
|
139 | //------------------------------------------------------------------------------
|
140 |
|
141 | module.exports = {
|
142 | write
|
143 | };
|