diff --git a/.circleci/config.yml b/.circleci/config.yml index 9df0e80932f..04eb37358f1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -243,6 +243,12 @@ commands: - ~/.cache/yarn key: << parameters.yarn_base_cache_key >>-{{ arch }}-{{ checksum "yarn.lock" }} + build_packages: + steps: + - run: + name: Build packages + command: yarn build + brew_install: parameters: package: @@ -1775,6 +1781,7 @@ jobs: cp $HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-release.tar.gz ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-ios-release.tar.gz - run_yarn + - build_packages - download_gradle_dependencies # START: Stables and nightlies @@ -1870,6 +1877,7 @@ jobs: steps: - checkout - run_yarn + - build_packages - run: name: Set NPM auth token command: echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc diff --git a/flow-typed/npm/parseargs_v0.11.x.js b/flow-typed/npm/parseargs_v0.11.x.js new file mode 100644 index 00000000000..396865dca4f --- /dev/null +++ b/flow-typed/npm/parseargs_v0.11.x.js @@ -0,0 +1,40 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + * @oncall react_native + */ + +declare module '@pkgjs/parseargs' { + declare type ParseArgsOptionConfig = { + type: 'string' | 'boolean', + short?: string, + multiple?: boolean, + }; + + declare type ParseArgsOptionsConfig = { + [longOption: string]: ParseArgsOptionConfig, + }; + + declare export type ParseArgsConfig = { + strict?: boolean, + allowPositionals?: boolean, + tokens?: boolean, + options?: ParseArgsOptionsConfig, + args?: string[], + }; + + declare type ParsedResults = { + values: { + [longOption: string]: void | string | boolean | Array, + }, + positionals: string[], + ... + }; + + declare export function parseArgs(config: ParseArgsConfig): ParsedResults; +} diff --git a/package.json b/package.json index fd6f101f8d3..7e351a5d8b7 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,8 @@ "scripts": { "start": "cd packages/rn-tester && npm run start", "android": "cd packages/rn-tester && npm run android", + "build": "node ./scripts/build/build.js", + "clean": "node ./scripts/build/clean.js", "test": "jest", "test-ci": "jest --maxWorkers=2 --ci --reporters=\"default\" --reporters=\"jest-junit\"", "flow": "flow", @@ -45,14 +47,20 @@ "@babel/eslint-parser": "^7.20.0", "@babel/generator": "^7.20.0", "@babel/plugin-transform-regenerator": "^7.20.0", + "@babel/preset-env": "^7.20.0", + "@babel/preset-flow": "^7.20.0", "@definitelytyped/dtslint": "^0.0.127", "@jest/create-cache-key-function": "^29.2.1", + "@pkgjs/parseargs": "^0.11.0", "@react-native/metro-babel-transformer": "^0.73.11", "@react-native/metro-config": "^0.73.0", "@types/react": "^18.0.18", "@typescript-eslint/parser": "^5.57.1", "async": "^3.2.2", + "babel-plugin-minify-dead-code-elimination": "^0.5.2", + "babel-plugin-transform-define": "^2.1.2", "babel-plugin-transform-flow-enums": "^0.0.2", + "chalk": "^4.0.0", "clang-format": "^1.8.0", "connect": "^3.6.5", "eslint": "^8.19.0", @@ -70,6 +78,7 @@ "eslint-plugin-redundant-undefined": "^0.4.0", "eslint-plugin-relay": "^1.8.3", "flow-bin": "^0.213.1", + "glob": "^7.1.1", "hermes-eslint": "0.15.0", "inquirer": "^7.1.0", "jest": "^29.2.1", @@ -77,6 +86,7 @@ "jscodeshift": "^0.14.0", "metro-babel-register": "0.77.0", "metro-memory-fs": "0.77.0", + "micromatch": "^4.0.4", "mkdirp": "^0.5.1", "mock-fs": "^5.1.4", "prettier": "2.8.8", diff --git a/packages/dev-middleware/.babelrc b/packages/dev-middleware/.babelrc deleted file mode 100644 index e6ab061db79..00000000000 --- a/packages/dev-middleware/.babelrc +++ /dev/null @@ -1,13 +0,0 @@ -{ - "presets": [ - "@babel/preset-flow", - [ - "@babel/preset-env", - { - "targets": { - "node": "16" - } - } - ] - ] -} diff --git a/packages/dev-middleware/index.js.flow b/packages/dev-middleware/index.js.flow index 5bccccabb8f..17ae7ce0503 100644 --- a/packages/dev-middleware/index.js.flow +++ b/packages/dev-middleware/index.js.flow @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow strict + * @flow * @format * @oncall react_native */ diff --git a/packages/dev-middleware/package.json b/packages/dev-middleware/package.json index 5fc0b5b79bc..d0af4698087 100644 --- a/packages/dev-middleware/package.json +++ b/packages/dev-middleware/package.json @@ -14,29 +14,19 @@ "directory": "packages/dev-middleware" }, "license": "MIT", - "exports": "./dist/index.js", + "exports": { + ".": "./src/index.js", + "./package.json": "./package.json" + }, "files": [ "dist" ], - "scripts": { - "build": "yarn clean && babel src --out-dir dist", - "dev": "babel src --out-dir dist --source-maps --watch", - "clean": "rimraf dist", - "prepare": "yarn build" - }, "dependencies": { "chrome-launcher": "^0.15.2", "connect": "^3.6.5", "node-fetch": "^2.2.0", "temp-dir": "^2.0.0" }, - "devDependencies": { - "@babel/cli": "^7.20.0", - "@babel/core": "^7.20.0", - "@babel/preset-env": "^7.20.0", - "@babel/preset-flow": "^7.20.0", - "rimraf": "^3.0.2" - }, "engines": { "node": ">=18" } diff --git a/packages/dev-middleware/src/index.flow.js b/packages/dev-middleware/src/index.flow.js new file mode 100644 index 00000000000..26f17c2499d --- /dev/null +++ b/packages/dev-middleware/src/index.flow.js @@ -0,0 +1,12 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + * @oncall react_native + */ + +export {default as createDevMiddleware} from './createDevMiddleware'; diff --git a/packages/dev-middleware/src/index.js b/packages/dev-middleware/src/index.js index 26f17c2499d..c95fbd8400e 100644 --- a/packages/dev-middleware/src/index.js +++ b/packages/dev-middleware/src/index.js @@ -4,9 +4,17 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @flow strict + * @flow * @format * @oncall react_native */ -export {default as createDevMiddleware} from './createDevMiddleware'; +/*:: +export type * from './index.flow'; +*/ + +if (!process.env.BUILD_EXCLUDE_BABEL_REGISTER) { + require('../../../scripts/build/babel-register').registerForMonorepo(); +} + +module.exports = require('./index.flow'); diff --git a/scripts/build/babel-register.js b/scripts/build/babel-register.js new file mode 100644 index 00000000000..b94a0a803c1 --- /dev/null +++ b/scripts/build/babel-register.js @@ -0,0 +1,54 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + * @oncall react_native + */ + +const path = require('path'); +const {PACKAGES_DIR} = require('./build'); +const {buildConfig, getBabelConfig} = require('./config'); + +let isRegisteredForMonorepo = false; + +/** + * Calling this function enables all Node.js packages to run from source when + * developing in the React Native repo. + * + * A call should located in each entry point file in a package (i.e. for all + * paths in "exports"), inside a special `if` condition that will be compiled + * away on build. + * + * if (!process.env.BUILD_EXCLUDE_BABEL_REGISTER) { + * require('../../../scripts/build/babel-register').registerForMonorepo(); + * } + */ +function registerForMonorepo() { + if (isRegisteredForMonorepo) { + return; + } + + for (const [packageName, {target}] of Object.entries(buildConfig.packages)) { + if (target === 'node') { + registerPackage(packageName); + } + } + + isRegisteredForMonorepo = true; +} + +function registerPackage(packageName /*: string */) { + const packageDir = path.join(PACKAGES_DIR, packageName); + + require('@babel/register')({ + ...getBabelConfig(packageName), + root: packageDir, + ignore: [/\/node_modules\//], + }); +} + +module.exports = {registerForMonorepo}; diff --git a/scripts/build/build.js b/scripts/build/build.js new file mode 100644 index 00000000000..c7c65d83ea7 --- /dev/null +++ b/scripts/build/build.js @@ -0,0 +1,186 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + * @oncall react_native + */ + +const babel = require('@babel/core'); +const {parseArgs} = require('@pkgjs/parseargs'); +const chalk = require('chalk'); +const glob = require('glob'); +const micromatch = require('micromatch'); +const fs = require('fs'); +const path = require('path'); +const prettier = require('prettier'); +const {buildConfig, getBabelConfig} = require('./config'); + +const PACKAGES_DIR /*: string */ = path.resolve(__dirname, '../../packages'); +const SRC_DIR = 'src'; +const BUILD_DIR = 'dist'; +const JS_FILES_PATTERN = '**/*.js'; +const IGNORE_PATTERN = '**/__{tests,mocks,fixtures}__/**'; + +const config = { + allowPositionals: true, + options: { + help: {type: 'boolean'}, + }, +}; + +function build() { + const { + positionals: packageNames, + values: {help}, + } = parseArgs(config); + + if (help) { + console.log(` + Usage: node ./scripts/build/build.js + + Build packages (shared monorepo build setup). + + By default, builds all packages defined in ./scripts/build/config.js. If a + a package list is provided, builds only those specified. + `); + process.exitCode = 0; + return; + } + + console.log('\n' + chalk.bold.inverse('Building packages') + '\n'); + + if (packageNames.length) { + packageNames + .filter(packageName => packageName in buildConfig.packages) + .forEach(buildPackage); + } else { + Object.keys(buildConfig.packages).forEach(buildPackage); + } + + process.exitCode = 0; +} + +function buildPackage(packageName /*: string */) { + const files = glob.sync( + path.resolve(PACKAGES_DIR, packageName, SRC_DIR, '**/*'), + {nodir: true}, + ); + const packageJsonPath = path.join(PACKAGES_DIR, packageName, 'package.json'); + + process.stdout.write( + `${packageName} ${chalk.dim('.').repeat(72 - packageName.length)} `, + ); + files.forEach(file => buildFile(path.normalize(file), true)); + rewritePackageExports(packageJsonPath); + process.stdout.write(chalk.reset.inverse.bold.green(' DONE ') + '\n'); +} + +function buildFile(file /*: string */, silent /*: boolean */ = false) { + const packageName = getPackageName(file); + const buildPath = getBuildPath(file); + + const logResult = ({copied, desc} /*: {copied: boolean, desc?: string} */) => + silent || + console.log( + chalk.dim(' - ') + + path.relative(PACKAGES_DIR, file) + + (copied ? ' -> ' + path.relative(PACKAGES_DIR, buildPath) : ' ') + + (desc != null ? ' (' + desc + ')' : ''), + ); + + if (micromatch.isMatch(file, IGNORE_PATTERN)) { + logResult({copied: false, desc: 'ignore'}); + return; + } + + fs.mkdirSync(path.dirname(buildPath), {recursive: true}); + + if (!micromatch.isMatch(file, JS_FILES_PATTERN)) { + fs.copyFileSync(file, buildPath); + logResult({copied: true, desc: 'copy'}); + } else { + const transformed = prettier.format( + babel.transformFileSync(file, getBabelConfig(packageName)).code, + {parser: 'babel'}, + ); + fs.writeFileSync(buildPath, transformed); + + if (/@flow/.test(fs.readFileSync(file, 'utf-8'))) { + fs.copyFileSync(file, buildPath + '.flow'); + } + + logResult({copied: true}); + } +} + +function getPackageName(file /*: string */) /*: string */ { + return path.relative(PACKAGES_DIR, file).split(path.sep)[0]; +} + +function getBuildPath(file /*: string */) /*: string */ { + const packageDir = path.join(PACKAGES_DIR, getPackageName(file)); + + return path.join( + packageDir, + file.replace(path.join(packageDir, SRC_DIR), BUILD_DIR), + ); +} + +function rewritePackageExports(packageJsonPath /*: string */) { + const pkg = JSON.parse(fs.readFileSync(packageJsonPath, {encoding: 'utf8'})); + + if (pkg.exports == null) { + return; + } + + pkg.exports = rewriteExportsField(pkg.exports); + + fs.writeFileSync( + packageJsonPath, + prettier.format(JSON.stringify(pkg), {parser: 'json'}), + ); +} + +/*:: +type ExportsField = { + [subpath: string]: ExportsField | string, +} | string; +*/ + +function rewriteExportsField( + exportsField /*: ExportsField */, +) /*: ExportsField */ { + if (typeof exportsField === 'string') { + return rewriteExportsTarget(exportsField); + } + + for (const key in exportsField) { + if (typeof exportsField[key] === 'string') { + exportsField[key] = rewriteExportsTarget(exportsField[key]); + } else if (typeof exportsField[key] === 'object') { + exportsField[key] = rewriteExportsField(exportsField[key]); + } + } + + return exportsField; +} + +function rewriteExportsTarget(target /*: string */) /*: string */ { + return target.replace('./' + SRC_DIR + '/', './' + BUILD_DIR + '/'); +} + +module.exports = { + buildFile, + getBuildPath, + BUILD_DIR, + PACKAGES_DIR, + SRC_DIR, +}; + +if (require.main === module) { + build(); +} diff --git a/scripts/build/clean.js b/scripts/build/clean.js new file mode 100644 index 00000000000..15296f06556 --- /dev/null +++ b/scripts/build/clean.js @@ -0,0 +1,51 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + * @oncall react_native + */ + +const {parseArgs} = require('@pkgjs/parseargs'); +const fs = require('fs'); +const path = require('path'); +const {BUILD_DIR, PACKAGES_DIR} = require('./build'); +const {buildConfig} = require('./config'); + +const config = { + options: { + help: {type: 'boolean'}, + }, +}; + +function clean() { + const { + values: {help}, + } = parseArgs(config); + + if (help) { + console.log(` + Usage: node ./scripts/build/clean.js + + Clean build directories for all packages defined in ./scripts/build/config.js. + `); + process.exitCode = 0; + return; + } + + for (const packageName of Object.keys(buildConfig.packages)) { + fs.rmSync(path.join(PACKAGES_DIR, packageName, BUILD_DIR), { + force: true, + recursive: true, + }); + } + + process.exitCode = 0; +} + +if (require.main === module) { + clean(); +} diff --git a/scripts/build/config.js b/scripts/build/config.js new file mode 100644 index 00000000000..994f785db8e --- /dev/null +++ b/scripts/build/config.js @@ -0,0 +1,71 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + * @format + * @oncall react_native + */ + +/*:: +import type {BabelCoreOptions} from '@babel/core'; + +export type BuildOptions = $ReadOnly<{ + target: 'node', +}>; + +export type BuildConfig = $ReadOnly<{ + packages: $ReadOnly<{[packageName: string]: BuildOptions}>, +}>; +*/ + +const TARGET_NODE_VERSION = '18'; + +const buildConfig /*: BuildConfig */ = { + // The packages to include for build and their build options + packages: { + 'dev-middleware': {target: 'node'}, + }, +}; + +function getBabelConfig( + packageName /*: $Keys */, +) /*: BabelCoreOptions */ { + const {target} = buildConfig.packages[packageName]; + + switch (target) { + case 'node': + return { + presets: [ + '@babel/preset-flow', + [ + '@babel/preset-env', + { + targets: { + node: TARGET_NODE_VERSION, + }, + }, + ], + ], + plugins: [ + [ + 'transform-define', + { + 'process.env.BUILD_EXCLUDE_BABEL_REGISTER': true, + }, + ], + [ + 'minify-dead-code-elimination', + {keepFnName: true, keepFnArgs: true, keepClassName: true}, + ], + ], + }; + } +} + +module.exports = { + buildConfig, + getBabelConfig, +}; diff --git a/yarn.lock b/yarn.lock index 6642cd54c2f..ac5d663236d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -305,9 +305,9 @@ type-fest "3.11.1" "@babel/cli@^7.20.0": - version "7.21.5" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.21.5.tgz#a685a5b50b785f2edfbf6e042c1265c653547d9d" - integrity sha512-TOKytQ9uQW9c4np8F+P7ZfPINy5Kv+pizDIUwSVH8X5zHgYHV4AA8HE5LA450xXeu4jEfmUckTYvv1I4S26M/g== + version "7.22.6" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.22.6.tgz#63f5be2a0abd587ccfbdc93424fa85f43142cc53" + integrity sha512-Be3/RfEDmkMRGT1+ru5nTkfcvWz5jDOYg1V9rXqTz2u9Qt96O1ryboGvxVBp7wOnYWDB8DNHIWb6DThrpudfOw== dependencies: "@jridgewell/trace-mapping" "^0.3.17" commander "^4.0.1" @@ -3563,7 +3563,7 @@ ansi-styles@^6.1.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== -anymatch@^3.0.3, anymatch@~3.1.2: +anymatch@^3.0.3: version "3.1.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== @@ -3571,6 +3571,14 @@ anymatch@^3.0.3, anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + appdirsjs@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/appdirsjs/-/appdirsjs-1.2.4.tgz#3ab582acc9fdfaaa0c1f81b3a25422ad4d95f9d4" @@ -4073,6 +4081,21 @@ babel-core@^7.0.0-bridge.0: resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== +babel-helper-evaluate-path@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz#a62fa9c4e64ff7ea5cea9353174ef023a900a67c" + integrity sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA== + +babel-helper-mark-eval-scopes@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz#d244a3bef9844872603ffb46e22ce8acdf551562" + integrity sha512-+d/mXPP33bhgHkdVOiPkmYoeXJ+rXRWi7OdhwpyseIqOS8CmzHQXHUp/+/Qr8baXsT0kjGpMHHofHs6C3cskdA== + +babel-helper-remove-or-void@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz#a4f03b40077a0ffe88e45d07010dee241ff5ae60" + integrity sha512-eYNceYtcGKpifHDir62gHJadVXdg9fAhuZEXiRQnJJ4Yi4oUTpqpNY//1pM4nVyjjDMPYaC2xSf0I+9IqVzwdA== + babel-jest@^29.2.1: version "29.2.1" resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.2.1.tgz#213c47e28072de11bdb98c9d29b89f2ab99664f1" @@ -4107,6 +4130,16 @@ babel-plugin-jest-hoist@^29.2.0: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" +babel-plugin-minify-dead-code-elimination@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.2.tgz#f386ceec77a80cc4e76022a04c21b7d68e0aa5eb" + integrity sha512-krq9Lwi0QIzyAlcNBXTL4usqUvevB4BzktdEsb8srcXC1AaYqRJiAQw6vdKdJSaXbz6snBvziGr6ch/aoRCfpA== + dependencies: + babel-helper-evaluate-path "^0.5.0" + babel-helper-mark-eval-scopes "^0.4.3" + babel-helper-remove-or-void "^0.4.3" + lodash "^4.17.11" + babel-plugin-polyfill-corejs2@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" @@ -4141,6 +4174,14 @@ babel-plugin-syntax-trailing-function-commas@^7.0.0-beta.0: resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz#aa213c1435e2bffeb6fca842287ef534ad05d5cf" integrity sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ== +babel-plugin-transform-define@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/babel-plugin-transform-define/-/babel-plugin-transform-define-2.1.2.tgz#d23e692cf14c68af90ca81500cd953f84678ca28" + integrity sha512-kiIiwIRiOVvSChdXg0efxsP+I7e7kLQUoZDHY+gbDIq7r4FcvXlYClWbbDzoeTGxDkiuivQvbQ4uOEaTIGHoKw== + dependencies: + lodash "^4.17.11" + traverse "0.6.6" + babel-plugin-transform-flow-enums@^0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz#d1d0cc9bdc799c850ca110d0ddc9f21b9ec3ef25" @@ -4849,7 +4890,12 @@ content-type@~1.0.4, content-type@~1.0.5: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== -convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: +convert-source-map@^1.1.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +convert-source-map@^1.4.0, convert-source-map@^1.6.0, convert-source-map@^1.7.0: version "1.8.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== @@ -10707,6 +10753,11 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +traverse@0.6.6: + version "0.6.6" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.6.6.tgz#cbdf560fd7b9af632502fed40f918c157ea97137" + integrity sha512-kdf4JKs8lbARxWdp7RKdNzoJBhGUcIalSYibuGyHJbmk40pOysQ0+QPvlkCOICOivDWU2IJo2rkrxyTK2AH4fw== + triple-beam@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9"