diff --git a/__e2e__/init.test.ts b/__e2e__/init.test.ts index bf295c651..8d8564e13 100644 --- a/__e2e__/init.test.ts +++ b/__e2e__/init.test.ts @@ -22,13 +22,10 @@ function createCustomTemplateFiles() { const customTemplateCopiedFiles = [ '.git', - '.yarn', - '.yarnrc.yml', // .yarnrc.yml for Yarn versions >= 2.0.0 'dir', 'file', - 'node_modules', + 'package-lock.json', 'package.json', - 'yarn.lock', ]; beforeEach(() => { @@ -150,50 +147,13 @@ test('init skips installation of dependencies with --skip-install', () => { expect(dirFiles).toEqual( customTemplateCopiedFiles.filter( - (file) => !['node_modules', 'yarn.lock'].includes(file), + (file) => !['node_modules', 'package-lock.json'].includes(file), ), ); }); -test('init uses npm as the package manager with --npm', () => { - createCustomTemplateFiles(); - - const {stdout} = runCLI(DIR, [ - 'init', - '--template', - templatePath, - PROJECT_NAME, - '--npm', - '--install-pods', - 'false', - ]); - - expect(stdout).toContain('Run instructions'); - - // make sure we don't leave garbage - expect(fs.readdirSync(DIR)).toContain('custom'); - - const initDirPath = path.join(DIR, PROJECT_NAME); - - // Remove yarn specific files and node_modules - const filteredFiles = customTemplateCopiedFiles.filter( - (file) => - !['yarn.lock', 'node_modules', '.yarnrc.yml', '.yarn'].includes(file), - ); - - // Add package-lock.json - const customTemplateCopiedFilesForNpm = [ - ...filteredFiles, - 'package-lock.json', - ]; - - // Assert for existence - customTemplateCopiedFilesForNpm.forEach((file) => { - expect(fs.existsSync(path.join(initDirPath, file))).toBe(true); - }); -}); - -test('init --platform-name should work for out of tree platform', () => { +// react-native-macos stopped shipping `template.config.js` for 0.75, so this test is disabled. in future releases we should re-enable once `template.config.js` will be there again. +test.skip('init --platform-name should work for out of tree platform', () => { createCustomTemplateFiles(); const outOfTreePlatformName = 'react-native-macos'; diff --git a/docs/commands.md b/docs/commands.md index e3574d59e..38baf13de 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -100,13 +100,6 @@ Skip dependencies installation Determine if CocoaPods should be installed when initializing a project. If set to `true` it will install pods, if set to `false`, it will skip the step entirely. If not used, prompt will be displayed -#### `--npm` - -> [!WARNING] -> `--npm` is deprecated and will be removed in the future. Please use `--pm npm` instead. - -Force use of npm during initialization - #### `--pm ` Use specific package manager to initialize the project. Available options: `yarn`, `npm`, `bun`. Default: `yarn` diff --git a/docs/init.md b/docs/init.md index 59a936366..74cb9a7ec 100644 --- a/docs/init.md +++ b/docs/init.md @@ -6,7 +6,7 @@ There are couple of ways to initialize new React Native projects. npx react-native@latest init ProjectName ``` -> Note: If you have both `yarn` and `npm` installed on your machine, React Native CLI will always try to use `yarn`, so even if you use `npx` utility, only `react-native` executable will be installed using `npm` and the rest of the work will be delegated to `yarn`. You can force usage of `npm` adding `--pm npm` flag to the command. +> Note: If you have both `yarn` and `npm` installed on your machine, React Native CLI will always try to use `npm`. You can force usage of `yarn` by adding `--pm yarn` flag to the command. > Note: for Yarn users, `yarn dlx` command similar to `npx` will be featured in Yarn 2.0: so we'll be able to use it in a similar fashion. @@ -31,7 +31,7 @@ npx react-native@${VERSION} init ProjectName It is possible to initialize a new application with a custom template with a `--template` option. -It should point to a valid package that can be installed with `yarn` or `npm` (if you're using `--npm` option). +It should point to a valid package that can be installed with `npm` or `yarn` (if you're using `--pm yarn` option). The most common options are: @@ -49,10 +49,10 @@ npx react-native@latest init ProjectName --template ${TEMPLATE_NAME} npx react-native@${VERSION} init ProjectName --template ${TEMPLATE_NAME} ``` -You can force usage of `npm` if you have both `yarn` and `npm` installed on your machine: +You can force usage of `yarn` if you have both `yarn` and `npm` installed on your machine: ```sh -npx react-native@latest init ProjectName --pm npm +npx react-native@latest init ProjectName --pm yarn ``` ## Creating custom template diff --git a/lerna.json b/lerna.json index 0d9497b38..c570c71c0 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "14.0.1", + "version": "15.0.0-alpha.2", "npmClient": "yarn", "exact": true, "$schema": "node_modules/lerna/schemas/lerna-schema.json" diff --git a/package.json b/package.json index 08f52d28d..8edf47f5c 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,6 @@ "eslint-plugin-import": "^2.25.3", "execa": "^5.0.0", "fast-glob": "^3.3.2", - "glob": "^7.1.3", "husky": "^8.0.2", "jest": "^26.6.2", "jest-circus": "^26.6.2", diff --git a/packages/cli-clean/package.json b/packages/cli-clean/package.json index e5809663e..eea143677 100644 --- a/packages/cli-clean/package.json +++ b/packages/cli-clean/package.json @@ -1,6 +1,6 @@ { "name": "@react-native-community/cli-clean", - "version": "14.0.1", + "version": "15.0.0-alpha.2", "license": "MIT", "main": "build/index.js", "publishConfig": { @@ -8,7 +8,7 @@ }, "types": "build/index.d.ts", "dependencies": { - "@react-native-community/cli-tools": "14.0.1", + "@react-native-community/cli-tools": "15.0.0-alpha.2", "chalk": "^4.1.2", "execa": "^5.0.0", "fast-glob": "^3.3.2" @@ -19,7 +19,7 @@ "!*.map" ], "devDependencies": { - "@react-native-community/cli-types": "14.0.1", + "@react-native-community/cli-types": "15.0.0-alpha.2", "@types/prompts": "^2.4.4" }, "homepage": "https://github.com/react-native-community/cli/tree/main/packages/cli-clean", diff --git a/packages/cli-config/package.json b/packages/cli-config/package.json index 90362907f..8b476916d 100644 --- a/packages/cli-config/package.json +++ b/packages/cli-config/package.json @@ -1,6 +1,6 @@ { "name": "@react-native-community/cli-config", - "version": "14.0.1", + "version": "15.0.0-alpha.2", "license": "MIT", "main": "build/index.js", "publishConfig": { @@ -8,7 +8,7 @@ }, "types": "build/index.d.ts", "dependencies": { - "@react-native-community/cli-tools": "14.0.1", + "@react-native-community/cli-tools": "15.0.0-alpha.2", "chalk": "^4.1.2", "cosmiconfig": "^9.0.0", "deepmerge": "^4.3.0", @@ -21,7 +21,7 @@ "!*.map" ], "devDependencies": { - "@react-native-community/cli-types": "14.0.1", + "@react-native-community/cli-types": "15.0.0-alpha.2", "@types/cosmiconfig": "^5.0.3" }, "homepage": "https://github.com/react-native-community/cli/tree/main/packages/cli-config", diff --git a/packages/cli-config/src/__tests__/findDependencies-test.ts b/packages/cli-config/src/__tests__/findDependencies-test.ts index 9f43f4437..84e3fafec 100644 --- a/packages/cli-config/src/__tests__/findDependencies-test.ts +++ b/packages/cli-config/src/__tests__/findDependencies-test.ts @@ -1,23 +1,35 @@ import findDependencies from '../findDependencies'; import {cleanup, writeFiles, getTempDirectory} from '../../../../jest/helpers'; -beforeEach(async () => { - cleanup(DIR); - jest.resetModules(); -}); +describe('findDependencies', () => { + const DIR = getTempDirectory('find_dependencies_test'); + + beforeEach(() => { + cleanup(DIR); + jest.resetModules(); + }); -afterEach(() => cleanup(DIR)); + afterEach(() => cleanup(DIR)); -const DIR = getTempDirectory('find_dependencies_test'); + test('returns packages from dependencies, peer and dev dependencies', () => { + writeFiles(DIR, { + 'package.json': JSON.stringify({ + dependencies: {'rnpm-plugin-test': '*'}, + peerDependencies: {'rnpm-plugin-test-2': '*'}, + devDependencies: {'rnpm-plugin-test-3': '*'}, + }), + }); + expect(findDependencies(DIR)).toHaveLength(3); + }); -test('returns plugins from both dependencies and dev dependencies', () => { - writeFiles(DIR, { - 'package.json': ` - { - "dependencies": {"rnpm-plugin-test": "*"}, - "devDependencies": {"rnpm-plugin-test-2": "*"} - } - `, + test('dedupes dependencies', () => { + writeFiles(DIR, { + 'package.json': JSON.stringify({ + dependencies: {'rnpm-plugin-test': '*'}, + peerDependencies: {'rnpm-plugin-test-2': '*'}, + devDependencies: {'rnpm-plugin-test-2': '*'}, + }), + }); + expect(findDependencies(DIR)).toHaveLength(2); }); - expect(findDependencies(DIR)).toHaveLength(2); }); diff --git a/packages/cli-config/src/findDependencies.ts b/packages/cli-config/src/findDependencies.ts index cb0f5ecd0..eecf22b22 100644 --- a/packages/cli-config/src/findDependencies.ts +++ b/packages/cli-config/src/findDependencies.ts @@ -8,17 +8,17 @@ export default function findDependencies(root: string): Array { let pjson; try { - pjson = JSON.parse( - fs.readFileSync(path.join(root, 'package.json'), 'utf8'), - ); + const content = fs.readFileSync(path.join(root, 'package.json'), 'utf8'); + pjson = JSON.parse(content); } catch (e) { return []; } - const deps = [ + const deps = new Set([ ...Object.keys(pjson.dependencies || {}), + ...Object.keys(pjson.peerDependencies || {}), ...Object.keys(pjson.devDependencies || {}), - ]; + ]); - return deps; + return Array.from(deps); } diff --git a/packages/cli-debugger-ui/package.json b/packages/cli-debugger-ui/package.json index 73e299b19..d67632dac 100644 --- a/packages/cli-debugger-ui/package.json +++ b/packages/cli-debugger-ui/package.json @@ -1,6 +1,6 @@ { "name": "@react-native-community/cli-debugger-ui", - "version": "14.0.1", + "version": "15.0.0-alpha.2", "license": "MIT", "main": "build/middleware/index.js", "targets": { diff --git a/packages/cli-doctor/package.json b/packages/cli-doctor/package.json index 83a6f8092..dcc966dae 100644 --- a/packages/cli-doctor/package.json +++ b/packages/cli-doctor/package.json @@ -1,6 +1,6 @@ { "name": "@react-native-community/cli-doctor", - "version": "14.0.1", + "version": "15.0.0-alpha.2", "license": "MIT", "main": "build/index.js", "publishConfig": { @@ -8,11 +8,11 @@ }, "types": "build/index.d.ts", "dependencies": { - "@react-native-community/cli-config": "14.0.1", - "@react-native-community/cli-platform-android": "14.0.1", - "@react-native-community/cli-platform-apple": "14.0.1", - "@react-native-community/cli-platform-ios": "14.0.1", - "@react-native-community/cli-tools": "14.0.1", + "@react-native-community/cli-config": "15.0.0-alpha.2", + "@react-native-community/cli-platform-android": "15.0.0-alpha.2", + "@react-native-community/cli-platform-apple": "15.0.0-alpha.2", + "@react-native-community/cli-platform-ios": "15.0.0-alpha.2", + "@react-native-community/cli-tools": "15.0.0-alpha.2", "chalk": "^4.1.2", "command-exists": "^1.2.8", "deepmerge": "^4.3.0", @@ -31,7 +31,7 @@ "!*.map" ], "devDependencies": { - "@react-native-community/cli-types": "14.0.1", + "@react-native-community/cli-types": "15.0.0-alpha.2", "@types/command-exists": "^1.2.0", "@types/envinfo": "^7.8.4", "@types/ip": "^1.1.0", diff --git a/packages/cli-link-assets/package.json b/packages/cli-link-assets/package.json index fb59978b7..af70046fd 100644 --- a/packages/cli-link-assets/package.json +++ b/packages/cli-link-assets/package.json @@ -1,6 +1,6 @@ { "name": "@react-native-community/cli-link-assets", - "version": "14.0.1", + "version": "15.0.0-alpha.2", "license": "MIT", "main": "build/index.js", "publishConfig": { @@ -8,12 +8,13 @@ }, "types": "build/index.d.ts", "dependencies": { - "@react-native-community/cli-config": "14.0.1", - "@react-native-community/cli-platform-android": "14.0.1", - "@react-native-community/cli-platform-apple": "14.0.1", - "@react-native-community/cli-platform-ios": "14.0.1", - "@react-native-community/cli-tools": "14.0.1", + "@react-native-community/cli-config": "15.0.0-alpha.2", + "@react-native-community/cli-platform-android": "15.0.0-alpha.2", + "@react-native-community/cli-platform-apple": "15.0.0-alpha.2", + "@react-native-community/cli-platform-ios": "15.0.0-alpha.2", + "@react-native-community/cli-tools": "15.0.0-alpha.2", "chalk": "^4.1.2", + "fast-glob": "^3.3.2", "fast-xml-parser": "^4.4.1", "opentype.js": "^1.3.4", "plist": "^3.1.0", @@ -25,7 +26,7 @@ "!*.map" ], "devDependencies": { - "@react-native-community/cli-types": "14.0.1", + "@react-native-community/cli-types": "15.0.0-alpha.2", "@types/plist": "^3.0.5", "type-fest": "^4.10.2" }, diff --git a/packages/cli-link-assets/src/tools/helpers/font/androidFontAssetHelpers.ts b/packages/cli-link-assets/src/tools/helpers/font/androidFontAssetHelpers.ts index 66546c903..1862effcb 100644 --- a/packages/cli-link-assets/src/tools/helpers/font/androidFontAssetHelpers.ts +++ b/packages/cli-link-assets/src/tools/helpers/font/androidFontAssetHelpers.ts @@ -2,7 +2,7 @@ import {isProjectUsingKotlin} from '@react-native-community/cli-platform-android import {CLIError, logger} from '@react-native-community/cli-tools'; import {XMLBuilder, XMLParser} from 'fast-xml-parser'; import fs from 'fs-extra'; -import {sync as globSync} from 'glob'; +import glob from 'fast-glob'; import OpenType from 'opentype.js'; import path from 'path'; @@ -77,7 +77,7 @@ function convertToAndroidResourceName(str: string) { function getProjectFilePath(rootPath: string, name: string) { const isUsingKotlin = isProjectUsingKotlin(rootPath); const ext = isUsingKotlin ? 'kt' : 'java'; - const filePath = globSync( + const filePath = glob.sync( path.join(rootPath, `app/src/main/java/**/${name}.${ext}`), )[0]; return filePath; diff --git a/packages/cli-platform-android/package.json b/packages/cli-platform-android/package.json index b51ba0438..7337c48fa 100644 --- a/packages/cli-platform-android/package.json +++ b/packages/cli-platform-android/package.json @@ -1,13 +1,13 @@ { "name": "@react-native-community/cli-platform-android", - "version": "14.0.1", + "version": "15.0.0-alpha.2", "license": "MIT", "main": "build/index.js", "publishConfig": { "access": "public" }, "dependencies": { - "@react-native-community/cli-tools": "14.0.1", + "@react-native-community/cli-tools": "15.0.0-alpha.2", "chalk": "^4.1.2", "execa": "^5.0.0", "fast-glob": "^3.3.2", @@ -21,7 +21,7 @@ "native_modules.gradle" ], "devDependencies": { - "@react-native-community/cli-types": "14.0.1", + "@react-native-community/cli-types": "15.0.0-alpha.2", "@types/fs-extra": "^8.1.0" }, "homepage": "https://github.com/react-native-community/cli/tree/main/packages/cli-platform-android", diff --git a/packages/cli-platform-android/src/config/findPackageClassName.ts b/packages/cli-platform-android/src/config/findPackageClassName.ts index 39cdd7ff0..5903efa62 100644 --- a/packages/cli-platform-android/src/config/findPackageClassName.ts +++ b/packages/cli-platform-android/src/config/findPackageClassName.ts @@ -32,11 +32,29 @@ export default function getPackageClassName(folder: string) { let files = getMainActivityFiles(folder); let packages = getClassNameMatches(files, folder); - if (!packages.length) { - files = getMainActivityFiles(folder, false); - packages = getClassNameMatches(files, folder); + if (packages && packages.length > 0 && Array.isArray(packages[0])) { + return packages[0][1]; } + /* + When module contains `expo-module.config.json` we return null + because expo modules follow other practices and don't implement + ReactPackage/TurboReactPackage directly, so it doesn't make sense + to scan and read hundreds of files to get package class name. + + Exception is `expo` package itself which contains `expo-module.config.json` + and implements `ReactPackage/TurboReactPackage`. + + Following logic is done due to performance optimization. + */ + + if (fs.existsSync(path.join(folder, '..', 'expo-module.config.json'))) { + return null; + } + + files = getMainActivityFiles(folder, false); + packages = getClassNameMatches(files, folder); + // @ts-ignore return packages.length ? packages[0][1] : null; } diff --git a/packages/cli-platform-apple/package.json b/packages/cli-platform-apple/package.json index 3c919d1d0..c23afecae 100644 --- a/packages/cli-platform-apple/package.json +++ b/packages/cli-platform-apple/package.json @@ -1,13 +1,13 @@ { "name": "@react-native-community/cli-platform-apple", - "version": "14.0.1", + "version": "15.0.0-alpha.2", "license": "MIT", "main": "build/index.js", "publishConfig": { "access": "public" }, "dependencies": { - "@react-native-community/cli-tools": "14.0.1", + "@react-native-community/cli-tools": "15.0.0-alpha.2", "chalk": "^4.1.2", "execa": "^5.0.0", "fast-glob": "^3.3.2", @@ -15,7 +15,7 @@ "ora": "^5.4.1" }, "devDependencies": { - "@react-native-community/cli-types": "14.0.1", + "@react-native-community/cli-types": "15.0.0-alpha.2", "@types/lodash": "^4.14.149", "hasbin": "^1.2.3" }, diff --git a/packages/cli-platform-apple/src/commands/runCommand/createRun.ts b/packages/cli-platform-apple/src/commands/runCommand/createRun.ts index 486b9ebf5..692334abb 100644 --- a/packages/cli-platform-apple/src/commands/runCommand/createRun.ts +++ b/packages/cli-platform-apple/src/commands/runCommand/createRun.ts @@ -149,7 +149,7 @@ const createRun = return; } - const devices = await listDevices(sdkNames); + let devices = await listDevices(sdkNames); if (devices.length === 0) { return logger.error( @@ -157,6 +157,24 @@ const createRun = ); } + const packageJson = getPackageJson(ctx.root); + + const preferredDevice = cacheManager.get( + packageJson.name, + 'lastUsedIOSDeviceId', + ); + + if (preferredDevice) { + const preferredDeviceIndex = devices.findIndex( + ({udid}) => udid === preferredDevice, + ); + + if (preferredDeviceIndex > -1) { + const [device] = devices.splice(preferredDeviceIndex, 1); + devices.unshift(device); + } + } + const fallbackSimulator = platformName === 'ios' ? getFallbackSimulator(args) : devices[0]; @@ -169,16 +187,7 @@ const createRun = ); } - const packageJson = getPackageJson(ctx.root); - const preferredDevice = cacheManager.get( - packageJson.name, - 'lastUsedIOSDeviceId', - ); - - const selectedDevice = await promptForDeviceSelection( - devices, - preferredDevice, - ); + const selectedDevice = await promptForDeviceSelection(devices); if (!selectedDevice) { throw new CLIError( diff --git a/packages/cli-platform-apple/src/tools/__tests__/getInfo.test.ts b/packages/cli-platform-apple/src/tools/__tests__/getInfo.test.ts new file mode 100644 index 000000000..8dbde0ff0 --- /dev/null +++ b/packages/cli-platform-apple/src/tools/__tests__/getInfo.test.ts @@ -0,0 +1,44 @@ +import type {IOSProjectInfo} from '@react-native-community/cli-types'; + +import execa from 'execa'; +import fs from 'fs'; +import {getInfo} from '../getInfo'; + +jest.mock('execa', () => ({ + sync: jest.fn(), +})); + +jest.mock('fs', () => ({ + readFileSync: jest.fn(), +})); + +describe('getInfo', () => { + it('handles non-project / workspace locations in a ', () => { + const name = `YourProjectName`; + (fs.readFileSync as jest.Mock) + .mockReturnValueOnce(` + + + + + + + +`); + (execa.sync as jest.Mock).mockReturnValue({stdout: '{}'}); + getInfo({isWorkspace: true, name} as IOSProjectInfo, 'some/path'); + + const execaSync = execa.sync as jest.Mock; + // Should not call on Pods or the other misc groups + expect(execaSync.mock.calls).toEqual([ + [ + 'xcodebuild', + ['-list', '-json', '-project', `some/path/${name}.xcodeproj`], + ], + ]); + }); +}); diff --git a/packages/cli-platform-apple/src/tools/getInfo.ts b/packages/cli-platform-apple/src/tools/getInfo.ts index a4de21ed8..7f45855d7 100644 --- a/packages/cli-platform-apple/src/tools/getInfo.ts +++ b/packages/cli-platform-apple/src/tools/getInfo.ts @@ -59,6 +59,10 @@ export function getInfo( return refs.reduce((result, ref) => { const location = ref['@_location']; + if (!location.endsWith('.xcodeproj')) { + return result; + } + // Ignore the project generated by CocoaPods if (location.endsWith('/Pods.xcodeproj')) { return result; diff --git a/packages/cli-platform-apple/src/tools/prompts.ts b/packages/cli-platform-apple/src/tools/prompts.ts index bfe6f53d9..b0dbf477c 100644 --- a/packages/cli-platform-apple/src/tools/prompts.ts +++ b/packages/cli-platform-apple/src/tools/prompts.ts @@ -40,25 +40,12 @@ export async function promptForConfigurationSelection( export async function promptForDeviceSelection( devices: Device[], - lastUsedIOSDeviceId?: string, ): Promise { - const sortedDevices = [...devices]; - const devicesIds = sortedDevices.map(({udid}) => udid); - - if (lastUsedIOSDeviceId) { - const preferredDeviceIndex = devicesIds.indexOf(lastUsedIOSDeviceId); - - if (preferredDeviceIndex > -1) { - const [preferredDevice] = sortedDevices.splice(preferredDeviceIndex, 1); - sortedDevices.unshift(preferredDevice); - } - } - const {device} = await prompt({ type: 'select', name: 'device', message: 'Select the device you want to use', - choices: sortedDevices + choices: devices .filter(({type}) => type === 'device' || type === 'simulator') .map((d) => { const availability = diff --git a/packages/cli-platform-ios/package.json b/packages/cli-platform-ios/package.json index 4dedc9d01..999caf87a 100644 --- a/packages/cli-platform-ios/package.json +++ b/packages/cli-platform-ios/package.json @@ -1,13 +1,13 @@ { "name": "@react-native-community/cli-platform-ios", - "version": "14.0.1", + "version": "15.0.0-alpha.2", "license": "MIT", "main": "build/index.js", "publishConfig": { "access": "public" }, "dependencies": { - "@react-native-community/cli-platform-apple": "14.0.1" + "@react-native-community/cli-platform-apple": "15.0.0-alpha.2" }, "files": [ "build", diff --git a/packages/cli-server-api/package.json b/packages/cli-server-api/package.json index e6f187e65..8d6e64180 100644 --- a/packages/cli-server-api/package.json +++ b/packages/cli-server-api/package.json @@ -1,14 +1,14 @@ { "name": "@react-native-community/cli-server-api", - "version": "14.0.1", + "version": "15.0.0-alpha.2", "license": "MIT", "main": "build/index.js", "publishConfig": { "access": "public" }, "dependencies": { - "@react-native-community/cli-debugger-ui": "14.0.1", - "@react-native-community/cli-tools": "14.0.1", + "@react-native-community/cli-debugger-ui": "15.0.0-alpha.2", + "@react-native-community/cli-tools": "15.0.0-alpha.2", "compression": "^1.7.1", "connect": "^3.6.5", "errorhandler": "^1.5.1", diff --git a/packages/cli-tools/package.json b/packages/cli-tools/package.json index 380d002ee..d6b615bed 100644 --- a/packages/cli-tools/package.json +++ b/packages/cli-tools/package.json @@ -1,6 +1,6 @@ { "name": "@react-native-community/cli-tools", - "version": "14.0.1", + "version": "15.0.0-alpha.2", "license": "MIT", "main": "build/index.js", "publishConfig": { @@ -14,15 +14,17 @@ "mime": "^2.4.1", "open": "^6.2.0", "ora": "^5.4.1", + "prompts": "^2.4.2", "semver": "^7.5.2", "shell-quote": "^1.7.3", "sudo-prompt": "^9.0.0" }, "devDependencies": { - "@react-native-community/cli-types": "14.0.1", + "@react-native-community/cli-types": "15.0.0-alpha.2", "@types/lodash": "^4.14.149", "@types/mime": "^2.0.1", "@types/node": "^18.0.0", + "@types/prompts": "^2.4.4", "@types/shell-quote": "^1.7.1" }, "files": [ diff --git a/packages/cli-types/package.json b/packages/cli-types/package.json index 4680e26a9..b2fd33761 100644 --- a/packages/cli-types/package.json +++ b/packages/cli-types/package.json @@ -1,6 +1,6 @@ { "name": "@react-native-community/cli-types", - "version": "14.0.1", + "version": "15.0.0-alpha.2", "main": "build", "publishConfig": { "access": "public" diff --git a/packages/cli/package.json b/packages/cli/package.json index 24d15f165..9e1de611f 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@react-native-community/cli", - "version": "14.0.1", + "version": "15.0.0-alpha.2", "description": "React Native CLI", "license": "MIT", "main": "build/index.js", @@ -24,13 +24,13 @@ "testEnvironment": "node" }, "dependencies": { - "@react-native-community/cli-clean": "14.0.1", - "@react-native-community/cli-config": "14.0.1", - "@react-native-community/cli-debugger-ui": "14.0.1", - "@react-native-community/cli-doctor": "14.0.1", - "@react-native-community/cli-server-api": "14.0.1", - "@react-native-community/cli-tools": "14.0.1", - "@react-native-community/cli-types": "14.0.1", + "@react-native-community/cli-clean": "15.0.0-alpha.2", + "@react-native-community/cli-config": "15.0.0-alpha.2", + "@react-native-community/cli-debugger-ui": "15.0.0-alpha.2", + "@react-native-community/cli-doctor": "15.0.0-alpha.2", + "@react-native-community/cli-server-api": "15.0.0-alpha.2", + "@react-native-community/cli-tools": "15.0.0-alpha.2", + "@react-native-community/cli-types": "15.0.0-alpha.2", "chalk": "^4.1.2", "commander": "^9.4.1", "deepmerge": "^4.3.0", diff --git a/packages/cli/src/commands/init/__tests__/version.test.ts b/packages/cli/src/commands/init/__tests__/version.test.ts new file mode 100644 index 000000000..09a507305 --- /dev/null +++ b/packages/cli/src/commands/init/__tests__/version.test.ts @@ -0,0 +1,41 @@ +import {createTemplateUri} from '../version'; +import type {Options} from '../types'; + +const mockGetTemplateVersion = jest.fn(); + +jest.mock('../../../tools/npm', () => ({ + __esModule: true, + getTemplateVersion: (...args) => mockGetTemplateVersion(...args), +})); + +const nullOptions = {} as Options; + +describe('createTemplateUri', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + describe('for < 0.75', () => { + it('use react-native for the template', async () => { + expect(await createTemplateUri(nullOptions, '0.74.1')).toEqual( + 'react-native@0.74.1', + ); + }); + it('looks DOES NOT use npm registry data to find the template', () => { + expect(mockGetTemplateVersion).not.toHaveBeenCalled(); + }); + }); + describe('for >= 0.75', () => { + it('use @react-native-community/template for the template', async () => { + // Imagine for React Native 0.75.1, template 1.2.3 was prepared for this version + mockGetTemplateVersion.mockReturnValue('1.2.3'); + expect(await createTemplateUri(nullOptions, '0.75.1')).toEqual( + '@react-native-community/template@1.2.3', + ); + }); + + it('looks at uses npm registry data to find the matching @react-native-community/template', async () => { + await createTemplateUri(nullOptions, '0.75.0'); + expect(mockGetTemplateVersion).toHaveBeenCalledWith('0.75.0'); + }); + }); +}); diff --git a/packages/cli/src/commands/init/constants.ts b/packages/cli/src/commands/init/constants.ts new file mode 100644 index 000000000..db0df6677 --- /dev/null +++ b/packages/cli/src/commands/init/constants.ts @@ -0,0 +1,7 @@ +export const TEMPLATE_PACKAGE_COMMUNITY = '@react-native-community/template'; +export const TEMPLATE_PACKAGE_LEGACY = 'react-native'; +export const TEMPLATE_PACKAGE_LEGACY_TYPESCRIPT = + 'react-native-template-typescript'; + +// This version moved from inlining the template to using @react-native-community/template +export const TEMPLATE_COMMUNITY_REACT_NATIVE_VERSION = '0.75.0'; diff --git a/packages/cli/src/commands/init/index.ts b/packages/cli/src/commands/init/index.ts index 2c36fb0d5..f89397840 100644 --- a/packages/cli/src/commands/init/index.ts +++ b/packages/cli/src/commands/init/index.ts @@ -14,16 +14,12 @@ export default { { name: '--template ', description: - 'Uses a custom template. Valid arguments are the ones supported by `yarn add [package]` or `npm install [package]`, if you are using `--npm` option', - }, - { - name: '--npm', - description: 'Forces using npm for initialization', + 'Uses a custom template. Valid arguments are the ones supported by `npm install [package]` or `yarn add [package]`, if you are using `--pm yarn` option', }, { name: '--pm ', description: - 'Use specific package manager to initialize the project. Available options: `yarn`, `npm`, `bun`. Default: `yarn`', + 'Use specific package manager to initialize the project. Available options: `yarn`, `npm`, `bun`. Default: `npm`', }, { name: '--directory ', diff --git a/packages/cli/src/commands/init/init.ts b/packages/cli/src/commands/init/init.ts index f4da03370..35e512057 100644 --- a/packages/cli/src/commands/init/init.ts +++ b/packages/cli/src/commands/init/init.ts @@ -38,36 +38,16 @@ import { import semver from 'semver'; import {executeCommand} from '../../tools/executeCommand'; import DirectoryAlreadyExistsError from './errors/DirectoryAlreadyExistsError'; +import {createTemplateUri} from './version'; +import {TEMPLATE_COMMUNITY_REACT_NATIVE_VERSION} from './constants'; +import type {Options} from './types'; const DEFAULT_VERSION = 'latest'; -// This version moved from inlining the template to using @react-native-community/template -const TEMPLATE_COMMUNITY_REACT_NATIVE_VERSION = '0.75.0'; -const TEMPLATE_PACKAGE_COMMUNITY = '@react-native-community/template'; -const TEMPLATE_PACKAGE_LEGACY = 'react-native'; -const TEMPLATE_PACKAGE_LEGACY_TYPESCRIPT = 'react-native-template-typescript'; - -type Options = { - template?: string; - npm?: boolean; - pm?: PackageManager.PackageManager; - directory?: string; - displayName?: string; - title?: string; - skipInstall?: boolean; - version: string; - packageName?: string; - installPods?: string | boolean; - platformName?: string; - skipGitInit?: boolean; - replaceDirectory?: string | boolean; - yarnConfigOptions?: Record; -}; interface TemplateOptions { projectName: string; shouldBumpYarnVersion: boolean; templateUri: string; - npm?: boolean; pm?: PackageManager.PackageManager; directory: string; projectTitle?: string; @@ -205,7 +185,6 @@ async function createFromTemplate({ projectName, shouldBumpYarnVersion, templateUri, - npm, pm, directory, projectTitle, @@ -228,16 +207,8 @@ async function createFromTemplate({ packageManager = pm; } else { const userAgentPM = userAgentPackageManager(); - // if possible, use the package manager from the user agent. Otherwise fallback to default (yarn) - packageManager = userAgentPM || 'yarn'; - } - - if (npm) { - logger.warn( - 'Flag --npm is deprecated and will be removed soon. In the future, please use --pm npm instead.', - ); - - packageManager = 'npm'; + // if possible, use the package manager from the user agent. Otherwise fallback to default (npm) + packageManager = userAgentPM || 'npm'; } // if the project with the name already has cache, remove the cache to avoid problems with pods installation @@ -310,43 +281,53 @@ async function createFromTemplate({ if (process.platform === 'darwin') { const installPodsValue = String(installCocoaPods); - if (installPodsValue === 'true') { - didInstallPods = true; - await installPods(loader); - loader.succeed(); - setEmptyHashForCachedDependencies(projectName); - } else if (installPodsValue === 'undefined') { - const {installCocoapods} = await prompt({ - type: 'confirm', - name: 'installCocoapods', - message: `Do you want to install CocoaPods now? ${chalk.reset.dim( - 'Only needed if you run your project in Xcode directly', - )}`, - }); - didInstallPods = installCocoapods; - - if (installCocoapods) { + try { + if (installPodsValue === 'true') { + didInstallPods = true; await installPods(loader); loader.succeed(); setEmptyHashForCachedDependencies(projectName); + } else if (installPodsValue === 'undefined') { + const {installCocoapods} = await prompt({ + type: 'confirm', + name: 'installCocoapods', + message: `Do you want to install CocoaPods now? ${chalk.reset.dim( + 'Only needed if you run your project in Xcode directly', + )}`, + }); + didInstallPods = installCocoapods; + + if (installCocoapods) { + await installPods(loader); + loader.succeed(); + setEmptyHashForCachedDependencies(projectName); + } } + } catch (error) { + logger.error( + `Installing Cocoapods failed. This doesn't affect project initialization and you can safely proceed. However, you will need to install Cocoapods manually when running iOS, follow additional steps in "Run instructions for iOS" section.\n\nError: ${ + (error as Error).message as string + }\n`, + ); } } } else { didInstallPods = false; loader.succeed('Dependencies installation skipped'); } + + fs.removeSync(templateSourceDir); } catch (e) { - loader.fail(); - if (e instanceof Error) { - logger.error( - 'Installing pods failed. This doesn\'t affect project initialization and you can safely proceed. \nHowever, you will need to install pods manually when running iOS, follow additional steps in "Run instructions for iOS" section.\n', - ); - logger.debug(e as any); + logger.log('\n'); + if (e instanceof CLIError) { + logger.error(e.message); + } else if (e instanceof Error) { + logger.error(`An unexpected error occurred: ${e.message}.`); } didInstallPods = false; - } finally { + logger.debug(e as any); fs.removeSync(templateSourceDir); + process.exit(1); } if (process.platform === 'darwin') { @@ -397,63 +378,6 @@ function checkPackageManagerAvailability( return false; } -async function createTemplateUri( - options: Options, - version: string, -): Promise { - if (options.platformName && options.platformName !== 'react-native') { - logger.debug('User has specified an out-of-tree platform, using it'); - return `${options.platformName}@${version}`; - } - - if (options.template === TEMPLATE_PACKAGE_LEGACY_TYPESCRIPT) { - logger.warn( - "Ignoring custom template: 'react-native-template-typescript'. Starting from React Native v0.71 TypeScript is used by default.", - ); - return TEMPLATE_PACKAGE_LEGACY; - } - - if (options.template) { - logger.debug(`Use the user provided --template=${options.template}`); - return options.template; - } - - // 0.75.0-nightly-20240618-5df5ed1a8' -> 0.75.0 - // 0.75.0-rc.1 -> 0.75.0 - const simpleVersion = semver.coerce(version) ?? version; - - // Does the react-native@version package *not* have a template embedded. We know that this applies to - // all version before 0.75. The 1st release candidate is the minimal version that has no template. - const useLegacyTemplate = semver.lt( - simpleVersion, - TEMPLATE_COMMUNITY_REACT_NATIVE_VERSION, - ); - - logger.debug( - `[template]: is '${version} (${simpleVersion})' < '${TEMPLATE_COMMUNITY_REACT_NATIVE_VERSION}' = ` + - (useLegacyTemplate - ? 'yes, look for template in react-native' - : 'no, look for template in @react-native-community/template'), - ); - - if (!useLegacyTemplate) { - if (/nightly/.test(version)) { - logger.debug( - "[template]: you're using a nightly version of react-native", - ); - // Template nightly versions and react-native@nightly versions don't match (template releases at a much - // lower cadence). We have to assume the user is running against the latest nightly by pointing to the tag. - return `${TEMPLATE_PACKAGE_COMMUNITY}@nightly`; - } - return `${TEMPLATE_PACKAGE_COMMUNITY}@${version}`; - } - - logger.debug( - `Using the legacy template because '${TEMPLATE_PACKAGE_LEGACY}' still contains a template folder`, - ); - return `${TEMPLATE_PACKAGE_LEGACY}@${version}`; -} - async function createProject( projectName: string, directory: string, @@ -491,7 +415,6 @@ async function createProject( projectName, shouldBumpYarnVersion, templateUri, - npm: options.npm, pm: options.pm, directory, projectTitle: options.title, diff --git a/packages/cli/src/commands/init/types.ts b/packages/cli/src/commands/init/types.ts new file mode 100644 index 000000000..57ff1e54a --- /dev/null +++ b/packages/cli/src/commands/init/types.ts @@ -0,0 +1,18 @@ +import type {PackageManager} from '../../tools/packageManager'; + +export type Options = { + template?: string; + npm?: boolean; + pm?: PackageManager; + directory?: string; + displayName?: string; + title?: string; + skipInstall?: boolean; + version: string; + packageName?: string; + installPods?: string | boolean; + platformName?: string; + skipGitInit?: boolean; + replaceDirectory?: string | boolean; + yarnConfigOptions?: Record; +}; diff --git a/packages/cli/src/commands/init/version.ts b/packages/cli/src/commands/init/version.ts new file mode 100644 index 000000000..2fb8dfcaf --- /dev/null +++ b/packages/cli/src/commands/init/version.ts @@ -0,0 +1,69 @@ +import {logger} from '@react-native-community/cli-tools'; +import {getTemplateVersion} from '../../tools/npm'; +import semver from 'semver'; + +import type {Options} from './types'; +import { + TEMPLATE_COMMUNITY_REACT_NATIVE_VERSION, + TEMPLATE_PACKAGE_COMMUNITY, + TEMPLATE_PACKAGE_LEGACY, + TEMPLATE_PACKAGE_LEGACY_TYPESCRIPT, +} from './constants'; + +export async function createTemplateUri( + options: Options, + version: string, +): Promise { + if (options.platformName && options.platformName !== 'react-native') { + logger.debug('User has specified an out-of-tree platform, using it'); + return `${options.platformName}@${version}`; + } + + if (options.template === TEMPLATE_PACKAGE_LEGACY_TYPESCRIPT) { + logger.warn( + "Ignoring custom template: 'react-native-template-typescript'. Starting from React Native v0.71 TypeScript is used by default.", + ); + return TEMPLATE_PACKAGE_LEGACY; + } + + if (options.template) { + logger.debug(`Use the user provided --template=${options.template}`); + return options.template; + } + + // 0.75.0-nightly-20240618-5df5ed1a8' -> 0.75.0 + // 0.75.0-rc.1 -> 0.75.0 + const simpleVersion = semver.coerce(version) ?? version; + + // Does the react-native@version package *not* have a template embedded. We know that this applies to + // all version before 0.75. The 1st release candidate is the minimal version that has no template. + const useLegacyTemplate = semver.lt( + simpleVersion, + TEMPLATE_COMMUNITY_REACT_NATIVE_VERSION, + ); + + logger.debug( + `[template]: is '${version} (${simpleVersion})' < '${TEMPLATE_COMMUNITY_REACT_NATIVE_VERSION}' = ` + + (useLegacyTemplate + ? 'yes, look for template in react-native' + : 'no, look for template in @react-native-community/template'), + ); + + if (!useLegacyTemplate) { + if (/nightly/.test(version)) { + logger.debug( + "[template]: you're using a nightly version of react-native", + ); + // Template nightly versions and react-native@nightly versions don't match (template releases at a much + // lower cadence). We have to assume the user is running against the latest nightly by pointing to the tag. + return `${TEMPLATE_PACKAGE_COMMUNITY}@nightly`; + } + const templateVersion = await getTemplateVersion(version); + return `${TEMPLATE_PACKAGE_COMMUNITY}@${templateVersion}`; + } + + logger.debug( + `Using the legacy template because '${TEMPLATE_PACKAGE_LEGACY}' still contains a template folder`, + ); + return `${TEMPLATE_PACKAGE_LEGACY}@${version}`; +} diff --git a/packages/cli/src/tools/__tests__/npm-test.ts b/packages/cli/src/tools/__tests__/npm-test.ts new file mode 100644 index 000000000..c60315d5f --- /dev/null +++ b/packages/cli/src/tools/__tests__/npm-test.ts @@ -0,0 +1,126 @@ +import {getTemplateVersion} from '../npm'; +import assert from 'assert'; + +let ref: any; + +global.fetch = jest.fn(); + +function fetchReturn(json: any): void { + assert(global.fetch != null, 'You forgot to backup global.fetch!'); + // @ts-ignore + global.fetch = jest.fn(() => + Promise.resolve({json: () => Promise.resolve(json)}), + ); +} + +describe('getTemplateVersion', () => { + beforeEach(() => { + ref = global.fetch; + }); + afterEach(() => { + global.fetch = ref; + }); + + it('should order matching versions with the most recent first', async () => { + const VERSION = '0.75.1'; + fetchReturn({ + versions: { + '3.2.1': {scripts: {version: VERSION}}, + '1.0.0': {scripts: {version: '0.75.0'}}, + '1.2.3': {scripts: {version: VERSION}}, + }, + time: { + '3.2.1': '2024-08-15T00:00:00.000Z', + '1.0.0': '2024-08-15T10:10:10.000Z', + '1.2.3': '2024-08-16T00:00:00.000Z', // Last published version + }, + }); + + expect(await getTemplateVersion(VERSION)).toEqual('1.2.3'); + }); + + it('should matching latest MAJOR.MINOR if MAJOR.MINOR.PATCH has no match', async () => { + fetchReturn({ + versions: { + '3.2.1': {scripts: {version: '0.75.1'}}, + '3.2.2': {scripts: {version: '0.75.2'}}, + }, + time: { + '3.2.1': '2024-08-15T00:00:00.000Z', + '3.2.2': '2024-08-16T00:00:00.000Z', // Last published version + }, + }); + + expect(await getTemplateVersion('0.75.3')).toEqual('3.2.2'); + }); + + it('should NOT matching when MAJOR.MINOR is not found', async () => { + fetchReturn({ + versions: { + '3.2.1': {scripts: {version: '0.75.1'}}, + '3.2.2': {scripts: {version: '0.75.2'}}, + }, + time: { + '3.2.1': '2024-08-15T00:00:00.000Z', + '3.2.2': '2024-08-16T00:00:00.000Z', // Last published version + }, + }); + + expect(await getTemplateVersion('0.76.0')).toEqual(undefined); + }); + + it('ignores packages that have weird script version entries', async () => { + fetchReturn({ + versions: { + '1': {}, + '2': {scripts: {}}, + '3': {scripts: {version: 'echo "not a semver entry"'}}, + win: {scripts: {version: '0.75.2'}}, + }, + time: { + '1': '2024-08-14T00:00:00.000Z', + win: '2024-08-15T00:00:00.000Z', + // These would normally both beat '3' on time: + '2': '2024-08-16T00:00:00.000Z', + '3': '2024-08-16T00:00:00.000Z', + }, + }); + + expect(await getTemplateVersion('0.75.2')).toEqual('win'); + }); + + it('support `version` and `reactNativeVersion` entries from npm', async () => { + fetchReturn({ + versions: { + '3.2.1': {scripts: {version: '0.75.1'}}, + '3.2.2': {scripts: {reactNativeVersion: '0.75.2'}}, + }, + time: { + '3.2.1': '2024-08-15T00:00:00.000Z', + '3.2.2': '2024-08-16T00:00:00.000Z', // Last published version + }, + }); + + expect(await getTemplateVersion('0.75.2')).toEqual('3.2.2'); + }); + + it('prefers `reactNativeVersion` over `version` entries from npm', async () => { + fetchReturn({ + versions: { + '3.2.1': {scripts: {version: '0.75.1'}}, + '3.2.2': { + scripts: { + reactNativeVersion: '0.75.2', + version: 'should prefer the other one', + }, + }, + }, + time: { + '3.2.1': '2024-08-15T00:00:00.000Z', + '3.2.2': '2024-08-16T00:00:00.000Z', // Last published version + }, + }); + + expect(await getTemplateVersion('0.75.2')).toEqual('3.2.2'); + }); +}); diff --git a/packages/cli/src/tools/npm.ts b/packages/cli/src/tools/npm.ts index 90c159bc0..c090571f1 100644 --- a/packages/cli/src/tools/npm.ts +++ b/packages/cli/src/tools/npm.ts @@ -8,6 +8,7 @@ import {execSync} from 'child_process'; import findUp from 'find-up'; +import semver from 'semver'; export function getNpmVersionIfAvailable() { let npmVersion; @@ -76,3 +77,111 @@ export async function npmResolveConcreteVersion( const json: any = await resp.json(); return json.version; } + +type TimeStampString = string; +type TemplateVersion = string; +type VersionedTemplates = { + [rnVersion: string]: Template[]; +}; + +type NpmTemplateResponse = { + versions: { + // Template version, semver including -rc candidates + [version: TemplateVersion]: { + scripts?: { + // Version of react-native this is built for + reactNativeVersion?: string; + // The initial implemntation used this, but moved to reactNativeVersion + version?: string; + }; + }; + }; + time: { + created: string; + modified: string; + [version: TemplateVersion]: TimeStampString; + }; +}; + +class Template { + version: string; + reactNativeVersion: string; + published: Date; + + constructor(version: string, reactNativeVersion: string, published: string) { + this.version = version; + this.reactNativeVersion = reactNativeVersion; + this.published = new Date(published); + } + + get isPreRelease() { + return this.version.includes('-rc'); + } +} + +const TEMPLATE_VERSIONS_URL = + 'https://registry.npmjs.org/@react-native-community/template'; +const minorVersion = (version: string) => { + const v = semver.parse(version)!; + return `${v.major}.${v.minor}`; +}; + +export async function getTemplateVersion( + reactNativeVersion: string, +): Promise { + const json = await fetch(TEMPLATE_VERSIONS_URL).then( + (resp) => resp.json() as Promise, + ); + + // We are abusing which npm metadata is publicly available through the registry. Scripts + // is always captured, and we use this in the Github Action that manages our releases to + // capture the version of React Native the template is built with. + // + // Users are interested in: + // - IF there a match for React Native MAJOR.MINOR.PATCH? + // - Yes: if there are >= 2 versions, pick the one last published. This lets us release + // specific fixes for React Native versions. + // - ELSE, is there a match for React Native MINOR.PATCH? + // - Yes: if there are >= 2 versions, pick the one last published. This decouples us from + // React Native releases. + // - No: we don't have a version of the template for a version of React Native. There should + // at a minimum be at last one version cut for each MINOR.PATCH since 0.75. Before this + // the template was shipped with React Native + const rnToTemplate: VersionedTemplates = {}; + for (const [templateVersion, pkg] of Object.entries(json.versions)) { + const rnVersion = pkg?.scripts?.reactNativeVersion ?? pkg?.scripts?.version; + if (rnVersion == null || !semver.valid(rnVersion)) { + // This is a very early version that doesn't have the correct metadata embedded + continue; + } + + const template = new Template( + templateVersion, + rnVersion, + json.time[templateVersion], + ); + + const rnMinorVersion = minorVersion(rnVersion); + + rnToTemplate[rnVersion] = rnToTemplate[rnVersion] ?? []; + rnToTemplate[rnVersion].push(template); + rnToTemplate[rnMinorVersion] = rnToTemplate[rnMinorVersion] ?? []; + rnToTemplate[rnMinorVersion].push(template); + } + + // Make sure the last published is the first one in each version of React Native + for (const v in rnToTemplate) { + rnToTemplate[v].sort( + (a, b) => b.published.getTime() - a.published.getTime(), + ); + } + + if (reactNativeVersion in rnToTemplate) { + return rnToTemplate[reactNativeVersion][0].version; + } + const rnMinorVersion = minorVersion(reactNativeVersion); + if (rnMinorVersion in rnToTemplate) { + return rnToTemplate[rnMinorVersion][0].version; + } + return; +} diff --git a/scripts/build.js b/scripts/build.js index 30a977307..9fbad060a 100644 --- a/scripts/build.js +++ b/scripts/build.js @@ -20,7 +20,7 @@ const fs = require('fs'); const path = require('path'); -const glob = require('glob'); +const glob = require('fast-glob'); const babel = require('@babel/core'); const chalk = require('chalk'); const micromatch = require('micromatch'); diff --git a/scripts/linkPackages.js b/scripts/linkPackages.js index 407ffb0d0..c0658cd1c 100644 --- a/scripts/linkPackages.js +++ b/scripts/linkPackages.js @@ -1,7 +1,7 @@ const execa = require('execa'); const chalk = require('chalk'); const path = require('path'); -const glob = require('glob'); +const glob = require('fast-glob'); const projects = glob.sync('packages/*/package.json'); diff --git a/yarn.lock b/yarn.lock index 6a6150371..8ed134331 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4799,20 +4799,20 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== deprecation@^2.0.0: version "2.3.1" resolved "https://registry.yarnpkg.com/deprecation/-/deprecation-2.3.1.tgz#6368cbdb40abf3373b525ac87e4a260c3a700919" integrity sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ== -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detect-indent@^5.0.0: version "5.0.0" @@ -6441,16 +6441,16 @@ http-cache-semantics@^4.1.1: resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz#abe02fcb2985460bf0323be664436ec3476a6d5a" integrity sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ== -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== dependencies: - depd "~1.1.2" + depd "2.0.0" inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" http-proxy-agent@^4.0.1: version "4.0.1" @@ -8624,16 +8624,16 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - ms@2.1.2, ms@^2.0.0, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +ms@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + msgpackr-extract@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/msgpackr-extract/-/msgpackr-extract-3.0.2.tgz#e05ec1bb4453ddf020551bcd5daaf0092a2c279d" @@ -9184,6 +9184,13 @@ object.values@^1.1.6: define-properties "^1.2.0" es-abstract "^1.22.1" +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== + dependencies: + ee-first "1.1.1" + on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -10306,34 +10313,34 @@ semver@^7.0.0, semver@^7.1.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semve dependencies: lru-cache "^6.0.0" -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" + depd "2.0.0" + destroy "1.2.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "~1.7.2" + http-errors "2.0.0" mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" + ms "2.1.3" + on-finished "2.4.1" range-parser "~1.2.1" - statuses "~1.5.0" + statuses "2.0.1" serve-static@^1.13.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== + version "1.16.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.0.tgz#2bf4ed49f8af311b519c46f272bf6ac3baf38a92" + integrity sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.17.1" + send "0.18.0" set-blocking@^2.0.0: version "2.0.0" @@ -10369,10 +10376,10 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== shallow-clone@^3.0.0: version "3.0.1" @@ -10707,7 +10714,12 @@ static-extend@^0.1.1: define-property "^0.2.5" object-copy "^0.1.0" -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +statuses@~1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= @@ -11151,10 +11163,10 @@ to-regex@^3.0.1, to-regex@^3.0.2: regex-not "^1.0.2" safe-regex "^1.1.0" -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== tough-cookie@^4.0.0: version "4.1.4"