21720:
[arvados.git] / services / workbench2 / config / modules.js
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 'use strict';
6
7 const fs = require('fs');
8 const path = require('path');
9 const paths = require('./paths');
10 const chalk = require('react-dev-utils/chalk');
11 const resolve = require('resolve');
12
13 /**
14  * Get additional module paths based on the baseUrl of a compilerOptions object.
15  *
16  * @param {Object} options
17  */
18 function getAdditionalModulePaths(options = {}) {
19   const baseUrl = options.baseUrl;
20
21   if (!baseUrl) {
22     return '';
23   }
24
25   const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
26
27   // We don't need to do anything if `baseUrl` is set to `node_modules`. This is
28   // the default behavior.
29   if (path.relative(paths.appNodeModules, baseUrlResolved) === '') {
30     return null;
31   }
32
33   // Allow the user set the `baseUrl` to `appSrc`.
34   if (path.relative(paths.appSrc, baseUrlResolved) === '') {
35     return [paths.appSrc];
36   }
37
38   // If the path is equal to the root directory we ignore it here.
39   // We don't want to allow importing from the root directly as source files are
40   // not transpiled outside of `src`. We do allow importing them with the
41   // absolute path (e.g. `src/Components/Button.js`) but we set that up with
42   // an alias.
43   if (path.relative(paths.appPath, baseUrlResolved) === '') {
44     return null;
45   }
46
47   // Otherwise, throw an error.
48   throw new Error(
49     chalk.red.bold(
50       "Your project's `baseUrl` can only be set to `src` or `node_modules`." +
51         ' Create React App does not support other values at this time.'
52     )
53   );
54 }
55
56 /**
57  * Get webpack aliases based on the baseUrl of a compilerOptions object.
58  *
59  * @param {*} options
60  */
61 function getWebpackAliases(options = {}) {
62   const baseUrl = options.baseUrl;
63
64   if (!baseUrl) {
65     return {};
66   }
67
68   const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
69
70   if (path.relative(paths.appPath, baseUrlResolved) === '') {
71     return {
72       src: paths.appSrc,
73     };
74   }
75 }
76
77 /**
78  * Get jest aliases based on the baseUrl of a compilerOptions object.
79  *
80  * @param {*} options
81  */
82 function getJestAliases(options = {}) {
83   const baseUrl = options.baseUrl;
84
85   if (!baseUrl) {
86     return {};
87   }
88
89   const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
90
91   if (path.relative(paths.appPath, baseUrlResolved) === '') {
92     return {
93       '^src/(.*)$': '<rootDir>/src/$1',
94     };
95   }
96 }
97
98 function getModules() {
99   // Check if TypeScript is setup
100   const hasTsConfig = fs.existsSync(paths.appTsConfig);
101   const hasJsConfig = fs.existsSync(paths.appJsConfig);
102
103   if (hasTsConfig && hasJsConfig) {
104     throw new Error(
105       'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.'
106     );
107   }
108
109   let config;
110
111   // If there's a tsconfig.json we assume it's a
112   // TypeScript project and set up the config
113   // based on tsconfig.json
114   if (hasTsConfig) {
115     const ts = require(resolve.sync('typescript', {
116       basedir: paths.appNodeModules,
117     }));
118     config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config;
119     // Otherwise we'll check if there is jsconfig.json
120     // for non TS projects.
121   } else if (hasJsConfig) {
122     config = require(paths.appJsConfig);
123   }
124
125   config = config || {};
126   const options = config.compilerOptions || {};
127
128   const additionalModulePaths = getAdditionalModulePaths(options);
129
130   return {
131     additionalModulePaths: additionalModulePaths,
132     webpackAliases: getWebpackAliases(options),
133     jestAliases: getJestAliases(options),
134     hasTsConfig,
135   };
136 }
137
138 module.exports = getModules();