Skip to content

Commit

Permalink
feat(react): remove unnecessary dependencies from @nrwl/react (#13525)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaysoo authored Dec 1, 2022
1 parent 4c723de commit cded83b
Show file tree
Hide file tree
Showing 69 changed files with 963 additions and 641 deletions.
34 changes: 34 additions & 0 deletions docs/generated/devkit/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ It only uses language primitives and immutable objects
- [defaultTasksRunner](../../devkit/index#defaulttasksrunner)
- [detectPackageManager](../../devkit/index#detectpackagemanager)
- [detectWorkspaceScope](../../devkit/index#detectworkspacescope)
- [ensurePackage](../../devkit/index#ensurepackage)
- [extractLayoutDirectory](../../devkit/index#extractlayoutdirectory)
- [formatFiles](../../devkit/index#formatfiles)
- [generateFiles](../../devkit/index#generatefiles)
Expand Down Expand Up @@ -1164,6 +1165,39 @@ Detect workspace scope from the package.json name

---

### ensurePackage

**ensurePackage**(`tree`, `pkg`, `requiredVersion`, `options?`): `Promise`<`void`\>

Ensure that dependencies and devDependencies from package.json are installed at the required versions.

For example:

```typescript
ensureDependencies(tree, {}, { '@nrwl/jest': nxVersion });
```

This will check that @nrwl/jest@<nxVersion> exists in devDependencies.
If it exists then function returns, otherwise it will install the package before continuing.
When running with --dryRun, the function will throw when dependencies are missing.

#### Parameters

| Name | Type | Description |
| :------------------------ | :-------------------------------- | :------------------------------------- |
| `tree` | [`Tree`](../../devkit/index#tree) | the file system tree |
| `pkg` | `string` | the package to check (e.g. @nrwl/jest) |
| `requiredVersion` | `string` | the version to check |
| `options` | `Object` | |
| `options.dev?` | `boolean` | - |
| `options.throwOnMissing?` | `boolean` | - |

#### Returns

`Promise`<`void`\>

---

### extractLayoutDirectory

**extractLayoutDirectory**(`directory`): `Object`
Expand Down
2 changes: 1 addition & 1 deletion docs/generated/packages/devkit.json

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions docs/generated/packages/webpack.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@
"description": "Init Webpack Plugin.",
"type": "object",
"properties": {
"uiFramework": {
"type": "string",
"description": "UI Framework to use for Vite.",
"enum": ["react", "none"],
"x-prompt": "What UI framework plugin should Webpack use?"
},
"compiler": {
"type": "string",
"enum": ["babel", "swc", "tsc"],
Expand Down
1 change: 1 addition & 0 deletions packages/devkit/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ export { readJsonFile, writeJsonFile } from 'nx/src/utils/fileutils';
*/
export {
addDependenciesToPackageJson,
ensurePackage,
removeDependenciesFromPackageJson,
} from './src/utils/package-json';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export async function* combineAsyncIterableIterators(
...iterators: { 0: AsyncIterableIterator<any> } & AsyncIterableIterator<any>[]
) {
export async function* combineAsyncIterableIterators<T = any>(
...iterators: { 0: AsyncIterableIterator<T> } & AsyncIterableIterator<T>[]
): AsyncGenerator<T> {
let [options] = iterators;
if (typeof options.next === 'function') {
options = Object.create(null);
Expand Down
4 changes: 4 additions & 0 deletions packages/devkit/src/utils/async-iterable/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './create-async-iterable';
export * from './combine-async-iteratable-iterators';
export * from './map-async-iteratable';
export * from './tap-async-iteratable';
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export async function* mapAsyncIterable<T = any, I = any, O = any>(
index?: number,
data?: AsyncIterable<T> | AsyncIterableIterator<T>
) => O
) {
): AsyncIterable<O> | AsyncIterableIterator<O> {
async function* f() {
const generator = data[Symbol.asyncIterator] || data[Symbol.iterator];
const iterator = generator.call(data);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { tapAsyncIterator } from './tap-async-iteratable';
import { tapAsyncIterable } from './tap-async-iteratable';

describe('tapAsyncIterator', () => {
it('should tap values', async () => {
Expand All @@ -11,7 +11,7 @@ describe('tapAsyncIterator', () => {
const tapped = [];
const results = [];

const c = tapAsyncIterator(f(), (x) => {
const c = tapAsyncIterable(f(), (x) => {
tapped.push(`tap: ${x}`);
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { mapAsyncIterable } from './map-async-iteratable';

export async function* tapAsyncIterator<T = any, I = any, O = any>(
export async function* tapAsyncIterable<T = any, I = any, O = any>(
data: AsyncIterable<T> | AsyncIterableIterator<T>,
fn: (input: I) => void
) {
): AsyncIterable<T> | AsyncIterableIterator<T> {
return yield* mapAsyncIterable(data, (x) => {
fn(x);
return x;
Expand Down
41 changes: 40 additions & 1 deletion packages/devkit/src/utils/package-json.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Tree } from 'nx/src/generators/tree';
import { readJson, writeJson } from 'nx/src/generators/utils/json';
import { addDependenciesToPackageJson } from './package-json';
import { addDependenciesToPackageJson, ensurePackage } from './package-json';
import { createTree } from 'nx/src/generators/testing-utils/create-tree';

describe('addDependenciesToPackageJson', () => {
Expand Down Expand Up @@ -310,3 +310,42 @@ describe('addDependenciesToPackageJson', () => {
expect(installTask).toBeDefined();
});
});

describe('ensureDependencies', () => {
let tree: Tree;

beforeEach(() => {
tree = createTree();
});

it('should return without error when dependency is satisfied', async () => {
writeJson(tree, 'package.json', {
devDependencies: {
'@nrwl/vite': '15.0.0',
},
});

await expect(
ensurePackage(tree, '@nrwl/vite', '>=15.0.0', {
throwOnMissing: true,
})
).resolves.toBeUndefined();
});

it('should throw when dependencies are missing', async () => {
writeJson(tree, 'package.json', {});

await expect(() =>
ensurePackage(tree, '@nrwl/does-not-exist', '>=15.0.0', {
throwOnMissing: true,
})
).rejects.toThrow(/-D( -W)? @nrwl\/does-not-exist@>=15.0.0/);

await expect(() =>
ensurePackage(tree, '@nrwl/does-not-exist', '>=15.0.0', {
dev: false,
throwOnMissing: true,
})
).rejects.toThrow('@nrwl/does-not-exist@>=15.0.0');
});
});
74 changes: 73 additions & 1 deletion packages/devkit/src/utils/package-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import { readJson, updateJson } from 'nx/src/generators/utils/json';
import { installPackagesTask } from '../tasks/install-packages-task';
import type { Tree } from 'nx/src/generators/tree';
import { GeneratorCallback } from 'nx/src/config/misc-interfaces';
import { coerce, gt } from 'semver';
import { coerce, gt, satisfies } from 'semver';
import { getPackageManagerCommand } from 'nx/src/utils/package-manager';
import { execSync } from 'child_process';

const NON_SEMVER_TAGS = {
'*': 2,
Expand Down Expand Up @@ -274,3 +276,73 @@ function requiresRemovingOfPackages(

return needsDepsUpdate || needsDevDepsUpdate;
}

/**
* @typedef EnsurePackageOptions
* @type {object}
* @property {boolean} dev indicate if the package is a dev dependency
* @property {throwOnMissing} boolean throws an error when the packag is missing
*/

/**
* Ensure that dependencies and devDependencies from package.json are installed at the required versions.
*
* For example:
* ```typescript
* ensureDependencies(tree, {}, { '@nrwl/jest': nxVersion })
* ```
* This will check that @nrwl/jest@<nxVersion> exists in devDependencies.
* If it exists then function returns, otherwise it will install the package before continuing.
* When running with --dryRun, the function will throw when dependencies are missing.
*
* @param tree the file system tree
* @param pkg the package to check (e.g. @nrwl/jest)
* @param requiredVersion the version to check
* @param {EnsurePackageOptions} options
* @returns {Promise<void>}
*/
export async function ensurePackage(
tree: Tree,
pkg: string,
requiredVersion: string,
options: {
dev?: boolean;
throwOnMissing?: boolean;
} = {}
): Promise<void> {
let version: string;

// Read package and version from root package.json file.
const packageJson = readJson(tree, 'package.json');
const dev = options.dev ?? true;
const throwOnMissing = options.throwOnMissing ?? !!process.env.NX_DRY_RUN; // NX_DRY_RUN is set in `packages/nx/src/command-line/generate.ts`
const pmc = getPackageManagerCommand();
const field = dev ? 'devDependencies' : 'dependencies';

version = packageJson[field]?.[pkg];

// If package not found, try to resolve it using Node and get its version.
if (!version) {
try {
version = require(`${pkg}/package.json`).version;
} catch {
// ignore
}
}

if (!satisfies(version, requiredVersion)) {
const installCmd = `${
dev ? pmc.addDev : pmc.add
} ${pkg}@${requiredVersion}`;
if (throwOnMissing) {
throw new Error(
`Required package ${pkg}@${requiredVersion} is missing. Run "${installCmd}", and then try again.`
);
} else {
execSync(installCmd, {
cwd: tree.root,
stdio: [0, 1, 2],
});
}
}
}
2 changes: 1 addition & 1 deletion packages/esbuild/src/executors/esbuild/esbuild.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { normalizeOptions } from './lib/normalize';

import { EsBuildExecutorOptions } from './schema';
import { removeSync, writeJsonSync } from 'fs-extra';
import { createAsyncIterable } from '@nrwl/js/src/utils/async-iterable/create-async-iterable';
import { createAsyncIterable } from '@nrwl/devkit/src/utils/async-iterable';
import { buildEsbuildOptions } from './lib/build-esbuild-options';
import { getExtraDependencies } from './lib/get-extra-dependencies';
import { DependentBuildableProjectNode } from '@nrwl/workspace/src/utilities/buildable-libs-utils';
Expand Down
1 change: 0 additions & 1 deletion packages/js/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
"builders": "./executors.json",
"dependencies": {
"@nrwl/devkit": "file:../devkit",
"@nrwl/jest": "file:../jest",
"@nrwl/linter": "file:../linter",
"@nrwl/workspace": "file:../workspace",
"chalk": "4.1.0",
Expand Down
4 changes: 3 additions & 1 deletion packages/js/src/generators/library/library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
addDependenciesToPackageJson,
addProjectConfiguration,
convertNxGenerator,
ensurePackage,
extractLayoutDirectory,
formatFiles,
generateFiles,
Expand All @@ -18,7 +19,6 @@ import {
writeJson,
} from '@nrwl/devkit';
import { getImportPath } from 'nx/src/utils/path';
import { jestProjectGenerator } from '@nrwl/jest';
import { Linter, lintProjectGenerator } from '@nrwl/linter';
import { runTasksInSerial } from '@nrwl/workspace/src/utilities/run-tasks-in-serial';
import {
Expand Down Expand Up @@ -293,6 +293,8 @@ async function addJest(
tree: Tree,
options: NormalizedSchema
): Promise<GeneratorCallback> {
await ensurePackage(tree, '@nrwl/jest', nxVersion);
const { jestProjectGenerator } = await import('@nrwl/jest');
return await jestProjectGenerator(tree, {
...options,
project: options.name,
Expand Down
2 changes: 1 addition & 1 deletion packages/js/src/utils/swc/compile-swc.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { cacheDir, ExecutorContext, logger } from '@nrwl/devkit';
import { exec, execSync } from 'child_process';
import { removeSync } from 'fs-extra';
import { createAsyncIterable } from '../async-iterable/create-async-iterable';
import { createAsyncIterable } from '@nrwl/devkit/src/utils/async-iterable';
import { NormalizedSwcExecutorOptions, SwcCliOptions } from '../schema';
import { printDiagnostics } from '../typescript/print-diagnostics';
import { runTypeCheck, TypeCheckOptions } from '../typescript/run-type-check';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
TypeScriptCompilationOptions,
} from '@nrwl/workspace/src/utilities/typescript/compilation';
import type { Diagnostic } from 'typescript';
import { createAsyncIterable } from '../async-iterable/create-async-iterable';
import { createAsyncIterable } from '@nrwl/devkit/src/utils/async-iterable';
import { NormalizedExecutorOptions } from '../schema';

const TYPESCRIPT_FOUND_N_ERRORS_WATCHING_FOR_FILE_CHANGES = 6194;
Expand Down
1 change: 0 additions & 1 deletion packages/linter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
},
"dependencies": {
"@nrwl/devkit": "file:../devkit",
"@nrwl/jest": "file:../jest",
"@phenomnomnominal/tsquery": "4.1.1",
"nx": "file:../nx",
"tmp": "~0.2.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
addDependenciesToPackageJson,
addProjectConfiguration,
convertNxGenerator,
ensurePackage,
formatFiles,
generateFiles,
joinPathFragments,
Expand All @@ -11,17 +12,22 @@ import {
Tree,
updateWorkspaceConfiguration,
} from '@nrwl/devkit';
import { addPropertyToJestConfig, jestProjectGenerator } from '@nrwl/jest';
import { getRelativePathToRootTsConfig } from '@nrwl/workspace/src/utilities/typescript';
import { join } from 'path';
import { workspaceLintPluginDir } from '../../utils/workspace-lint-rules';
import { swcCoreVersion, swcNodeVersion } from 'nx/src/utils/versions';
import { nxVersion } from '../../utils/versions';

export const WORKSPACE_RULES_PROJECT_NAME = 'eslint-rules';

export const WORKSPACE_PLUGIN_DIR = 'tools/eslint-rules';

export async function lintWorkspaceRulesProjectGenerator(tree: Tree) {
await ensurePackage(tree, '@nrwl/jest/', nxVersion);
const { addPropertyToJestConfig, jestProjectGenerator } = await import(
'@nrwl/jest'
);

// Noop if the workspace rules project already exists
try {
readProjectConfiguration(tree, WORKSPACE_RULES_PROJECT_NAME);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ import {
Tree,
visitNotIgnoredFiles,
} from '@nrwl/devkit';
import { addPropertyToJestConfig } from '@nrwl/jest';
import { tsquery } from '@phenomnomnominal/tsquery';

export default async function eslint8Updates(tree: Tree) {
try {
const { addPropertyToJestConfig } = await import('@nrwl/jest');
const existingJestConfigPath = normalizePath(
'tools/eslint-rules/jest.config.js'
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import {
import { createTreeWithEmptyV1Workspace } from '@nrwl/devkit/testing';
import { exampleRootTslintJson } from '@nrwl/linter';
import { conversionGenerator } from './convert-tslint-to-eslint';
import * as devkit from '@nrwl/devkit';

/**
* Don't run actual child_process implementation of installPackagesTask()
*/
jest.mock('child_process');
// jest.mock('child_process');

const appProjectName = 'nest-app-1';
const appProjectRoot = `apps/${appProjectName}`;
Expand Down Expand Up @@ -101,6 +102,7 @@ describe('convert-tslint-to-eslint', () => {
let host: Tree;

beforeEach(async () => {
jest.spyOn(devkit, 'installPackagesTask');
host = createTreeWithEmptyV1Workspace();

writeJson(host, 'tslint.json', exampleRootTslintJson.raw);
Expand Down
Loading

1 comment on commit cded83b

@vercel
Copy link

@vercel vercel bot commented on cded83b Dec 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-five.vercel.app
nx-dev-git-master-nrwl.vercel.app
nx-dev-nrwl.vercel.app
nx.dev

Please sign in to comment.