2015-09-22 16:00:04 +00:00
|
|
|
/**
|
|
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
2016-10-22 13:07:01 +00:00
|
|
|
*
|
|
|
|
* @flow
|
2015-09-22 16:00:04 +00:00
|
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
|
2017-06-25 00:04:27 +00:00
|
|
|
const blacklist = require('metro-bundler/src/blacklist');
|
2017-06-13 16:11:57 +00:00
|
|
|
const findSymlinksPaths = require('./findSymlinksPaths');
|
2015-09-22 16:00:04 +00:00
|
|
|
const fs = require('fs');
|
2017-05-03 09:47:38 +00:00
|
|
|
const invariant = require('fbjs/lib/invariant');
|
2015-09-22 16:00:04 +00:00
|
|
|
const path = require('path');
|
|
|
|
|
2017-06-25 00:04:27 +00:00
|
|
|
const {providesModuleNodeModules} = require('metro-bundler/src/defaults');
|
2017-05-03 13:38:40 +00:00
|
|
|
|
2015-09-22 16:00:04 +00:00
|
|
|
const RN_CLI_CONFIG = 'rn-cli.config.js';
|
|
|
|
|
2017-06-25 00:04:27 +00:00
|
|
|
import type {GetTransformOptions, PostMinifyProcess, PostProcessModules} from 'metro-bundler/src/Bundler';
|
|
|
|
import type {HasteImpl} from 'metro-bundler/src/node-haste/Module';
|
|
|
|
import type {TransformVariants} from 'metro-bundler/src/ModuleGraph/types.flow';
|
|
|
|
import type {PostProcessModules as PostProcessModulesForBuck} from 'metro-bundler/src/ModuleGraph/types.flow.js';
|
2017-05-03 13:38:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Configuration file of the CLI.
|
|
|
|
*/
|
|
|
|
export type ConfigT = {
|
|
|
|
extraNodeModules: {[id: string]: string},
|
|
|
|
/**
|
2017-05-04 12:06:27 +00:00
|
|
|
* Specify any additional asset file extensions to be used by the packager.
|
2017-05-03 13:38:40 +00:00
|
|
|
* For example, if you want to include a .ttf file, you would return ['ttf']
|
|
|
|
* from here and use `require('./fonts/example.ttf')` inside your app.
|
|
|
|
*/
|
|
|
|
getAssetExts: () => Array<string>,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns a regular expression for modules that should be ignored by the
|
|
|
|
* packager on a given platform.
|
|
|
|
*/
|
|
|
|
getBlacklistRE(): RegExp,
|
|
|
|
|
2017-05-17 11:56:03 +00:00
|
|
|
/**
|
|
|
|
* Specify any additional polyfill modules that should be processed
|
|
|
|
* before regular module loading.
|
|
|
|
*/
|
|
|
|
getPolyfillModuleNames: () => Array<string>,
|
|
|
|
|
2017-05-03 13:38:40 +00:00
|
|
|
/**
|
|
|
|
* Specify any additional platforms to be used by the packager.
|
|
|
|
* For example, if you want to add a "custom" platform, and use modules
|
|
|
|
* ending in .custom.js, you would return ['custom'] here.
|
|
|
|
*/
|
|
|
|
getPlatforms: () => Array<string>,
|
|
|
|
|
|
|
|
getProjectRoots(): Array<string>,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Specify any additional node modules that should be processed for
|
|
|
|
* providesModule declarations.
|
|
|
|
*/
|
|
|
|
getProvidesModuleNodeModules?: () => Array<string>,
|
2017-05-04 12:06:27 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Specify any additional source file extensions to be used by the packager.
|
|
|
|
* For example, if you want to include a .ts file, you would return ['ts']
|
|
|
|
* from here and use `require('./module/example')` to require the file with
|
|
|
|
* path 'module/example.ts' inside your app.
|
|
|
|
*/
|
|
|
|
getSourceExts: () => Array<string>,
|
|
|
|
|
2017-05-03 13:38:40 +00:00
|
|
|
/**
|
|
|
|
* Returns the path to a custom transformer. This can also be overridden
|
|
|
|
* with the --transformer commandline argument.
|
|
|
|
*/
|
|
|
|
getTransformModulePath: () => string,
|
|
|
|
getTransformOptions: GetTransformOptions,
|
|
|
|
|
2017-05-30 11:39:43 +00:00
|
|
|
/**
|
|
|
|
* Returns the path to the worker that is used for transformation.
|
|
|
|
*/
|
2017-06-08 17:32:28 +00:00
|
|
|
getWorkerPath: () => ?string,
|
2017-05-30 11:39:43 +00:00
|
|
|
|
2017-05-03 13:38:40 +00:00
|
|
|
/**
|
|
|
|
* An optional function that can modify the code and source map of bundle
|
|
|
|
* after the minifaction took place.
|
|
|
|
*/
|
|
|
|
postMinifyProcess: PostMinifyProcess,
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An optional function that can modify the module array before the bundle is
|
|
|
|
* finalized.
|
|
|
|
*/
|
|
|
|
postProcessModules: PostProcessModules,
|
|
|
|
|
2017-05-22 15:57:04 +00:00
|
|
|
/**
|
|
|
|
* Same as `postProcessModules` but for the Buck worker. Eventually we do want
|
|
|
|
* to unify both variants.
|
|
|
|
*/
|
|
|
|
postProcessModulesForBuck: PostProcessModulesForBuck,
|
|
|
|
|
2017-05-03 13:38:40 +00:00
|
|
|
/**
|
|
|
|
* A module that exports:
|
|
|
|
* - a `getHasteName(filePath)` method that returns `hasteName` for module at
|
|
|
|
* `filePath`, or undefined if `filePath` is not a haste module.
|
|
|
|
*/
|
|
|
|
hasteImpl?: HasteImpl,
|
|
|
|
|
2017-05-04 15:28:50 +00:00
|
|
|
transformVariants: () => TransformVariants,
|
2017-05-03 13:38:40 +00:00
|
|
|
};
|
|
|
|
|
Fix broken default getProjectRoots
Summary:
In <= 0.44, the default implementation of getProjectRoots() came from `local-cli/core/default.config.js`. With changes happening in the CLI and the packager over the course of the last two months, various pieces of this logic (specifically `local-cli/utils/Config.js`) were rewritten, and though default.config.js was still being imported and used in `local-cli/core/index.js`, the default `getProjectRoots()` was being overriden by the defaults specified in `local-cli/utils/Config.js`.
This PR moves the logic from default.config.js into Config.js and index.js, as appropriate. Specifically:
- The `getProjectCommands()`, `getProjectConfig()`, and `getDependencyConfig()` methods, which have traditionally not been part of the rn-cli.config.js spec, are now defined in `local-cli/core/index.js`.
- The `getProjectRoots()` method, which contained logic for properly resolving the _actual_ project root as well as resolving symlinks within that root, has been moved to `local-cli/utils/Config.js`, to match the fact that other default rn-cli.config.js definitions live there.
Closes https://github.com/facebook/react-native/pull/14412
Differential Revision: D5216887
Pulled By: hramos
fbshipit-source-id: 7a3840ecf0ad8ea3f6d7bbd3d54e4f02950c6a32
2017-06-09 08:14:37 +00:00
|
|
|
function getProjectPath() {
|
|
|
|
if (__dirname.match(/node_modules[\/\\]react-native[\/\\]local-cli[\/\\]util$/)) {
|
|
|
|
// Packager is running from node_modules.
|
|
|
|
// This is the default case for all projects created using 'react-native init'.
|
|
|
|
return path.resolve(__dirname, '../../../..');
|
|
|
|
} else if (__dirname.match(/Pods[\/\\]React[\/\\]packager$/)) {
|
|
|
|
// React Native was installed using CocoaPods.
|
|
|
|
return path.resolve(__dirname, '../../../..');
|
|
|
|
}
|
|
|
|
return path.resolve(__dirname, '../..');
|
|
|
|
}
|
|
|
|
|
|
|
|
const resolveSymlink = (roots) =>
|
|
|
|
roots.concat(
|
|
|
|
findSymlinksPaths(
|
|
|
|
path.join(getProjectPath(), 'node_modules'),
|
|
|
|
roots
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
2015-09-22 16:00:04 +00:00
|
|
|
/**
|
Merge `rnpm config` with the `cli config`, step 1
Summary:
This is step one on merging the `rnpm` config with the `cli config`. The plan is to remove two sources of truth (rnpm package.json config and rn-cli Javascript config)
Rationale:
As of now, we have `rnpm` config, that used to live in the `local-cli/core/config/index.js` and the `rn-cli` config, living in `default.config.js` and `utils/Config.js`.
This PR moves all the things into one file, called `local-cli/core', simplifies things, enhances types (Config now has better types, added missing properties and fixed descriptions).
One notable addition is that users can now opt-in to override the commands that are loaded at the package level. Previously it was only possible to add a command by writing a plugin. Now, you can just tweak the `rn-cli.config.js`.
This is one of the several improvements I have on my roadmap, with better documentation for the CLI as well.
Closes https://github.com/facebook/react-native/pull/11564
Differential Revision: D4360095
fbshipit-source-id: feaec7c88df63e51cef1f9620c7eedeb738d3d00
2017-01-09 15:49:29 +00:00
|
|
|
* Module capable of getting the configuration out of a given file.
|
2015-10-20 23:58:13 +00:00
|
|
|
*
|
Merge `rnpm config` with the `cli config`, step 1
Summary:
This is step one on merging the `rnpm` config with the `cli config`. The plan is to remove two sources of truth (rnpm package.json config and rn-cli Javascript config)
Rationale:
As of now, we have `rnpm` config, that used to live in the `local-cli/core/config/index.js` and the `rn-cli` config, living in `default.config.js` and `utils/Config.js`.
This PR moves all the things into one file, called `local-cli/core', simplifies things, enhances types (Config now has better types, added missing properties and fixed descriptions).
One notable addition is that users can now opt-in to override the commands that are loaded at the package level. Previously it was only possible to add a command by writing a plugin. Now, you can just tweak the `rn-cli.config.js`.
This is one of the several improvements I have on my roadmap, with better documentation for the CLI as well.
Closes https://github.com/facebook/react-native/pull/11564
Differential Revision: D4360095
fbshipit-source-id: feaec7c88df63e51cef1f9620c7eedeb738d3d00
2017-01-09 15:49:29 +00:00
|
|
|
* The function will return all the default configuration, as specified by the
|
2017-06-02 16:23:48 +00:00
|
|
|
* `DEFAULTS` param overriden by those found on `rn-cli.config.js` files, if any. If no
|
Merge `rnpm config` with the `cli config`, step 1
Summary:
This is step one on merging the `rnpm` config with the `cli config`. The plan is to remove two sources of truth (rnpm package.json config and rn-cli Javascript config)
Rationale:
As of now, we have `rnpm` config, that used to live in the `local-cli/core/config/index.js` and the `rn-cli` config, living in `default.config.js` and `utils/Config.js`.
This PR moves all the things into one file, called `local-cli/core', simplifies things, enhances types (Config now has better types, added missing properties and fixed descriptions).
One notable addition is that users can now opt-in to override the commands that are loaded at the package level. Previously it was only possible to add a command by writing a plugin. Now, you can just tweak the `rn-cli.config.js`.
This is one of the several improvements I have on my roadmap, with better documentation for the CLI as well.
Closes https://github.com/facebook/react-native/pull/11564
Differential Revision: D4360095
fbshipit-source-id: feaec7c88df63e51cef1f9620c7eedeb738d3d00
2017-01-09 15:49:29 +00:00
|
|
|
* default config is provided and no configuration can be found in the directory
|
|
|
|
* hierarchy, an error will be thrown.
|
2015-09-22 16:00:04 +00:00
|
|
|
*/
|
|
|
|
const Config = {
|
2017-06-02 16:23:48 +00:00
|
|
|
DEFAULTS: ({
|
|
|
|
extraNodeModules: Object.create(null),
|
|
|
|
getAssetExts: () => [],
|
|
|
|
getBlacklistRE: () => blacklist(),
|
|
|
|
getPlatforms: () => [],
|
|
|
|
getPolyfillModuleNames: () => [],
|
Fix broken default getProjectRoots
Summary:
In <= 0.44, the default implementation of getProjectRoots() came from `local-cli/core/default.config.js`. With changes happening in the CLI and the packager over the course of the last two months, various pieces of this logic (specifically `local-cli/utils/Config.js`) were rewritten, and though default.config.js was still being imported and used in `local-cli/core/index.js`, the default `getProjectRoots()` was being overriden by the defaults specified in `local-cli/utils/Config.js`.
This PR moves the logic from default.config.js into Config.js and index.js, as appropriate. Specifically:
- The `getProjectCommands()`, `getProjectConfig()`, and `getDependencyConfig()` methods, which have traditionally not been part of the rn-cli.config.js spec, are now defined in `local-cli/core/index.js`.
- The `getProjectRoots()` method, which contained logic for properly resolving the _actual_ project root as well as resolving symlinks within that root, has been moved to `local-cli/utils/Config.js`, to match the fact that other default rn-cli.config.js definitions live there.
Closes https://github.com/facebook/react-native/pull/14412
Differential Revision: D5216887
Pulled By: hramos
fbshipit-source-id: 7a3840ecf0ad8ea3f6d7bbd3d54e4f02950c6a32
2017-06-09 08:14:37 +00:00
|
|
|
getProjectRoots: () => {
|
|
|
|
const root = process.env.REACT_NATIVE_APP_ROOT;
|
|
|
|
if (root) {
|
|
|
|
return resolveSymlink([path.resolve(root)]);
|
|
|
|
}
|
|
|
|
return resolveSymlink([getProjectPath()]);
|
|
|
|
},
|
2017-06-02 16:23:48 +00:00
|
|
|
getProvidesModuleNodeModules: () => providesModuleNodeModules.slice(),
|
|
|
|
getSourceExts: () => [],
|
2017-06-25 00:04:27 +00:00
|
|
|
getTransformModulePath: () => require.resolve('metro-bundler/src/transformer.js'),
|
2017-06-02 16:23:48 +00:00
|
|
|
getTransformOptions: async () => ({}),
|
|
|
|
postMinifyProcess: x => x,
|
|
|
|
postProcessModules: modules => modules,
|
|
|
|
postProcessModulesForBuck: modules => modules,
|
|
|
|
transformVariants: () => ({default: {}}),
|
2017-06-08 17:32:28 +00:00
|
|
|
getWorkerPath: () => null,
|
2017-06-02 16:23:48 +00:00
|
|
|
}: ConfigT),
|
|
|
|
|
2017-05-03 13:38:40 +00:00
|
|
|
find(startDir: string): ConfigT {
|
2017-06-02 16:23:48 +00:00
|
|
|
return Config.findCustom(startDir, Config.DEFAULTS);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This allows a callsite to grab a config that may have custom fields or
|
|
|
|
* a different version of the config. In that case the defaults have to be
|
|
|
|
* specified explicitely.
|
|
|
|
*/
|
|
|
|
findCustom<TConfig: {}>(startDir: string, defaults: TConfig): TConfig {
|
|
|
|
return Config.findWithPathCustom(startDir, defaults).config;
|
2017-05-25 11:23:19 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
findWithPath(startDir: string): {config: ConfigT, projectPath: string} {
|
2017-06-02 16:23:48 +00:00
|
|
|
return Config.findWithPathCustom(startDir, Config.DEFAULTS);
|
|
|
|
},
|
|
|
|
|
|
|
|
findWithPathCustom<TConfig: {}>(startDir: string, defaults: TConfig): {config: TConfig, projectPath: string} {
|
2017-05-03 09:47:38 +00:00
|
|
|
const configPath = findConfigPath(startDir);
|
|
|
|
invariant(
|
|
|
|
configPath,
|
|
|
|
`Can't find "${RN_CLI_CONFIG}" file in any parent folder of "${startDir}"`,
|
|
|
|
);
|
2017-05-25 11:23:19 +00:00
|
|
|
const projectPath = path.dirname(configPath);
|
2017-06-02 16:23:48 +00:00
|
|
|
return {config: Config.loadFileCustom(configPath, defaults), projectPath};
|
2017-05-03 09:47:38 +00:00
|
|
|
},
|
2015-09-22 16:00:04 +00:00
|
|
|
|
2017-05-03 13:38:40 +00:00
|
|
|
findOptional(startDir: string): ConfigT {
|
2017-06-02 16:23:48 +00:00
|
|
|
return Config.findOptionalCustom(startDir, Config.DEFAULTS);
|
|
|
|
},
|
|
|
|
|
|
|
|
findOptionalCustom<TConfig: {}>(startDir: string, defaults: TConfig): TConfig {
|
2017-05-03 09:47:38 +00:00
|
|
|
const configPath = findConfigPath(startDir);
|
|
|
|
return configPath
|
2017-06-02 16:23:48 +00:00
|
|
|
? Config.loadFileCustom(configPath, defaults)
|
|
|
|
: {...defaults};
|
2016-08-12 18:46:04 +00:00
|
|
|
},
|
2015-10-20 23:58:13 +00:00
|
|
|
|
2017-05-03 13:38:42 +00:00
|
|
|
loadFile(pathToConfig: string): ConfigT {
|
2017-06-02 16:23:48 +00:00
|
|
|
return Config.loadFileCustom(pathToConfig, Config.DEFAULTS);
|
|
|
|
},
|
|
|
|
|
|
|
|
loadFileCustom<TConfig: {}>(pathToConfig: string, defaults: TConfig): TConfig {
|
2017-05-03 13:38:42 +00:00
|
|
|
//$FlowFixMe: necessary dynamic require
|
|
|
|
const config: {} = require(pathToConfig);
|
2017-06-02 16:23:48 +00:00
|
|
|
return {...defaults, ...config};
|
2016-08-12 18:46:04 +00:00
|
|
|
},
|
2015-09-22 16:00:04 +00:00
|
|
|
};
|
|
|
|
|
2017-05-03 09:47:38 +00:00
|
|
|
function findConfigPath(cwd: string): ?string {
|
|
|
|
const parentDir = findParentDirectory(cwd, RN_CLI_CONFIG);
|
|
|
|
return parentDir ? path.join(parentDir, RN_CLI_CONFIG) : null;
|
|
|
|
}
|
|
|
|
|
2015-09-22 16:00:04 +00:00
|
|
|
// Finds the most near ancestor starting at `currentFullPath` that has
|
|
|
|
// a file named `filename`
|
|
|
|
function findParentDirectory(currentFullPath, filename) {
|
|
|
|
const root = path.parse(currentFullPath).root;
|
|
|
|
const testDir = (parts) => {
|
|
|
|
if (parts.length === 0) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
const fullPath = path.join(root, parts.join(path.sep));
|
|
|
|
|
|
|
|
var exists = fs.existsSync(path.join(fullPath, filename));
|
|
|
|
return exists ? fullPath : testDir(parts.slice(0, -1));
|
|
|
|
};
|
|
|
|
|
2016-03-21 01:08:23 +00:00
|
|
|
return testDir(currentFullPath.substring(root.length).split(path.sep));
|
2015-09-22 16:00:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
module.exports = Config;
|