UNPKG

4.97 kBJavaScriptView Raw
1const fs = require("fs");
2const path = require("path");
3const _set = require("lodash/set");
4const _get = require("lodash/get");
5const _clone = require("lodash/clone");
6const compileConfig = require("./compile-config");
7const defaults = require("./defaults.json");
8
9const KNOWN_CLI_OPTIONS = [
10 "baseDir",
11 "config",
12 "doNotFollow",
13 "exclude",
14 "focus",
15 "help",
16 "includeOnly",
17 "info",
18 "init",
19 "maxDepth",
20 "moduleSystems",
21 "outputTo",
22 "outputType",
23 "prefix",
24 "preserveSymlinks",
25 "tsPreCompilationDeps",
26 "tsConfig",
27 "babelConfig",
28 "validate",
29 "version",
30 "webpackConfig",
31];
32
33function getOptionValue(pDefault) {
34 return (pValue) => {
35 let lReturnValue = pDefault;
36
37 if (typeof pValue === "string") {
38 lReturnValue = pValue;
39 }
40 return lReturnValue;
41 };
42}
43
44function isKnownCLIOption(pCandidateString) {
45 return KNOWN_CLI_OPTIONS.some((pString) => pString === pCandidateString);
46}
47
48/**
49 * Remove all attributes from the input object (which'd typically be
50 * originating from commander) that are not functional dependency-cruiser
51 * options so a clean object can be passed through to the main function
52 *
53 * @param {any} pOptions - an options object e.g. as output from commander
54 * @returns {ICruiseOptions} - an options object that only contains stuff we care about
55 */
56function ejectNonCLIOptions(pOptions) {
57 return Object.keys(pOptions)
58 .filter(isKnownCLIOption)
59 .reduce((pAll, pKey) => {
60 pAll[pKey] = pOptions[pKey];
61 return pAll;
62 }, {});
63}
64
65function normalizeConfigFile(pOptions, pConfigWrapperName, pDefault) {
66 let lOptions = _clone(pOptions);
67
68 if (Object.prototype.hasOwnProperty.call(lOptions, pConfigWrapperName)) {
69 _set(
70 lOptions,
71 `ruleSet.options.${pConfigWrapperName}.fileName`,
72 getOptionValue(pDefault)(lOptions[pConfigWrapperName])
73 /* eslint security/detect-object-injection: 0 */
74 );
75 Reflect.deleteProperty(lOptions, pConfigWrapperName);
76 }
77
78 if (_get(lOptions, `ruleSet.options.${pConfigWrapperName}`, null)) {
79 if (
80 !_get(lOptions, `ruleSet.options.${pConfigWrapperName}.fileName`, null)
81 ) {
82 _set(
83 lOptions,
84 `ruleSet.options.${pConfigWrapperName}.fileName`,
85 pDefault
86 );
87 }
88 }
89
90 return lOptions;
91}
92
93function fileExists(pFileName) {
94 try {
95 fs.accessSync(pFileName, fs.R_OK);
96 return true;
97 } catch (pError) {
98 return false;
99 }
100}
101
102function validateAndGetCustomRulesFileName(pValidate) {
103 let lReturnValue = "";
104
105 if (fileExists(pValidate)) {
106 lReturnValue = pValidate;
107 } else {
108 throw new Error(
109 `Can't open '${pValidate}' for reading. Does it exist?` +
110 ` (You can create a dependency-cruiser configuration file with depcruise --init .)\n`
111 );
112 }
113 return lReturnValue;
114}
115
116function validateAndGetDefaultRulesFileName() {
117 let lReturnValue = defaults.RULES_FILE_NAME_SEARCH_ARRAY.find(fileExists);
118
119 if (typeof lReturnValue === "undefined") {
120 throw new TypeError(
121 `Can't open '${defaults.RULES_FILE_NAME}' for reading. Does it exist?\n`
122 );
123 }
124 return lReturnValue;
125}
126
127function validateAndNormalizeRulesFileName(pValidate) {
128 let lReturnValue = "";
129
130 if (typeof pValidate === "string") {
131 lReturnValue = validateAndGetCustomRulesFileName(pValidate);
132 } else {
133 lReturnValue = validateAndGetDefaultRulesFileName();
134 }
135
136 return lReturnValue;
137}
138
139/**
140 * returns the pOptions, so that the returned value contains a
141 * valid value for each possible option
142 *
143 * @param {object} pOptionsAsPassedFromCommander [description]
144 * @return {object} [description]
145 */
146module.exports = (pOptionsAsPassedFromCommander) => {
147 let lOptions = {
148 outputTo: defaults.OUTPUT_TO,
149 outputType: defaults.OUTPUT_TYPE,
150 ...ejectNonCLIOptions(pOptionsAsPassedFromCommander),
151 };
152
153 if (Object.prototype.hasOwnProperty.call(lOptions, "moduleSystems")) {
154 lOptions.moduleSystems = lOptions.moduleSystems
155 .split(",")
156 .map((pString) => pString.trim());
157 }
158
159 if (Object.prototype.hasOwnProperty.call(lOptions, "config")) {
160 lOptions.validate = lOptions.config;
161 }
162
163 if (Object.prototype.hasOwnProperty.call(lOptions, "validate")) {
164 lOptions.rulesFile = validateAndNormalizeRulesFileName(lOptions.validate);
165 lOptions.ruleSet = compileConfig(
166 path.isAbsolute(lOptions.rulesFile)
167 ? lOptions.rulesFile
168 : `./${lOptions.rulesFile}`
169 );
170 lOptions.validate = true;
171 }
172
173 lOptions = normalizeConfigFile(
174 lOptions,
175 "webpackConfig",
176 defaults.WEBPACK_CONFIG
177 );
178 lOptions = normalizeConfigFile(
179 lOptions,
180 "tsConfig",
181 defaults.TYPESCRIPT_CONFIG
182 );
183 lOptions = normalizeConfigFile(
184 lOptions,
185 "babelConfig",
186 defaults.BABEL_CONFIG
187 );
188
189 lOptions.validate = Object.prototype.hasOwnProperty.call(
190 lOptions,
191 "validate"
192 );
193
194 return lOptions;
195};
196
197module.exports.determineRulesFileName = getOptionValue(
198 defaults.RULES_FILE_NAME
199);