1 | const fs = require("fs");
|
2 | const path = require("path");
|
3 | const _set = require("lodash/set");
|
4 | const _get = require("lodash/get");
|
5 | const _clone = require("lodash/clone");
|
6 | const compileConfig = require("./compile-config");
|
7 | const defaults = require("./defaults.json");
|
8 |
|
9 | const 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 |
|
33 | function 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 |
|
44 | function isKnownCLIOption(pCandidateString) {
|
45 | return KNOWN_CLI_OPTIONS.some((pString) => pString === pCandidateString);
|
46 | }
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 | function 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 |
|
65 | function 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 |
|
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 |
|
93 | function fileExists(pFileName) {
|
94 | try {
|
95 | fs.accessSync(pFileName, fs.R_OK);
|
96 | return true;
|
97 | } catch (pError) {
|
98 | return false;
|
99 | }
|
100 | }
|
101 |
|
102 | function 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 |
|
116 | function 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 |
|
127 | function 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 |
|
141 |
|
142 |
|
143 |
|
144 |
|
145 |
|
146 | module.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 |
|
197 | module.exports.determineRulesFileName = getOptionValue(
|
198 | defaults.RULES_FILE_NAME
|
199 | );
|