diff --git a/packages/cli/src/cliEntry.js b/packages/cli/src/cliEntry.js index 9758eb849..81036907d 100644 --- a/packages/cli/src/cliEntry.js +++ b/packages/cli/src/cliEntry.js @@ -12,9 +12,9 @@ import childProcess from 'child_process'; import commander from 'commander'; import path from 'path'; -import type {CommandT, ContextT} from './tools/types.flow'; +import type {CommandT, ConfigT} from './tools/config/types.flow'; -import {getCommands} from './commands'; +import commands from './commands'; import init from './commands/init/initCompat'; import assertRequiredOptions from './tools/assertRequiredOptions'; import {logger} from '@react-native-community/cli-tools'; @@ -95,7 +95,7 @@ function printUnknownCommand(cmdName) { } } -const addCommand = (command: CommandT, ctx: ContextT) => { +const addCommand = (command: CommandT, ctx: ConfigT) => { const options = command.options || []; const cmd = commander @@ -162,9 +162,7 @@ async function setupAndRun() { setProjectDir(ctx.root); - const commands = getCommands(ctx); - - commands.forEach(command => addCommand(command, ctx)); + [...commands, ...ctx.commands].forEach(command => addCommand(command, ctx)); commander.parse(process.argv); diff --git a/packages/cli/src/commands/bundle/buildBundle.js b/packages/cli/src/commands/bundle/buildBundle.js index e11f7512a..89211c746 100644 --- a/packages/cli/src/commands/bundle/buildBundle.js +++ b/packages/cli/src/commands/bundle/buildBundle.js @@ -13,14 +13,14 @@ import outputBundle from 'metro/src/shared/output/bundle'; import path from 'path'; import chalk from 'chalk'; import type {CommandLineArgs} from './bundleCommandLineArgs'; -import type {ContextT} from '../../tools/types.flow'; +import type {ConfigT} from '../../tools/config/types.flow'; import saveAssets from './saveAssets'; import loadMetroConfig from '../../tools/loadMetroConfig'; import {logger} from '@react-native-community/cli-tools'; async function buildBundle( args: CommandLineArgs, - ctx: ContextT, + ctx: ConfigT, output: typeof outputBundle = outputBundle, ) { const config = await loadMetroConfig(ctx, { diff --git a/packages/cli/src/commands/config/config.js b/packages/cli/src/commands/config/config.js index 51fd05243..83fa8bffb 100644 --- a/packages/cli/src/commands/config/config.js +++ b/packages/cli/src/commands/config/config.js @@ -1,11 +1,11 @@ /** * @flow */ -import {type ContextT} from '../../tools/types.flow'; +import {type ConfigT} from '../../tools/config/types.flow'; export default { name: 'config', description: 'Print CLI configuration', - func: async (argv: string[], ctx: ContextT) => { + func: async (argv: string[], ctx: ConfigT) => { console.log(JSON.stringify(ctx, null, 2)); }, }; diff --git a/packages/cli/src/commands/index.js b/packages/cli/src/commands/index.js index 86920456c..97e20dc6b 100644 --- a/packages/cli/src/commands/index.js +++ b/packages/cli/src/commands/index.js @@ -1,15 +1,8 @@ /** * @flow */ +import {type CommandT} from '../tools/config/types.flow'; -import path from 'path'; -import type { - CommandT, - ProjectCommandT, - LocalCommandT, -} from '../tools/types.flow'; - -import {type ContextT} from '../tools/types.flow'; import server from './server/server'; import runIOS from './runIOS/runIOS'; import runAndroid from './runAndroid/runAndroid'; @@ -27,11 +20,7 @@ import info from './info/info'; import config from './config/config'; import init from './init'; -/** - * List of built-in commands - */ - -const loadLocalCommands: Array = [ +export default ([ server, runIOS, runAndroid, @@ -48,57 +37,4 @@ const loadLocalCommands: Array = [ info, config, init, -]; - -/** - * Returns an array of commands that are defined in the project. - * - * This checks all CLI plugins for presence of 3rd party packages that define commands - * and loads them - */ -const loadProjectCommands = ({ - root, - commands, -}: ContextT): Array => { - return commands.reduce((acc: Array, cmdPath: string) => { - /** - * `pathToCommand` is a path to a file where commands are defined, relative to `node_modules` - * folder. - * - * Following code gets the name of the package name out of the path, taking scope - * into consideration. - */ - const name = - cmdPath[0] === '@' - ? cmdPath - .split(path.sep) - .slice(0, 2) - .join(path.sep) - : cmdPath.split(path.sep)[0]; - - const pkg = require(path.join(root, 'node_modules', name, 'package.json')); - - const requiredCommands: - | ProjectCommandT - | Array = require(path.join( - root, - 'node_modules', - cmdPath, - )); - - if (Array.isArray(requiredCommands)) { - return acc.concat( - requiredCommands.map(requiredCommand => ({...requiredCommand, pkg})), - ); - } - - return acc.concat({...requiredCommands, pkg}); - }, []); -}; - -/** - * Loads all the commands inside a given `root` folder - */ -export function getCommands(ctx: ContextT): Array { - return [...loadLocalCommands, ...loadProjectCommands(ctx)]; -} +]: CommandT[]); diff --git a/packages/cli/src/commands/info/info.js b/packages/cli/src/commands/info/info.js index 4faae7860..f404c5d92 100644 --- a/packages/cli/src/commands/info/info.js +++ b/packages/cli/src/commands/info/info.js @@ -9,11 +9,11 @@ import envinfo from 'envinfo'; import {logger} from '@react-native-community/cli-tools'; -import type {ContextT} from '../../tools/types.flow'; +import type {ConfigT} from '../../tools/config/types.flow'; const info = async function getInfo( argv: Array, - ctx: ContextT, + ctx: ConfigT, options: {}, ) { try { diff --git a/packages/cli/src/commands/init/init.js b/packages/cli/src/commands/init/init.js index 77279d7ba..35e2811a5 100644 --- a/packages/cli/src/commands/init/init.js +++ b/packages/cli/src/commands/init/init.js @@ -2,7 +2,7 @@ import fs from 'fs-extra'; import minimist from 'minimist'; import semver from 'semver'; -import type {ContextT} from '../../tools/types.flow'; +import type {ConfigT} from '../../tools/config/types.flow'; import {validateProjectName} from './validate'; import DirectoryAlreadyExistsError from './errors/DirectoryAlreadyExistsError'; import printRunInstructions from './printRunInstructions'; @@ -153,7 +153,7 @@ function createProject(projectName: string, options: Options, version: string) { export default (async function initialize( [projectName]: Array, - _context: ContextT, + _context: ConfigT, options: Options, ) { validateProjectName(projectName); diff --git a/packages/cli/src/commands/install/install.js b/packages/cli/src/commands/install/install.js index 4750087b5..7b6e5d6f5 100644 --- a/packages/cli/src/commands/install/install.js +++ b/packages/cli/src/commands/install/install.js @@ -7,13 +7,13 @@ * @flow */ -import type {ContextT} from '../../tools/types.flow'; +import type {ConfigT} from '../../tools/config/types.flow'; import {logger} from '@react-native-community/cli-tools'; import * as PackageManager from '../../tools/packageManager'; import link from '../link/link'; import loadConfig from '../../tools/config'; -async function install(args: Array, ctx: ContextT) { +async function install(args: Array, ctx: ConfigT) { const name = args[0]; logger.info(`Installing "${name}"...`); diff --git a/packages/cli/src/commands/install/uninstall.js b/packages/cli/src/commands/install/uninstall.js index a8173d26e..85f4f4563 100644 --- a/packages/cli/src/commands/install/uninstall.js +++ b/packages/cli/src/commands/install/uninstall.js @@ -7,12 +7,12 @@ * @flow */ -import type {ContextT} from '../../tools/types.flow'; +import type {ConfigT} from '../../tools/config/types.flow'; import {logger} from '@react-native-community/cli-tools'; import * as PackageManager from '../../tools/packageManager'; import link from '../link/unlink'; -async function uninstall(args: Array, ctx: ContextT) { +async function uninstall(args: Array, ctx: ConfigT) { const name = args[0]; logger.info(`Unlinking "${name}"...`); diff --git a/packages/cli/src/commands/link/link.js b/packages/cli/src/commands/link/link.js index 94f10bb2c..2be0d3f72 100644 --- a/packages/cli/src/commands/link/link.js +++ b/packages/cli/src/commands/link/link.js @@ -10,7 +10,7 @@ import {pick} from 'lodash'; import dedent from 'dedent'; -import {type ContextT} from '../../tools/types.flow'; +import {type ConfigT} from '../../tools/config/types.flow'; import {CLIError} from '../../tools/errors'; @@ -34,7 +34,7 @@ type FlagsType = { * @param args If optional argument [packageName] is provided, * only that package is processed. */ -function link([rawPackageName]: Array, ctx: ContextT, opts: FlagsType) { +function link([rawPackageName]: Array, ctx: ConfigT, opts: FlagsType) { let platforms = ctx.platforms; let project = ctx.project; diff --git a/packages/cli/src/commands/link/unlink.js b/packages/cli/src/commands/link/unlink.js index b593f21a2..3bcf48758 100644 --- a/packages/cli/src/commands/link/unlink.js +++ b/packages/cli/src/commands/link/unlink.js @@ -8,7 +8,7 @@ */ import {flatMap, values, difference} from 'lodash'; -import type {ContextT} from '../../tools/types.flow'; +import type {ConfigT} from '../../tools/config/types.flow'; import dedent from 'dedent'; import {logger} from '@react-native-community/cli-tools'; import promiseWaterfall from './promiseWaterfall'; @@ -77,7 +77,7 @@ const unlinkDependency = ( * If optional argument [packageName] is provided, it's the only one * that's checked */ -function unlink(args: Array, ctx: ContextT) { +function unlink(args: Array, ctx: ConfigT) { const packageName = args[0]; const {[packageName]: dependency, ...otherDependencies} = ctx.dependencies; diff --git a/packages/cli/src/commands/runAndroid/runAndroid.js b/packages/cli/src/commands/runAndroid/runAndroid.js index ac5577ffa..9fc40a551 100644 --- a/packages/cli/src/commands/runAndroid/runAndroid.js +++ b/packages/cli/src/commands/runAndroid/runAndroid.js @@ -13,7 +13,7 @@ import fs from 'fs'; import isString from 'lodash/isString'; import isPackagerRunning from '../../tools/isPackagerRunning'; -import type {ContextT} from '../../tools/types.flow'; +import type {ConfigT} from '../../tools/config/types.flow'; import adb from './adb'; import runOnAllDevices from './runOnAllDevices'; @@ -30,7 +30,7 @@ function checkAndroid(root) { /** * Starts the app on a connected Android emulator or device. */ -function runAndroid(argv: Array, ctx: ContextT, args: Object) { +function runAndroid(argv: Array, ctx: ConfigT, args: Object) { if (!checkAndroid(args.root)) { logger.error( 'Android project not found. Are you sure this is a React Native project?', diff --git a/packages/cli/src/commands/runIOS/runIOS.js b/packages/cli/src/commands/runIOS/runIOS.js index 20e968e1a..898b6697e 100644 --- a/packages/cli/src/commands/runIOS/runIOS.js +++ b/packages/cli/src/commands/runIOS/runIOS.js @@ -11,7 +11,7 @@ import child_process from 'child_process'; import fs from 'fs'; import path from 'path'; -import type {ContextT} from '../../tools/types.flow'; +import type {ConfigT} from '../../tools/config/types.flow'; import findXcodeProject from './findXcodeProject'; import parseIOSDevicesList from './parseIOSDevicesList'; import findMatchingSimulator from './findMatchingSimulator'; @@ -30,7 +30,7 @@ type FlagsT = { port: number, }; -function runIOS(_: Array, ctx: ContextT, args: FlagsT) { +function runIOS(_: Array, ctx: ConfigT, args: FlagsT) { if (!fs.existsSync(args.projectPath)) { throw new Error( 'iOS project folder not found. Are you sure this is a React Native project?', diff --git a/packages/cli/src/commands/server/runServer.js b/packages/cli/src/commands/server/runServer.js index 8b20376c1..586fb4274 100644 --- a/packages/cli/src/commands/server/runServer.js +++ b/packages/cli/src/commands/server/runServer.js @@ -13,7 +13,7 @@ import {Terminal} from 'metro-core'; import morgan from 'morgan'; import path from 'path'; -import type {ContextT} from '../../tools/types.flow'; +import type {ConfigT} from '../../tools/config/types.flow'; import messageSocket from './messageSocket'; import webSocketProxy from './webSocketProxy'; import MiddlewareManager from './middleware/MiddlewareManager'; @@ -40,7 +40,7 @@ export type Args = {| config?: string, |}; -async function runServer(argv: Array, ctx: ContextT, args: Args) { +async function runServer(argv: Array, ctx: ConfigT, args: Args) { const terminal = new Terminal(process.stdout); const ReporterImpl = getReporterImpl(args.customLogReporterPath || null); const reporter = new ReporterImpl(terminal); diff --git a/packages/cli/src/commands/upgrade/legacyUpgrade.js b/packages/cli/src/commands/upgrade/legacyUpgrade.js index ccb93eef7..a416d5098 100644 --- a/packages/cli/src/commands/upgrade/legacyUpgrade.js +++ b/packages/cli/src/commands/upgrade/legacyUpgrade.js @@ -11,7 +11,7 @@ import fs from 'fs'; import path from 'path'; import semver from 'semver'; -import type {ContextT} from '../../tools/types.flow'; +import type {ConfigT} from '../../tools/config/types.flow'; import {logger} from '@react-native-community/cli-tools'; import copyProjectTemplateAndReplace from '../../tools/generator/copyProjectTemplateAndReplace'; @@ -19,7 +19,7 @@ import copyProjectTemplateAndReplace from '../../tools/generator/copyProjectTemp * Migrate application to a new version of React Native. * See http://facebook.github.io/react-native/docs/upgrading.html */ -function validateAndUpgrade(argv: Array, ctx: ContextT) { +function validateAndUpgrade(argv: Array, ctx: ConfigT) { const projectDir = ctx.root; const packageJSON = JSON.parse( diff --git a/packages/cli/src/commands/upgrade/upgrade.js b/packages/cli/src/commands/upgrade/upgrade.js index 816e6cdd0..f7c4f9056 100644 --- a/packages/cli/src/commands/upgrade/upgrade.js +++ b/packages/cli/src/commands/upgrade/upgrade.js @@ -4,7 +4,7 @@ import fs from 'fs'; import chalk from 'chalk'; import semver from 'semver'; import execa from 'execa'; -import type {ContextT} from '../../tools/types.flow'; +import type {ConfigT} from '../../tools/config/types.flow'; import {logger} from '@react-native-community/cli-tools'; import * as PackageManager from '../../tools/packageManager'; import {fetch} from '../../tools/fetch'; @@ -176,7 +176,7 @@ const applyPatch = async ( /** * Upgrade application to a new version of React Native. */ -async function upgrade(argv: Array, ctx: ContextT, args: FlagsT) { +async function upgrade(argv: Array, ctx: ConfigT, args: FlagsT) { if (args.legacy) { return legacyUpgrade.func(argv, ctx); } diff --git a/packages/cli/src/tools/config/__tests__/__snapshots__/index-test.js.snap b/packages/cli/src/tools/config/__tests__/__snapshots__/index-test.js.snap index 3fc391a4b..e2389afcb 100644 --- a/packages/cli/src/tools/config/__tests__/__snapshots__/index-test.js.snap +++ b/packages/cli/src/tools/config/__tests__/__snapshots__/index-test.js.snap @@ -1,5 +1,62 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`should automatically put "react-native" into haste config 1`] = ` +Object { + "platforms": Array [ + "ios", + "android", + ], + "providesModuleNodeModules": Array [ + "react-native", + ], +} +`; + +exports[`should have a valid structure by default 1`] = ` +Object { + "assets": Array [], + "commands": Array [], + "dependencies": Object {}, + "haste": Object { + "platforms": Array [], + "providesModuleNodeModules": Array [], + }, + "platforms": Object {}, + "project": Object {}, + "reactNativePath": ".", + "root": "<>", +} +`; + +exports[`should load an out-of-tree "windows" platform that ships with a dependency 1`] = ` +Object { + "haste": Object { + "platforms": Array [ + "windows", + ], + "providesModuleNodeModules": Array [ + "react-native-windows", + ], + }, + "platforms": Object { + "windows": Object {}, + }, +} +`; + +exports[`should load commands from "react-native-foo" and "react-native-bar" packages 1`] = ` +Array [ + Object { + "func": [Function], + "name": "foo-command", + }, + Object { + "func": [Function], + "name": "bar-command", + }, +] +`; + exports[`should merge project configuration with default values 1`] = ` Object { "assets": Array [], @@ -61,45 +118,6 @@ Object { } `; -exports[`should have a valid structure by default 1`] = ` -Object { - "assets": Array [], - "commands": Array [], - "dependencies": Object {}, - "haste": Object { - "platforms": Array [], - "providesModuleNodeModules": Array [], - }, - "platforms": Object {}, - "project": Object {}, - "reactNativePath": ".", - "root": "<>", -} -`; - -exports[`should load an out-of-tree "windows" platform that ships with a dependency 1`] = ` -Object { - "haste": Object { - "platforms": Array [ - "windows", - ], - "providesModuleNodeModules": Array [ - "react-native-windows", - ], - }, - "platforms": Object { - "windows": Object {}, - }, -} -`; - -exports[`should load commands from "react-native-foo" and "react-native-bar" packages 1`] = ` -Array [ - "react-native-foo/command-foo.js", - "react-native-bar/command-bar.js", -] -`; - exports[`should read \`rnpm\` config from a dependency and transform it to a new format 1`] = ` Object { "assets": Array [], @@ -183,15 +201,3 @@ Object { }, } `; - -exports[`should automatically put "react-native" into haste config 1`] = ` -Object { - "platforms": Array [ - "ios", - "android", - ], - "providesModuleNodeModules": Array [ - "react-native", - ], -} -`; diff --git a/packages/cli/src/tools/config/__tests__/index-test.js b/packages/cli/src/tools/config/__tests__/index-test.js index a12f6464e..bb917ce9c 100644 --- a/packages/cli/src/tools/config/__tests__/index-test.js +++ b/packages/cli/src/tools/config/__tests__/index-test.js @@ -47,9 +47,6 @@ test('should return dependencies from package.json', () => { "dependencies": { "react-native": "0.0.1", "react-native-test": "0.0.1" - }, - "react-native": { - "reactNativePath": "." } }`, }); @@ -75,9 +72,6 @@ test('should read a config of a dependency and use it to load other settings', ( "dependencies": { "react-native": "0.0.1", "react-native-test": "0.0.1" - }, - "react-native": { - "reactNativePath": "." } }`, }); @@ -138,9 +132,6 @@ test('should read `rnpm` config from a dependency and transform it to a new form "dependencies": { "react-native": "0.0.1", "react-native-foo": "0.0.1" - }, - "react-native": { - "reactNativePath": "." } }`, }); @@ -150,32 +141,33 @@ test('should read `rnpm` config from a dependency and transform it to a new form test('should load commands from "react-native-foo" and "react-native-bar" packages', () => { writeFiles(DIR, { - 'node_modules/react-native-foo/package.json': `{ - "react-native": { - "commands": [ - "./command-foo.js" - ] - } + 'node_modules/react-native-foo/package.json': '{}', + 'node_modules/react-native-foo/react-native.config.js': `module.exports = { + commands: [ + { + name: 'foo-command', + func: () => console.log('foo') + } + ] }`, - 'node_modules/react-native-bar/package.json': `{ - "react-native": { - "commands": [ - "./command-bar.js" - ] - } + 'node_modules/react-native-bar/package.json': '{}', + 'node_modules/react-native-bar/react-native.config.js': `module.exports = { + commands: [ + { + name: 'bar-command', + func: () => console.log('bar') + } + ] }`, 'package.json': `{ "dependencies": { "react-native-foo": "0.0.1", "react-native-bar": "0.0.1" - }, - "react-native": { - "reactNativePath": "." } }`, }); const {commands} = loadConfig(DIR); - expect(removeString(commands, DIR)).toMatchSnapshot(); + expect(commands).toMatchSnapshot(); }); test('should load an out-of-tree "windows" platform that ships with a dependency', () => { @@ -183,6 +175,9 @@ test('should load an out-of-tree "windows" platform that ships with a dependency 'node_modules/react-native-windows/platform.js': ` module.exports = {"windows": {}}; `, + 'node_modules/react-native-windows/plugin.js': ` + module.exports = []; + `, 'node_modules/react-native-windows/package.json': `{ "name": "react-native-windows", "rnpm": { @@ -201,9 +196,6 @@ test('should load an out-of-tree "windows" platform that ships with a dependency 'package.json': `{ "dependencies": { "react-native-windows": "0.0.1" - }, - "react-native": { - "reactNativePath": "." } }`, }); @@ -217,9 +209,6 @@ test('should automatically put "react-native" into haste config', () => { 'package.json': `{ "dependencies": { "react-native": "0.0.1" - }, - "react-native": { - "reactNativePath": "." } }`, }); diff --git a/packages/cli/src/tools/config/index.js b/packages/cli/src/tools/config/index.js index 03df4add4..aa903cea7 100644 --- a/packages/cli/src/tools/config/index.js +++ b/packages/cli/src/tools/config/index.js @@ -83,11 +83,7 @@ function loadConfig(projectRoot: string = process.cwd()): ConfigT { ); }, }), - commands: acc.commands.concat( - config.commands.map(pathToCommand => - path.join(dependencyName, pathToCommand), - ), - ), + commands: [...acc.commands, ...config.commands], platforms: { ...acc.platforms, ...config.platforms, diff --git a/packages/cli/src/tools/config/readConfigFromDisk.js b/packages/cli/src/tools/config/readConfigFromDisk.js index edc86091d..fda58d138 100644 --- a/packages/cli/src/tools/config/readConfigFromDisk.js +++ b/packages/cli/src/tools/config/readConfigFromDisk.js @@ -7,11 +7,16 @@ import Joi from 'joi'; import cosmiconfig from 'cosmiconfig'; import path from 'path'; -import {type UserDependencyConfigT, type UserConfigT} from './types.flow'; +import { + type UserDependencyConfigT, + type UserConfigT, + type CommandT, +} from './types.flow'; import {JoiError} from '../errors'; import * as schema from './schema'; + import {logger} from '@react-native-community/cli-tools'; /** @@ -60,6 +65,27 @@ export function readDependencyConfigFromDisk( return result.value; } +/** + * Returns an array of commands that are defined in the project. + * + * `config.project` can be either an array of paths or a single string. + * Each of the files can export a commands (object) or an array of commands + */ +const loadProjectCommands = ( + root, + commands: ?(Array | string), +): Array => { + return [] + .concat(commands || []) + .reduce((acc: Array, cmdPath: string) => { + const cmds: Array | CommandT = require(path.join( + root, + cmdPath, + )); + return acc.concat(cmds); + }, []); +}; + /** * Reads a legacy configuaration from a `package.json` "rnpm" key. */ @@ -82,7 +108,7 @@ export function readLegacyDependencyConfigFromDisk( hooks: config.commands, params: config.params, }, - commands: [].concat(config.plugin || []), + commands: loadProjectCommands(rootFolder, config.plugin), platforms: config.platform ? require(path.join(rootFolder, config.platform)) : undefined, diff --git a/packages/cli/src/tools/config/schema.js b/packages/cli/src/tools/config/schema.js index 067395c52..094c4e335 100644 --- a/packages/cli/src/tools/config/schema.js +++ b/packages/cli/src/tools/config/schema.js @@ -9,6 +9,30 @@ const map = (key, value) => .unknown(true) .pattern(key, value); +/** + * Schema for CommandT + */ +const command = t.object({ + name: t.string().required(), + description: t.string(), + usage: t.string(), + func: t.func().required(), + options: t.array().items( + t.object({ + command: t.string().required(), + description: t.string(), + parse: t.func(), + default: t.alternatives().try([t.bool(), t.number(), t.string()]), + }), + ), + examples: t.array().items( + t.object({ + desc: t.string().required(), + cmd: t.string().required(), + }), + ), +}); + /** * Schema for UserDependencyConfigT */ @@ -62,7 +86,7 @@ export const dependencyConfig = t ).default(), commands: t .array() - .items(t.string()) + .items(command) .default([]), }) .default(); @@ -142,7 +166,7 @@ export const projectConfig = t .default([]), commands: t .array() - .items(t.string()) + .items(command) .default([]), }) .default(); diff --git a/packages/cli/src/tools/config/types.flow.js b/packages/cli/src/tools/config/types.flow.js index 9e038d86b..93d6725c7 100644 --- a/packages/cli/src/tools/config/types.flow.js +++ b/packages/cli/src/tools/config/types.flow.js @@ -1,6 +1,22 @@ /** * @flow */ +export type CommandT = { + name: string, + description?: string, + usage?: string, + func: (argv: Array, ctx: ConfigT, args: Object) => ?Promise, + options?: Array<{ + command: string, + description?: string, + parse?: (val: string) => any, + default?: string | boolean | number, + }>, + examples?: Array<{ + desc: string, + cmd: string, + }>, +}; /** * Opaque type that describes the Inquirer question format. Not typed, since we just @@ -122,7 +138,7 @@ export type ConfigT = {| }, // An array of commands that are present in 3rd party packages - commands: string[], + commands: CommandT[], // Haste configuration resolved based on available plugins haste: { @@ -159,7 +175,7 @@ export type UserDependencyConfigT = { }, // An array of commands that ship with the dependency - commands: string[], + commands: CommandT[], // An array of extra platforms to load platforms: { diff --git a/packages/cli/src/tools/loadMetroConfig.js b/packages/cli/src/tools/loadMetroConfig.js index 8a380f0d9..14c4c5b18 100644 --- a/packages/cli/src/tools/loadMetroConfig.js +++ b/packages/cli/src/tools/loadMetroConfig.js @@ -5,7 +5,7 @@ import path from 'path'; import {createBlacklist} from 'metro'; import {loadConfig} from 'metro-config'; -import {type ContextT} from './types.flow'; +import {type ConfigT} from './config/types.flow'; import findSymlinkedModules from './findSymlinkedModules'; const resolveSymlinksForRoots = roots => @@ -30,7 +30,7 @@ const getBlacklistRE = () => createBlacklist([/.*\/__fixtures__\/.*/]); * @todo(grabbou): As a separate PR, haste.platforms should be added before "native". * Otherwise, a.native.js will not load on Windows or other platforms */ -export const getDefaultConfig = (ctx: ContextT) => { +export const getDefaultConfig = (ctx: ConfigT) => { return { resolver: { resolverMainFields: ['react-native', 'browser', 'main'], @@ -80,7 +80,7 @@ export type ConfigOptionsT = {| * * This allows the CLI to always overwrite the file settings. */ -export default function load(ctx: ContextT, options?: ConfigOptionsT) { +export default function load(ctx: ConfigT, options?: ConfigOptionsT) { const defaultConfig = getDefaultConfig(ctx); return loadConfig({cwd: ctx.root, ...options}, defaultConfig); diff --git a/packages/cli/src/tools/types.flow.js b/packages/cli/src/tools/types.flow.js deleted file mode 100644 index 5926e655c..000000000 --- a/packages/cli/src/tools/types.flow.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @flow - */ - -import {type ConfigT} from './config/types.flow'; - -export type ContextT = ConfigT; - -export type LocalCommandT = { - name: string, - description?: string, - usage?: string, - func: (argv: Array, ctx: ContextT, args: Object) => ?Promise, - options?: Array<{ - command: string, - description?: string, - parse?: (val: string) => any, - default?: string | boolean | number, - }>, - examples?: Array<{ - desc: string, - cmd: string, - }>, -}; - -type Package = { - version: string, - name: string, -}; - -/** - * User can define command either as an object (RequiredCommandT) or - * as an array of commands (Array). - */ -export type ProjectCommandT = LocalCommandT & { - pkg: Package, -}; - -/** - * Main type. Can be either local or a project command. - */ -export type CommandT = LocalCommandT | ProjectCommandT;