1 | "use strict";
|
2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4 | return new (P || (P = Promise))(function (resolve, reject) {
|
5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9 | });
|
10 | };
|
11 | var __importDefault = (this && this.__importDefault) || function (mod) {
|
12 | return (mod && mod.__esModule) ? mod : { "default": mod };
|
13 | };
|
14 | Object.defineProperty(exports, "__esModule", { value: true });
|
15 | const json_file_1 = __importDefault(require("@expo/json-file"));
|
16 | const fs_extra_1 = __importDefault(require("fs-extra"));
|
17 | const globby_1 = __importDefault(require("globby"));
|
18 | const path_1 = __importDefault(require("path"));
|
19 | const semver_1 = __importDefault(require("semver"));
|
20 | const slugify_1 = __importDefault(require("slugify"));
|
21 | const Errors_1 = require("./Errors");
|
22 | const getConfig_1 = require("./getConfig");
|
23 | const Modules_1 = require("./Modules");
|
24 | const Project_1 = require("./Project");
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 | function reduceExpoObject(config) {
|
32 | if (!config)
|
33 | return config === undefined ? null : config;
|
34 | if (typeof config.expo === 'object') {
|
35 |
|
36 | return config.expo;
|
37 | }
|
38 | return config;
|
39 | }
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 | function getSupportedPlatforms(projectRoot, exp) {
|
47 | const platforms = [];
|
48 | if (Modules_1.projectHasModule('react-native', projectRoot, exp)) {
|
49 | platforms.push('ios', 'android');
|
50 | }
|
51 | if (Modules_1.projectHasModule('react-native-web', projectRoot, exp)) {
|
52 | platforms.push('web');
|
53 | }
|
54 | return platforms;
|
55 | }
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 | function getConfig(projectRoot, options = {}) {
|
80 | const paths = getConfigFilePaths(projectRoot);
|
81 | const rawStaticConfig = paths.staticConfigPath ? getConfig_1.getStaticConfig(paths.staticConfigPath) : null;
|
82 |
|
83 | const rootConfig = (rawStaticConfig || {});
|
84 | const staticConfig = reduceExpoObject(rawStaticConfig) || {};
|
85 | const jsonFileWithNodeModulesPath = reduceExpoObject(rootConfig);
|
86 |
|
87 | const [packageJson, packageJsonPath] = getPackageJsonAndPath(projectRoot, jsonFileWithNodeModulesPath);
|
88 | function fillAndReturnConfig(config, dynamicConfigObjectType) {
|
89 | return Object.assign(Object.assign({}, ensureConfigHasDefaultValues(projectRoot, config, packageJson, options.skipSDKVersionRequirement)), { dynamicConfigObjectType,
|
90 | rootConfig, dynamicConfigPath: paths.dynamicConfigPath, staticConfigPath: paths.staticConfigPath });
|
91 | }
|
92 |
|
93 | function getContextConfig(config = {}) {
|
94 | return ensureConfigHasDefaultValues(projectRoot, config, packageJson, true).exp;
|
95 | }
|
96 | if (paths.dynamicConfigPath) {
|
97 |
|
98 | const { exportedObjectType, config: rawDynamicConfig } = getConfig_1.getDynamicConfig(paths.dynamicConfigPath, {
|
99 | projectRoot,
|
100 | staticConfigPath: paths.staticConfigPath,
|
101 | packageJsonPath,
|
102 | config: getContextConfig(staticConfig),
|
103 | });
|
104 |
|
105 |
|
106 | const dynamicConfig = reduceExpoObject(rawDynamicConfig) || {};
|
107 | return fillAndReturnConfig(dynamicConfig, exportedObjectType);
|
108 | }
|
109 |
|
110 | return fillAndReturnConfig(staticConfig || {}, null);
|
111 | }
|
112 | exports.getConfig = getConfig;
|
113 | function getPackageJson(projectRoot, config = {}) {
|
114 | const [pkg] = getPackageJsonAndPath(projectRoot, config);
|
115 | return pkg;
|
116 | }
|
117 | exports.getPackageJson = getPackageJson;
|
118 | function getPackageJsonAndPath(projectRoot, config = {}) {
|
119 | const packageJsonPath = Modules_1.getRootPackageJsonPath(projectRoot, config);
|
120 | return [json_file_1.default.read(packageJsonPath), packageJsonPath];
|
121 | }
|
122 | function readConfigJson(projectRoot, skipValidation = false, skipNativeValidation = false) {
|
123 | const paths = getConfigFilePaths(projectRoot);
|
124 | const rawStaticConfig = paths.staticConfigPath ? getConfig_1.getStaticConfig(paths.staticConfigPath) : null;
|
125 | const getConfigName = () => {
|
126 | if (paths.staticConfigPath)
|
127 | ` \`${path_1.default.basename(paths.staticConfigPath)}\``;
|
128 | return '';
|
129 | };
|
130 | let outputRootConfig = rawStaticConfig;
|
131 | if (outputRootConfig === null || typeof outputRootConfig !== 'object') {
|
132 | if (skipValidation) {
|
133 | outputRootConfig = { expo: {} };
|
134 | }
|
135 | else {
|
136 | throw new Errors_1.ConfigError(`Project at path ${path_1.default.resolve(projectRoot)} does not contain a valid Expo config${getConfigName()}`, 'NOT_OBJECT');
|
137 | }
|
138 | }
|
139 | let exp = outputRootConfig.expo;
|
140 | if (exp === null || typeof exp !== 'object') {
|
141 | throw new Errors_1.ConfigError(`Property 'expo' in${getConfigName()} for project at path ${path_1.default.resolve(projectRoot)} is not an object. Please make sure${getConfigName()} includes a managed Expo app config like this: ${APP_JSON_EXAMPLE}`, 'NO_EXPO');
|
142 | }
|
143 | exp = Object.assign({}, exp);
|
144 | const [pkg] = getPackageJsonAndPath(projectRoot, exp);
|
145 | return Object.assign(Object.assign(Object.assign({}, ensureConfigHasDefaultValues(projectRoot, exp, pkg, skipNativeValidation)), { dynamicConfigPath: null, dynamicConfigObjectType: null, rootConfig: Object.assign({}, outputRootConfig) }), paths);
|
146 | }
|
147 | exports.readConfigJson = readConfigJson;
|
148 | function readConfigJsonAsync(projectRoot, skipValidation = false, skipNativeValidation = false) {
|
149 | return __awaiter(this, void 0, void 0, function* () {
|
150 | return readConfigJson(projectRoot, skipValidation, skipNativeValidation);
|
151 | });
|
152 | }
|
153 | exports.readConfigJsonAsync = readConfigJsonAsync;
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 | function getConfigFilePaths(projectRoot) {
|
160 | const customPaths = getCustomConfigFilePaths(projectRoot);
|
161 | if (customPaths) {
|
162 | return customPaths;
|
163 | }
|
164 | return {
|
165 | dynamicConfigPath: getDynamicConfigFilePath(projectRoot),
|
166 | staticConfigPath: getStaticConfigFilePath(projectRoot),
|
167 | };
|
168 | }
|
169 | exports.getConfigFilePaths = getConfigFilePaths;
|
170 | function getCustomConfigFilePaths(projectRoot) {
|
171 | if (!customConfigPaths[projectRoot]) {
|
172 | return null;
|
173 | }
|
174 |
|
175 | if (isDynamicFilePath(customConfigPaths[projectRoot])) {
|
176 | return {
|
177 | dynamicConfigPath: customConfigPaths[projectRoot],
|
178 | staticConfigPath: null,
|
179 | };
|
180 | }
|
181 |
|
182 | return { staticConfigPath: customConfigPaths[projectRoot], dynamicConfigPath: null };
|
183 | }
|
184 | function getDynamicConfigFilePath(projectRoot) {
|
185 | for (const fileName of ['app.config.ts', 'app.config.js']) {
|
186 | const configPath = path_1.default.join(projectRoot, fileName);
|
187 | if (fs_extra_1.default.existsSync(configPath)) {
|
188 | return configPath;
|
189 | }
|
190 | }
|
191 | return null;
|
192 | }
|
193 | function getStaticConfigFilePath(projectRoot) {
|
194 | for (const fileName of ['app.config.json', 'app.json']) {
|
195 | const configPath = path_1.default.join(projectRoot, fileName);
|
196 | if (fs_extra_1.default.existsSync(configPath)) {
|
197 | return configPath;
|
198 | }
|
199 | }
|
200 | return null;
|
201 | }
|
202 |
|
203 | function findConfigFile(projectRoot) {
|
204 | let configPath;
|
205 |
|
206 | if (customConfigPaths[projectRoot]) {
|
207 | configPath = customConfigPaths[projectRoot];
|
208 |
|
209 |
|
210 | return {
|
211 | configPath,
|
212 | configName: path_1.default.basename(configPath),
|
213 | configNamespace: 'expo',
|
214 | };
|
215 | }
|
216 | else {
|
217 |
|
218 | configPath = path_1.default.join(projectRoot, 'app.config.json');
|
219 | if (!fs_extra_1.default.existsSync(configPath)) {
|
220 | configPath = path_1.default.join(projectRoot, 'app.json');
|
221 | }
|
222 | }
|
223 | return {
|
224 | configPath,
|
225 | configName: path_1.default.basename(configPath),
|
226 | configNamespace: 'expo',
|
227 | };
|
228 | }
|
229 | exports.findConfigFile = findConfigFile;
|
230 |
|
231 | function configFilename(projectRoot) {
|
232 | return findConfigFile(projectRoot).configName;
|
233 | }
|
234 | exports.configFilename = configFilename;
|
235 | function readExpRcAsync(projectRoot) {
|
236 | return __awaiter(this, void 0, void 0, function* () {
|
237 | const expRcPath = path_1.default.join(projectRoot, '.exprc');
|
238 | return yield json_file_1.default.readAsync(expRcPath, { json5: true, cantReadFileDefault: {} });
|
239 | });
|
240 | }
|
241 | exports.readExpRcAsync = readExpRcAsync;
|
242 | const customConfigPaths = {};
|
243 | function setCustomConfigPath(projectRoot, configPath) {
|
244 | customConfigPaths[projectRoot] = configPath;
|
245 | }
|
246 | exports.setCustomConfigPath = setCustomConfigPath;
|
247 |
|
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 |
|
254 |
|
255 |
|
256 |
|
257 |
|
258 | function modifyConfigAsync(projectRoot, modifications, readOptions = {}, writeOptions = {}) {
|
259 | return __awaiter(this, void 0, void 0, function* () {
|
260 | const config = getConfig(projectRoot, readOptions);
|
261 | if (config.dynamicConfigPath) {
|
262 |
|
263 | |
264 |
|
265 |
|
266 |
|
267 |
|
268 |
|
269 |
|
270 |
|
271 |
|
272 |
|
273 |
|
274 |
|
275 | return {
|
276 | type: 'warn',
|
277 | message: `Cannot automatically write to dynamic config at: ${path_1.default.relative(projectRoot, config.dynamicConfigPath)}`,
|
278 | config: null,
|
279 | };
|
280 | }
|
281 | else if (config.staticConfigPath) {
|
282 |
|
283 | let outputConfig;
|
284 |
|
285 | if (config.rootConfig.expo) {
|
286 | outputConfig = Object.assign(Object.assign({}, config.rootConfig), { expo: Object.assign(Object.assign({}, config.rootConfig.expo), modifications) });
|
287 | }
|
288 | else {
|
289 |
|
290 | outputConfig = Object.assign(Object.assign({}, config.rootConfig), modifications);
|
291 | }
|
292 | if (!writeOptions.dryRun) {
|
293 | yield json_file_1.default.writeAsync(config.staticConfigPath, outputConfig, { json5: false });
|
294 | }
|
295 | return { type: 'success', config: outputConfig };
|
296 | }
|
297 | return { type: 'fail', message: 'No config exists', config: null };
|
298 | });
|
299 | }
|
300 | exports.modifyConfigAsync = modifyConfigAsync;
|
301 | const APP_JSON_EXAMPLE = JSON.stringify({
|
302 | expo: {
|
303 | name: 'My app',
|
304 | slug: 'my-app',
|
305 | sdkVersion: '...',
|
306 | },
|
307 | });
|
308 | function ensureConfigHasDefaultValues(projectRoot, exp, pkg, skipSDKVersionRequirement = false) {
|
309 | if (!exp)
|
310 | exp = {};
|
311 | if (!exp.name) {
|
312 | if (typeof pkg.name !== 'string') {
|
313 | pkg.name = path_1.default.basename(projectRoot);
|
314 | }
|
315 | exp.name = pkg.name;
|
316 | }
|
317 | if (!exp.description && typeof pkg.description === 'string') {
|
318 | exp.description = pkg.description;
|
319 | }
|
320 | if (!exp.slug && typeof exp.name === 'string') {
|
321 | exp.slug = slugify_1.default(exp.name.toLowerCase());
|
322 | }
|
323 | if (!exp.version) {
|
324 | if (typeof pkg.version === 'string') {
|
325 | exp.version = pkg.version;
|
326 | }
|
327 | else {
|
328 | pkg.version = '1.0.0';
|
329 | }
|
330 | exp.version = pkg.version;
|
331 | }
|
332 | if (exp.nodeModulesPath) {
|
333 | exp.nodeModulesPath = path_1.default.resolve(projectRoot, exp.nodeModulesPath);
|
334 | }
|
335 | try {
|
336 | exp.sdkVersion = Project_1.getExpoSDKVersion(projectRoot, exp);
|
337 | }
|
338 | catch (error) {
|
339 | if (!skipSDKVersionRequirement)
|
340 | throw error;
|
341 | }
|
342 | if (!exp.platforms) {
|
343 | exp.platforms = getSupportedPlatforms(projectRoot, exp);
|
344 | }
|
345 | return { exp, pkg };
|
346 | }
|
347 | function writeConfigJsonAsync(projectRoot, options) {
|
348 | return __awaiter(this, void 0, void 0, function* () {
|
349 | const paths = getConfigFilePaths(projectRoot);
|
350 | let { exp, pkg, rootConfig, dynamicConfigObjectType, staticConfigPath, } = yield readConfigJsonAsync(projectRoot);
|
351 | exp = Object.assign(Object.assign({}, rootConfig.expo), options);
|
352 | rootConfig = Object.assign(Object.assign({}, rootConfig), { expo: exp });
|
353 | if (paths.staticConfigPath) {
|
354 | yield json_file_1.default.writeAsync(paths.staticConfigPath, rootConfig, { json5: false });
|
355 | }
|
356 | else {
|
357 | console.log('Failed to write to config: ', options);
|
358 | }
|
359 | return Object.assign({ exp,
|
360 | pkg,
|
361 | rootConfig,
|
362 | staticConfigPath,
|
363 | dynamicConfigObjectType }, paths);
|
364 | });
|
365 | }
|
366 | exports.writeConfigJsonAsync = writeConfigJsonAsync;
|
367 | const DEFAULT_BUILD_PATH = `web-build`;
|
368 | function getWebOutputPath(config = {}) {
|
369 | var _a, _b, _c;
|
370 | if (process.env.WEBPACK_BUILD_OUTPUT_PATH) {
|
371 | return process.env.WEBPACK_BUILD_OUTPUT_PATH;
|
372 | }
|
373 | const expo = config.expo || config || {};
|
374 | return ((_c = (_b = (_a = expo) === null || _a === void 0 ? void 0 : _a.web) === null || _b === void 0 ? void 0 : _b.build) === null || _c === void 0 ? void 0 : _c.output) || DEFAULT_BUILD_PATH;
|
375 | }
|
376 | exports.getWebOutputPath = getWebOutputPath;
|
377 | function getNameFromConfig(exp = {}) {
|
378 |
|
379 | const appManifest = exp.expo || exp;
|
380 | const { web = {} } = appManifest;
|
381 |
|
382 | const appName = exp.displayName || appManifest.displayName || appManifest.name;
|
383 | const webName = web.name || appName;
|
384 | return {
|
385 | appName,
|
386 | webName,
|
387 | };
|
388 | }
|
389 | exports.getNameFromConfig = getNameFromConfig;
|
390 | function getDefaultTarget(projectRoot) {
|
391 | const { exp } = getConfig(projectRoot, { skipSDKVersionRequirement: true });
|
392 |
|
393 | if (exp.sdkVersion && exp.sdkVersion !== 'UNVERSIONED' && semver_1.default.lt(exp.sdkVersion, '37.0.0')) {
|
394 | return 'managed';
|
395 | }
|
396 | return isBareWorkflowProject(projectRoot) ? 'bare' : 'managed';
|
397 | }
|
398 | exports.getDefaultTarget = getDefaultTarget;
|
399 | function isBareWorkflowProject(projectRoot) {
|
400 | const { pkg } = getConfig(projectRoot, {
|
401 | skipSDKVersionRequirement: true,
|
402 | });
|
403 | if (pkg.dependencies && pkg.dependencies.expokit) {
|
404 | return false;
|
405 | }
|
406 | if (fs_extra_1.default.existsSync(path_1.default.resolve(projectRoot, 'ios'))) {
|
407 | const xcodeprojFiles = globby_1.default.sync([path_1.default.join(projectRoot, 'ios', '/**/*.xcodeproj')]);
|
408 | if (xcodeprojFiles.length) {
|
409 | return true;
|
410 | }
|
411 | }
|
412 | if (fs_extra_1.default.existsSync(path_1.default.resolve(projectRoot, 'android'))) {
|
413 | const gradleFiles = globby_1.default.sync([path_1.default.join(projectRoot, 'android', '/**/*.gradle')]);
|
414 | if (gradleFiles.length) {
|
415 | return true;
|
416 | }
|
417 | }
|
418 | return false;
|
419 | }
|
420 |
|
421 |
|
422 |
|
423 |
|
424 |
|
425 | function isDynamicFilePath(filePath) {
|
426 | return !!filePath.match(/\.[j|t]s$/);
|
427 | }
|
428 |
|
429 |
|
430 |
|
431 |
|
432 |
|
433 |
|
434 |
|
435 | function getProjectConfigDescription(projectRoot, projectConfig) {
|
436 | if (projectConfig.dynamicConfigPath) {
|
437 | const relativeDynamicConfigPath = path_1.default.relative(projectRoot, projectConfig.dynamicConfigPath);
|
438 | if (projectConfig.staticConfigPath) {
|
439 | return `Using dynamic config \`${relativeDynamicConfigPath}\` and static config \`${path_1.default.relative(projectRoot, projectConfig.staticConfigPath)}\``;
|
440 | }
|
441 | return `Using dynamic config \`${relativeDynamicConfigPath}\``;
|
442 | }
|
443 | else if (projectConfig.staticConfigPath) {
|
444 | return `Using static config \`${path_1.default.relative(projectRoot, projectConfig.staticConfigPath)}\``;
|
445 | }
|
446 | return null;
|
447 | }
|
448 | exports.getProjectConfigDescription = getProjectConfigDescription;
|
449 |
|
\ | No newline at end of file |