From 70c6353904e39ebbfa9c08db2691103dd401ca68 Mon Sep 17 00:00:00 2001 From: Craigory Coppola Date: Thu, 17 Mar 2022 13:27:46 -0400 Subject: [PATCH] chore(repo): move add-nx into main nx repo --- .../src/add-nx-to-monorepo.test.ts | 28 +- e2e/utils/index.ts | 6 +- package.json | 1 + packages/add-nx-to-monorepo/.eslintrc.json | 5 + packages/add-nx-to-monorepo/LICENSE | 22 + packages/add-nx-to-monorepo/README.md | 20 + packages/add-nx-to-monorepo/jest.config.js | 14 + packages/add-nx-to-monorepo/package.json | 33 ++ packages/add-nx-to-monorepo/project.json | 72 ++++ packages/add-nx-to-monorepo/publish.sh | 15 + .../src/add-nx-to-monorepo.ts | 376 ++++++++++++++++++ packages/add-nx-to-monorepo/tsconfig.json | 13 + packages/add-nx-to-monorepo/tsconfig.lib.json | 11 + .../add-nx-to-monorepo/tsconfig.spec.json | 15 + packages/cra-to-nx/.eslintrc.json | 5 + packages/cra-to-nx/LICENSE | 22 + packages/cra-to-nx/README.md | 56 +++ packages/cra-to-nx/jest.config.js | 14 + packages/cra-to-nx/package.json | 23 ++ packages/cra-to-nx/project.json | 53 +++ packages/cra-to-nx/src/index.ts | 16 + .../src/lib/add-cra-commands-to-nx.ts | 13 + .../src/lib/check-for-uncommitted-changes.ts | 13 + packages/cra-to-nx/src/lib/clean-up-files.ts | 16 + packages/cra-to-nx/src/lib/cra-to-nx.ts | 187 +++++++++ .../src/lib/read-name-from-package-json.ts | 18 + .../cra-to-nx/src/lib/setup-e2e-project.ts | 46 +++ packages/cra-to-nx/src/lib/tsconfig-setup.ts | 113 ++++++ .../cra-to-nx/src/lib/write-craco-config.ts | 61 +++ packages/cra-to-nx/tsconfig.json | 13 + packages/cra-to-nx/tsconfig.lib.json | 11 + packages/cra-to-nx/tsconfig.spec.json | 15 + .../make-angular-cli-faster/.eslintrc.json | 5 + packages/make-angular-cli-faster/LICENSE | 22 + packages/make-angular-cli-faster/README.md | 19 + .../make-angular-cli-faster/jest.config.js | 9 + packages/make-angular-cli-faster/package.json | 34 ++ packages/make-angular-cli-faster/project.json | 38 ++ packages/make-angular-cli-faster/publish.sh | 15 + .../src/make-angular-cli-faster.ts | 95 +++++ .../make-angular-cli-faster/tsconfig.json | 16 + .../make-angular-cli-faster/tsconfig.lib.json | 11 + .../tsconfig.spec.json | 15 + scripts/e2e-build-package-publish.ts | 37 +- scripts/nx-release.js | 3 + scripts/package.sh | 8 +- workspace.json | 3 + 47 files changed, 1633 insertions(+), 23 deletions(-) create mode 100644 packages/add-nx-to-monorepo/.eslintrc.json create mode 100644 packages/add-nx-to-monorepo/LICENSE create mode 100644 packages/add-nx-to-monorepo/README.md create mode 100644 packages/add-nx-to-monorepo/jest.config.js create mode 100644 packages/add-nx-to-monorepo/package.json create mode 100644 packages/add-nx-to-monorepo/project.json create mode 100755 packages/add-nx-to-monorepo/publish.sh create mode 100644 packages/add-nx-to-monorepo/src/add-nx-to-monorepo.ts create mode 100644 packages/add-nx-to-monorepo/tsconfig.json create mode 100644 packages/add-nx-to-monorepo/tsconfig.lib.json create mode 100644 packages/add-nx-to-monorepo/tsconfig.spec.json create mode 100644 packages/cra-to-nx/.eslintrc.json create mode 100644 packages/cra-to-nx/LICENSE create mode 100644 packages/cra-to-nx/README.md create mode 100644 packages/cra-to-nx/jest.config.js create mode 100644 packages/cra-to-nx/package.json create mode 100644 packages/cra-to-nx/project.json create mode 100644 packages/cra-to-nx/src/index.ts create mode 100644 packages/cra-to-nx/src/lib/add-cra-commands-to-nx.ts create mode 100644 packages/cra-to-nx/src/lib/check-for-uncommitted-changes.ts create mode 100644 packages/cra-to-nx/src/lib/clean-up-files.ts create mode 100644 packages/cra-to-nx/src/lib/cra-to-nx.ts create mode 100644 packages/cra-to-nx/src/lib/read-name-from-package-json.ts create mode 100644 packages/cra-to-nx/src/lib/setup-e2e-project.ts create mode 100644 packages/cra-to-nx/src/lib/tsconfig-setup.ts create mode 100644 packages/cra-to-nx/src/lib/write-craco-config.ts create mode 100644 packages/cra-to-nx/tsconfig.json create mode 100644 packages/cra-to-nx/tsconfig.lib.json create mode 100644 packages/cra-to-nx/tsconfig.spec.json create mode 100644 packages/make-angular-cli-faster/.eslintrc.json create mode 100644 packages/make-angular-cli-faster/LICENSE create mode 100644 packages/make-angular-cli-faster/README.md create mode 100644 packages/make-angular-cli-faster/jest.config.js create mode 100644 packages/make-angular-cli-faster/package.json create mode 100644 packages/make-angular-cli-faster/project.json create mode 100755 packages/make-angular-cli-faster/publish.sh create mode 100644 packages/make-angular-cli-faster/src/make-angular-cli-faster.ts create mode 100644 packages/make-angular-cli-faster/tsconfig.json create mode 100644 packages/make-angular-cli-faster/tsconfig.lib.json create mode 100644 packages/make-angular-cli-faster/tsconfig.spec.json diff --git a/e2e/add-nx-to-monorepo/src/add-nx-to-monorepo.test.ts b/e2e/add-nx-to-monorepo/src/add-nx-to-monorepo.test.ts index a24dee67764643..bfb991c0b53586 100644 --- a/e2e/add-nx-to-monorepo/src/add-nx-to-monorepo.test.ts +++ b/e2e/add-nx-to-monorepo/src/add-nx-to-monorepo.test.ts @@ -1,12 +1,13 @@ import { createNonNxProjectDirectory, + runCLI, runCommand, tmpProjPath, updateFile, } from '@nrwl/e2e/utils'; import { Workspaces } from 'nx/src/shared/workspace'; -describe('add-nx-to-monorepo', () => { +describe.each(['npx', 'pnpx'])('%s add-nx-to-monorepo', (command) => { it('should not throw', () => { // Arrange createNonNxProjectDirectory(); @@ -24,12 +25,33 @@ describe('add-nx-to-monorepo', () => { ); // Act - const output = runCommand('npx add-nx-to-monorepo'); + const output = runCommand(`${command} add-nx-to-monorepo --nx-cloud false`); + console.log(output) // Assert - expect(output).toBeTruthy(); + expect(output).toContain('๐ŸŽ‰ Done!'); expect(readWorkspaceConfig().projects['package-a']).toBeTruthy(); expect(readWorkspaceConfig().projects['package-b']).toBeTruthy(); }); + + it('should build', () => { + // Arrange + createNonNxProjectDirectory(); + updateFile( + 'packages/package-a/package.json', + JSON.stringify({ + name: 'package-a', + scripts: { + build: 'echo "build successful"', + }, + }) + ); + + // Act + runCommand(`${command} add-nx-to-monorepo --nx-cloud false`); + const output = runCLI('build package-a'); + // Assert + expect(output).toContain('build successful'); + }); }); const readWorkspaceConfig = () => diff --git a/e2e/utils/index.ts b/e2e/utils/index.ts index 5fe0e8b99f9ea7..795beab8f03ea2 100644 --- a/e2e/utils/index.ts +++ b/e2e/utils/index.ts @@ -5,7 +5,7 @@ import { WorkspaceJsonConfiguration, } from '@nrwl/devkit'; import { angularCliVersion } from '@nrwl/workspace/src/utils/versions'; -import { ChildProcess, exec, execSync } from 'child_process'; +import { ChildProcess, exec, execSync, ExecSyncOptions } from 'child_process'; import { copySync, createFileSync, @@ -503,7 +503,7 @@ export function expectTestsPass(v: { stdout: string; stderr: string }) { expect(v.stderr).not.toContain('fail'); } -export function runCommand(command: string): string { +export function runCommand(command: string, options?: Partial): string { try { const r = execSync(command, { cwd: tmpProjPath(), @@ -514,12 +514,14 @@ export function runCommand(command: string): string { NX_INVOKED_BY_RUNNER: undefined, }, encoding: 'utf-8', + ...options }).toString(); if (process.env.NX_VERBOSE_LOGGING) { console.log(r); } return r; } catch (e) { + console.log('ERROR CAUGHT', e) // this is intentional // npm ls fails if package is not found return e.stdout?.toString() + e.stderr?.toString(); diff --git a/package.json b/package.json index f6fa6ebfbd700d..3d5999f817da3e 100644 --- a/package.json +++ b/package.json @@ -275,6 +275,7 @@ "@tailwindcss/typography": "^0.5.0", "classnames": "^2.3.1", "core-js": "^3.6.5", + "enquirer": "~2.3.6", "fast-glob": "^3.2.7", "framer-motion": "^4.1.17", "glob": "7.1.4", diff --git a/packages/add-nx-to-monorepo/.eslintrc.json b/packages/add-nx-to-monorepo/.eslintrc.json new file mode 100644 index 00000000000000..fea46111a20ae8 --- /dev/null +++ b/packages/add-nx-to-monorepo/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "rules": {} +} diff --git a/packages/add-nx-to-monorepo/LICENSE b/packages/add-nx-to-monorepo/LICENSE new file mode 100644 index 00000000000000..1ec6dd22ba8d40 --- /dev/null +++ b/packages/add-nx-to-monorepo/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2017-2021 Narwhal Technologies Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/add-nx-to-monorepo/README.md b/packages/add-nx-to-monorepo/README.md new file mode 100644 index 00000000000000..3e51b4459ccd3a --- /dev/null +++ b/packages/add-nx-to-monorepo/README.md @@ -0,0 +1,20 @@ +# `> npx add-nx-to-monorepo` + +

+ +
+ +[![License](https://img.shields.io/npm/l/@nrwl/workspace.svg?style=flat-square)]() +[![NPM Version](https://badge.fury.io/js/%40nrwl%2Fworkspace.svg)](https://www.npmjs.com/@nrwl/workspace) +[![Join the chat at https://gitter.im/nrwl-nx/community](https://badges.gitter.im/nrwl-nx/community.svg)](https://gitter.im/nrwl-nx/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Join us @nrwl/community on slack](https://img.shields.io/badge/slack-%40nrwl%2Fcommunity-brightgreen)](https://join.slack.com/t/nrwlcommunity/shared_invite/enQtNzU5MTE4OTQwOTk0LTgxY2E0ZWYzMWE0YzA5ZDA2MWM1NDVhNmI2ZWMyYmZhNWJiODk3MjkxZjY3MzU5ZjRmM2NmNWU1OTgyZmE4Mzc) + +
+ +An easy way to add Nx computation caching to any monorepo (Yarn Workspaces, PNPM, Lerna, etc). + +Simply run: `npx add-nx-to-monorepo` in your monorepo. + +## Learn More + +- See [https://github.com/nrwl/nx](https://github.com/nrwl/nx) to learn more about Nx. diff --git a/packages/add-nx-to-monorepo/jest.config.js b/packages/add-nx-to-monorepo/jest.config.js new file mode 100644 index 00000000000000..af263c0bd9d428 --- /dev/null +++ b/packages/add-nx-to-monorepo/jest.config.js @@ -0,0 +1,14 @@ +module.exports = { + displayName: 'add-nx-to-monorepo', + preset: '../../jest.preset.js', + globals: { + 'ts-jest': { + tsConfig: '/tsconfig.spec.json', + }, + }, + transform: { + '^.+\\.[tj]sx?$': 'ts-jest', + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], + coverageDirectory: '../../coverage/projects/add-nx-to-monorepo', +}; diff --git a/packages/add-nx-to-monorepo/package.json b/packages/add-nx-to-monorepo/package.json new file mode 100644 index 00000000000000..c8665c8630a1dd --- /dev/null +++ b/packages/add-nx-to-monorepo/package.json @@ -0,0 +1,33 @@ +{ + "name": "add-nx-to-monorepo", + "version": "0.0.1", + "description": "Make any monorepo faster by adding Nx to it", + "repository": { + "type": "git", + "url": "git+https://github.com/nrwl/add-nx.git" + }, + "keywords": [ + "Monorepo", + "React", + "Web", + "Node", + "Nest", + "Lerna", + "Yarn", + "CLI" + ], + "bin": { + "add-nx-to-monorepo": "./src/add-nx-to-monorepo.js" + }, + "author": "Victor Savkin", + "license": "MIT", + "bugs": { + "url": "https://github.com/nrwl/add-nx/issues" + }, + "homepage": "https://nx.dev", + "dependencies": { + "strip-json-comments": "3.1.1", + "ignore": "^5.0.4", + "@nrwl/workspace": "*" + } +} diff --git a/packages/add-nx-to-monorepo/project.json b/packages/add-nx-to-monorepo/project.json new file mode 100644 index 00000000000000..e7de316112d47a --- /dev/null +++ b/packages/add-nx-to-monorepo/project.json @@ -0,0 +1,72 @@ +{ + "root": "packages/add-nx-to-monorepo", + "sourceRoot": "packages/add-nx-to-monorepo/src", + "projectType": "library", + "targets": { + "lint": { + "executor": "@nrwl/linter:eslint", + "options": { + "lintFilePatterns": [ + "packages/add-nx-to-monorepo/**/*.ts" + ] + } + }, + "test": { + "executor": "@nrwl/jest:jest", + "outputs": [ + "coverage/packages/add-nx-to-monorepo" + ], + "options": { + "jestConfig": "packages/add-nx-to-monorepo/jest.config.js", + "passWithNoTests": true + } + }, + "build-base": { + "executor": "@nrwl/js:tsc", + "outputs": [ + "{options.outputPath}" + ], + "options": { + "outputPath": "build/packages/add-nx-to-monorepo", + "tsConfig": "packages/add-nx-to-monorepo/tsconfig.lib.json", + "packageJson": "packages/add-nx-to-monorepo/package.json", + "main": "packages/add-nx-to-monorepo/src/index.ts", + "assets": [ + "packages/add-nx-to-monorepo/LICENSE", + "packages/add-nx-to-monorepo/*.md" + ] + } + }, + "build": { + "executor": "@nrwl/workspace:run-commands", + "outputs": ["build/packages/add-nx-to-monorepo"], + "options": { + "commands": [ + { + "command": "node ./scripts/chmod build/packages/add-nx-to-monorepo/src/add-nx-to-monorepo.js" + }, + { + "command": "node ./scripts/copy-readme.js add-nx-to-monorepo" + } + ], + "parallel": false + } + }, + "test-against-repo": { + "executor": "@nrwl/workspace:run-commands", + "options": { + "commands": [ + { + "command": "nx build add-nx-to-monorepo", + "forwardAllArgs": false + }, + { + "command": "export JS_SCRIPT=$PWD/dist/packages/add-nx-to-monorepo/src/add-nx-to-monorepo.js && cd {args.repo} && echo $PWD && node $JS_SCRIPT", + "forwardAllArgs": false + } + ], + "parallel": false + } + } + } + } \ No newline at end of file diff --git a/packages/add-nx-to-monorepo/publish.sh b/packages/add-nx-to-monorepo/publish.sh new file mode 100755 index 00000000000000..2d08ef12547507 --- /dev/null +++ b/packages/add-nx-to-monorepo/publish.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +echo "Publishing add-nx-to-monorepo@$1" + +nx build add-nx-to-monorepo +cd dist/projects/add-nx-to-monorepo + +if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i "" "s|REPLACE|$1|g" package.json +else + sed -i "s|REPLACE|$1|g" package.json +fi + +npm adduser +npm publish --access public --tag latest + diff --git a/packages/add-nx-to-monorepo/src/add-nx-to-monorepo.ts b/packages/add-nx-to-monorepo/src/add-nx-to-monorepo.ts new file mode 100644 index 00000000000000..da7c8d4c5feaa6 --- /dev/null +++ b/packages/add-nx-to-monorepo/src/add-nx-to-monorepo.ts @@ -0,0 +1,376 @@ +#!/usr/bin/env node + +import * as stripJsonComments from 'strip-json-comments'; +import * as path from 'path'; +import * as fs from 'fs'; +import * as cp from 'child_process'; +import { output } from '@nrwl/workspace/src/utils/output'; +// eslint-disable-next-line @typescript-eslint/no-var-requires +import * as enquirer from 'enquirer'; +import * as yargsParser from 'yargs-parser'; + +import { execSync } from 'child_process'; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const ignore = require('ignore'); +const parsedArgs = yargsParser(process.argv, { + boolean: ['nxCloud'], + configuration: { + 'strip-dashed': true, + 'strip-aliased': true, + }, +}); + +addNxToMonorepo().catch((e) => console.error(e)); + +export async function addNxToMonorepo() { + const repoRoot = process.cwd(); + + output.log({ + title: `๐Ÿณ Nx initialization`, + }); + + const useCloud = await askAboutNxCloud(parsedArgs); + + output.log({ + title: `๐Ÿง‘โ€๐Ÿ”ง Analyzing the source code and creating configuration file`, + }); + + const packageJsonFiles = allProjectPackageJsonFiles(repoRoot); + + const pds = createProjectDesc(repoRoot, packageJsonFiles); + + if (pds.length === 0) { + output.error({ title: `Cannot find any projects in this monorepo` }); + process.exit(1); + } + + createNxJsonFile(repoRoot); + createTsConfigIfMissing(repoRoot); + + addDepsToPackageJson(repoRoot, useCloud); + + output.log({ title: `๐Ÿ“ฆ Installing dependencies` }); + runInstall(repoRoot); + + if (useCloud) { + initCloud(repoRoot); + } + + printFinalMessage(repoRoot); +} + +async function askAboutNxCloud(parsedArgs: any) { + if (parsedArgs.nxCloud === undefined) { + return enquirer + .prompt([ + { + name: 'NxCloud', + message: `Use Nx Cloud? (It's free and doesn't require registration.)`, + type: 'select', + choices: [ + { + name: 'Yes', + hint: 'Faster builds, run details, GitHub integration. Learn more at https://nx.app', + }, + + { + name: 'No', + }, + ], + initial: 'No' as any, + }, + ]) + .then((a: { NxCloud: 'Yes' | 'No' }) => a.NxCloud === 'Yes'); + } else { + return parsedArgs.nxCloud; + } +} + +// scanning package.json files +function allProjectPackageJsonFiles(repoRoot: string) { + const packageJsonFiles = allPackageJsonFiles(repoRoot, repoRoot); + return packageJsonFiles.filter((c) => c != 'package.json'); +} + +function allPackageJsonFiles(repoRoot: string, dirName: string) { + const ignoredGlobs = getIgnoredGlobs(repoRoot); + const relDirName = path.relative(repoRoot, dirName); + if ( + relDirName && + (ignoredGlobs.ignores(relDirName) || + relDirName.indexOf(`node_modules`) > -1) + ) { + return []; + } + + let res = []; + try { + fs.readdirSync(dirName).forEach((c) => { + const child = path.join(dirName, c); + if (ignoredGlobs.ignores(path.relative(repoRoot, child))) { + return; + } + try { + const s = fs.statSync(child); + if (!s.isDirectory() && c == 'package.json') { + res.push(path.relative(repoRoot, child)); + } else if (s.isDirectory()) { + res = [...res, ...allPackageJsonFiles(repoRoot, child)]; + } + // eslint-disable-next-line no-empty + } catch (e) {} + }); + // eslint-disable-next-line no-empty + } catch (e) {} + return res; +} + +function getIgnoredGlobs(repoRoot: string) { + const ig = ignore(); + try { + ig.add(fs.readFileSync(`${repoRoot}/.gitignore`).toString()); + // eslint-disable-next-line no-empty + } catch (e) {} + return ig; +} + +// creating project descs +interface ProjectDesc { + name: string; + dir: string; + mainFilePath: string; +} + +function createProjectDesc( + repoRoot: string, + packageJsonFiles: string[] +): ProjectDesc[] { + const res = []; + packageJsonFiles.forEach((p) => { + const dir = path.dirname(p); + const packageJson = readJsonFile(repoRoot, p); + if (!packageJson.name) return; + + if (packageJson.main) { + res.push({ + name: packageJson.name, + dir, + mainFilePath: path.join(dir, packageJson.main), + }); + } else if (packageJson.index) { + res.push({ + name: packageJson.name, + dir, + mainFilePath: path.join(dir, packageJson.index), + }); + } else { + res.push({ name: packageJson.name, dir, mainFilePath: null }); + } + }); + return res; +} + +function readJsonFile(repoRoot: string, file: string) { + return JSON.parse( + stripJsonComments(fs.readFileSync(path.join(repoRoot, file)).toString()) + ); +} + +function detectWorkspaceScope(repoRoot: string) { + let scope = readJsonFile(repoRoot, `package.json`).name; + if (!scope) return 'undetermined'; + + if (scope.startsWith('@')) { + scope = scope.substring(1); + } + + return scope.split('/')[0]; +} + +function createNxJsonFile(repoRoot: string) { + const scope = detectWorkspaceScope(repoRoot); + const res = { + extends: '@nrwl/workspace/presets/npm.json', + npmScope: scope, + tasksRunnerOptions: { + default: { + runner: '@nrwl/workspace/tasks-runners/default', + options: { + cacheableOperations: ['build', 'test', 'lint', 'package', 'prepare'], + }, + }, + }, + targetDependencies: { + build: [{ target: 'build', projects: 'dependencies' }], + prepare: [{ target: 'prepare', projects: 'dependencies' }], + package: [{ target: 'package', projects: 'dependencies' }], + }, + affected: { + defaultBase: deduceDefaultBase(), + }, + workspaceLayout: deduceWorkspaceLayout(repoRoot), + pluginsConfig: { + '@nrwl/js': { + analyzeSourceFiles: false, + }, + }, + }; + + fs.writeFileSync(`${repoRoot}/nx.json`, JSON.stringify(res, null, 2)); +} + +function deduceWorkspaceLayout(repoRoot: string) { + if (exists(path.join(repoRoot, 'packages'))) { + return undefined; + } else if (exists(path.join(repoRoot, 'projects'))) { + return { libsDir: 'projects', appsDir: 'projects' }; + } else { + return undefined; + } +} + +function exists(folder: string) { + try { + const s = fs.statSync(folder); + return s.isDirectory(); + // eslint-disable-next-line no-empty + } catch (e) { + return false; + } +} + +function deduceDefaultBase() { + try { + execSync(`git rev-parse --verify main`, { + stdio: ['ignore', 'ignore', 'ignore'], + }); + return 'main'; + } catch (e) { + try { + execSync(`git rev-parse --verify dev`, { + stdio: ['ignore', 'ignore', 'ignore'], + }); + return 'dev'; + } catch (e) { + try { + execSync(`git rev-parse --verify next`, { + stdio: ['ignore', 'ignore', 'ignore'], + }); + return 'next'; + } catch (e) { + return 'master'; + } + } + } +} + +function createTsConfigIfMissing(repoRoot: string) { + if (!hasRootTsConfig(repoRoot)) { + fs.writeFileSync( + 'tsconfig.base.json', + JSON.stringify({ compilerOptions: {} }, null, 2) + ); + } +} + +function hasRootTsConfig(repoRoot: string) { + try { + readJsonFile(repoRoot, `tsconfig.base.json`); + return true; + } catch (e) { + try { + readJsonFile(repoRoot, `tsconfig.json`); + return true; + } catch (e) { + return false; + } + } +} + +// add dependencies +function addDepsToPackageJson(repoRoot: string, useCloud: boolean) { + const json = readJsonFile(repoRoot, `package.json`); + if (!json.devDependencies) json.devDependencies = {}; + json.devDependencies['@nrwl/workspace'] = 'NX_VERSION'; + json.devDependencies['@nrwl/cli'] = 'NX_VERSION'; + json.devDependencies['nx'] = 'NX_VERSION'; + if ( + !(json.dependencies && json.dependencies['typescript']) && + !json.devDependencies['typescript'] + ) { + json.devDependencies['typescript'] = '4.2.4'; + } + if (useCloud) { + json.devDependencies['@nrwl/nx-cloud'] = 'latest'; + } + fs.writeFileSync(`package.json`, JSON.stringify(json, null, 2)); +} + +function runInstall(repoRoot: string) { + cp.execSync(getPackageManagerCommand(repoRoot).install, { stdio: [0, 1, 2] }); +} + +function initCloud(repoRoot: string) { + execSync( + `${getPackageManagerCommand(repoRoot).exec} nx g @nrwl/nx-cloud:init`, + { + stdio: [0, 1, 2], + } + ); +} + +function getPackageManagerCommand(repoRoot: string): { + install: string; + exec: string; +} { + const packageManager = fs.existsSync(path.join(repoRoot, 'yarn.lock')) + ? 'yarn' + : fs.existsSync(path.join(repoRoot, 'pnpm-lock.yaml')) + ? 'pnpm' + : 'npm'; + + switch (packageManager) { + case 'yarn': + return { + install: 'yarn', + exec: 'yarn', + }; + + case 'pnpm': + return { + install: 'pnpm install --no-frozen-lockfile', // explicitly disable in case of CI + exec: 'pnpx', + }; + + case 'npm': + return { + install: 'npm install --legacy-peer-deps', + exec: 'npx', + }; + } +} + +function printFinalMessage(repoRoot) { + output.success({ + title: `๐ŸŽ‰ Done!`, + bodyLines: [ + `- Enabled Computation caching!`, + `- Run "${ + getPackageManagerCommand(repoRoot).exec + } nx run-many --target=build --all" to run the build script for every project in the monorepo.`, + `- Run it again to replay the cached computation.`, + `- Run "${ + getPackageManagerCommand(repoRoot).exec + } nx graph" to see the structure of the monorepo.`, + `- Learn more at https://nx.dev/migration/adding-to-monorepo`, + ], + }); +} + +function removeWindowsDriveLetter(osSpecificPath: string): string { + return osSpecificPath.replace(/^[A-Z]:/, ''); +} + +function normalizePath(osSpecificPath: string): string { + return removeWindowsDriveLetter(osSpecificPath).split(path.sep).join('/'); +} diff --git a/packages/add-nx-to-monorepo/tsconfig.json b/packages/add-nx-to-monorepo/tsconfig.json new file mode 100644 index 00000000000000..62ebbd946474ce --- /dev/null +++ b/packages/add-nx-to-monorepo/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/packages/add-nx-to-monorepo/tsconfig.lib.json b/packages/add-nx-to-monorepo/tsconfig.lib.json new file mode 100644 index 00000000000000..037d796f286235 --- /dev/null +++ b/packages/add-nx-to-monorepo/tsconfig.lib.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node"] + }, + "exclude": ["**/*.spec.ts"], + "include": ["**/*.ts"] +} diff --git a/packages/add-nx-to-monorepo/tsconfig.spec.json b/packages/add-nx-to-monorepo/tsconfig.spec.json new file mode 100644 index 00000000000000..559410b96af678 --- /dev/null +++ b/packages/add-nx-to-monorepo/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "**/*.spec.ts", + "**/*.spec.tsx", + "**/*.spec.js", + "**/*.spec.jsx", + "**/*.d.ts" + ] +} diff --git a/packages/cra-to-nx/.eslintrc.json b/packages/cra-to-nx/.eslintrc.json new file mode 100644 index 00000000000000..fea46111a20ae8 --- /dev/null +++ b/packages/cra-to-nx/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "extends": ["../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "rules": {} +} diff --git a/packages/cra-to-nx/LICENSE b/packages/cra-to-nx/LICENSE new file mode 100644 index 00000000000000..1ec6dd22ba8d40 --- /dev/null +++ b/packages/cra-to-nx/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2017-2021 Narwhal Technologies Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/cra-to-nx/README.md b/packages/cra-to-nx/README.md new file mode 100644 index 00000000000000..1cbcb0dc036ae5 --- /dev/null +++ b/packages/cra-to-nx/README.md @@ -0,0 +1,56 @@ +# CRA - to - Nx + +This package will turn your React app into an [Nx workspace](https://nx.dev/). To use this package, your React app must have been generated and kept the structure of [Create-React-App](https://reactjs.org/docs/create-a-new-react-app.html), with files generated either in js/jsx or ts/tsx. + +This tool follows the steps described in this [migration guide](https://nx.dev/latest/react/migration/migration-cra), with some enhancements. + +It will, essentially, generate a new Nx workspace, and then place your existing CRA React app in the `apps` directory of the Nx workspace, while configuring the Nx workspace as needed. + +## Before starting + +As this package will change your folder structure and edit some of your files, you must commit any local changes you have, to start with clean history. In any case, to protect you, the package will exit if there are local uncommited changes. + +## How to use + +Go to your CRA React app directory and run the following command: + +``` +npx cra-to-nx +``` + +Then just sit back and wait. After a while you will be able to take advantage of the [full magic of Nx](https://nx.dev/latest/react/getting-started/getting-started). + +## Ok, it's done, what do I do now? + +### Run, build, lint, test + +You can try the following commands: + +``` +nx serve your-app-name +nx build your-app-name +nx lint your-app-name +nx test your-app-name +``` + +### Generate code + +Take a look at [this guide](https://nx.dev/latest/react/workspace/generators/using-schematics) + +Or just try generating a library: + +``` +nx generate lib ui-button +``` + +### Courses, guides, docs + +- [Follow the Nx React tutorial](https://nx.dev/react/tutorial/01-create-application) + +- [Free Nx course on Egghead.io](https://egghead.io/playlists/scale-react-development-with-nx-4038) + +- Or just use the VS Code Nx Extension, [Nx Console](https://nx.dev/latest/react/getting-started/console) to do all these using a UI. + +## So, now I just have my React app in a monorepo? + +No. You have your React app in an **Nx workspace**. So you also have the full power of Nx tools. You can watch this [10-minute quick overview](https://youtu.be/sNz-4PUM0k8) if you want to know more. diff --git a/packages/cra-to-nx/jest.config.js b/packages/cra-to-nx/jest.config.js new file mode 100644 index 00000000000000..747eadb8b79a2f --- /dev/null +++ b/packages/cra-to-nx/jest.config.js @@ -0,0 +1,14 @@ +module.exports = { + displayName: 'cra-to-nx', + preset: '../../jest.preset.js', + globals: { + 'ts-jest': { + tsConfig: '/tsconfig.spec.json', + }, + }, + transform: { + '^.+\\.[tj]sx?$': 'ts-jest', + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'], + coverageDirectory: '../../coverage/projects/cra-to-nx', +}; diff --git a/packages/cra-to-nx/package.json b/packages/cra-to-nx/package.json new file mode 100644 index 00000000000000..80a05e13c4299b --- /dev/null +++ b/packages/cra-to-nx/package.json @@ -0,0 +1,23 @@ +{ + "name": "cra-to-nx", + "version": "0.0.1", + "repository": { + "type": "git", + "url": "git+https://github.com/nrwl/add-nx.git" + }, + "main": "src/index.js", + "typings": "src/index.d.ts", + "bin": { + "cra-to-nx": "src/index.js" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/nrwl/add-nx/issues" + }, + "dependencies": { + "tslib": "2.3.0", + "@nrwl/workspace": "*", + "fs-extra": "^9.1.0", + "yargs-parser": "^20.0.0" + } +} \ No newline at end of file diff --git a/packages/cra-to-nx/project.json b/packages/cra-to-nx/project.json new file mode 100644 index 00000000000000..0efbe67080c8ce --- /dev/null +++ b/packages/cra-to-nx/project.json @@ -0,0 +1,53 @@ +{ + "root": "packages/cra-to-nx", + "sourceRoot": "packages/cra-to-nx/src", + "projectType": "library", + "targets": { + "lint": { + "executor": "@nrwl/linter:eslint", + "options": { + "lintFilePatterns": ["packages/cra-to-nx/**/*.ts"] + } + }, + "test": { + "executor": "@nrwl/jest:jest", + "outputs": ["coverage/packages/cra-to-nx"], + "options": { + "jestConfig": "packages/cra-to-nx/jest.config.js", + "passWithNoTests": true + } + }, + "build-base": { + "executor": "@nrwl/js:tsc", + "outputs": ["{options.outputPath}"], + "options": { + "outputPath": "build/packages/cra-to-nx", + "tsConfig": "packages/cra-to-nx/tsconfig.lib.json", + "packageJson": "packages/cra-to-nx/package.json", + "main": "packages/cra-to-nx/src/index.ts", + "assets": ["packages/cra-to-nx/*.md", "packages/cra-to-nx/package.json"] + } + }, + "build": { + "executor": "@nrwl/workspace:run-commands", + "outputs": ["build/packages/cra-to-nx"], + "options": { + "commands": [ + { + "command": "node ./scripts/chmod build/packages/cra-to-nx/src/index.js" + }, + { + "command": "node ./scripts/copy-readme.js cra-to-nx" + } + ], + "parallel": false + } + }, + "publish": { + "executor": "@nrwl/workspace:run-commands", + "options": { + "command": "node tools/scripts/publish.js cra-to-nx {args.ver} {args.tag} {args.local}" + } + } + } +} diff --git a/packages/cra-to-nx/src/index.ts b/packages/cra-to-nx/src/index.ts new file mode 100644 index 00000000000000..943ca63d318f94 --- /dev/null +++ b/packages/cra-to-nx/src/index.ts @@ -0,0 +1,16 @@ +#!/usr/bin/env node +import { createNxWorkspaceForReact } from './lib/cra-to-nx'; +import * as yargsParser from 'yargs-parser'; + +export * from './lib/cra-to-nx'; + +const args = yargsParser(process.argv); + +createNxWorkspaceForReact(args) + .then(() => { + process.exit(0); + }) + .catch((e) => { + console.log(e); + process.exit(1); + }); diff --git a/packages/cra-to-nx/src/lib/add-cra-commands-to-nx.ts b/packages/cra-to-nx/src/lib/add-cra-commands-to-nx.ts new file mode 100644 index 00000000000000..c8a63a5304a2e0 --- /dev/null +++ b/packages/cra-to-nx/src/lib/add-cra-commands-to-nx.ts @@ -0,0 +1,13 @@ +import { readJsonSync, writeJsonSync } from 'fs-extra'; + +export function addCRAcracoScriptsToPackageJson(appName: string) { + const packageJson = readJsonSync(`apps/${appName}/package.json`); + packageJson.scripts = { + ...packageJson.scripts, + start: 'craco start', + serve: 'npm start', + build: `BUILD_PATH=../../dist/apps/${appName} craco build`, + test: 'craco test', + }; + writeJsonSync(`apps/${appName}/package.json`, packageJson, { spaces: 2 }); +} diff --git a/packages/cra-to-nx/src/lib/check-for-uncommitted-changes.ts b/packages/cra-to-nx/src/lib/check-for-uncommitted-changes.ts new file mode 100644 index 00000000000000..0b17571ebf21b2 --- /dev/null +++ b/packages/cra-to-nx/src/lib/check-for-uncommitted-changes.ts @@ -0,0 +1,13 @@ +import { execSync } from "child_process"; + +export function checkForUncommittedChanges() { + const gitResult = execSync(`git status --porcelain`); + if (gitResult.length > 0) { + console.log('โ—๏ธ Careful!'); + console.log('You have uncommited changes in your repository.'); + console.log(''); + console.log(gitResult.toString()); + console.log('Please commit your changes before running the migrator!'); + process.exit(1); + } +} diff --git a/packages/cra-to-nx/src/lib/clean-up-files.ts b/packages/cra-to-nx/src/lib/clean-up-files.ts new file mode 100644 index 00000000000000..acdffd1aaf74a7 --- /dev/null +++ b/packages/cra-to-nx/src/lib/clean-up-files.ts @@ -0,0 +1,16 @@ +import { removeSync } from 'fs-extra'; +import * as fs from 'fs'; + +export function cleanUpFiles(appName: string) { + // Delete targets from project since we delegate to npm scripts. + const data = fs.readFileSync(`apps/${appName}/project.json`); + const json = JSON.parse(data.toString()); + delete json.targets; + fs.writeFileSync( + `apps/${appName}/project.json`, + JSON.stringify(json, null, 2) + ); + + removeSync('temp-workspace'); + removeSync('workspace.json'); +} diff --git a/packages/cra-to-nx/src/lib/cra-to-nx.ts b/packages/cra-to-nx/src/lib/cra-to-nx.ts new file mode 100644 index 00000000000000..b0c4405cca3f25 --- /dev/null +++ b/packages/cra-to-nx/src/lib/cra-to-nx.ts @@ -0,0 +1,187 @@ +#!/usr/bin/env node +import { fileExists } from '@nrwl/workspace/src/utilities/fileutils'; +import { output } from '@nrwl/workspace/src/utilities/output'; +import { execSync } from 'child_process'; +import { + copySync, + existsSync, + moveSync, + readJsonSync, + removeSync, + readdirSync, +} from 'fs-extra'; + +import { addCRAcracoScriptsToPackageJson } from './add-cra-commands-to-nx'; +import { checkForUncommittedChanges } from './check-for-uncommitted-changes'; +import { setupE2eProject } from './setup-e2e-project'; +import { readNameFromPackageJson } from './read-name-from-package-json'; +import { setupTsConfig } from './tsconfig-setup'; +import { writeCracoConfig } from './write-craco-config'; +import { cleanUpFiles } from './clean-up-files'; + +let packageManager: string; +function checkPackageManager() { + packageManager = existsSync('yarn.lock') + ? 'yarn' + : existsSync('pnpm-lock.yaml') + ? 'pnpm' + : 'npm'; +} + +function addDependency(dep: string, dev?: boolean) { + output.log({ title: `๐Ÿ“ฆ Adding dependency: ${dep}` }); + if (packageManager === 'yarn') { + execSync(`yarn add ${dev ? '-D ' : ''}${dep}`, { stdio: [0, 1, 2] }); + } else if (packageManager === 'pnpm') { + execSync(`pnpm i ${dev ? '--save-dev ' : ''}${dep}`, { stdio: [0, 1, 2] }); + } else { + execSync(`npm i --force ${dev ? '--save-dev ' : ''}${dep}`, { + stdio: [0, 1, 2], + }); + } +} + +export async function createNxWorkspaceForReact(options: Record) { + checkForUncommittedChanges(); + checkPackageManager(); + + output.log({ title: '๐Ÿณ Nx initialization' }); + + let appIsJs = true; + + if (fileExists(`tsconfig.json`)) { + appIsJs = false; + } + + const reactAppName = readNameFromPackageJson(); + const packageJson = readJsonSync('package.json'); + const deps = { + ...packageJson.dependencies, + ...packageJson.devDependencies, + }; + const isCRA5 = /^[^~]?5/.test(deps['react-scripts']); + + execSync( + `npx -y create-nx-workspace@latest temp-workspace --appName=${reactAppName} --preset=react --style=css --nx-cloud --packageManager=${packageManager}`, + { stdio: [0, 1, 2] } + ); + + output.log({ title: '๐Ÿ‘‹ Welcome to Nx!' }); + + output.log({ title: '๐Ÿงน Clearing unused files' }); + + copySync(`temp-workspace/apps/${reactAppName}/project.json`, 'project.json'); + removeSync(`temp-workspace/apps/${reactAppName}/`); + removeSync('node_modules'); + + output.log({ title: '๐Ÿšš Moving your React app in your new Nx workspace' }); + + const requiredCraFiles = [ + 'project.json', + 'package.json', + 'src', + 'public', + appIsJs ? null : 'tsconfig.json', + packageManager === 'yarn' ? 'yarn.lock' : null, + packageManager === 'pnpm' ? 'pnpm-lock.yaml' : null, + packageManager === 'npm' ? 'package-lock.json' : null, + ]; + + const optionalCraFiles = ['README.md']; + + const filesToMove = [...requiredCraFiles, ...optionalCraFiles].filter( + Boolean + ); + + filesToMove.forEach((f) => { + try { + moveSync(f, `temp-workspace/apps/${reactAppName}/${f}`, { + overwrite: true, + }); + } catch (error) { + if (requiredCraFiles.includes(f)) { + throw error; + } + } + }); + + process.chdir('temp-workspace/'); + + output.log({ title: '๐Ÿคน Add CRA craco scripts to package.json' }); + + addCRAcracoScriptsToPackageJson(reactAppName); + + output.log({ title: '๐Ÿง‘โ€๐Ÿ”ง Customize webpack ' + deps['react-scripts'] }); + + writeCracoConfig(reactAppName, isCRA5); + + output.log({ + title: '๐Ÿ›ฌ Skip CRA preflight check since Nx manages the monorepo', + }); + + execSync(`echo "SKIP_PREFLIGHT_CHECK=true" > .env`, { stdio: [0, 1, 2] }); + + output.log({ title: '๐Ÿงถ Add all node_modules to .gitignore' }); + + execSync(`echo "node_modules" >> .gitignore`, { stdio: [0, 1, 2] }); + + process.chdir('../'); + + output.log({ title: '๐Ÿšš Folder restructuring.' }); + + readdirSync('./temp-workspace').forEach((f) => { + moveSync(`temp-workspace/${f}`, `./${f}`, { overwrite: true }); + }); + + output.log({ title: '๐Ÿงน Cleaning up.' }); + + cleanUpFiles(reactAppName); + + output.log({ title: "๐Ÿ“ƒ Extend the app's tsconfig.json from the base" }); + + setupTsConfig(reactAppName); + + if (options.e2e) { + output.log({ title: '๐Ÿ“ƒ Setup e2e tests' }); + setupE2eProject(reactAppName); + } else { + removeSync(`apps/${reactAppName}-e2e`); + } + + output.log({ title: '๐Ÿ™‚ Please be patient, one final step remaining!' }); + + output.log({ + title: '๐Ÿงถ Adding npm packages to your new Nx workspace to support CRA', + }); + + addDependency('react-scripts', true); + addDependency('@testing-library/jest-dom', true); + addDependency('eslint-config-react-app', true); + addDependency('@craco/craco', true); + addDependency('web-vitals', true); + addDependency('jest-watch-typeahead', true); // Only for ts apps? + + output.log({ + title: '๐ŸŽ‰ Done!', + }); + output.note({ + title: 'First time using Nx? Check out this interactive Nx tutorial.', + bodyLines: [ + `https://nx.dev/react/tutorial/01-create-application`, + ` `, + `Prefer watching videos? Check out this free Nx course on Egghead.io.`, + `https://egghead.io/playlists/scale-react-development-with-nx-4038`, + ], + }); + + output.note({ + title: 'Or, you can try the commands!', + bodyLines: [ + `npx nx serve ${reactAppName}`, + `npx nx build ${reactAppName}`, + `npx nx test ${reactAppName}`, + ` `, + `https://nx.dev/latest/react/migration/migration-cra#10-try-the-commands`, + ], + }); +} diff --git a/packages/cra-to-nx/src/lib/read-name-from-package-json.ts b/packages/cra-to-nx/src/lib/read-name-from-package-json.ts new file mode 100644 index 00000000000000..3719bd324ccca7 --- /dev/null +++ b/packages/cra-to-nx/src/lib/read-name-from-package-json.ts @@ -0,0 +1,18 @@ +import { fileExists } from '@nrwl/workspace/src/utilities/fileutils'; +import * as fs from 'fs'; + +export function readNameFromPackageJson(): string { + let appName = 'webapp'; + if (fileExists('package.json')) { + const data = fs.readFileSync('package.json'); + const json = JSON.parse(data.toString()); + if ( + json['name'] && + json['name'].length && + json['name'].replace(/\s/g, '').length + ) { + appName = json['name'].replace(/\s/g, ''); + } + } + return appName; +} diff --git a/packages/cra-to-nx/src/lib/setup-e2e-project.ts b/packages/cra-to-nx/src/lib/setup-e2e-project.ts new file mode 100644 index 00000000000000..c915c82c3c40c3 --- /dev/null +++ b/packages/cra-to-nx/src/lib/setup-e2e-project.ts @@ -0,0 +1,46 @@ +import { fileExists } from '@nrwl/workspace/src/utilities/fileutils'; +import * as fs from 'fs'; + +export function setupE2eProject(appName: string) { + const data = fs.readFileSync(`apps/${appName}-e2e/project.json`); + const json = JSON.parse(data.toString()); + json.targets.e2e = { + executor: '@nrwl/workspace:run-commands', + options: { + commands: [`nx e2e-serve ${appName}-e2e`, `nx e2e-run ${appName}-e2e`], + }, + }; + json.targets['e2e-run'] = { + executor: '@nrwl/cypress:cypress', + options: { + cypressConfig: `apps/${appName}-e2e/cypress.json`, + tsConfig: `apps/${appName}-e2e/tsconfig.e2e.json`, + baseUrl: 'http://localhost:3000', + }, + }; + json.targets['e2e-serve'] = { + executor: '@nrwl/workspace:run-commands', + options: { + commands: [`nx serve ${appName}`], + readyWhen: 'can now view', + }, + }; + fs.writeFileSync( + `apps/${appName}-e2e/project.json`, + JSON.stringify(json, null, 2) + ); + + if (fileExists(`apps/${appName}-e2e/src/integration/app.spec.ts`)) { + const integrationE2eTest = ` + describe('${appName}', () => { + beforeEach(() => cy.visit('/')); + it('should contain a body', () => { + cy.get('body').should('exist'); + }); + });`; + fs.writeFileSync( + `apps/${appName}-e2e/src/integration/app.spec.ts`, + integrationE2eTest + ); + } +} diff --git a/packages/cra-to-nx/src/lib/tsconfig-setup.ts b/packages/cra-to-nx/src/lib/tsconfig-setup.ts new file mode 100644 index 00000000000000..9a898b62d34890 --- /dev/null +++ b/packages/cra-to-nx/src/lib/tsconfig-setup.ts @@ -0,0 +1,113 @@ +import { fileExists } from '@nrwl/workspace/src/utilities/fileutils'; +import * as fs from 'fs'; + +const defaultTsConfig = { + extends: '../../tsconfig.base.json', + compilerOptions: { + jsx: 'react', + allowJs: true, + esModuleInterop: true, + allowSyntheticDefaultImports: true, + }, + files: [], + include: [], + references: [ + { + path: './tsconfig.app.json', + }, + { + path: './tsconfig.spec.json', + }, + ], +}; + +const defaultTsConfigApp = { + extends: './tsconfig.json', + compilerOptions: { + outDir: '../../dist/out-tsc', + types: ['node'], + }, + files: [ + '../../node_modules/@nrwl/react/typings/cssmodule.d.ts', + '../../node_modules/@nrwl/react/typings/image.d.ts', + ], + exclude: ['**/*.spec.ts', '**/*.spec.tsx'], + include: ['**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx'], +}; + +const defaultTsConfigSpec = { + extends: './tsconfig.json', + compilerOptions: { + outDir: '../../dist/out-tsc', + module: 'commonjs', + types: ['jest', 'node'], + }, + include: [ + '**/*.spec.ts', + '**/*.spec.tsx', + '**/*.spec.js', + '**/*.spec.jsx', + '**/*.d.ts', + ], + files: [ + '../../node_modules/@nrwl/react/typings/cssmodule.d.ts', + '../../node_modules/@nrwl/react/typings/image.d.ts', + ], +}; + +export function setupTsConfig(appName: string) { + if (fileExists(`apps/${appName}/tsconfig.json`)) { + const data = fs.readFileSync(`apps/${appName}/tsconfig.json`); + const json = JSON.parse(data.toString()); + json.extends = '../../tsconfig.base.json'; + if (json.compilerOptions) { + json.compilerOptions.jsx = 'react'; + } else { + json.compilerOptions = { + jsx: 'react', + allowJs: true, + esModuleInterop: true, + allowSyntheticDefaultImports: true, + }; + } + fs.writeFileSync( + `apps/${appName}/tsconfig.json`, + JSON.stringify(json, null, 2) + ); + } else { + fs.writeFileSync( + `apps/${appName}/tsconfig.json`, + JSON.stringify(defaultTsConfig, null, 2) + ); + } + + if (fileExists(`apps/${appName}/tsconfig.app.json`)) { + const data = fs.readFileSync(`apps/${appName}/tsconfig.app.json`); + const json = JSON.parse(data.toString()); + json.extends = './tsconfig.json'; + fs.writeFileSync( + `apps/${appName}/tsconfig.app.json`, + JSON.stringify(json, null, 2) + ); + } else { + fs.writeFileSync( + `apps/${appName}/tsconfig.app.json`, + JSON.stringify(defaultTsConfigApp, null, 2) + ); + } + + if (fileExists(`apps/${appName}/tsconfig.spec.json`)) { + const data = fs.readFileSync(`apps/${appName}/tsconfig.spec.json`); + const json = JSON.parse(data.toString()); + json.extends = './tsconfig.json'; + fs.writeFileSync( + `apps/${appName}/tsconfig.spec.json`, + JSON.stringify(json, null, 2) + ); + } else { + fs.writeFileSync( + `apps/${appName}/tsconfig.spec.json`, + JSON.stringify(defaultTsConfigSpec, null, 2) + ); + } +} diff --git a/packages/cra-to-nx/src/lib/write-craco-config.ts b/packages/cra-to-nx/src/lib/write-craco-config.ts new file mode 100644 index 00000000000000..2e789b5e8ba226 --- /dev/null +++ b/packages/cra-to-nx/src/lib/write-craco-config.ts @@ -0,0 +1,61 @@ +import * as fs from 'fs'; + +export function writeCracoConfig(appName: string, isCRA5: boolean) { + const configOverride = ` + const path = require('path'); + const TsConfigPathsPlugin = require('tsconfig-paths-webpack-plugin'); + const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin'); + module.exports = { + webpack: { + configure: (config) => { + // Remove guard against importing modules outside of \`src\`. + // Needed for workspace projects. + config.resolve.plugins = config.resolve.plugins.filter( + (plugin) => !(plugin instanceof ModuleScopePlugin) + ); + // Add support for importing workspace projects. + config.resolve.plugins.push( + new TsConfigPathsPlugin({ + configFile: path.resolve(__dirname, 'tsconfig.json'), + extensions: ['.ts', '.tsx', '.js', '.jsx'], + mainFields: ['module', 'main'], + }) + ); + ${ + isCRA5 + ? ` + // Replace include option for babel loader with exclude + // so babel will handle workspace projects as well. + config.module.rules[1].oneOf.forEach((r) => { + if (r.loader && r.loader.indexOf('babel') !== -1) { + r.exclude = /node_modules/; + delete r.include; + } + });` + : ` + // Replace include option for babel loader with exclude + // so babel will handle workspace projects as well. + config.module.rules.forEach((r) => { + if (r.oneOf) { + const babelLoader = r.oneOf.find( + (rr) => rr.loader.indexOf('babel-loader') !== -1 + ); + babelLoader.exclude = /node_modules/; + delete babelLoader.include; + } + }); + ` + } + return config; + }, + }, + jest: { + configure: (config) => { + config.resolver = '@nrwl/jest/plugins/resolver'; + return config; + }, + }, + }; + `; + fs.writeFileSync(`apps/${appName}/craco.config.js`, configOverride); +} diff --git a/packages/cra-to-nx/tsconfig.json b/packages/cra-to-nx/tsconfig.json new file mode 100644 index 00000000000000..62ebbd946474ce --- /dev/null +++ b/packages/cra-to-nx/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.base.json", + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/packages/cra-to-nx/tsconfig.lib.json b/packages/cra-to-nx/tsconfig.lib.json new file mode 100644 index 00000000000000..037d796f286235 --- /dev/null +++ b/packages/cra-to-nx/tsconfig.lib.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node"] + }, + "exclude": ["**/*.spec.ts"], + "include": ["**/*.ts"] +} diff --git a/packages/cra-to-nx/tsconfig.spec.json b/packages/cra-to-nx/tsconfig.spec.json new file mode 100644 index 00000000000000..559410b96af678 --- /dev/null +++ b/packages/cra-to-nx/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "**/*.spec.ts", + "**/*.spec.tsx", + "**/*.spec.js", + "**/*.spec.jsx", + "**/*.d.ts" + ] +} diff --git a/packages/make-angular-cli-faster/.eslintrc.json b/packages/make-angular-cli-faster/.eslintrc.json new file mode 100644 index 00000000000000..9afd5d63f09f7d --- /dev/null +++ b/packages/make-angular-cli-faster/.eslintrc.json @@ -0,0 +1,5 @@ +{ + "extends": "../../.eslintrc", + "rules": {}, + "ignorePatterns": ["!**/*"] +} diff --git a/packages/make-angular-cli-faster/LICENSE b/packages/make-angular-cli-faster/LICENSE new file mode 100644 index 00000000000000..85bd11dc55edad --- /dev/null +++ b/packages/make-angular-cli-faster/LICENSE @@ -0,0 +1,22 @@ +(The MIT License) + +Copyright (c) 2017-2021 Narwhal Technologies Inc. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/make-angular-cli-faster/README.md b/packages/make-angular-cli-faster/README.md new file mode 100644 index 00000000000000..364ef1f4d842c4 --- /dev/null +++ b/packages/make-angular-cli-faster/README.md @@ -0,0 +1,19 @@ +# `> npx make-angular-cli-faster` + +

+ +
+ +[![License](https://img.shields.io/npm/l/@nrwl/workspace.svg?style=flat-square)]() +[![NPM Version](https://badge.fury.io/js/%40nrwl%2Fworkspace.svg)](https://www.npmjs.com/@nrwl/workspace) +[![Join the chat at https://gitter.im/nrwl-nx/community](https://badges.gitter.im/nrwl-nx/community.svg)](https://gitter.im/nrwl-nx/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) +[![Join us @nrwl/community on slack](https://img.shields.io/badge/slack-%40nrwl%2Fcommunity-brightgreen)](https://join.slack.com/t/nrwlcommunity/shared_invite/enQtNzU5MTE4OTQwOTk0LTgxY2E0ZWYzMWE0YzA5ZDA2MWM1NDVhNmI2ZWMyYmZhNWJiODk3MjkxZjY3MzU5ZjRmM2NmNWU1OTgyZmE4Mzc) + +
+ +An easy way to add Nx computation caching to an Angular CLI project without changing anything about the project. + + +## Learn More + +* See [https://github.com/nrwl/nx](https://github.com/nrwl/nx) to learn more about Nx. diff --git a/packages/make-angular-cli-faster/jest.config.js b/packages/make-angular-cli-faster/jest.config.js new file mode 100644 index 00000000000000..3d3d92d60c3d34 --- /dev/null +++ b/packages/make-angular-cli-faster/jest.config.js @@ -0,0 +1,9 @@ +module.exports = { + name: 'make-angular-cli-faster', + preset: '../../jest.config.js', + transform: { + '^.+\\.[tj]sx?$': 'ts-jest', + }, + moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'], + coverageDirectory: '../../coverage/projects/make-angular-cli-faster', +}; diff --git a/packages/make-angular-cli-faster/package.json b/packages/make-angular-cli-faster/package.json new file mode 100644 index 00000000000000..a67e238928b458 --- /dev/null +++ b/packages/make-angular-cli-faster/package.json @@ -0,0 +1,34 @@ +{ + "name": "make-angular-cli-faster", + "version": "0.0.1", + "description": "Make Angular CLI faster by enabling distributed computation caching", + "repository": { + "type": "git", + "url": "git+https://github.com/nrwl/add-nx.git" + }, + "keywords": [ + "Monorepo", + "Angular", + "Web", + "Node", + "Nest", + "Jest", + "Cypress", + "CLI" + ], + "bin": { + "make-angular-cli-faster": "./make-angular-cli-faster.js" + }, + "author": "Victor Savkin", + "license": "MIT", + "bugs": { + "url": "https://github.com/nrwl/add-nx/issues" + }, + "homepage": "https://nx.dev", + "dependencies": { + "yargs-parser": "20.0.0", + "yargs": "15.4.1", + "enquirer": "^2.3.6", + "@nrwl/workspace": "*" + } +} diff --git a/packages/make-angular-cli-faster/project.json b/packages/make-angular-cli-faster/project.json new file mode 100644 index 00000000000000..8a22e1d521f582 --- /dev/null +++ b/packages/make-angular-cli-faster/project.json @@ -0,0 +1,38 @@ +{ + "root": "packages/make-angular-cli-faster", + "sourceRoot": "packages/make-angular-cli-faster/src", + "projectType": "library", + "generators": {}, + "targets": { + "build-base": { + "executor": "@nrwl/js:tsc", + "options": { + "outputPath": "build/packages/make-angular-cli-faster", + "tsConfig": "packages/make-angular-cli-faster/tsconfig.lib.json", + "packageJson": "packages/make-angular-cli-faster/package.json", + "main": "packages/make-angular-cli-faster/src/index.ts", + "assets": [ + "packages/make-angular-cli-faster/LICENSE", + "packages/make-angular-cli-faster/*.md" + ], + "srcRootForCompilationRoot": "packages/make-angular-cli-faster/src" + }, + "outputs": ["{options.outputPath}"] + }, + "build": { + "executor": "@nrwl/workspace:run-commands", + "outputs": ["build/packages/make-angular-cli-faster"], + "options": { + "commands": [ + { + "command": "node ./scripts/chmod build/packages/make-angular-cli-faster/src/make-angular-cli-faster.js" + }, + { + "command": "node ./scripts/copy-readme.js make-angular-cli-faster" + } + ], + "parallel": false + } + } + } +} diff --git a/packages/make-angular-cli-faster/publish.sh b/packages/make-angular-cli-faster/publish.sh new file mode 100755 index 00000000000000..07111bddeda6ac --- /dev/null +++ b/packages/make-angular-cli-faster/publish.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash +echo "Publishing make-angular-cli-faster@$1" + +nx build make-angular-cli-faster +cd dist/projects/make-angular-cli-faster + +if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i "" "s|REPLACE|$1|g" package.json +else + sed -i "s|REPLACE|$1|g" package.json +fi + +npm adduser +npm publish --access public --tag latest + diff --git a/packages/make-angular-cli-faster/src/make-angular-cli-faster.ts b/packages/make-angular-cli-faster/src/make-angular-cli-faster.ts new file mode 100644 index 00000000000000..40b849940bd391 --- /dev/null +++ b/packages/make-angular-cli-faster/src/make-angular-cli-faster.ts @@ -0,0 +1,95 @@ +#!/usr/bin/env node + +import { statSync } from 'fs'; +import { execSync } from 'child_process'; +import * as yargsParser from 'yargs-parser'; + +const enquirer = require('enquirer'); + +const parsedArgs = yargsParser(process.argv, { + string: ['version'], + boolean: ['verbose'], +}); + +function isYarn() { + try { + statSync('yarn.lock'); + return true; + } catch (e) { + return false; + } +} + +function addDependency(dep: string) { + const stdio = parsedArgs.verbose ? [0, 1, 2] : ['ignore', 'ignore', 'ignore']; + if (isYarn()) { + execSync(`yarn add -D ${dep}`, { stdio: stdio as any }); + } else { + execSync(`npm i --save-dev ${dep}`, { stdio: stdio as any }); + } +} + +function addNxCloud() { + return enquirer + .prompt([ + { + name: 'NxCloud', + message: `Use the free tier of the distributed cache provided by Nx Cloud?`, + type: 'list', + choices: [ + { + value: 'yes', + name: + 'Yes [Faster command execution, faster CI. Learn more at https://nx.app]', + }, + + { + value: 'no', + name: 'No [Only use local computation cache]', + }, + ], + default: 'no', + }, + ]) + .then((a: { NxCloud: 'yes' | 'no' }) => a.NxCloud === 'yes'); +} + +async function main() { + const version = parsedArgs.version ? parsedArgs.version : `latest`; + + const output = require('@nrwl/workspace/src/utils/output').output; + output.log({ title: 'Nx initialization' }); + + addDependency(`nx@${version}`); + addDependency(`@nrwl/cli@${version}`); + addDependency(`@nrwl/workspace@${version}`); + execSync(`nx g @nrwl/workspace:ng-add --preserve-angular-cli-layout`, { + stdio: [0, 1, 2], + }); + + if (await addNxCloud()) { + output.log({ title: 'Nx Cloud initialization' }); + addDependency(`@nrwl/nx-cloud`); + execSync(`nx g @nrwl/nx-cloud:init`, { stdio: [0, 1, 2] }); + } + + execSync('npm install', { stdio: ['ignore', 'ignore', 'ignore'] }); + + output.success({ + title: 'Angular CLI is faster now!', + bodyLines: [ + `Execute 'npx ng build' twice to see the computation caching in action.`, + `Learn more about computation caching, how it is shared with your teammates,`, + `and how it can speed up your CI by up to 10 times at https://nx.dev/angular`, + ], + }); +} + +main() + .then(() => { + process.exit(0); + }) + .catch((e) => { + console.log(e); + process.exit(1); + }); diff --git a/packages/make-angular-cli-faster/tsconfig.json b/packages/make-angular-cli-faster/tsconfig.json new file mode 100644 index 00000000000000..58bd2c97a66f5e --- /dev/null +++ b/packages/make-angular-cli-faster/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "types": ["node", "jest"] + }, + "include": [], + "files": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ] +} diff --git a/packages/make-angular-cli-faster/tsconfig.lib.json b/packages/make-angular-cli-faster/tsconfig.lib.json new file mode 100644 index 00000000000000..037d796f286235 --- /dev/null +++ b/packages/make-angular-cli-faster/tsconfig.lib.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "outDir": "../../dist/out-tsc", + "declaration": true, + "types": ["node"] + }, + "exclude": ["**/*.spec.ts"], + "include": ["**/*.ts"] +} diff --git a/packages/make-angular-cli-faster/tsconfig.spec.json b/packages/make-angular-cli-faster/tsconfig.spec.json new file mode 100644 index 00000000000000..559410b96af678 --- /dev/null +++ b/packages/make-angular-cli-faster/tsconfig.spec.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "module": "commonjs", + "types": ["jest", "node"] + }, + "include": [ + "**/*.spec.ts", + "**/*.spec.tsx", + "**/*.spec.js", + "**/*.spec.jsx", + "**/*.d.ts" + ] +} diff --git a/scripts/e2e-build-package-publish.ts b/scripts/e2e-build-package-publish.ts index 4e0e21210b9ee9..df430ef0d44461 100644 --- a/scripts/e2e-build-package-publish.ts +++ b/scripts/e2e-build-package-publish.ts @@ -161,31 +161,36 @@ function build(nxVersion: string) { 'js', ].map((f) => `${f}/src/utils/versions.js`), ...[ - 'react', - 'next', - 'web', - 'jest', - 'node', - 'express', - 'nest', - 'cypress', - 'storybook', + 'add-nx-to-monorepo', 'angular', - 'workspace', 'cli', - 'linter', - 'tao', + 'cra-to-nx', + 'create-nx-plugin', + 'create-nx-workspace', + 'cypress', + 'detox', 'devkit', 'eslint-plugin-nx', - 'create-nx-workspace', - 'create-nx-plugin', + 'express', + 'jest', + 'js', + 'linter', + 'make-angular-cli-faster', + 'nest', + 'next', + 'node', 'nx-plugin', 'react-native', - 'detox', - 'js', + 'react', + 'storybook', + 'tao', + 'web', + 'workspace', ].map((f) => `${f}/package.json`), 'create-nx-workspace/bin/create-nx-workspace.js', 'create-nx-plugin/bin/create-nx-plugin.js', + 'make-angular-cli-faster/src/make-angular-cli-faster.js', + 'add-nx-to-monorepo/src/add-nx-to-monorepo.js' ].map((f) => `${BUILD_DIR}/${f}`); files.forEach((f) => { diff --git a/scripts/nx-release.js b/scripts/nx-release.js index d5d006a70e780c..a8e3ff61773a0e 100755 --- a/scripts/nx-release.js +++ b/scripts/nx-release.js @@ -52,6 +52,8 @@ if (!parsedArgs.local) { function updatePackageJsonFiles(parsedVersion, isLocal) { let pkgFiles = [ 'package.json', + 'build/npm/add-nx-to-monorepo/package.json', + 'build/npm/cra-to-nx/package.json', 'build/npm/create-nx-workspace/package.json', 'build/npm/create-nx-plugin/package.json', 'build/npm/jest/package.json', @@ -70,6 +72,7 @@ function updatePackageJsonFiles(parsedVersion, isLocal) { 'build/npm/devkit/package.json', 'build/npm/eslint-plugin-nx/package.json', 'build/npm/linter/package.json', + 'build/npm/make-angular-cli-faster/package.json', 'build/npm/nx-plugin/package.json', 'build/npm/nx/package.json', 'build/npm/react-native/package.json', diff --git a/scripts/package.sh b/scripts/package.sh index 6f620225670962..5cea3d11f039d8 100755 --- a/scripts/package.sh +++ b/scripts/package.sh @@ -28,6 +28,8 @@ if [[ "$OSTYPE" == "darwin"* ]]; then sed -i "" "s|ANGULAR_CLI_VERSION|$ANGULAR_CLI_VERSION|g" create-nx-plugin/bin/create-nx-plugin.js sed -i "" "s|TYPESCRIPT_VERSION|$TYPESCRIPT_VERSION|g" create-nx-plugin/bin/create-nx-plugin.js sed -i "" "s|PRETTIER_VERSION|$PRETTIER_VERSION|g" create-nx-plugin/bin/create-nx-plugin.js + sed -i "" "s|NX_VERSION|$NX_VERSION|g" make-angular-cli-faster/src/make-angular-cli-faster.js + sed -i "" "s|NX_VERSION|$NX_VERSION|g" add-nx-to-monorepo/src/add-nx-to-monorepo.js else sed -i "s|exports.nxVersion = '\*';|exports.nxVersion = '$NX_VERSION';|g" {react,next,web,jest,node,linter,express,nest,cypress,storybook,angular,workspace,nx-plugin,react-native,detox,js}/src/utils/versions.js sed -i "s|\*|$NX_VERSION|g" {nx,react,next,web,jest,node,express,nest,cypress,storybook,angular,workspace,cli,linter,tao,devkit,eslint-plugin-nx,create-nx-workspace,create-nx-plugin,nx-plugin,react-native,detox,js}/package.json @@ -39,13 +41,15 @@ else sed -i "s|ANGULAR_CLI_VERSION|$ANGULAR_CLI_VERSION|g" create-nx-plugin/bin/create-nx-plugin.js sed -i "s|TYPESCRIPT_VERSION|$TYPESCRIPT_VERSION|g" create-nx-plugin/bin/create-nx-plugin.js sed -i "s|PRETTIER_VERSION|$PRETTIER_VERSION|g" create-nx-plugin/bin/create-nx-plugin.js + sed -i "s|NX_VERSION|$NX_VERSION|g" make-angular-cli-faster/src/make-angular-cli-faster.js + sed -i "s|NX_VERSION|$NX_VERSION|g" add-nx-to-monorepo/src/add-nx-to-monorepo.js fi if [[ $NX_VERSION == "*" ]]; then if [[ "$OSTYPE" == "darwin"* ]]; then - sed -E -i "" "s|\"@nrwl\/([^\"]+)\": \"\\*\"|\"@nrwl\/\1\": \"file:$PWD\/\1\"|" {nx,jest,web,react,next,node,express,nest,cypress,storybook,angular,workspace,linter,cli,tao,devkit,eslint-plugin-nx,create-nx-workspace,create-nx-plugin,nx-plugin,react-native,detox}/package.json + sed -E -i "" "s|\"@nrwl\/([^\"]+)\": \"\\*\"|\"@nrwl\/\1\": \"file:$PWD\/\1\"|" {nx,jest,web,react,next,node,express,nest,cypress,storybook,angular,workspace,linter,cli,tao,devkit,eslint-plugin-nx,create-nx-workspace,create-nx-plugin,nx-plugin,react-native,detox,cra-to-nx,make-angular-cli-faster,create-nx-workspace}/package.json else echo $PWD - sed -E -i "s|\"@nrwl\/([^\"]+)\": \"\\*\"|\"@nrwl\/\1\": \"file:$PWD\/\1\"|" {nx,jest,web,react,next,node,express,nest,cypress,storybook,angular,workspace,linter,cli,tao,devkit,eslint-plugin-nx,create-nx-workspace,create-nx-plugin,nx-plugin,react-native,detox}/package.json + sed -E -i "s|\"@nrwl\/([^\"]+)\": \"\\*\"|\"@nrwl\/\1\": \"file:$PWD\/\1\"|" {nx,jest,web,react,next,node,express,nest,cypress,storybook,angular,workspace,linter,cli,tao,devkit,eslint-plugin-nx,create-nx-workspace,create-nx-plugin,nx-plugin,react-native,detox,cra-to-nx,make-angular-cli-faster,create-nx-workspace}/package.json fi fi diff --git a/workspace.json b/workspace.json index afaab9b2214706..c94ce88f15de48 100644 --- a/workspace.json +++ b/workspace.json @@ -1,8 +1,10 @@ { "version": 2, "projects": { + "add-nx-to-monorepo": "packages/add-nx-to-monorepo", "angular": "packages/angular", "cli": "packages/cli", + "cra-to-nx": "packages/cra-to-nx", "create-nx-plugin": "packages/create-nx-plugin", "create-nx-workspace": "packages/create-nx-workspace", "cypress": "packages/cypress", @@ -36,6 +38,7 @@ "jest": "packages/jest", "js": "packages/js", "linter": "packages/linter", + "make-angular-cli-faster": "packages/make-angular-cli-faster", "nest": "packages/nest", "next": "packages/next", "node": "packages/node",