1"use strict"; 2 3Object.defineProperty(exports, "__esModule", { 4 value: true 5}); 6var _exportNames = { 7 getConfig: true, 8 getPackageJson: true, 9 readConfigJson: true, 10 getConfigFilePaths: true, 11 findConfigFile: true, 12 configFilename: true, 13 readExpRcAsync: true, 14 resetCustomConfigPaths: true, 15 setCustomConfigPath: true, 16 modifyConfigAsync: true, 17 writeConfigJsonAsync: true, 18 getWebOutputPath: true, 19 getNameFromConfig: true, 20 getDefaultTarget: true, 21 getProjectConfigDescription: true, 22 getProjectConfigDescriptionWithPaths: true, 23 isLegacyImportsEnabled: true 24}; 25exports.configFilename = configFilename; 26exports.findConfigFile = findConfigFile; 27exports.getConfig = getConfig; 28exports.getConfigFilePaths = getConfigFilePaths; 29exports.getDefaultTarget = getDefaultTarget; 30exports.getNameFromConfig = getNameFromConfig; 31exports.getPackageJson = getPackageJson; 32exports.getProjectConfigDescription = getProjectConfigDescription; 33exports.getProjectConfigDescriptionWithPaths = getProjectConfigDescriptionWithPaths; 34exports.getWebOutputPath = getWebOutputPath; 35Object.defineProperty(exports, "isLegacyImportsEnabled", { 36 enumerable: true, 37 get: function () { 38 return _isLegacyImportsEnabled().isLegacyImportsEnabled; 39 } 40}); 41exports.modifyConfigAsync = modifyConfigAsync; 42exports.readConfigJson = readConfigJson; 43exports.readExpRcAsync = readExpRcAsync; 44exports.resetCustomConfigPaths = resetCustomConfigPaths; 45exports.setCustomConfigPath = setCustomConfigPath; 46exports.writeConfigJsonAsync = writeConfigJsonAsync; 47 48function _jsonFile() { 49 const data = _interopRequireDefault(require("@expo/json-file")); 50 51 _jsonFile = function () { 52 return data; 53 }; 54 55 return data; 56} 57 58function _fs() { 59 const data = _interopRequireDefault(require("fs")); 60 61 _fs = function () { 62 return data; 63 }; 64 65 return data; 66} 67 68function _glob() { 69 const data = require("glob"); 70 71 _glob = function () { 72 return data; 73 }; 74 75 return data; 76} 77 78function _path() { 79 const data = _interopRequireDefault(require("path")); 80 81 _path = function () { 82 return data; 83 }; 84 85 return data; 86} 87 88function _resolveFrom() { 89 const data = _interopRequireDefault(require("resolve-from")); 90 91 _resolveFrom = function () { 92 return data; 93 }; 94 95 return data; 96} 97 98function _semver() { 99 const data = _interopRequireDefault(require("semver")); 100 101 _semver = function () { 102 return data; 103 }; 104 105 return data; 106} 107 108function _slugify() { 109 const data = _interopRequireDefault(require("slugify")); 110 111 _slugify = function () { 112 return data; 113 }; 114 115 return data; 116} 117 118function _Errors() { 119 const data = require("./Errors"); 120 121 _Errors = function () { 122 return data; 123 }; 124 125 return data; 126} 127 128function _Project() { 129 const data = require("./Project"); 130 131 _Project = function () { 132 return data; 133 }; 134 135 return data; 136} 137 138function _getConfig() { 139 const data = require("./getConfig"); 140 141 _getConfig = function () { 142 return data; 143 }; 144 145 return data; 146} 147 148function _getFullName() { 149 const data = require("./getFullName"); 150 151 _getFullName = function () { 152 return data; 153 }; 154 155 return data; 156} 157 158function _withConfigPlugins() { 159 const data = require("./plugins/withConfigPlugins"); 160 161 _withConfigPlugins = function () { 162 return data; 163 }; 164 165 return data; 166} 167 168function _withInternal() { 169 const data = require("./plugins/withInternal"); 170 171 _withInternal = function () { 172 return data; 173 }; 174 175 return data; 176} 177 178function _resolvePackageJson() { 179 const data = require("./resolvePackageJson"); 180 181 _resolvePackageJson = function () { 182 return data; 183 }; 184 185 return data; 186} 187 188var _Config = require("./Config.types"); 189 190Object.keys(_Config).forEach(function (key) { 191 if (key === "default" || key === "__esModule") return; 192 if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return; 193 if (key in exports && exports[key] === _Config[key]) return; 194 Object.defineProperty(exports, key, { 195 enumerable: true, 196 get: function () { 197 return _Config[key]; 198 } 199 }); 200}); 201 202function _isLegacyImportsEnabled() { 203 const data = require("./isLegacyImportsEnabled"); 204 205 _isLegacyImportsEnabled = function () { 206 return data; 207 }; 208 209 return data; 210} 211 212function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 213 214/** 215 * If a config has an `expo` object then that will be used as the config. 216 * This method reduces out other top level values if an `expo` object exists. 217 * 218 * @param config Input config object to reduce 219 */ 220function reduceExpoObject(config) { 221 var _config$expo; 222 223 if (!config) return config === undefined ? null : config; 224 const { 225 mods, 226 ...expo 227 } = (_config$expo = config.expo) !== null && _config$expo !== void 0 ? _config$expo : config; 228 return { 229 expo, 230 mods 231 }; 232} 233/** 234 * Get all platforms that a project is currently capable of running. 235 * 236 * @param projectRoot 237 * @param exp 238 */ 239 240 241function getSupportedPlatforms(projectRoot) { 242 const platforms = []; 243 244 if (_resolveFrom().default.silent(projectRoot, 'react-native')) { 245 platforms.push('ios', 'android'); 246 } 247 248 if (_resolveFrom().default.silent(projectRoot, 'react-native-web')) { 249 platforms.push('web'); 250 } 251 252 return platforms; 253} 254/** 255 * Evaluate the config for an Expo project. 256 * If a function is exported from the `app.config.js` then a partial config will be passed as an argument. 257 * The partial config is composed from any existing app.json, and certain fields from the `package.json` like name and description. 258 * 259 * If options.isPublicConfig is true, the Expo config will include only public-facing options (omitting private keys). 260 * The resulting config should be suitable for hosting or embedding in a publicly readable location. 261 * 262 * **Example** 263 * ```js 264 * module.exports = function({ config }) { 265 * // mutate the config before returning it. 266 * config.slug = 'new slug' 267 * return { expo: config }; 268 * } 269 * ``` 270 * 271 * **Supports** 272 * - `app.config.ts` 273 * - `app.config.js` 274 * - `app.config.json` 275 * - `app.json` 276 * 277 * @param projectRoot the root folder containing all of your application code 278 * @param options enforce criteria for a project config 279 */ 280 281 282function getConfig(projectRoot, options = {}) { 283 const paths = getConfigFilePaths(projectRoot); 284 const rawStaticConfig = paths.staticConfigPath ? (0, _getConfig().getStaticConfig)(paths.staticConfigPath) : null; // For legacy reasons, always return an object. 285 286 const rootConfig = rawStaticConfig || {}; 287 const staticConfig = reduceExpoObject(rawStaticConfig) || {}; // Can only change the package.json location if an app.json or app.config.json exists 288 289 const [packageJson, packageJsonPath] = getPackageJsonAndPath(projectRoot); 290 291 function fillAndReturnConfig(config, dynamicConfigObjectType) { 292 const configWithDefaultValues = { ...ensureConfigHasDefaultValues({ 293 projectRoot, 294 exp: config.expo, 295 pkg: packageJson, 296 skipSDKVersionRequirement: options.skipSDKVersionRequirement, 297 paths, 298 packageJsonPath 299 }), 300 mods: config.mods, 301 dynamicConfigObjectType, 302 rootConfig, 303 dynamicConfigPath: paths.dynamicConfigPath, 304 staticConfigPath: paths.staticConfigPath 305 }; 306 307 if (options.isModdedConfig) { 308 var _config$mods; 309 310 // @ts-ignore: Add the mods back to the object. 311 configWithDefaultValues.exp.mods = (_config$mods = config.mods) !== null && _config$mods !== void 0 ? _config$mods : null; 312 } // Apply static json plugins, should be done after _internal 313 314 315 configWithDefaultValues.exp = (0, _withConfigPlugins().withConfigPlugins)(configWithDefaultValues.exp, !!options.skipPlugins); 316 317 if (!options.isModdedConfig) { 318 // @ts-ignore: Delete mods added by static plugins when they won't have a chance to be evaluated 319 delete configWithDefaultValues.exp.mods; 320 } 321 322 if (options.isPublicConfig) { 323 var _configWithDefaultVal, _configWithDefaultVal2, _configWithDefaultVal3, _configWithDefaultVal4; 324 325 // Remove internal values with references to user's file paths from the public config. 326 delete configWithDefaultValues.exp._internal; 327 328 if (configWithDefaultValues.exp.hooks) { 329 delete configWithDefaultValues.exp.hooks; 330 } 331 332 if ((_configWithDefaultVal = configWithDefaultValues.exp.ios) !== null && _configWithDefaultVal !== void 0 && _configWithDefaultVal.config) { 333 delete configWithDefaultValues.exp.ios.config; 334 } 335 336 if ((_configWithDefaultVal2 = configWithDefaultValues.exp.android) !== null && _configWithDefaultVal2 !== void 0 && _configWithDefaultVal2.config) { 337 delete configWithDefaultValues.exp.android.config; 338 } // These value will be overwritten when the manifest is being served from the host (i.e. not completely accurate). 339 // @ts-ignore: currentFullName not on type yet. 340 341 342 configWithDefaultValues.exp.currentFullName = (0, _getFullName().getFullName)(configWithDefaultValues.exp); // @ts-ignore: originalFullName not on type yet. 343 344 configWithDefaultValues.exp.originalFullName = (0, _getFullName().getFullName)(configWithDefaultValues.exp); 345 (_configWithDefaultVal3 = configWithDefaultValues.exp.updates) === null || _configWithDefaultVal3 === void 0 ? true : delete _configWithDefaultVal3.codeSigningCertificate; 346 (_configWithDefaultVal4 = configWithDefaultValues.exp.updates) === null || _configWithDefaultVal4 === void 0 ? true : delete _configWithDefaultVal4.codeSigningMetadata; 347 } 348 349 return configWithDefaultValues; 350 } // Fill in the static config 351 352 353 function getContextConfig(config) { 354 return ensureConfigHasDefaultValues({ 355 projectRoot, 356 exp: config.expo, 357 pkg: packageJson, 358 skipSDKVersionRequirement: true, 359 paths, 360 packageJsonPath 361 }).exp; 362 } 363 364 if (paths.dynamicConfigPath) { 365 // No app.config.json or app.json but app.config.js 366 const { 367 exportedObjectType, 368 config: rawDynamicConfig 369 } = (0, _getConfig().getDynamicConfig)(paths.dynamicConfigPath, { 370 projectRoot, 371 staticConfigPath: paths.staticConfigPath, 372 packageJsonPath, 373 config: getContextConfig(staticConfig) 374 }); // Allow for the app.config.js to `export default null;` 375 // Use `dynamicConfigPath` to detect if a dynamic config exists. 376 377 const dynamicConfig = reduceExpoObject(rawDynamicConfig) || {}; 378 return fillAndReturnConfig(dynamicConfig, exportedObjectType); 379 } // No app.config.js but json or no config 380 381 382 return fillAndReturnConfig(staticConfig || {}, null); 383} 384 385function getPackageJson(projectRoot) { 386 const [pkg] = getPackageJsonAndPath(projectRoot); 387 return pkg; 388} 389 390function getPackageJsonAndPath(projectRoot) { 391 const packageJsonPath = (0, _resolvePackageJson().getRootPackageJsonPath)(projectRoot); 392 return [_jsonFile().default.read(packageJsonPath), packageJsonPath]; 393} 394 395function readConfigJson(projectRoot, skipValidation = false, skipSDKVersionRequirement = false) { 396 const paths = getConfigFilePaths(projectRoot); 397 const rawStaticConfig = paths.staticConfigPath ? (0, _getConfig().getStaticConfig)(paths.staticConfigPath) : null; 398 399 const getConfigName = () => { 400 if (paths.staticConfigPath) return ` \`${_path().default.basename(paths.staticConfigPath)}\``; 401 return ''; 402 }; 403 404 let outputRootConfig = rawStaticConfig; 405 406 if (outputRootConfig === null || typeof outputRootConfig !== 'object') { 407 if (skipValidation) { 408 outputRootConfig = { 409 expo: {} 410 }; 411 } else { 412 throw new (_Errors().ConfigError)(`Project at path ${_path().default.resolve(projectRoot)} does not contain a valid Expo config${getConfigName()}`, 'NOT_OBJECT'); 413 } 414 } 415 416 let exp = outputRootConfig.expo; 417 418 if (exp === null || typeof exp !== 'object') { 419 throw new (_Errors().ConfigError)(`Property 'expo' in${getConfigName()} for project at path ${_path().default.resolve(projectRoot)} is not an object. Please make sure${getConfigName()} includes a managed Expo app config like this: ${APP_JSON_EXAMPLE}`, 'NO_EXPO'); 420 } 421 422 exp = { ...exp 423 }; 424 const [pkg, packageJsonPath] = getPackageJsonAndPath(projectRoot); 425 return { ...ensureConfigHasDefaultValues({ 426 projectRoot, 427 exp, 428 pkg, 429 skipSDKVersionRequirement, 430 paths, 431 packageJsonPath 432 }), 433 mods: null, 434 dynamicConfigObjectType: null, 435 rootConfig: { ...outputRootConfig 436 }, 437 ...paths 438 }; 439} 440/** 441 * Get the static and dynamic config paths for a project. Also accounts for custom paths. 442 * 443 * @param projectRoot 444 */ 445 446 447function getConfigFilePaths(projectRoot) { 448 const customPaths = getCustomConfigFilePaths(projectRoot); 449 450 if (customPaths) { 451 return customPaths; 452 } 453 454 return { 455 dynamicConfigPath: getDynamicConfigFilePath(projectRoot), 456 staticConfigPath: getStaticConfigFilePath(projectRoot) 457 }; 458} 459 460function getCustomConfigFilePaths(projectRoot) { 461 if (!customConfigPaths[projectRoot]) { 462 return null; 463 } // If the user picks a custom config path, we will only use that and skip searching for a secondary config. 464 465 466 if (isDynamicFilePath(customConfigPaths[projectRoot])) { 467 return { 468 dynamicConfigPath: customConfigPaths[projectRoot], 469 staticConfigPath: null 470 }; 471 } // Anything that's not js or ts will be treated as json. 472 473 474 return { 475 staticConfigPath: customConfigPaths[projectRoot], 476 dynamicConfigPath: null 477 }; 478} 479 480function getDynamicConfigFilePath(projectRoot) { 481 for (const fileName of ['app.config.ts', 'app.config.js']) { 482 const configPath = _path().default.join(projectRoot, fileName); 483 484 if (_fs().default.existsSync(configPath)) { 485 return configPath; 486 } 487 } 488 489 return null; 490} 491 492function getStaticConfigFilePath(projectRoot) { 493 for (const fileName of ['app.config.json', 'app.json']) { 494 const configPath = _path().default.join(projectRoot, fileName); 495 496 if (_fs().default.existsSync(configPath)) { 497 return configPath; 498 } 499 } 500 501 return null; 502} // TODO: This should account for dynamic configs 503 504 505function findConfigFile(projectRoot) { 506 let configPath; // Check for a custom config path first. 507 508 if (customConfigPaths[projectRoot]) { 509 configPath = customConfigPaths[projectRoot]; // We shouldn't verify if the file exists because 510 // the user manually specified that this path should be used. 511 512 return { 513 configPath, 514 configName: _path().default.basename(configPath), 515 configNamespace: 'expo' 516 }; 517 } else { 518 // app.config.json takes higher priority over app.json 519 configPath = _path().default.join(projectRoot, 'app.config.json'); 520 521 if (!_fs().default.existsSync(configPath)) { 522 configPath = _path().default.join(projectRoot, 'app.json'); 523 } 524 } 525 526 return { 527 configPath, 528 configName: _path().default.basename(configPath), 529 configNamespace: 'expo' 530 }; 531} // TODO: deprecate 532 533 534function configFilename(projectRoot) { 535 return findConfigFile(projectRoot).configName; 536} 537 538async function readExpRcAsync(projectRoot) { 539 const expRcPath = _path().default.join(projectRoot, '.exprc'); 540 541 return await _jsonFile().default.readAsync(expRcPath, { 542 json5: true, 543 cantReadFileDefault: {} 544 }); 545} 546 547const customConfigPaths = {}; 548 549function resetCustomConfigPaths() { 550 for (const key of Object.keys(customConfigPaths)) { 551 delete customConfigPaths[key]; 552 } 553} 554 555function setCustomConfigPath(projectRoot, configPath) { 556 customConfigPaths[projectRoot] = configPath; 557} 558/** 559 * Attempt to modify an Expo project config. 560 * This will only fully work if the project is using static configs only. 561 * Otherwise 'warn' | 'fail' will return with a message about why the config couldn't be updated. 562 * The potentially modified config object will be returned for testing purposes. 563 * 564 * @param projectRoot 565 * @param modifications modifications to make to an existing config 566 * @param readOptions options for reading the current config file 567 * @param writeOptions If true, the static config file will not be rewritten 568 */ 569 570 571async function modifyConfigAsync(projectRoot, modifications, readOptions = {}, writeOptions = {}) { 572 const config = getConfig(projectRoot, readOptions); 573 574 if (config.dynamicConfigPath) { 575 // We cannot automatically write to a dynamic config. 576 577 /* Currently we should just use the safest approach possible, informing the user that they'll need to manually modify their dynamic config. 578 if (config.staticConfigPath) { 579 // Both a dynamic and a static config exist. 580 if (config.dynamicConfigObjectType === 'function') { 581 // The dynamic config exports a function, this means it possibly extends the static config. 582 } else { 583 // Dynamic config ignores the static config, there isn't a reason to automatically write to it. 584 // Instead we should warn the user to add values to their dynamic config. 585 } 586 } 587 */ 588 return { 589 type: 'warn', 590 message: `Cannot automatically write to dynamic config at: ${_path().default.relative(projectRoot, config.dynamicConfigPath)}`, 591 config: null 592 }; 593 } else if (config.staticConfigPath) { 594 // Static with no dynamic config, this means we can append to the config automatically. 595 let outputConfig; // If the config has an expo object (app.json) then append the options to that object. 596 597 if (config.rootConfig.expo) { 598 outputConfig = { ...config.rootConfig, 599 expo: { ...config.rootConfig.expo, 600 ...modifications 601 } 602 }; 603 } else { 604 // Otherwise (app.config.json) just add the config modification to the top most level. 605 outputConfig = { ...config.rootConfig, 606 ...modifications 607 }; 608 } 609 610 if (!writeOptions.dryRun) { 611 await _jsonFile().default.writeAsync(config.staticConfigPath, outputConfig, { 612 json5: false 613 }); 614 } 615 616 return { 617 type: 'success', 618 config: outputConfig 619 }; 620 } 621 622 return { 623 type: 'fail', 624 message: 'No config exists', 625 config: null 626 }; 627} 628 629const APP_JSON_EXAMPLE = JSON.stringify({ 630 expo: { 631 name: 'My app', 632 slug: 'my-app', 633 sdkVersion: '...' 634 } 635}); 636 637function ensureConfigHasDefaultValues({ 638 projectRoot, 639 exp, 640 pkg, 641 paths, 642 packageJsonPath, 643 skipSDKVersionRequirement = false 644}) { 645 var _exp$name, _exp$slug, _exp$version; 646 647 if (!exp) { 648 exp = {}; 649 } 650 651 exp = (0, _withInternal().withInternal)(exp, { 652 projectRoot, 653 ...(paths !== null && paths !== void 0 ? paths : {}), 654 packageJsonPath 655 }); // Defaults for package.json fields 656 657 const pkgName = typeof pkg.name === 'string' ? pkg.name : _path().default.basename(projectRoot); 658 const pkgVersion = typeof pkg.version === 'string' ? pkg.version : '1.0.0'; 659 const pkgWithDefaults = { ...pkg, 660 name: pkgName, 661 version: pkgVersion 662 }; // Defaults for app.json/app.config.js fields 663 664 const name = (_exp$name = exp.name) !== null && _exp$name !== void 0 ? _exp$name : pkgName; 665 const slug = (_exp$slug = exp.slug) !== null && _exp$slug !== void 0 ? _exp$slug : (0, _slugify().default)(name.toLowerCase()); 666 const version = (_exp$version = exp.version) !== null && _exp$version !== void 0 ? _exp$version : pkgVersion; 667 let description = exp.description; 668 669 if (!description && typeof pkg.description === 'string') { 670 description = pkg.description; 671 } 672 673 const expWithDefaults = { ...exp, 674 name, 675 slug, 676 version, 677 description 678 }; 679 let sdkVersion; 680 681 try { 682 sdkVersion = (0, _Project().getExpoSDKVersion)(projectRoot, expWithDefaults); 683 } catch (error) { 684 if (!skipSDKVersionRequirement) throw error; 685 } 686 687 let platforms = exp.platforms; 688 689 if (!platforms) { 690 platforms = getSupportedPlatforms(projectRoot); 691 } 692 693 return { 694 exp: { ...expWithDefaults, 695 sdkVersion, 696 platforms 697 }, 698 pkg: pkgWithDefaults 699 }; 700} 701 702async function writeConfigJsonAsync(projectRoot, options) { 703 const paths = getConfigFilePaths(projectRoot); 704 let { 705 exp, 706 pkg, 707 rootConfig, 708 dynamicConfigObjectType 709 } = readConfigJson(projectRoot); 710 exp = { ...rootConfig.expo, 711 ...options 712 }; 713 rootConfig = { ...rootConfig, 714 expo: exp 715 }; 716 717 if (paths.staticConfigPath) { 718 await _jsonFile().default.writeAsync(paths.staticConfigPath, rootConfig, { 719 json5: false 720 }); 721 } else { 722 console.log('Failed to write to config: ', options); 723 } 724 725 return { 726 exp, 727 pkg, 728 rootConfig, 729 dynamicConfigObjectType, 730 ...paths 731 }; 732} 733 734const DEFAULT_BUILD_PATH = `web-build`; 735 736function getWebOutputPath(config = {}) { 737 var _expo$web, _expo$web$build; 738 739 if (process.env.WEBPACK_BUILD_OUTPUT_PATH) { 740 return process.env.WEBPACK_BUILD_OUTPUT_PATH; 741 } 742 743 const expo = config.expo || config || {}; 744 return (expo === null || expo === void 0 ? void 0 : (_expo$web = expo.web) === null || _expo$web === void 0 ? void 0 : (_expo$web$build = _expo$web.build) === null || _expo$web$build === void 0 ? void 0 : _expo$web$build.output) || DEFAULT_BUILD_PATH; 745} 746 747function getNameFromConfig(exp = {}) { 748 // For RN CLI support 749 const appManifest = exp.expo || exp; 750 const { 751 web = {} 752 } = appManifest; // rn-cli apps use a displayName value as well. 753 754 const appName = exp.displayName || appManifest.displayName || appManifest.name; 755 const webName = web.name || appName; 756 return { 757 appName, 758 webName 759 }; 760} 761 762function getDefaultTarget(projectRoot, exp) { 763 var _exp; 764 765 (_exp = exp) !== null && _exp !== void 0 ? _exp : exp = getConfig(projectRoot, { 766 skipSDKVersionRequirement: true 767 }).exp; // before SDK 37, always default to managed to preserve previous behavior 768 769 if (exp.sdkVersion && exp.sdkVersion !== 'UNVERSIONED' && _semver().default.lt(exp.sdkVersion, '37.0.0')) { 770 return 'managed'; 771 } 772 773 return isBareWorkflowProject(projectRoot) ? 'bare' : 'managed'; 774} 775 776function isBareWorkflowProject(projectRoot) { 777 const [pkg] = getPackageJsonAndPath(projectRoot); 778 779 if (pkg.dependencies && pkg.dependencies.expokit) { 780 return false; 781 } 782 783 const xcodeprojFiles = (0, _glob().sync)('ios/**/*.xcodeproj', { 784 absolute: true, 785 cwd: projectRoot 786 }); 787 788 if (xcodeprojFiles.length) { 789 return true; 790 } 791 792 const gradleFiles = (0, _glob().sync)('android/**/*.gradle', { 793 absolute: true, 794 cwd: projectRoot 795 }); 796 797 if (gradleFiles.length) { 798 return true; 799 } 800 801 return false; 802} 803/** 804 * true if the file is .js or .ts 805 * 806 * @param filePath 807 */ 808 809 810function isDynamicFilePath(filePath) { 811 return !!filePath.match(/\.[j|t]s$/); 812} 813/** 814 * Return a useful name describing the project config. 815 * - dynamic: app.config.js 816 * - static: app.json 817 * - custom path app config relative to root folder 818 * - both: app.config.js or app.json 819 */ 820 821 822function getProjectConfigDescription(projectRoot) { 823 const paths = getConfigFilePaths(projectRoot); 824 return getProjectConfigDescriptionWithPaths(projectRoot, paths); 825} 826/** 827 * Returns a string describing the configurations used for the given project root. 828 * Will return null if no config is found. 829 * 830 * @param projectRoot 831 * @param projectConfig 832 */ 833 834 835function getProjectConfigDescriptionWithPaths(projectRoot, projectConfig) { 836 if (projectConfig.dynamicConfigPath) { 837 const relativeDynamicConfigPath = _path().default.relative(projectRoot, projectConfig.dynamicConfigPath); 838 839 if (projectConfig.staticConfigPath) { 840 return `${relativeDynamicConfigPath} or ${_path().default.relative(projectRoot, projectConfig.staticConfigPath)}`; 841 } 842 843 return relativeDynamicConfigPath; 844 } else if (projectConfig.staticConfigPath) { 845 return _path().default.relative(projectRoot, projectConfig.staticConfigPath); 846 } // If a config doesn't exist, our tooling will generate a static app.json 847 848 849 return 'app.json'; 850} 851//# sourceMappingURL=Config.js.map