feat(angular): set angular devkit packages as peer deps (#14723)
This commit is contained in:
parent
b7fe0a2311
commit
fe6ffa20d9
@ -1,6 +1,6 @@
|
||||
import {
|
||||
cleanupProject,
|
||||
newProject,
|
||||
newAngularProject,
|
||||
runCLI,
|
||||
uniq,
|
||||
updateFile,
|
||||
@ -9,7 +9,7 @@ import * as path from 'path';
|
||||
|
||||
describe('Angular Package', () => {
|
||||
describe('linting', () => {
|
||||
beforeAll(() => newProject());
|
||||
beforeAll(() => newAngularProject());
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
it('should support eslint and pass linting on the standard generated code', async () => {
|
||||
|
||||
@ -1,20 +1,16 @@
|
||||
import {
|
||||
expectTestsPass,
|
||||
newProject,
|
||||
cleanupProject,
|
||||
expectTestsPass,
|
||||
newAngularProject,
|
||||
readJson,
|
||||
runCLI,
|
||||
runCLIAsync,
|
||||
uniq,
|
||||
updateFile,
|
||||
removeFile,
|
||||
checkFilesDoNotExist,
|
||||
isNotWindows,
|
||||
readJson,
|
||||
createFile,
|
||||
} from '@nrwl/e2e/utils';
|
||||
|
||||
describe('Angular Config', () => {
|
||||
beforeAll(() => newProject());
|
||||
beforeAll(() => newAngularProject());
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
it('should upgrade the config correctly', async () => {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import {
|
||||
cleanupProject,
|
||||
newProject,
|
||||
newAngularProject,
|
||||
promisifiedTreeKill,
|
||||
readProjectConfig,
|
||||
runCLI,
|
||||
@ -16,7 +16,7 @@ import { names } from '@nrwl/devkit';
|
||||
describe('Angular Projects', () => {
|
||||
let proj: string;
|
||||
|
||||
beforeAll(() => (proj = newProject()));
|
||||
beforeAll(() => (proj = newAngularProject()));
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
it('should serve the host and remote apps successfully, even with a shared library with a secondary entry point between them', async () => {
|
||||
|
||||
@ -3,7 +3,7 @@ import {
|
||||
cleanupProject,
|
||||
getSize,
|
||||
killPorts,
|
||||
newProject,
|
||||
newAngularProject,
|
||||
promisifiedTreeKill,
|
||||
readFile,
|
||||
runCLI,
|
||||
@ -20,7 +20,7 @@ import { names } from '@nrwl/devkit';
|
||||
describe('Angular Projects', () => {
|
||||
let proj: string;
|
||||
|
||||
beforeAll(() => (proj = newProject()));
|
||||
beforeAll(() => (proj = newAngularProject()));
|
||||
afterAll(() => cleanupProject());
|
||||
|
||||
it('should generate an app, a lib, link them, build, serve and test both correctly', async () => {
|
||||
|
||||
@ -2,7 +2,7 @@ import {
|
||||
checkFilesDoNotExist,
|
||||
cleanupProject,
|
||||
createFile,
|
||||
newProject,
|
||||
newAngularProject,
|
||||
runCLI,
|
||||
uniq,
|
||||
updateFile,
|
||||
@ -17,7 +17,7 @@ describe('Angular Cypress Component Tests', () => {
|
||||
const buildableLibName = uniq('cy-angular-buildable-lib');
|
||||
|
||||
beforeAll(async () => {
|
||||
projectName = newProject({ name: uniq('cy-ng') });
|
||||
projectName = newAngularProject({ name: uniq('cy-ng') });
|
||||
runCLI(`generate @nrwl/angular:app ${appName} --no-interactive`);
|
||||
runCLI(
|
||||
`generate @nrwl/angular:component fancy-component --project=${appName} --no-interactive`
|
||||
|
||||
@ -1,13 +1,9 @@
|
||||
import {
|
||||
checkFilesExist,
|
||||
cleanupProject,
|
||||
newProject,
|
||||
readFile,
|
||||
newAngularProject,
|
||||
runCLI,
|
||||
uniq,
|
||||
updateFile,
|
||||
} from '@nrwl/e2e/utils';
|
||||
import { classify } from '@nrwl/workspace/src/utils/strings';
|
||||
|
||||
describe('Move Angular Project', () => {
|
||||
let proj: string;
|
||||
@ -16,7 +12,7 @@ describe('Move Angular Project', () => {
|
||||
let newPath: string;
|
||||
|
||||
beforeAll(() => {
|
||||
proj = newProject();
|
||||
proj = newAngularProject();
|
||||
app1 = uniq('app1');
|
||||
app2 = uniq('app2');
|
||||
newPath = `subfolder/${app2}`;
|
||||
|
||||
@ -2,7 +2,7 @@ import {
|
||||
cleanupProject,
|
||||
expectTestsPass,
|
||||
getSelectedPackageManager,
|
||||
newProject,
|
||||
newAngularProject,
|
||||
readJson,
|
||||
runCLI,
|
||||
runCLIAsync,
|
||||
@ -10,15 +10,12 @@ import {
|
||||
} from '@nrwl/e2e/utils';
|
||||
|
||||
describe('Angular Package', () => {
|
||||
let previousPM = process.env.SELECTED_PM;
|
||||
describe('ngrx', () => {
|
||||
beforeAll(() => {
|
||||
process.env.SELECTED_PM = 'npm';
|
||||
newProject();
|
||||
newAngularProject();
|
||||
});
|
||||
afterAll(() => {
|
||||
cleanupProject();
|
||||
process.env.SELECTED_PM = previousPM;
|
||||
});
|
||||
|
||||
it('should work', async () => {
|
||||
|
||||
@ -3,7 +3,7 @@ process.env.SELECTED_CLI = 'angular';
|
||||
import {
|
||||
cleanupProject,
|
||||
listFiles,
|
||||
newProject,
|
||||
newAngularProject,
|
||||
readFile,
|
||||
removeFile,
|
||||
runCLI,
|
||||
@ -118,10 +118,8 @@ describe('Tailwind support', () => {
|
||||
updateFile(tailwindConfigPath, tailwindConfigUpdated);
|
||||
};
|
||||
|
||||
let previousPM = process.env.SELECTED_PM;
|
||||
beforeAll(() => {
|
||||
process.env.SELECTED_PM = 'npm';
|
||||
project = newProject();
|
||||
project = newAngularProject();
|
||||
|
||||
// Create tailwind config in the workspace root
|
||||
createWorkspaceTailwindConfigFile();
|
||||
@ -129,7 +127,6 @@ describe('Tailwind support', () => {
|
||||
|
||||
afterAll(() => {
|
||||
cleanupProject();
|
||||
process.env.SELECTED_PM = previousPM;
|
||||
});
|
||||
|
||||
describe('Libraries', () => {
|
||||
|
||||
@ -1,4 +1,10 @@
|
||||
import { newProject, runCLI, uniq, runCLIAsync } from '@nrwl/e2e/utils';
|
||||
import {
|
||||
newAngularProject,
|
||||
newProject,
|
||||
runCLI,
|
||||
runCLIAsync,
|
||||
uniq,
|
||||
} from '@nrwl/e2e/utils';
|
||||
|
||||
describe('Jest root projects', () => {
|
||||
const myapp = uniq('myapp');
|
||||
@ -6,7 +12,7 @@ describe('Jest root projects', () => {
|
||||
|
||||
describe('angular', () => {
|
||||
beforeAll(() => {
|
||||
newProject();
|
||||
newAngularProject();
|
||||
});
|
||||
|
||||
it('should test root level app projects', async () => {
|
||||
|
||||
@ -3,6 +3,7 @@ import {
|
||||
checkFilesExist,
|
||||
cleanupProject,
|
||||
createFile,
|
||||
newAngularProject,
|
||||
newProject,
|
||||
readFile,
|
||||
readJson,
|
||||
@ -185,7 +186,7 @@ describe('Linter', () => {
|
||||
}, 1000000);
|
||||
|
||||
it('lint plugin should ensure module boundaries', () => {
|
||||
const proj = newProject();
|
||||
const proj = newAngularProject();
|
||||
const myapp = uniq('myapp');
|
||||
const myapp2 = uniq('myapp2');
|
||||
const mylib = uniq('mylib');
|
||||
@ -515,7 +516,7 @@ export function tslibC(): string {
|
||||
const myapp = uniq('myapp');
|
||||
const mylib = uniq('mylib');
|
||||
|
||||
newProject();
|
||||
newAngularProject();
|
||||
runCLI(`generate @nrwl/angular:app ${myapp} --rootProject=true`);
|
||||
|
||||
let rootEslint = readJson('.eslintrc.json');
|
||||
|
||||
@ -2,7 +2,6 @@ import {
|
||||
joinPathFragments,
|
||||
parseJson,
|
||||
ProjectConfiguration,
|
||||
ProjectsConfigurations,
|
||||
readJsonFile,
|
||||
workspaceRoot,
|
||||
} from '@nrwl/devkit';
|
||||
@ -365,6 +364,21 @@ export function newProject({
|
||||
}
|
||||
}
|
||||
|
||||
export function newAngularProject({
|
||||
name = uniq('proj'),
|
||||
packageManager = getSelectedPackageManager(),
|
||||
} = {}): string {
|
||||
const projScope = newProject({ name, packageManager });
|
||||
|
||||
const angularPackages = [
|
||||
'@angular-devkit/core',
|
||||
'@angular-devkit/schematics',
|
||||
'@schematics/angular',
|
||||
];
|
||||
packageInstall(angularPackages.join(` `), projScope, 'latest');
|
||||
return projScope;
|
||||
}
|
||||
|
||||
export function newLernaWorkspace({
|
||||
name = uniq('lerna-proj'),
|
||||
packageManager = getSelectedPackageManager(),
|
||||
|
||||
@ -197,6 +197,12 @@
|
||||
"version": "15.5.0-beta.0",
|
||||
"description": "Update the @angular/cli package version to ~15.1.0.",
|
||||
"factory": "./src/migrations/update-15-5-0/update-angular-cli"
|
||||
},
|
||||
"install-required-packages": {
|
||||
"cli": "nx",
|
||||
"version": "15.7.0-beta.1",
|
||||
"description": "Install the required angular-devkit packages as we do not directly depend on them anymore",
|
||||
"factory": "./src/migrations/update-15-7-0/install-required-packages"
|
||||
}
|
||||
},
|
||||
"packageJsonUpdates": {
|
||||
|
||||
@ -36,7 +36,6 @@
|
||||
"migrations": "./migrations.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular-devkit/schematics": "~15.1.0",
|
||||
"@nrwl/cypress": "file:../cypress",
|
||||
"@nrwl/devkit": "file:../devkit",
|
||||
"@nrwl/jest": "file:../jest",
|
||||
@ -44,7 +43,6 @@
|
||||
"@nrwl/webpack": "file:../webpack",
|
||||
"@nrwl/workspace": "file:../workspace",
|
||||
"@phenomnomnominal/tsquery": "4.1.1",
|
||||
"@schematics/angular": "~15.1.0",
|
||||
"chalk": "^4.1.0",
|
||||
"chokidar": "^3.5.1",
|
||||
"http-server": "^14.1.0",
|
||||
@ -58,7 +56,12 @@
|
||||
"webpack-merge": "5.7.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@nguniversal/builders": "~15.1.0",
|
||||
"@angular-devkit/architect": ">= 0.1400.0 < 0.1600.0",
|
||||
"@angular-devkit/build-angular": ">= 14.0.0 < 16.0.0",
|
||||
"@angular-devkit/schematics": ">= 14.0.0 < 16.0.0",
|
||||
"@schematics/angular": ">= 14.0.0 < 16.0.0",
|
||||
"@angular-devkit/core": ">= 14.0.0 < 16.0.0",
|
||||
"@nguniversal/builders": ">= 14.0.0 < 16.0.0",
|
||||
"rxjs": "^6.5.3 || ^7.5.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
|
||||
@ -0,0 +1,213 @@
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import { readJson, updateJson } from '@nrwl/devkit';
|
||||
import installRequiredPackages from './install-required-packages';
|
||||
|
||||
describe('installed-required-packages', () => {
|
||||
it('should install the dependencies if they do not exist for v15', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
updateJson(tree, 'package.json', (pkg) => ({
|
||||
...pkg,
|
||||
dependencies: {
|
||||
'@angular/core': '~15.0.0',
|
||||
},
|
||||
devDependencies: {
|
||||
'@angular/cli': '~15.0.0',
|
||||
},
|
||||
}));
|
||||
|
||||
// ACT
|
||||
await installRequiredPackages(tree);
|
||||
|
||||
// ASSERT
|
||||
const pkgJson = readJson(tree, 'package.json');
|
||||
expect(pkgJson.dependencies).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"@angular/core": "~15.0.0",
|
||||
}
|
||||
`);
|
||||
expect(pkgJson.devDependencies).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"@angular-devkit/core": "~15.0.0",
|
||||
"@angular-devkit/schematics": "~15.0.0",
|
||||
"@angular/cli": "~15.0.0",
|
||||
"@schematics/angular": "~15.0.0",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should install the dependencies if they do not exist for v14', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
updateJson(tree, 'package.json', (pkg) => ({
|
||||
...pkg,
|
||||
dependencies: {
|
||||
'@angular/core': '~14.0.0',
|
||||
},
|
||||
devDependencies: {
|
||||
'@angular/cli': '~14.0.0',
|
||||
},
|
||||
}));
|
||||
|
||||
// ACT
|
||||
await installRequiredPackages(tree);
|
||||
|
||||
// ASSERT
|
||||
const pkgJson = readJson(tree, 'package.json');
|
||||
expect(pkgJson.dependencies).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"@angular/core": "~14.0.0",
|
||||
}
|
||||
`);
|
||||
expect(pkgJson.devDependencies).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"@angular-devkit/core": "~14.0.0",
|
||||
"@angular-devkit/schematics": "~14.0.0",
|
||||
"@angular/cli": "~14.0.0",
|
||||
"@schematics/angular": "~14.0.0",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should not install the dependencies if they exist for v15', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
updateJson(tree, 'package.json', (pkg) => ({
|
||||
...pkg,
|
||||
dependencies: {
|
||||
'@angular/core': '~15.0.0',
|
||||
},
|
||||
devDependencies: {
|
||||
'@angular/cli': '~15.0.0',
|
||||
'@angular-devkit/core': '~15.0.0',
|
||||
'@angular-devkit/schematics': '~15.0.0',
|
||||
'@schematics/angular': '~15.0.0',
|
||||
},
|
||||
}));
|
||||
|
||||
// ACT
|
||||
await installRequiredPackages(tree);
|
||||
|
||||
// ASSERT
|
||||
const pkgJson = readJson(tree, 'package.json');
|
||||
expect(pkgJson.dependencies).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"@angular/core": "~15.0.0",
|
||||
}
|
||||
`);
|
||||
expect(pkgJson.devDependencies).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"@angular-devkit/core": "~15.0.0",
|
||||
"@angular-devkit/schematics": "~15.0.0",
|
||||
"@angular/cli": "~15.0.0",
|
||||
"@schematics/angular": "~15.0.0",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should not install the dependencies if they exist for v14', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
updateJson(tree, 'package.json', (pkg) => ({
|
||||
...pkg,
|
||||
dependencies: {
|
||||
'@angular/core': '~14.0.0',
|
||||
},
|
||||
devDependencies: {
|
||||
'@angular/cli': '~14.0.0',
|
||||
'@angular-devkit/core': '~14.0.0',
|
||||
'@angular-devkit/schematics': '~14.0.0',
|
||||
'@schematics/angular': '~14.0.0',
|
||||
},
|
||||
}));
|
||||
|
||||
// ACT
|
||||
await installRequiredPackages(tree);
|
||||
|
||||
// ASSERT
|
||||
const pkgJson = readJson(tree, 'package.json');
|
||||
expect(pkgJson.dependencies).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"@angular/core": "~14.0.0",
|
||||
}
|
||||
`);
|
||||
expect(pkgJson.devDependencies).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"@angular-devkit/core": "~14.0.0",
|
||||
"@angular-devkit/schematics": "~14.0.0",
|
||||
"@angular/cli": "~14.0.0",
|
||||
"@schematics/angular": "~14.0.0",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should install the missing dependencies for v15', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
updateJson(tree, 'package.json', (pkg) => ({
|
||||
...pkg,
|
||||
dependencies: {
|
||||
'@angular/core': '~15.0.0',
|
||||
},
|
||||
devDependencies: {
|
||||
'@angular/cli': '~15.0.0',
|
||||
'@angular-devkit/core': '~15.0.0',
|
||||
'@schematics/angular': '~15.0.0',
|
||||
},
|
||||
}));
|
||||
|
||||
// ACT
|
||||
await installRequiredPackages(tree);
|
||||
|
||||
// ASSERT
|
||||
const pkgJson = readJson(tree, 'package.json');
|
||||
expect(pkgJson.dependencies).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"@angular/core": "~15.0.0",
|
||||
}
|
||||
`);
|
||||
expect(pkgJson.devDependencies).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"@angular-devkit/core": "~15.0.0",
|
||||
"@angular-devkit/schematics": "~15.0.0",
|
||||
"@angular/cli": "~15.0.0",
|
||||
"@schematics/angular": "~15.0.0",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('should not install the missing dependencies for v14', async () => {
|
||||
// ARRANGE
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
updateJson(tree, 'package.json', (pkg) => ({
|
||||
...pkg,
|
||||
dependencies: {
|
||||
'@angular/core': '~14.0.0',
|
||||
},
|
||||
devDependencies: {
|
||||
'@angular/cli': '~14.0.0',
|
||||
'@angular-devkit/core': '~14.0.0',
|
||||
'@schematics/angular': '~14.0.0',
|
||||
},
|
||||
}));
|
||||
|
||||
// ACT
|
||||
await installRequiredPackages(tree);
|
||||
|
||||
// ASSERT
|
||||
const pkgJson = readJson(tree, 'package.json');
|
||||
expect(pkgJson.dependencies).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"@angular/core": "~14.0.0",
|
||||
}
|
||||
`);
|
||||
expect(pkgJson.devDependencies).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"@angular-devkit/core": "~14.0.0",
|
||||
"@angular-devkit/schematics": "~14.0.0",
|
||||
"@angular/cli": "~14.0.0",
|
||||
"@schematics/angular": "~14.0.0",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,32 @@
|
||||
import type { Tree } from '@nrwl/devkit';
|
||||
import { addDependenciesToPackageJson, readJson } from '@nrwl/devkit';
|
||||
import { getInstalledAngularMajorVersion } from '../../generators/utils/version-utils';
|
||||
import { getPkgVersionForAngularMajorVersion } from '../../utils/version-utils';
|
||||
|
||||
export default async function (tree: Tree) {
|
||||
const packagesToInstall = [
|
||||
'@angular-devkit/core',
|
||||
'@angular-devkit/schematics',
|
||||
'@schematics/angular',
|
||||
];
|
||||
const pkgJson = readJson(tree, 'package.json');
|
||||
|
||||
const angularMajorVersion = getInstalledAngularMajorVersion(tree);
|
||||
const angularDevkitVersion = getPkgVersionForAngularMajorVersion(
|
||||
'angularDevkitVersion',
|
||||
angularMajorVersion
|
||||
);
|
||||
|
||||
const angularCliVersion =
|
||||
pkgJson.devDependencies['@angular/cli'] ??
|
||||
pkgJson.dependencies['@angular/cli'] ??
|
||||
angularDevkitVersion;
|
||||
|
||||
const filteredPackages: Record<string, string> = packagesToInstall
|
||||
.filter(
|
||||
(pkg) => !pkgJson.devDependencies[pkg] && !pkgJson.dependencies[pkg]
|
||||
)
|
||||
.reduce((allPkgs, pkg) => ({ ...allPkgs, [pkg]: angularCliVersion }), {});
|
||||
|
||||
addDependenciesToPackageJson(tree, {}, { ...filteredPackages });
|
||||
}
|
||||
@ -6,7 +6,10 @@ Object {
|
||||
"@nrwl/angular": "0.0.1",
|
||||
},
|
||||
"devDependencies": Object {
|
||||
"@angular-devkit/core": "~15.1.0",
|
||||
"@angular-devkit/schematics": "~15.1.0",
|
||||
"@nrwl/workspace": "0.0.1",
|
||||
"@schematics/angular": "~15.1.0",
|
||||
"nx": "0.0.1",
|
||||
"prettier": "^2.6.2",
|
||||
"typescript": "~4.8.2",
|
||||
|
||||
@ -4,7 +4,7 @@ import {
|
||||
Tree,
|
||||
} from '@nrwl/devkit';
|
||||
import { Preset } from '../utils/presets';
|
||||
import { nxVersion } from '../../utils/versions';
|
||||
import { angularCliVersion, nxVersion } from '../../utils/versions';
|
||||
import { getNpmPackageVersion } from '../utils/get-npm-package-version';
|
||||
import { NormalizedSchema } from './new';
|
||||
import { join } from 'path';
|
||||
@ -89,7 +89,14 @@ function getPresetDependencies(preset: string, version?: string) {
|
||||
|
||||
case Preset.AngularMonorepo:
|
||||
case Preset.AngularStandalone:
|
||||
return { dependencies: { '@nrwl/angular': nxVersion }, dev: {} };
|
||||
return {
|
||||
dependencies: { '@nrwl/angular': nxVersion },
|
||||
dev: {
|
||||
'@angular-devkit/core': angularCliVersion,
|
||||
'@angular-devkit/schematics': angularCliVersion,
|
||||
'@schematics/angular': angularCliVersion,
|
||||
},
|
||||
};
|
||||
|
||||
case Preset.Express:
|
||||
return { dependencies: {}, dev: { '@nrwl/express': nxVersion } };
|
||||
|
||||
@ -33,6 +33,7 @@ function check() {
|
||||
'packages/workspace/src/command-line/report.spec.ts',
|
||||
'packages/workspace/src/core/file-command-line-utils.ts',
|
||||
'packages/workspace/src/generators/preset/preset.ts',
|
||||
'packages/workspace/src/generators/new/generate-preset.ts',
|
||||
'packages/workspace/src/generators/init/init.ts',
|
||||
'packages/workspace/src/utils/update-task.ts',
|
||||
'packages/workspace/src/migrations/update-8-3-0/update-8-3-0.spec.ts',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user