xref: /expo/packages/@expo/config/build/paths/paths.js (revision 5697f03e)
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4  value: true
5});
6exports.ensureSlash = ensureSlash;
7exports.getEntryPoint = getEntryPoint;
8exports.getEntryPointWithExtensions = getEntryPointWithExtensions;
9exports.getFileWithExtensions = getFileWithExtensions;
10exports.getPossibleProjectRoot = getPossibleProjectRoot;
11exports.resolveEntryPoint = resolveEntryPoint;
12exports.resolveFromSilentWithExtensions = resolveFromSilentWithExtensions;
13function _fs() {
14  const data = _interopRequireDefault(require("fs"));
15  _fs = function () {
16    return data;
17  };
18  return data;
19}
20function _path() {
21  const data = _interopRequireDefault(require("path"));
22  _path = function () {
23    return data;
24  };
25  return data;
26}
27function _resolveFrom() {
28  const data = _interopRequireDefault(require("resolve-from"));
29  _resolveFrom = function () {
30    return data;
31  };
32  return data;
33}
34function _Config() {
35  const data = require("../Config");
36  _Config = function () {
37    return data;
38  };
39  return data;
40}
41function _Errors() {
42  const data = require("../Errors");
43  _Errors = function () {
44    return data;
45  };
46  return data;
47}
48function _extensions() {
49  const data = require("./extensions");
50  _extensions = function () {
51    return data;
52  };
53  return data;
54}
55function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
56// https://github.com/facebook/create-react-app/blob/9750738cce89a967cc71f28390daf5d4311b193c/packages/react-scripts/config/paths.js#L22
57function ensureSlash(inputPath, needsSlash) {
58  const hasSlash = inputPath.endsWith('/');
59  if (hasSlash && !needsSlash) {
60    return inputPath.substr(0, inputPath.length - 1);
61  } else if (!hasSlash && needsSlash) {
62    return `${inputPath}/`;
63  } else {
64    return inputPath;
65  }
66}
67function getPossibleProjectRoot() {
68  return _fs().default.realpathSync(process.cwd());
69}
70const nativePlatforms = ['ios', 'android'];
71function resolveEntryPoint(projectRoot, {
72  platform,
73  projectConfig
74}) {
75  const platforms = nativePlatforms.includes(platform) ? [platform, 'native'] : [platform];
76  return getEntryPoint(projectRoot, ['./index'], platforms, projectConfig);
77}
78function getEntryPoint(projectRoot, entryFiles, platforms, projectConfig) {
79  const extensions = (0, _extensions().getBareExtensions)(platforms);
80  return getEntryPointWithExtensions(projectRoot, entryFiles, extensions, projectConfig);
81}
82
83// Used to resolve the main entry file for a project.
84function getEntryPointWithExtensions(projectRoot, entryFiles, extensions, projectConfig) {
85  if (!projectConfig) {
86    // drop all logging abilities
87    const original = process.stdout.write;
88    process.stdout.write = () => true;
89    try {
90      projectConfig = (0, _Config().getConfig)(projectRoot, {
91        skipSDKVersionRequirement: true
92      });
93    } finally {
94      process.stdout.write = original;
95    }
96  }
97  const {
98    exp,
99    pkg
100  } = projectConfig;
101  if (typeof (exp === null || exp === void 0 ? void 0 : exp.entryPoint) === 'string') {
102    // We want to stop reading the app.json for determining the entry file in SDK +49
103    throw new (_Errors().ConfigError)('expo.entryPoint has been removed in favor of the main field in the package.json.', 'DEPRECATED');
104  }
105  if (pkg) {
106    // If the config doesn't define a custom entry then we want to look at the `package.json`s `main` field, and try again.
107    const {
108      main
109    } = pkg;
110    if (main && typeof main === 'string') {
111      // Testing the main field against all of the provided extensions - for legacy reasons we can't use node module resolution as the package.json allows you to pass in a file without a relative path and expect it as a relative path.
112      let entry = getFileWithExtensions(projectRoot, main, extensions);
113      if (!entry) {
114        // Allow for paths like: `{ "main": "expo/AppEntry" }`
115        entry = resolveFromSilentWithExtensions(projectRoot, main, extensions);
116        if (!entry) throw new Error(`Cannot resolve entry file: The \`main\` field defined in your \`package.json\` points to a non-existent path.`);
117      }
118      return entry;
119    }
120  }
121
122  // Now we will start looking for a default entry point using the provided `entryFiles` argument.
123  // This will add support for create-react-app (src/index.js) and react-native-cli (index.js) which don't define a main.
124  for (const fileName of entryFiles) {
125    const entry = resolveFromSilentWithExtensions(projectRoot, fileName, extensions);
126    if (entry) return entry;
127  }
128  try {
129    // If none of the default files exist then we will attempt to use the main Expo entry point.
130    // This requires `expo` to be installed in the project to work as it will use `node_module/expo/AppEntry.js`
131    // Doing this enables us to create a bare minimum Expo project.
132
133    // TODO(Bacon): We may want to do a check against `./App` and `expo` in the `package.json` `dependencies` as we can more accurately ensure that the project is expo-min without needing the modules installed.
134    return (0, _resolveFrom().default)(projectRoot, 'expo/AppEntry');
135  } catch {
136    throw new Error(`The project entry file could not be resolved. Please define it in the \`main\` field of the \`package.json\`, create an \`index.js\`, or install the \`expo\` package.`);
137  }
138}
139
140// Resolve from but with the ability to resolve like a bundler
141function resolveFromSilentWithExtensions(fromDirectory, moduleId, extensions) {
142  for (const extension of extensions) {
143    const modulePath = _resolveFrom().default.silent(fromDirectory, `${moduleId}.${extension}`);
144    if (modulePath && modulePath.endsWith(extension)) {
145      return modulePath;
146    }
147  }
148  return _resolveFrom().default.silent(fromDirectory, moduleId) || null;
149}
150
151// Statically attempt to resolve a module but with the ability to resolve like a bundler.
152// This won't use node module resolution.
153function getFileWithExtensions(fromDirectory, moduleId, extensions) {
154  const modulePath = _path().default.join(fromDirectory, moduleId);
155  if (_fs().default.existsSync(modulePath)) {
156    return modulePath;
157  }
158  for (const extension of extensions) {
159    const modulePath = _path().default.join(fromDirectory, `${moduleId}.${extension}`);
160    if (_fs().default.existsSync(modulePath)) {
161      return modulePath;
162    }
163  }
164  return null;
165}
166//# sourceMappingURL=paths.js.map