diff --git a/packages/cli/package.json b/packages/cli/package.json index 7f4689f80..65dab618f 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -68,6 +68,8 @@ "devDependencies": { "@types/command-exists": "^1.2.0", "@types/graceful-fs": "^4.1.3", + "@types/minimist": "^1.2.0", + "@types/mkdirp": "^0.5.2", "@types/semver": "^6.0.2", "slash": "^3.0.0", "snapshot-diff": "^0.5.0" diff --git a/packages/cli/src/cliEntry.js b/packages/cli/src/cliEntry.js index 6a65e1fea..062960709 100644 --- a/packages/cli/src/cliEntry.js +++ b/packages/cli/src/cliEntry.js @@ -15,6 +15,7 @@ import path from 'path'; import type {CommandT, ConfigT} from 'types'; // $FlowFixMe - converted to TS import commands from './commands'; +// $FlowFixMe - converted to TS import init from './commands/init/initCompat'; // $FlowFixMe - converted to TS import assertRequiredOptions from './tools/assertRequiredOptions'; diff --git a/packages/cli/src/commands/index.ts b/packages/cli/src/commands/index.ts index 3d1c5258a..7601bc17e 100644 --- a/packages/cli/src/commands/index.ts +++ b/packages/cli/src/commands/index.ts @@ -16,7 +16,6 @@ import upgrade from './upgrade/upgrade'; import info from './info/info'; // @ts-ignore - JS file import config from './config/config'; // eslint-disable-line import/namespace, import/default -// @ts-ignore - JS file import init from './init'; // @ts-ignore - JS file import doctor from './doctor'; diff --git a/packages/cli/src/commands/init/__tests__/__snapshots__/editTemplate.test.js.snap b/packages/cli/src/commands/init/__tests__/__snapshots__/editTemplate.test.ts.snap similarity index 100% rename from packages/cli/src/commands/init/__tests__/__snapshots__/editTemplate.test.js.snap rename to packages/cli/src/commands/init/__tests__/__snapshots__/editTemplate.test.ts.snap diff --git a/packages/cli/src/commands/init/__tests__/editTemplate.test.js b/packages/cli/src/commands/init/__tests__/editTemplate.test.ts similarity index 98% rename from packages/cli/src/commands/init/__tests__/editTemplate.test.js rename to packages/cli/src/commands/init/__tests__/editTemplate.test.ts index f1e40a0a7..8b9722e03 100644 --- a/packages/cli/src/commands/init/__tests__/editTemplate.test.js +++ b/packages/cli/src/commands/init/__tests__/editTemplate.test.ts @@ -1,11 +1,9 @@ -// @flow import os from 'os'; import path from 'path'; import fs from 'fs-extra'; import snapshotDiff from 'snapshot-diff'; import slash from 'slash'; import walk from '../../../tools/walk'; -// $FlowFixMe - converted to TS import copyFiles from '../../../tools/copyFiles'; import {changePlaceholderInTemplate} from '../editTemplate'; diff --git a/packages/cli/src/commands/init/__tests__/template.test.js b/packages/cli/src/commands/init/__tests__/template.test.ts similarity index 96% rename from packages/cli/src/commands/init/__tests__/template.test.js rename to packages/cli/src/commands/init/__tests__/template.test.ts index afa903838..472e2e864 100644 --- a/packages/cli/src/commands/init/__tests__/template.test.js +++ b/packages/cli/src/commands/init/__tests__/template.test.ts @@ -1,8 +1,6 @@ -// @flow jest.mock('execa', () => jest.fn()); import execa from 'execa'; import path from 'path'; -// $FlowFixMe - converted to TS import * as PackageManger from '../../../tools/packageManager'; import { installTemplatePackage, @@ -10,7 +8,6 @@ import { copyTemplate, executePostInitScript, } from '../template'; -// $FlowFixMe - converted to TS import * as copyFiles from '../../../tools/copyFiles'; const TEMPLATE_NAME = 'templateName'; @@ -22,7 +19,7 @@ afterEach(() => { }); test('installTemplatePackage', async () => { - jest.spyOn(PackageManger, 'install').mockImplementationOnce(() => {}); + jest.spyOn(PackageManger, 'install').mockImplementationOnce(() => null); await installTemplatePackage(TEMPLATE_NAME, TEMPLATE_SOURCE_DIR, true); @@ -63,7 +60,7 @@ test('copyTemplate', async () => { const CWD = '.'; jest.spyOn(path, 'resolve').mockImplementationOnce((...e) => e.join('/')); - jest.spyOn(copyFiles, 'default').mockImplementationOnce(() => {}); + jest.spyOn(copyFiles, 'default').mockImplementationOnce(() => null); jest.spyOn(process, 'cwd').mockImplementationOnce(() => CWD); await copyTemplate(TEMPLATE_NAME, TEMPLATE_DIR, TEMPLATE_SOURCE_DIR); diff --git a/packages/cli/src/commands/init/__tests__/templateName.test.js b/packages/cli/src/commands/init/__tests__/templateName.test.ts similarity index 99% rename from packages/cli/src/commands/init/__tests__/templateName.test.js rename to packages/cli/src/commands/init/__tests__/templateName.test.ts index d01636e46..87dfcd261 100644 --- a/packages/cli/src/commands/init/__tests__/templateName.test.js +++ b/packages/cli/src/commands/init/__tests__/templateName.test.ts @@ -1,4 +1,3 @@ -// @flow import {processTemplateName} from '../templateName'; const RN_NPM_PACKAGE = 'react-native'; diff --git a/packages/cli/src/commands/init/__tests__/validate.test.js b/packages/cli/src/commands/init/__tests__/validate.test.ts similarity index 76% rename from packages/cli/src/commands/init/__tests__/validate.test.js rename to packages/cli/src/commands/init/__tests__/validate.test.ts index e7e1745ab..4d8042079 100644 --- a/packages/cli/src/commands/init/__tests__/validate.test.js +++ b/packages/cli/src/commands/init/__tests__/validate.test.ts @@ -1,4 +1,3 @@ -// @flow import {validateProjectName} from '../validate'; import InvalidNameError from '../errors/InvalidNameError'; import ReservedNameError from '../errors/ReservedNameError'; @@ -28,6 +27,8 @@ test.each([ name: 'helloworld_test', error: HelloWorldError, }, -])("'%s' is invalid name", ({name, error}: {name: string, error: Error}) => { + // @ts-ignore-next-line FIXME extending the Error class causes weird TS validation errors + // https://stackoverflow.com/questions/41102060/typescript-extending-error-class +])("'%s' is invalid name", ({name, error}: {name: string; error: Error}) => { expect(() => validateProjectName(name)).toThrowError(error); }); diff --git a/packages/cli/src/commands/init/banner.js b/packages/cli/src/commands/init/banner.ts similarity index 99% rename from packages/cli/src/commands/init/banner.js rename to packages/cli/src/commands/init/banner.ts index aa6981c59..f772725ef 100644 --- a/packages/cli/src/commands/init/banner.js +++ b/packages/cli/src/commands/init/banner.ts @@ -1,4 +1,3 @@ -// @flow import chalk from 'chalk'; const reactLogoArray = [ diff --git a/packages/cli/src/commands/init/editTemplate.js b/packages/cli/src/commands/init/editTemplate.ts similarity index 92% rename from packages/cli/src/commands/init/editTemplate.js rename to packages/cli/src/commands/init/editTemplate.ts index a1da9f0b5..22029e7f9 100644 --- a/packages/cli/src/commands/init/editTemplate.js +++ b/packages/cli/src/commands/init/editTemplate.ts @@ -1,8 +1,15 @@ -// @flow import fs from 'fs'; import path from 'path'; -import walk from '../../tools/walk'; import {logger} from '@react-native-community/cli-tools'; +// @ts-ignore FIXME after converting walk to typescript +import walk from '../../tools/walk'; + +interface PlaceholderConfig { + projectName: string; + placeholderName: string; + placeholderTitle?: string; + projectTitle?: string; +} /** TODO: This is a default placeholder for title in react-native template. @@ -73,12 +80,7 @@ export function changePlaceholderInTemplate({ placeholderName, placeholderTitle = DEFAULT_TITLE_PLACEHOLDER, projectTitle = projectName, -}: { - projectName: string, - placeholderName: string, - placeholderTitle?: string, - projectTitle?: string, -}) { +}: PlaceholderConfig) { logger.debug(`Changing ${placeholderName} for ${projectName} in template`); walk(process.cwd()) diff --git a/packages/cli/src/commands/init/errors/DirectoryAlreadyExistsError.js b/packages/cli/src/commands/init/errors/DirectoryAlreadyExistsError.ts similarity index 95% rename from packages/cli/src/commands/init/errors/DirectoryAlreadyExistsError.js rename to packages/cli/src/commands/init/errors/DirectoryAlreadyExistsError.ts index c24352d17..5bdb5deb9 100644 --- a/packages/cli/src/commands/init/errors/DirectoryAlreadyExistsError.js +++ b/packages/cli/src/commands/init/errors/DirectoryAlreadyExistsError.ts @@ -1,4 +1,3 @@ -// @flow export default class DirectoryAlreadyExistsError extends Error { constructor(directory: string) { super( diff --git a/packages/cli/src/commands/init/errors/HelloWorldError.js b/packages/cli/src/commands/init/errors/HelloWorldError.ts similarity index 95% rename from packages/cli/src/commands/init/errors/HelloWorldError.js rename to packages/cli/src/commands/init/errors/HelloWorldError.ts index ae515b696..18f2eb389 100644 --- a/packages/cli/src/commands/init/errors/HelloWorldError.js +++ b/packages/cli/src/commands/init/errors/HelloWorldError.ts @@ -1,4 +1,3 @@ -// @flow export default class HelloWorldError extends Error { constructor() { super( diff --git a/packages/cli/src/commands/init/errors/InvalidNameError.js b/packages/cli/src/commands/init/errors/InvalidNameError.ts similarity index 95% rename from packages/cli/src/commands/init/errors/InvalidNameError.js rename to packages/cli/src/commands/init/errors/InvalidNameError.ts index b7391cd54..08de3b6cb 100644 --- a/packages/cli/src/commands/init/errors/InvalidNameError.js +++ b/packages/cli/src/commands/init/errors/InvalidNameError.ts @@ -1,4 +1,3 @@ -// @flow export default class InvalidNameError extends Error { constructor(name: string) { super( diff --git a/packages/cli/src/commands/init/errors/ReservedNameError.js b/packages/cli/src/commands/init/errors/ReservedNameError.ts similarity index 95% rename from packages/cli/src/commands/init/errors/ReservedNameError.js rename to packages/cli/src/commands/init/errors/ReservedNameError.ts index 6c747caac..9f4063cee 100644 --- a/packages/cli/src/commands/init/errors/ReservedNameError.js +++ b/packages/cli/src/commands/init/errors/ReservedNameError.ts @@ -1,4 +1,3 @@ -// @flow export default class ReservedNameError extends Error { constructor() { super( diff --git a/packages/cli/src/commands/init/index.js b/packages/cli/src/commands/init/index.ts similarity index 98% rename from packages/cli/src/commands/init/index.js rename to packages/cli/src/commands/init/index.ts index 6caa013f5..4b76ba7f3 100644 --- a/packages/cli/src/commands/init/index.js +++ b/packages/cli/src/commands/init/index.ts @@ -1,4 +1,3 @@ -// @flow import init from './init'; export default { diff --git a/packages/cli/src/commands/init/init.js b/packages/cli/src/commands/init/init.ts similarity index 86% rename from packages/cli/src/commands/init/init.js rename to packages/cli/src/commands/init/init.ts index d36bce322..14459a898 100644 --- a/packages/cli/src/commands/init/init.js +++ b/packages/cli/src/commands/init/init.ts @@ -1,17 +1,17 @@ -// @flow import os from 'os'; import path from 'path'; import fs from 'fs-extra'; -import Ora from 'ora'; import minimist from 'minimist'; +import ora from 'ora'; import semver from 'semver'; +// @ts-ignore untyped import inquirer from 'inquirer'; import mkdirp from 'mkdirp'; -import type {ConfigT} from 'types'; import {validateProjectName} from './validate'; import DirectoryAlreadyExistsError from './errors/DirectoryAlreadyExistsError'; import printRunInstructions from './printRunInstructions'; -import {logger} from '@react-native-community/cli-tools'; +import {CLIError, logger} from '@react-native-community/cli-tools'; +import {Config} from '@react-native-community/cli-types'; import { installTemplatePackage, getTemplateConfig, @@ -19,35 +19,45 @@ import { executePostInitScript, } from './template'; import {changePlaceholderInTemplate} from './editTemplate'; -// $FlowFixMe - converted to TS import * as PackageManager from '../../tools/packageManager'; -// $FlowFixMe - converted to TS import installPods from '../../tools/installPods'; import {processTemplateName} from './templateName'; import banner from './banner'; -// $FlowFixMe - converted to TS import {getLoader} from '../../tools/loader'; -import {CLIError} from '@react-native-community/cli-tools'; const DEFAULT_VERSION = 'latest'; -type Options = {| - template?: string, - npm?: boolean, - directory?: string, - displayName?: string, - title?: string, -|}; +type Options = { + template?: string; + npm?: boolean; + directory?: string; + displayName?: string; + title?: string; +}; + +interface TemplateOptions { + projectName: string; + templateName: string; + npm?: boolean; + directory: string; + projectTitle?: string; +} function doesDirectoryExist(dir: string) { return fs.existsSync(dir); } -function getProjectDirectory({projectName, directory}): string { +function getProjectDirectory({ + projectName, + directory, +}: { + projectName: string; + directory: string; +}): string { return path.relative(process.cwd(), directory || projectName); } -async function setProjectDirectory(directory) { +async function setProjectDirectory(directory: string) { const directoryExists = doesDirectoryExist(directory); if (directoryExists) { const {shouldReplaceprojectDirectory} = await inquirer.prompt([ @@ -79,7 +89,7 @@ async function setProjectDirectory(directory) { } } -function adjustNameIfUrl(name, cwd) { +function adjustNameIfUrl(name: string, cwd: string) { // We use package manager to infer the name of the template module for us. // That's why we get it from temporary package.json, where the name is the // first and only dependency (hence 0). @@ -98,13 +108,7 @@ async function createFromTemplate({ npm, directory, projectTitle, -}: { - projectName: string, - templateName: string, - npm?: boolean, - directory: string, - projectTitle?: string, -}) { +}: TemplateOptions) { logger.debug('Initializing new project'); logger.log(banner); @@ -136,7 +140,7 @@ async function createFromTemplate({ projectName, projectTitle, placeholderName: templateConfig.placeholderName, - titlePlaceholder: templateConfig.titlePlaceholder, + placeholderTitle: templateConfig.titlePlaceholder, }); loader.succeed(); @@ -162,9 +166,9 @@ async function installDependencies({ npm, loader, }: { - projectName: string, - npm?: boolean, - loader: typeof Ora, + projectName: string; + npm?: boolean; + loader: ora.Ora; }) { loader.start('Installing dependencies'); @@ -209,7 +213,7 @@ async function createProject( export default (async function initialize( [projectName]: Array, - context: ConfigT, + context: Config, options: Options, ) { const rootFolder = context.root; diff --git a/packages/cli/src/commands/init/initCompat.js b/packages/cli/src/commands/init/initCompat.ts similarity index 91% rename from packages/cli/src/commands/init/initCompat.js rename to packages/cli/src/commands/init/initCompat.ts index 3116f130b..15c475e9f 100644 --- a/packages/cli/src/commands/init/initCompat.js +++ b/packages/cli/src/commands/init/initCompat.ts @@ -4,7 +4,6 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @format */ import fs from 'fs'; @@ -26,7 +25,7 @@ import installPods from '../../tools/installPods'; * @param options Command line options passed from the react-native-cli directly. * E.g. `{ version: '0.43.0', template: 'navigation' }` */ -async function initCompat(projectDir, argsOrName) { +async function initCompat(projectDir: string, argsOrName: string | string[]) { const args = Array.isArray(argsOrName) ? argsOrName // argsOrName was e.g. ['AwesomeApp', '--verbose'] : [argsOrName].concat(process.argv.slice(4)); // argsOrName was e.g. 'AwesomeApp' @@ -49,16 +48,19 @@ async function initCompat(projectDir, argsOrName) { * @param Absolute path at which the project folder should be created. * @param options Command line arguments parsed by minimist. */ -async function generateProject(destinationRoot, newProjectName, options) { +async function generateProject( + destinationRoot: string, + newProjectName: string, + options: any, +) { const pkgJson = require('react-native/package.json'); const reactVersion = pkgJson.peerDependencies.react; - await PackageManager.setProjectDir(destinationRoot); + PackageManager.setProjectDir(destinationRoot); await createProjectFromTemplate( destinationRoot, newProjectName, options.template, - destinationRoot, ); logger.info('Adding required dependencies'); @@ -90,9 +92,9 @@ async function generateProject(destinationRoot, newProjectName, options) { /** * Add Jest-related stuff to package.json, which was created by the react-native-cli. */ -function addJestToPackageJson(destinationRoot) { +function addJestToPackageJson(destinationRoot: string) { const packageJSONPath = path.join(destinationRoot, 'package.json'); - const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath)); + const packageJSON = JSON.parse(fs.readFileSync(packageJSONPath).toString()); packageJSON.scripts.test = 'jest'; packageJSON.scripts.lint = 'eslint .'; diff --git a/packages/cli/src/commands/init/printRunInstructions.js b/packages/cli/src/commands/init/printRunInstructions.ts similarity index 99% rename from packages/cli/src/commands/init/printRunInstructions.js rename to packages/cli/src/commands/init/printRunInstructions.ts index c7068e5b2..649fdb9fc 100644 --- a/packages/cli/src/commands/init/printRunInstructions.js +++ b/packages/cli/src/commands/init/printRunInstructions.ts @@ -5,7 +5,6 @@ * LICENSE file in the root directory of this source tree. * * @format - * @flow */ import path from 'path'; diff --git a/packages/cli/src/commands/init/template.js b/packages/cli/src/commands/init/template.ts similarity index 89% rename from packages/cli/src/commands/init/template.js rename to packages/cli/src/commands/init/template.ts index f01cb86ca..683d24c71 100644 --- a/packages/cli/src/commands/init/template.js +++ b/packages/cli/src/commands/init/template.ts @@ -1,19 +1,15 @@ -// @flow import execa from 'execa'; import path from 'path'; -// $FlowFixMe - converted to TS -import * as PackageManager from '../../tools/packageManager'; import {logger} from '@react-native-community/cli-tools'; -// $FlowFixMe - converted to TS +import * as PackageManager from '../../tools/packageManager'; import copyFiles from '../../tools/copyFiles'; -// $FlowFixMe - converted to TS import replacePathSepForRegex from '../../tools/replacePathSepForRegex'; export type TemplateConfig = { - placeholderName: string, - templateDir: string, - postInitScript?: string, - titlePlaceholder?: string, + placeholderName: string; + templateDir: string; + postInitScript?: string; + titlePlaceholder?: string; }; export function installTemplatePackage( diff --git a/packages/cli/src/commands/init/templateName.js b/packages/cli/src/commands/init/templateName.ts similarity index 99% rename from packages/cli/src/commands/init/templateName.js rename to packages/cli/src/commands/init/templateName.ts index ed19e3f86..8a8fcb558 100644 --- a/packages/cli/src/commands/init/templateName.js +++ b/packages/cli/src/commands/init/templateName.ts @@ -1,4 +1,3 @@ -// @flow import path from 'path'; import {URL} from 'url'; diff --git a/packages/cli/src/commands/init/validate.js b/packages/cli/src/commands/init/validate.ts similarity index 98% rename from packages/cli/src/commands/init/validate.js rename to packages/cli/src/commands/init/validate.ts index bf707b89f..84775a21c 100644 --- a/packages/cli/src/commands/init/validate.js +++ b/packages/cli/src/commands/init/validate.ts @@ -1,4 +1,3 @@ -// @flow import InvalidNameError from './errors/InvalidNameError'; import ReservedNameError from './errors/ReservedNameError'; import HelloWorldError from './errors/HelloWorldError'; diff --git a/packages/cli/src/tools/__tests__/copyFiles.test.ts b/packages/cli/src/tools/__tests__/copyFiles.test.ts index 75a22d9a9..cc6394f0a 100644 --- a/packages/cli/src/tools/__tests__/copyFiles.test.ts +++ b/packages/cli/src/tools/__tests__/copyFiles.test.ts @@ -3,7 +3,6 @@ import fs from 'fs'; import path from 'path'; import copyFiles from '../copyFiles'; import {cleanup, getTempDirectory} from '../../../../../jest/helpers'; -// $FlowFixMe - converted to TS import replacePathSepForRegex from '../replacePathSepForRegex'; const DIR = getTempDirectory('copyFiles-test'); diff --git a/packages/cli/src/tools/installPods.ts b/packages/cli/src/tools/installPods.ts index c53c70d6c..d4032b87f 100644 --- a/packages/cli/src/tools/installPods.ts +++ b/packages/cli/src/tools/installPods.ts @@ -103,7 +103,7 @@ async function installPods({ }: { projectName: string; loader?: ora.Ora; - shouldUpdatePods: boolean; + shouldUpdatePods?: boolean; }) { loader = loader || new NoopLoader(); try { diff --git a/packages/cli/src/tools/loader.ts b/packages/cli/src/tools/loader.ts index f3940c1be..d9ec81c64 100644 --- a/packages/cli/src/tools/loader.ts +++ b/packages/cli/src/tools/loader.ts @@ -42,7 +42,8 @@ class OraNoop implements ora.Ora { } export function getLoader() { - return logger.isVerbose() ? OraNoop : ora; + // FIXME refactor getLoader to not rely on class instantiation to avoid type conflict or implement an default Ora Loader Class definition + return logger.isVerbose() ? OraNoop : (ora as any); } export const NoopLoader = OraNoop; diff --git a/yarn.lock b/yarn.lock index c33e45351..43348e117 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2104,6 +2104,11 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== +"@types/minimist@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.0.tgz#69a23a3ad29caf0097f06eda59b361ee2f0639f6" + integrity sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY= + "@types/mkdirp@^0.5.2": version "0.5.2" resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f"