feat(angular): support angular v14.0.0-rc.2 (#8883)
This commit is contained in:
parent
daddcde73c
commit
62afcb79b0
@ -299,6 +299,11 @@
|
||||
"default": false,
|
||||
"alias": "t"
|
||||
},
|
||||
"standalone": {
|
||||
"description": "Whether the generated component is standalone.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"viewEncapsulation": {
|
||||
"description": "The view encapsulation strategy to use in the new component.",
|
||||
"enum": ["Emulated", "None", "ShadowDom"],
|
||||
@ -2304,7 +2309,8 @@
|
||||
"properties": {
|
||||
"input": {
|
||||
"type": "string",
|
||||
"description": "The file to include."
|
||||
"description": "The file to include.",
|
||||
"pattern": "\\.[cm]?jsx?$"
|
||||
},
|
||||
"bundleName": {
|
||||
"type": "string",
|
||||
@ -2320,7 +2326,11 @@
|
||||
"additionalProperties": false,
|
||||
"required": ["input"]
|
||||
},
|
||||
{ "type": "string", "description": "The file to include." }
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The file to include.",
|
||||
"pattern": "\\.[cm]?jsx?$"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -2335,7 +2345,8 @@
|
||||
"properties": {
|
||||
"input": {
|
||||
"type": "string",
|
||||
"description": "The file to include."
|
||||
"description": "The file to include.",
|
||||
"pattern": "\\.(?:css|scss|sass|less|styl)$"
|
||||
},
|
||||
"bundleName": {
|
||||
"type": "string",
|
||||
@ -2351,7 +2362,11 @@
|
||||
"additionalProperties": false,
|
||||
"required": ["input"]
|
||||
},
|
||||
{ "type": "string", "description": "The file to include." }
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The file to include.",
|
||||
"pattern": "\\.(?:css|scss|sass|less|styl)$"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
@ -2606,15 +2621,9 @@
|
||||
"description": "Extract all licenses in a separate file.",
|
||||
"default": true
|
||||
},
|
||||
"showCircularDependencies": {
|
||||
"type": "boolean",
|
||||
"description": "Show circular dependency warnings on builds.",
|
||||
"default": false,
|
||||
"x-deprecated": "The recommended method to detect circular dependencies in project code is to use either a lint rule or other external tooling."
|
||||
},
|
||||
"buildOptimizer": {
|
||||
"type": "boolean",
|
||||
"description": "Enables '@angular-devkit/build-optimizer' optimizations when using the 'aot' option.",
|
||||
"description": "Enables advanced build optimizations when using the 'aot' option.",
|
||||
"default": true
|
||||
},
|
||||
"namedChunks": {
|
||||
@ -2829,32 +2838,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"extraEntryPoint": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"input": {
|
||||
"type": "string",
|
||||
"description": "The file to include."
|
||||
},
|
||||
"bundleName": {
|
||||
"type": "string",
|
||||
"pattern": "^[\\w\\-.]*$",
|
||||
"description": "The bundle name for this extra entry point."
|
||||
},
|
||||
"inject": {
|
||||
"type": "boolean",
|
||||
"description": "If the bundle will be referenced in the HTML file.",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["input"]
|
||||
},
|
||||
{ "type": "string", "description": "The file to include." }
|
||||
]
|
||||
},
|
||||
"budget": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@ -85,13 +85,13 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
updateFile('tsconfig.json', JSON.stringify(tsConfig, null, 2));
|
||||
|
||||
// add an extra script file
|
||||
updateFile('src/scripts.ts', 'const x = 1;');
|
||||
updateFile('src/scripts.js', 'const x = 1;');
|
||||
|
||||
// update angular.json
|
||||
const angularJson = readJson('angular.json');
|
||||
angularJson.projects[project].architect.build.options.scripts =
|
||||
angularJson.projects[project].architect.test.options.scripts = [
|
||||
'src/scripts.ts',
|
||||
'src/scripts.js',
|
||||
];
|
||||
angularJson.projects[project].architect.test.options.styles = [
|
||||
'src/styles.css',
|
||||
@ -144,7 +144,6 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
defaultCollection: '@nrwl/angular',
|
||||
packageManager: packageManager,
|
||||
},
|
||||
defaultProject: project,
|
||||
implicitDependencies: {
|
||||
'.eslintrc.json': '*',
|
||||
'package.json': {
|
||||
@ -196,7 +195,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
`apps/${project}/src/assets`,
|
||||
],
|
||||
styles: [`apps/${project}/src/styles.css`],
|
||||
scripts: [`apps/${project}/src/scripts.ts`],
|
||||
scripts: [`apps/${project}/src/scripts.js`],
|
||||
},
|
||||
configurations: {
|
||||
production: {
|
||||
@ -251,7 +250,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
`apps/${project}/src/assets`,
|
||||
],
|
||||
styles: [`apps/${project}/src/styles.css`],
|
||||
scripts: [`apps/${project}/src/scripts.ts`],
|
||||
scripts: [`apps/${project}/src/scripts.js`],
|
||||
},
|
||||
});
|
||||
expect(projectConfig.targets.e2e).toBeUndefined();
|
||||
@ -271,7 +270,7 @@ describe('convert Angular CLI workspace to an Nx workspace', () => {
|
||||
},
|
||||
});
|
||||
|
||||
runCLI('build --configuration production --outputHashing none');
|
||||
runCLI(`build ${project} --configuration production --outputHashing none`);
|
||||
checkFilesExist(`dist/apps/${project}/main.js`);
|
||||
});
|
||||
|
||||
|
||||
@ -193,44 +193,9 @@ describe('Angular Projects', () => {
|
||||
runCLI(
|
||||
`generate @nrwl/angular:library ${childLib} --publishable=true --importPath=@${proj}/${childLib} --no-interactive`
|
||||
);
|
||||
|
||||
// create secondary entrypoint
|
||||
updateFile(
|
||||
`libs/${childLib}/sub/package.json`,
|
||||
`
|
||||
{
|
||||
"ngPackage": {}
|
||||
}
|
||||
`
|
||||
runCLI(
|
||||
`generate @nrwl/angular:secondary-entry-point --name=sub --library=${childLib} --no-interactive`
|
||||
);
|
||||
updateFile(
|
||||
`libs/${childLib}/sub/src/lib/sub.module.ts`,
|
||||
`
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
@NgModule({ imports: [CommonModule] })
|
||||
export class SubModule {}
|
||||
`
|
||||
);
|
||||
|
||||
updateFile(
|
||||
`libs/${childLib}/sub/src/public_api.ts`,
|
||||
`export * from './lib/sub.module';`
|
||||
);
|
||||
|
||||
updateFile(
|
||||
`libs/${childLib}/sub/src/index.ts`,
|
||||
`export * from './public_api';`
|
||||
);
|
||||
|
||||
updateFile(`tsconfig.base.json`, (s) => {
|
||||
return s.replace(
|
||||
`"@${proj}/${childLib}": ["libs/${childLib}/src/index.ts"],`,
|
||||
`"@${proj}/${childLib}": ["libs/${childLib}/src/index.ts"],
|
||||
"@${proj}/${childLib}/sub": ["libs/${childLib}/sub/src/index.ts"],
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
const moduleContent = `
|
||||
import { NgModule } from '@angular/core';
|
||||
|
||||
@ -260,14 +260,10 @@ export function runNgNew(
|
||||
): string {
|
||||
projName = projectName;
|
||||
|
||||
// Use the latest version of the currently supported @angular/cli major version
|
||||
// to cover existing usage out there while avoiding the tests to fail when a new
|
||||
// major comes out and is still not supported
|
||||
const ngCliMajorVersion = coerce(angularCliVersion).major;
|
||||
const npmMajorVersion = getNpmMajorVersion();
|
||||
const command = `npx ${
|
||||
+npmMajorVersion >= 7 ? '--yes' : ''
|
||||
} @angular/cli@${ngCliMajorVersion} new ${projectName} --package-manager=${packageManager}`;
|
||||
} @angular/cli@${angularCliVersion} new ${projectName} --package-manager=${packageManager}`;
|
||||
|
||||
return execSync(command, {
|
||||
cwd: e2eCwd,
|
||||
|
||||
@ -469,7 +469,6 @@ describe('Move Angular Project', () => {
|
||||
expect(moveOutput).toContain(
|
||||
`CREATE apps/${newPath}/src/environments/environment.ts`
|
||||
);
|
||||
expect(moveOutput).toContain(`UPDATE nx.json`);
|
||||
expect(moveOutput).toContain(`UPDATE workspace.json`);
|
||||
});
|
||||
|
||||
|
||||
65
package.json
65
package.json
@ -25,24 +25,24 @@
|
||||
"prepare": "is-ci || husky install"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/architect": "~0.1303.0",
|
||||
"@angular-devkit/build-angular": "~13.3.0",
|
||||
"@angular-devkit/core": "~13.3.0",
|
||||
"@angular-devkit/schematics": "~13.3.0",
|
||||
"@angular-eslint/eslint-plugin": "~13.1.0",
|
||||
"@angular-eslint/eslint-plugin-template": "~13.1.0",
|
||||
"@angular-eslint/template-parser": "~13.1.0",
|
||||
"@angular/cli": "~13.3.0",
|
||||
"@angular/common": "~13.3.0",
|
||||
"@angular/compiler": "~13.3.0",
|
||||
"@angular/compiler-cli": "~13.3.0",
|
||||
"@angular/core": "~13.3.0",
|
||||
"@angular/forms": "~13.3.0",
|
||||
"@angular/platform-browser": "~13.3.0",
|
||||
"@angular/platform-browser-dynamic": "~13.3.0",
|
||||
"@angular/router": "~13.3.0",
|
||||
"@angular/service-worker": "~13.3.0",
|
||||
"@angular/upgrade": "~13.3.0",
|
||||
"@angular-devkit/architect": "~0.1400.0-rc.2",
|
||||
"@angular-devkit/build-angular": "~14.0.0-rc.2",
|
||||
"@angular-devkit/core": "~14.0.0-rc.2",
|
||||
"@angular-devkit/schematics": "~14.0.0-rc.2",
|
||||
"@angular-eslint/eslint-plugin": "~13.2.1",
|
||||
"@angular-eslint/eslint-plugin-template": "~13.2.1",
|
||||
"@angular-eslint/template-parser": "~13.2.1",
|
||||
"@angular/cli": "~14.0.0-rc.2",
|
||||
"@angular/common": "~14.0.0-rc.2",
|
||||
"@angular/compiler": "~14.0.0-rc.2",
|
||||
"@angular/compiler-cli": "~14.0.0-rc.2",
|
||||
"@angular/core": "~14.0.0-rc.2",
|
||||
"@angular/forms": "~14.0.0-rc.2",
|
||||
"@angular/platform-browser": "~14.0.0-rc.2",
|
||||
"@angular/platform-browser-dynamic": "~14.0.0-rc.2",
|
||||
"@angular/router": "~14.0.0-rc.2",
|
||||
"@angular/service-worker": "~14.0.0-rc.2",
|
||||
"@angular/upgrade": "~14.0.0-rc.2",
|
||||
"@babel/helper-create-regexp-features-plugin": "^7.14.5",
|
||||
"@cypress/webpack-preprocessor": "^5.9.1",
|
||||
"@nestjs/common": "^8.0.0",
|
||||
@ -51,13 +51,13 @@
|
||||
"@nestjs/schematics": "^8.0.0",
|
||||
"@nestjs/swagger": "^5.0.9",
|
||||
"@nestjs/testing": "^8.0.0",
|
||||
"@ngrx/component-store": "~13.0.0",
|
||||
"@ngrx/effects": "~13.0.0",
|
||||
"@ngrx/entity": "~13.0.0",
|
||||
"@ngrx/router-store": "~13.0.0",
|
||||
"@ngrx/schematics": "~13.0.0",
|
||||
"@ngrx/store": "~13.0.0",
|
||||
"@ngrx/store-devtools": "~13.0.0",
|
||||
"@ngrx/component-store": "~13.2.0",
|
||||
"@ngrx/effects": "~13.2.0",
|
||||
"@ngrx/entity": "~13.2.0",
|
||||
"@ngrx/router-store": "~13.2.0",
|
||||
"@ngrx/schematics": "~13.2.0",
|
||||
"@ngrx/store": "~13.2.0",
|
||||
"@ngrx/store-devtools": "~13.2.0",
|
||||
"@nrwl/eslint-plugin-nx": "14.1.9-beta.1",
|
||||
"@nrwl/jest": "14.1.9-beta.1",
|
||||
"@nrwl/next": "14.1.9-beta.1",
|
||||
@ -74,7 +74,7 @@
|
||||
"@rollup/plugin-image": "^2.1.0",
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@rollup/plugin-node-resolve": "^13.0.4",
|
||||
"@schematics/angular": "~13.3.0",
|
||||
"@schematics/angular": "~14.0.0-rc.2",
|
||||
"@storybook/addon-essentials": "~6.5.4",
|
||||
"@storybook/addon-knobs": "~6.3.0",
|
||||
"@storybook/angular": "~6.5.4",
|
||||
@ -107,9 +107,9 @@
|
||||
"@types/tar-stream": "^2.2.2",
|
||||
"@types/tmp": "^0.2.0",
|
||||
"@types/yargs": "^17.0.10",
|
||||
"@typescript-eslint/eslint-plugin": "5.18.0",
|
||||
"@typescript-eslint/experimental-utils": "5.18.0",
|
||||
"@typescript-eslint/parser": "5.18.0",
|
||||
"@typescript-eslint/eslint-plugin": "~5.24.0",
|
||||
"@typescript-eslint/experimental-utils": "~5.24.0",
|
||||
"@typescript-eslint/parser": "~5.24.0",
|
||||
"@xstate/immer": "^0.2.0",
|
||||
"@xstate/inspect": "^0.5.1",
|
||||
"@xstate/react": "^1.6.3",
|
||||
@ -135,7 +135,7 @@
|
||||
"dotenv": "~10.0.0",
|
||||
"ejs": "^3.1.7",
|
||||
"enhanced-resolve": "^5.8.3",
|
||||
"eslint": "8.12.0",
|
||||
"eslint": "8.15.0",
|
||||
"eslint-config-next": "12.1.5",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"eslint-plugin-cypress": "^2.10.3",
|
||||
@ -164,7 +164,7 @@
|
||||
"jasmine-spec-reporter": "~4.2.1",
|
||||
"jest": "27.5.1",
|
||||
"jest-circus": "27.2.3",
|
||||
"jest-preset-angular": "11.1.1",
|
||||
"jest-preset-angular": "~11.1.2",
|
||||
"jsonc-eslint-parser": "^2.1.0",
|
||||
"jsonc-parser": "3.0.0",
|
||||
"karma": "~4.0.0",
|
||||
@ -185,7 +185,7 @@
|
||||
"mini-css-extract-plugin": "~2.4.7",
|
||||
"minimatch": "3.0.5",
|
||||
"next-sitemap": "^1.6.108",
|
||||
"ng-packagr": "~13.3.0",
|
||||
"ng-packagr": "~14.0.0-rc.0",
|
||||
"ngrx-store-freeze": "0.2.4",
|
||||
"node-fetch": "^2.6.7",
|
||||
"nx": "14.1.9-beta.1",
|
||||
@ -301,7 +301,6 @@
|
||||
"weak-napi": "^2.0.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"ng-packagr/rxjs": "6.6.7",
|
||||
"**/xmlhttprequest-ssl": "~1.6.2",
|
||||
"minimist": "^1.2.6"
|
||||
}
|
||||
|
||||
@ -112,6 +112,36 @@
|
||||
"version": "14.0.0-beta.1",
|
||||
"description": "Rename mfe.config.js to module-federation.config.js for consistent terminology.",
|
||||
"factory": "./src/migrations/update-14-0-0/rename-mf-config"
|
||||
},
|
||||
"remove-show-circular-dependencies-option": {
|
||||
"cli": "nx",
|
||||
"version": "14.2.0-beta.0",
|
||||
"description": "Remove 'showCircularDependencies' option from browser and server executors.",
|
||||
"factory": "./src/migrations/update-14-2-0/remove-show-circular-dependencies-option"
|
||||
},
|
||||
"update-angular-cli-version": {
|
||||
"cli": "nx",
|
||||
"version": "14.2.0-beta.0",
|
||||
"description": "Update the @angular/cli package version.",
|
||||
"factory": "./src/migrations/update-14-2-0/update-angular-cli"
|
||||
},
|
||||
"update-libraries-secondary-entrypoints": {
|
||||
"cli": "nx",
|
||||
"version": "14.2.0-beta.0",
|
||||
"description": "Remove 'package.json' files from library projects secondary entrypoints.",
|
||||
"factory": "./src/migrations/update-14-2-0/update-libraries-secondary-entrypoints"
|
||||
},
|
||||
"update-postinstall-script-ngcc-target": {
|
||||
"cli": "nx",
|
||||
"version": "14.2.0-beta.0",
|
||||
"description": "Update postinstall script running ngcc to use ES2020 target.",
|
||||
"factory": "./src/migrations/update-14-2-0/update-ngcc-target"
|
||||
},
|
||||
"update-tsconfig-target": {
|
||||
"cli": "nx",
|
||||
"version": "14.2.0-beta.0",
|
||||
"description": "Update TypeScript compilation target to 'ES2020'.",
|
||||
"factory": "./src/migrations/update-14-2-0/update-tsconfig-target"
|
||||
}
|
||||
},
|
||||
"packageJsonUpdates": {
|
||||
@ -1088,6 +1118,87 @@
|
||||
"alwaysAddToPackageJson": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"14.2.0": {
|
||||
"version": "14.2.0-beta.0",
|
||||
"packages": {
|
||||
"@angular-devkit/architect": {
|
||||
"version": "~0.1400.0-rc.2",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-devkit/build-angular": {
|
||||
"version": "~14.0.0-rc.2",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-devkit/build-webpack": {
|
||||
"version": "~0.1400.0-rc.2",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-devkit/core": {
|
||||
"version": "~14.0.0-rc.2",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-devkit/schematics": {
|
||||
"version": "~14.0.0-rc.2",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular/core": {
|
||||
"version": "~14.0.0-rc.2",
|
||||
"alwaysAddToPackageJson": true
|
||||
},
|
||||
"@angular/material": {
|
||||
"version": "~14.0.0-rc.1",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"ng-packagr": {
|
||||
"version": "~14.0.0-rc.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-eslint/eslint-plugin": {
|
||||
"version": "~13.2.1",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-eslint/eslint-plugin-template": {
|
||||
"version": "~13.2.1",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@angular-eslint/template-parser": {
|
||||
"version": "~13.2.1",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@ngrx/store": {
|
||||
"version": "~13.2.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@ngrx/effects": {
|
||||
"version": "~13.2.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@ngrx/entity": {
|
||||
"version": "~13.2.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@ngrx/router-store": {
|
||||
"version": "~13.2.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@ngrx/schematics": {
|
||||
"version": "~13.2.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@ngrx/store-devtools": {
|
||||
"version": "~13.2.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"@ngrx/component-store": {
|
||||
"version": "~13.2.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
},
|
||||
"jest-preset-angular": {
|
||||
"version": "~11.1.2",
|
||||
"alwaysAddToPackageJson": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
"migrations": "./migrations.json"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular-devkit/schematics": "~13.3.0",
|
||||
"@angular-devkit/schematics": "~14.0.0-rc.2",
|
||||
"@nrwl/cypress": "file:../cypress",
|
||||
"@nrwl/devkit": "file:../devkit",
|
||||
"@nrwl/jest": "file:../jest",
|
||||
@ -45,7 +45,7 @@
|
||||
"@nrwl/storybook": "file:../storybook",
|
||||
"@nrwl/workspace": "file:../workspace",
|
||||
"@phenomnomnominal/tsquery": "4.1.1",
|
||||
"@schematics/angular": "~13.3.0",
|
||||
"@schematics/angular": "~14.0.0-rc.2",
|
||||
"chalk": "4.1.0",
|
||||
"chokidar": "^3.5.1",
|
||||
"http-server": "^14.1.0",
|
||||
|
||||
@ -47,7 +47,35 @@
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/extraEntryPoint"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"input": {
|
||||
"type": "string",
|
||||
"description": "The file to include.",
|
||||
"pattern": "\\.[cm]?jsx?$"
|
||||
},
|
||||
"bundleName": {
|
||||
"type": "string",
|
||||
"pattern": "^[\\w\\-.]*$",
|
||||
"description": "The bundle name for this extra entry point."
|
||||
},
|
||||
"inject": {
|
||||
"type": "boolean",
|
||||
"description": "If the bundle will be referenced in the HTML file.",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["input"]
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The file to include.",
|
||||
"pattern": "\\.[cm]?jsx?$"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"styles": {
|
||||
@ -55,7 +83,35 @@
|
||||
"type": "array",
|
||||
"default": [],
|
||||
"items": {
|
||||
"$ref": "#/definitions/extraEntryPoint"
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"input": {
|
||||
"type": "string",
|
||||
"description": "The file to include.",
|
||||
"pattern": "\\.(?:css|scss|sass|less|styl)$"
|
||||
},
|
||||
"bundleName": {
|
||||
"type": "string",
|
||||
"pattern": "^[\\w\\-.]*$",
|
||||
"description": "The bundle name for this extra entry point."
|
||||
},
|
||||
"inject": {
|
||||
"type": "boolean",
|
||||
"description": "If the bundle will be referenced in the HTML file.",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["input"]
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The file to include.",
|
||||
"pattern": "\\.(?:css|scss|sass|less|styl)$"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"inlineStyleLanguage": {
|
||||
@ -291,15 +347,9 @@
|
||||
"description": "Extract all licenses in a separate file.",
|
||||
"default": true
|
||||
},
|
||||
"showCircularDependencies": {
|
||||
"type": "boolean",
|
||||
"description": "Show circular dependency warnings on builds.",
|
||||
"default": false,
|
||||
"x-deprecated": "The recommended method to detect circular dependencies in project code is to use either a lint rule or other external tooling."
|
||||
},
|
||||
"buildOptimizer": {
|
||||
"type": "boolean",
|
||||
"description": "Enables '@angular-devkit/build-optimizer' optimizations when using the 'aot' option.",
|
||||
"description": "Enables advanced build optimizations when using the 'aot' option.",
|
||||
"default": true
|
||||
},
|
||||
"namedChunks": {
|
||||
@ -471,35 +521,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"extraEntryPoint": {
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"input": {
|
||||
"type": "string",
|
||||
"description": "The file to include."
|
||||
},
|
||||
"bundleName": {
|
||||
"type": "string",
|
||||
"pattern": "^[\\w\\-.]*$",
|
||||
"description": "The bundle name for this extra entry point."
|
||||
},
|
||||
"inject": {
|
||||
"type": "boolean",
|
||||
"description": "If the bundle will be referenced in the HTML file.",
|
||||
"default": true
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
"required": ["input"]
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "The file to include."
|
||||
}
|
||||
]
|
||||
},
|
||||
"budget": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
import { logger } from '@nrwl/devkit';
|
||||
import { BuildGraph } from 'ng-packagr/lib/graph/build-graph';
|
||||
import { Node } from 'ng-packagr/lib/graph/node';
|
||||
import { transformFromPromise } from 'ng-packagr/lib/graph/transform';
|
||||
import { NgEntryPoint } from 'ng-packagr/lib/ng-package/entry-point/entry-point';
|
||||
@ -22,6 +23,7 @@ import { NgPackage } from 'ng-packagr/lib/ng-package/package';
|
||||
import { copyFile, rmdir, stat, writeFile } from 'ng-packagr/lib/utils/fs';
|
||||
import { globFiles } from 'ng-packagr/lib/utils/glob';
|
||||
import { ensureUnixPath } from 'ng-packagr/lib/utils/path';
|
||||
import { AssetPattern } from 'ng-packagr/ng-package.schema';
|
||||
import * as path from 'path';
|
||||
|
||||
export const nxWritePackageTransform = (options: NgPackagrOptions) =>
|
||||
@ -31,69 +33,22 @@ export const nxWritePackageTransform = (options: NgPackagrOptions) =>
|
||||
const ngPackageNode: PackageNode = graph.find(isPackage);
|
||||
const ngPackage = ngPackageNode.data;
|
||||
const { destinationFiles } = entryPoint.data;
|
||||
const ignorePaths: string[] = [
|
||||
'.gitkeep',
|
||||
'**/.DS_Store',
|
||||
'**/Thumbs.db',
|
||||
'**/node_modules/**',
|
||||
`${ngPackage.dest}/**`,
|
||||
];
|
||||
|
||||
if (!ngEntryPoint.isSecondaryEntryPoint) {
|
||||
const assetFiles: string[] = [];
|
||||
|
||||
// COPY ASSET FILES TO DESTINATION
|
||||
logger.log('Copying assets');
|
||||
|
||||
try {
|
||||
for (const asset of ngPackage.assets) {
|
||||
let assetFullPath = path.join(ngPackage.src, asset);
|
||||
|
||||
try {
|
||||
const stats = await stat(assetFullPath);
|
||||
if (stats.isFile()) {
|
||||
assetFiles.push(assetFullPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (stats.isDirectory()) {
|
||||
assetFullPath = path.join(assetFullPath, '**/*');
|
||||
}
|
||||
} catch {}
|
||||
|
||||
const files = await globFiles(assetFullPath, {
|
||||
ignore: ignorePaths,
|
||||
cache: ngPackageNode.cache.globCache,
|
||||
dot: true,
|
||||
nodir: true,
|
||||
});
|
||||
|
||||
if (files.length) {
|
||||
assetFiles.push(...files);
|
||||
}
|
||||
}
|
||||
|
||||
for (const file of assetFiles) {
|
||||
const relativePath = path.relative(ngPackage.src, file);
|
||||
const destination = path.resolve(ngPackage.dest, relativePath);
|
||||
const nodeUri = fileUrl(ensureUnixPath(file));
|
||||
let node = graph.get(nodeUri);
|
||||
if (!node) {
|
||||
node = new Node(nodeUri);
|
||||
graph.put(node);
|
||||
}
|
||||
|
||||
entryPoint.dependsOn(node);
|
||||
await copyFile(file, destination);
|
||||
}
|
||||
await copyAssets(graph, entryPoint, ngPackageNode);
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// 6. WRITE PACKAGE.JSON
|
||||
// As of APF 14 only the primary entrypoint has a package.json
|
||||
if (!ngEntryPoint.isSecondaryEntryPoint) {
|
||||
try {
|
||||
logger.info('Writing package metadata');
|
||||
logger.info('Writing package manifest');
|
||||
const relativeUnixFromDestPath = (filePath: string) =>
|
||||
ensureUnixPath(path.relative(ngEntryPoint.destinationPath, filePath));
|
||||
|
||||
@ -113,11 +68,98 @@ export const nxWritePackageTransform = (options: NgPackagrOptions) =>
|
||||
} catch (error) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
logger.info(`Built ${ngEntryPoint.moduleId}`);
|
||||
|
||||
return graph;
|
||||
});
|
||||
|
||||
type AssetEntry = Exclude<AssetPattern, string>;
|
||||
|
||||
async function copyAssets(
|
||||
graph: BuildGraph,
|
||||
entryPointNode: EntryPointNode,
|
||||
ngPackageNode: PackageNode
|
||||
): Promise<void> {
|
||||
const ngPackage = ngPackageNode.data;
|
||||
|
||||
const globsForceIgnored: string[] = [
|
||||
'.gitkeep',
|
||||
'**/.DS_Store',
|
||||
'**/Thumbs.db',
|
||||
`${ngPackage.dest}/**`,
|
||||
];
|
||||
|
||||
const assets: AssetEntry[] = [];
|
||||
|
||||
for (const item of ngPackage.assets) {
|
||||
const asset: Partial<AssetEntry> = {};
|
||||
if (typeof item == 'object') {
|
||||
asset.glob = item.glob;
|
||||
asset.input = path.join(ngPackage.src, item.input);
|
||||
asset.output = path.join(ngPackage.dest, item.output);
|
||||
asset.ignore = item.ignore;
|
||||
} else {
|
||||
const assetPath = item; // might be a glob
|
||||
const assetFullPath = path.join(ngPackage.src, assetPath);
|
||||
const [isDir, isFile] = await stat(assetFullPath)
|
||||
.then((stats) => [stats.isDirectory(), stats.isFile()])
|
||||
.catch(() => [false, false]);
|
||||
if (isDir) {
|
||||
asset.glob = '**/*';
|
||||
asset.input = assetFullPath;
|
||||
asset.output = path.join(ngPackage.dest, assetPath);
|
||||
} else if (isFile) {
|
||||
asset.glob = path.basename(assetFullPath); // filenames are their own glob
|
||||
asset.input = path.dirname(assetFullPath);
|
||||
asset.output = path.dirname(path.join(ngPackage.dest, assetPath));
|
||||
} else {
|
||||
asset.glob = assetPath;
|
||||
asset.input = ngPackage.src;
|
||||
asset.output = ngPackage.dest;
|
||||
}
|
||||
}
|
||||
|
||||
const isAncestorPath = (target: string, datum: string) =>
|
||||
path.relative(datum, target).startsWith('..');
|
||||
if (isAncestorPath(asset.input, ngPackage.src)) {
|
||||
throw new Error(
|
||||
'Cannot read assets from a location outside of the project root.'
|
||||
);
|
||||
}
|
||||
if (isAncestorPath(asset.output, ngPackage.dest)) {
|
||||
throw new Error(
|
||||
'Cannot write assets to a location outside of the output path.'
|
||||
);
|
||||
}
|
||||
|
||||
assets.push(asset as AssetEntry);
|
||||
}
|
||||
|
||||
for (const asset of assets) {
|
||||
const filePaths = await globFiles(asset.glob, {
|
||||
cwd: asset.input,
|
||||
ignore: [...(asset.ignore ?? []), ...globsForceIgnored],
|
||||
cache: ngPackageNode.cache.globCache,
|
||||
dot: true,
|
||||
nodir: true,
|
||||
follow: asset.followSymlinks,
|
||||
});
|
||||
for (const filePath of filePaths) {
|
||||
const fileSrcFullPath = path.join(asset.input, filePath);
|
||||
const fileDestFullPath = path.join(asset.output, filePath);
|
||||
const nodeUri = fileUrl(ensureUnixPath(fileSrcFullPath));
|
||||
let node = graph.get(nodeUri);
|
||||
if (!node) {
|
||||
node = new Node(nodeUri);
|
||||
graph.put(node);
|
||||
}
|
||||
entryPointNode.dependsOn(node);
|
||||
await copyFile(fileSrcFullPath, fileDestFullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and writes a `package.json` file of the entry point used by the `node_module`
|
||||
* resolution strategies.
|
||||
@ -146,7 +188,6 @@ async function writePackageJson(
|
||||
// version at least matches that of angular if we use require('tslib').version
|
||||
// it will get what installed and not the minimum version nor if it is a `~` or `^`
|
||||
// this is only required for primary
|
||||
if (!entryPoint.isSecondaryEntryPoint) {
|
||||
if (isWatchMode) {
|
||||
// Needed because of Webpack's 5 `cachemanagedpaths`
|
||||
// https://github.com/angular/angular-cli/issues/20962
|
||||
@ -181,7 +222,6 @@ async function writePackageJson(
|
||||
|
||||
delete packageJson.peerDependencies.tslib;
|
||||
}
|
||||
}
|
||||
|
||||
// Verify non-peerDependencies as they can easily lead to duplicate installs or version conflicts
|
||||
// in the node_modules folder of an application
|
||||
|
||||
@ -12,12 +12,10 @@ import { BuildGraph } from 'ng-packagr/lib/graph/build-graph';
|
||||
import { Node } from 'ng-packagr/lib/graph/node';
|
||||
import { EntryPointNode, fileUrl } from 'ng-packagr/lib/ng-package/nodes';
|
||||
import { ensureUnixPath } from 'ng-packagr/lib/utils/path';
|
||||
import { NgPackageConfig } from 'ng-packagr/ng-package.schema';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
import {
|
||||
InlineStyleLanguage,
|
||||
StylesheetProcessor,
|
||||
} from '../styles/stylesheet-processor';
|
||||
import { StylesheetProcessor } from '../styles/stylesheet-processor';
|
||||
|
||||
export function cacheCompilerHost(
|
||||
graph: BuildGraph,
|
||||
@ -25,7 +23,7 @@ export function cacheCompilerHost(
|
||||
compilerOptions: CompilerOptions,
|
||||
moduleResolutionCache: ts.ModuleResolutionCache,
|
||||
stylesheetProcessor?: StylesheetProcessor,
|
||||
inlineStyleLanguage?: InlineStyleLanguage,
|
||||
inlineStyleLanguage?: NgPackageConfig['inlineStyleLanguage'],
|
||||
sourcesFileCache: FileCache = entryPoint.cache.sourcesFileCache
|
||||
): CompilerHost {
|
||||
const compilerHost = ts.createIncrementalCompilerHost(compilerOptions);
|
||||
@ -47,6 +45,11 @@ export function cacheCompilerHost(
|
||||
entryPoint.dependsOn(node);
|
||||
};
|
||||
|
||||
const { flatModuleFile, entryFile } = entryPoint.data.entryPoint;
|
||||
const flatModuleFileDtsFilename = `${flatModuleFile}.d.ts`;
|
||||
const hasIndexEntryFile =
|
||||
path.basename(entryFile.toLowerCase()) === 'index.ts';
|
||||
|
||||
return {
|
||||
...compilerHost,
|
||||
|
||||
@ -82,6 +85,18 @@ export function cacheCompilerHost(
|
||||
sourceFiles?: ReadonlyArray<ts.SourceFile>
|
||||
) => {
|
||||
if (fileName.endsWith('.d.ts')) {
|
||||
if (
|
||||
hasIndexEntryFile &&
|
||||
path.basename(fileName) === flatModuleFileDtsFilename
|
||||
) {
|
||||
// In case the entry file is index.ts, we should not emit the `d.ts` which are a re-export of the `index.ts`.
|
||||
// Because it will cause a conflict.
|
||||
return;
|
||||
}
|
||||
|
||||
// Rename file to index.d.ts so that TypeScript can resolve types without
|
||||
// them needing to be referenced in the package.json manifest.
|
||||
fileName = fileName.replace(flatModuleFileDtsFilename, 'index.d.ts');
|
||||
sourceFiles.forEach((source) => {
|
||||
const cache = sourcesFileCache.getOrCreate(source.fileName);
|
||||
if (!cache.declarationFileName) {
|
||||
|
||||
@ -17,7 +17,7 @@ import {
|
||||
saveCacheEntry,
|
||||
} from 'ng-packagr/lib/utils/cache';
|
||||
import * as log from 'ng-packagr/lib/utils/log';
|
||||
import { dirname, extname, join, resolve } from 'path';
|
||||
import { dirname, extname, join } from 'path';
|
||||
import * as postcssPresetEnv from 'postcss-preset-env';
|
||||
import * as postcssUrl from 'postcss-url';
|
||||
import {
|
||||
@ -34,13 +34,6 @@ export enum CssUrl {
|
||||
none = 'none',
|
||||
}
|
||||
|
||||
export enum InlineStyleLanguage {
|
||||
sass = 'sass',
|
||||
scss = 'scss',
|
||||
css = 'css',
|
||||
less = 'less',
|
||||
}
|
||||
|
||||
export interface Result {
|
||||
css: string;
|
||||
warnings: string[];
|
||||
|
||||
@ -12,12 +12,10 @@ import { BuildGraph } from 'ng-packagr/lib/graph/build-graph';
|
||||
import { Node } from 'ng-packagr/lib/graph/node';
|
||||
import { EntryPointNode, fileUrl } from 'ng-packagr/lib/ng-package/nodes';
|
||||
import { ensureUnixPath } from 'ng-packagr/lib/utils/path';
|
||||
import { NgPackageConfig } from 'ng-packagr/ng-package.schema';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
import {
|
||||
InlineStyleLanguage,
|
||||
StylesheetProcessor,
|
||||
} from '../styles/stylesheet-processor';
|
||||
import { StylesheetProcessor } from '../styles/stylesheet-processor';
|
||||
|
||||
export function cacheCompilerHost(
|
||||
graph: BuildGraph,
|
||||
@ -25,7 +23,7 @@ export function cacheCompilerHost(
|
||||
compilerOptions: CompilerOptions,
|
||||
moduleResolutionCache: ts.ModuleResolutionCache,
|
||||
stylesheetProcessor?: StylesheetProcessor,
|
||||
inlineStyleLanguage?: InlineStyleLanguage,
|
||||
inlineStyleLanguage?: NgPackageConfig['inlineStyleLanguage'],
|
||||
sourcesFileCache: FileCache = entryPoint.cache.sourcesFileCache
|
||||
): CompilerHost {
|
||||
const compilerHost = ts.createIncrementalCompilerHost(compilerOptions);
|
||||
@ -47,6 +45,11 @@ export function cacheCompilerHost(
|
||||
entryPoint.dependsOn(node);
|
||||
};
|
||||
|
||||
const { flatModuleFile, entryFile } = entryPoint.data.entryPoint;
|
||||
const flatModuleFileDtsFilename = `${flatModuleFile}.d.ts`;
|
||||
const hasIndexEntryFile =
|
||||
path.basename(entryFile.toLowerCase()) === 'index.ts';
|
||||
|
||||
return {
|
||||
...compilerHost,
|
||||
|
||||
@ -82,6 +85,18 @@ export function cacheCompilerHost(
|
||||
sourceFiles?: ReadonlyArray<ts.SourceFile>
|
||||
) => {
|
||||
if (fileName.endsWith('.d.ts')) {
|
||||
if (
|
||||
hasIndexEntryFile &&
|
||||
path.basename(fileName) === flatModuleFileDtsFilename
|
||||
) {
|
||||
// In case the entry file is index.ts, we should not emit the `d.ts` which are a re-export of the `index.ts`.
|
||||
// Because it will cause a conflict.
|
||||
return;
|
||||
}
|
||||
|
||||
// Rename file to index.d.ts so that TypeScript can resolve types without
|
||||
// them needing to be referenced in the package.json manifest.
|
||||
fileName = fileName.replace(flatModuleFileDtsFilename, 'index.d.ts');
|
||||
sourceFiles.forEach((source) => {
|
||||
const cache = sourcesFileCache.getOrCreate(source.fileName);
|
||||
if (!cache.declarationFileName) {
|
||||
|
||||
@ -168,6 +168,7 @@ Object {
|
||||
exports[`app not nested should generate files 1`] = `
|
||||
Object {
|
||||
"angularCompilerOptions": Object {
|
||||
"enableI18nLegacyMessageIdFormat": false,
|
||||
"strictInjectionParameters": true,
|
||||
"strictInputAccessModifiers": true,
|
||||
"strictTemplates": true,
|
||||
|
||||
@ -34,6 +34,7 @@ export function enableStrictTypeChecking(
|
||||
// update Angular Template Settings
|
||||
json.angularCompilerOptions = {
|
||||
...(json.angularCompilerOptions ?? {}),
|
||||
enableI18nLegacyMessageIdFormat: false,
|
||||
strictInjectionParameters: true,
|
||||
strictInputAccessModifiers: true,
|
||||
strictTemplates: true,
|
||||
|
||||
@ -25,12 +25,17 @@ function updateTsConfigOptions(host: Tree, options: NormalizedSchema) {
|
||||
compilerOptions: {
|
||||
...json.compilerOptions,
|
||||
outDir: `${offsetFromRoot(options.appProjectRoot)}dist/out-tsc`,
|
||||
target: 'ES2017',
|
||||
},
|
||||
exclude: [
|
||||
...new Set([...(json.exclude || []), '**/*.test.ts', '**/*.spec.ts']),
|
||||
],
|
||||
}));
|
||||
|
||||
// tsconfig.json
|
||||
updateJson(host, `${options.appProjectRoot}/tsconfig.json`, (json) => ({
|
||||
...json,
|
||||
compilerOptions: { ...json.compilerOptions, target: 'es2020' },
|
||||
}));
|
||||
}
|
||||
|
||||
function updateAppAndE2EProjectConfigurations(
|
||||
|
||||
@ -60,10 +60,6 @@ function exportComponent(tree: Tree, schema: Schema) {
|
||||
);
|
||||
|
||||
if (projectType === 'application') {
|
||||
logger.warn(
|
||||
'--export=true was ignored as the project the component being generated in is not a library.'
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -5,6 +5,7 @@ export interface Schema {
|
||||
displayBlock?: boolean;
|
||||
inlineStyle?: boolean;
|
||||
inlineTemplate?: boolean;
|
||||
standalone?: boolean;
|
||||
viewEncapsulation?: 'Emulated' | 'None' | 'ShadowDom';
|
||||
changeDetection?: 'Default' | 'OnPush';
|
||||
style?: 'css' | 'scss' | 'sass' | 'less' | 'none';
|
||||
|
||||
@ -47,6 +47,11 @@
|
||||
"default": false,
|
||||
"alias": "t"
|
||||
},
|
||||
"standalone": {
|
||||
"description": "Whether the generated component is standalone.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"viewEncapsulation": {
|
||||
"description": "The view encapsulation strategy to use in the new component.",
|
||||
"enum": ["Emulated", "None", "ShadowDom"],
|
||||
|
||||
@ -573,14 +573,14 @@ exports[`convert-tslint-to-eslint should work for Angular applications 1`] = `
|
||||
Object {
|
||||
"dependencies": Object {},
|
||||
"devDependencies": Object {
|
||||
"@angular-eslint/eslint-plugin": "~13.1.0",
|
||||
"@angular-eslint/eslint-plugin-template": "~13.1.0",
|
||||
"@angular-eslint/template-parser": "~13.1.0",
|
||||
"@angular-eslint/eslint-plugin": "~13.2.1",
|
||||
"@angular-eslint/eslint-plugin-template": "~13.2.1",
|
||||
"@angular-eslint/template-parser": "~13.2.1",
|
||||
"@nrwl/eslint-plugin-nx": "0.0.1",
|
||||
"@nrwl/linter": "0.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "~5.18.0",
|
||||
"@typescript-eslint/parser": "~5.18.0",
|
||||
"eslint": "~8.12.0",
|
||||
"@typescript-eslint/eslint-plugin": "~5.24.0",
|
||||
"@typescript-eslint/parser": "~5.24.0",
|
||||
"eslint": "~8.15.0",
|
||||
"eslint-config-prettier": "8.1.0",
|
||||
"eslint-plugin-import": "latest",
|
||||
},
|
||||
@ -931,14 +931,14 @@ exports[`convert-tslint-to-eslint should work for Angular libraries 1`] = `
|
||||
Object {
|
||||
"dependencies": Object {},
|
||||
"devDependencies": Object {
|
||||
"@angular-eslint/eslint-plugin": "~13.1.0",
|
||||
"@angular-eslint/eslint-plugin-template": "~13.1.0",
|
||||
"@angular-eslint/template-parser": "~13.1.0",
|
||||
"@angular-eslint/eslint-plugin": "~13.2.1",
|
||||
"@angular-eslint/eslint-plugin-template": "~13.2.1",
|
||||
"@angular-eslint/template-parser": "~13.2.1",
|
||||
"@nrwl/eslint-plugin-nx": "0.0.1",
|
||||
"@nrwl/linter": "0.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "~5.18.0",
|
||||
"@typescript-eslint/parser": "~5.18.0",
|
||||
"eslint": "~8.12.0",
|
||||
"@typescript-eslint/eslint-plugin": "~5.24.0",
|
||||
"@typescript-eslint/parser": "~5.24.0",
|
||||
"eslint": "~8.15.0",
|
||||
"eslint-config-prettier": "8.1.0",
|
||||
"eslint-plugin-import": "latest",
|
||||
},
|
||||
|
||||
@ -54,7 +54,7 @@ describe('init', () => {
|
||||
|
||||
// ASSERT
|
||||
expect(packageJson.scripts.postinstall).toEqual(
|
||||
'ngcc --properties es2015 browser module main'
|
||||
'ngcc --properties es2020 browser module main'
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -87,7 +87,7 @@ function setDefaults(host: Tree, options: Schema) {
|
||||
function addPostInstall(host: Tree) {
|
||||
updateJson(host, 'package.json', (pkgJson) => {
|
||||
pkgJson.scripts = pkgJson.scripts ?? {};
|
||||
const command = 'ngcc --properties es2015 browser module main';
|
||||
const command = 'ngcc --properties es2020 browser module main';
|
||||
if (!pkgJson.scripts.postinstall) {
|
||||
pkgJson.scripts.postinstall = command;
|
||||
} else if (!pkgJson.scripts.postinstall.includes('ngcc')) {
|
||||
|
||||
@ -49,6 +49,7 @@ function updateTsConfig(host: Tree, options: NormalizedSchema) {
|
||||
// update Angular Template Settings
|
||||
json.angularCompilerOptions = {
|
||||
...(json.angularCompilerOptions ?? {}),
|
||||
enableI18nLegacyMessageIdFormat: false,
|
||||
strictInjectionParameters: true,
|
||||
strictInputAccessModifiers: true,
|
||||
strictTemplates: true,
|
||||
|
||||
@ -39,6 +39,12 @@ function updateProjectConfig(host: Tree, options: NormalizedSchema) {
|
||||
];
|
||||
return json;
|
||||
});
|
||||
|
||||
// tsconfig.json
|
||||
updateJson(host, `${options.projectRoot}/tsconfig.json`, (json) => ({
|
||||
...json,
|
||||
compilerOptions: { ...json.compilerOptions, target: 'es2020' },
|
||||
}));
|
||||
}
|
||||
|
||||
function updateProjectIvyConfig(host: Tree, options: NormalizedSchema) {
|
||||
|
||||
@ -287,6 +287,7 @@ describe('lib', () => {
|
||||
expect(tsconfigJson).toEqual({
|
||||
extends: '../../tsconfig.base.json',
|
||||
angularCompilerOptions: {
|
||||
enableI18nLegacyMessageIdFormat: false,
|
||||
strictInjectionParameters: true,
|
||||
strictInputAccessModifiers: true,
|
||||
strictTemplates: true,
|
||||
@ -298,6 +299,7 @@ describe('lib', () => {
|
||||
noImplicitOverride: true,
|
||||
noImplicitReturns: true,
|
||||
strict: true,
|
||||
target: 'es2020',
|
||||
},
|
||||
files: [],
|
||||
include: [],
|
||||
@ -653,6 +655,7 @@ describe('lib', () => {
|
||||
expect(tsconfigJson).toEqual({
|
||||
extends: '../../../tsconfig.base.json',
|
||||
angularCompilerOptions: {
|
||||
enableI18nLegacyMessageIdFormat: false,
|
||||
strictInjectionParameters: true,
|
||||
strictInputAccessModifiers: true,
|
||||
strictTemplates: true,
|
||||
@ -664,6 +667,7 @@ describe('lib', () => {
|
||||
noImplicitOverride: true,
|
||||
noImplicitReturns: true,
|
||||
strict: true,
|
||||
target: 'es2020',
|
||||
},
|
||||
files: [],
|
||||
include: [],
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import {
|
||||
addDependenciesToPackageJson,
|
||||
formatFiles,
|
||||
installPackagesTask,
|
||||
moveFilesToNewDirectory,
|
||||
removeDependenciesFromPackageJson,
|
||||
Tree,
|
||||
} from '@nrwl/devkit';
|
||||
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
|
||||
@ -9,6 +11,7 @@ import { jestProjectGenerator } from '@nrwl/jest';
|
||||
import { Linter } from '@nrwl/linter';
|
||||
import { convertToNxProjectGenerator } from '@nrwl/workspace/generators';
|
||||
import init from '../../generators/init/init';
|
||||
import { ngPackagrVersion } from '../../utils/versions';
|
||||
import addLintingGenerator from '../add-linting/add-linting';
|
||||
import karmaProjectGenerator from '../karma-project/karma-project';
|
||||
import setupTailwindGenerator from '../setup-tailwind/setup-tailwind';
|
||||
@ -86,6 +89,14 @@ export async function libraryGenerator(host: Tree, schema: Partial<Schema>) {
|
||||
}
|
||||
|
||||
if (options.buildable || options.publishable) {
|
||||
removeDependenciesFromPackageJson(host, [], ['ng-packagr']);
|
||||
addDependenciesToPackageJson(
|
||||
host,
|
||||
{},
|
||||
{
|
||||
'ng-packagr': ngPackagrVersion,
|
||||
}
|
||||
);
|
||||
addBuildableLibrariesPostCssDependencies(host);
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,12 @@
|
||||
import type { Tree } from '@nrwl/devkit';
|
||||
import { joinPathFragments, logger } from '@nrwl/devkit';
|
||||
import {
|
||||
joinPathFragments,
|
||||
logger,
|
||||
Tree,
|
||||
visitNotIgnoredFiles,
|
||||
} from '@nrwl/devkit';
|
||||
import { tsquery } from '@phenomnomnominal/tsquery';
|
||||
import { basename, dirname } from 'path';
|
||||
import type { SourceFile, Statement } from 'typescript';
|
||||
import { basename, dirname, extname, relative } from 'path';
|
||||
import type { Identifier, SourceFile, Statement } from 'typescript';
|
||||
import { SyntaxKind } from 'typescript';
|
||||
import { getTsSourceFile } from '../../../utils/nx-devkit/ast-utils';
|
||||
import { getModuleDeclaredComponents } from './module-info';
|
||||
@ -43,6 +47,47 @@ export function getComponentsInfo(
|
||||
});
|
||||
}
|
||||
|
||||
export function getStandaloneComponentsInfo(
|
||||
tree: Tree,
|
||||
projectPath: string
|
||||
): ComponentInfo[] {
|
||||
const componentsInfo: ComponentInfo[] = [];
|
||||
|
||||
visitNotIgnoredFiles(tree, projectPath, (filePath: string) => {
|
||||
if (extname(filePath) !== '.ts') {
|
||||
return;
|
||||
}
|
||||
|
||||
const standaloneComponents = getStandaloneComponents(tree, filePath);
|
||||
if (!standaloneComponents.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
standaloneComponents.forEach((componentName) => {
|
||||
componentsInfo.push({
|
||||
componentFileName: basename(filePath, '.ts'),
|
||||
moduleFolderPath: projectPath,
|
||||
name: componentName,
|
||||
path: dirname(relative(projectPath, filePath)),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return componentsInfo;
|
||||
}
|
||||
|
||||
function getStandaloneComponents(tree: Tree, filePath: string): string[] {
|
||||
const fileContent = tree.read(filePath, 'utf-8');
|
||||
const ast = tsquery.ast(fileContent);
|
||||
const components = tsquery<Identifier>(
|
||||
ast,
|
||||
'ClassDeclaration:has(Decorator > CallExpression:has(Identifier[name=Component]) ObjectLiteralExpression PropertyAssignment Identifier[name=standalone] ~ TrueKeyword) > Identifier',
|
||||
{ visitAllChildren: true }
|
||||
);
|
||||
|
||||
return components.map((component) => component.getText());
|
||||
}
|
||||
|
||||
function getComponentImportPath(
|
||||
componentName: string,
|
||||
imports: Statement[]
|
||||
|
||||
@ -3,7 +3,10 @@ import { logger } from '@nrwl/devkit';
|
||||
import { getProjectRootPath } from '@nrwl/workspace/src/utilities/project-type';
|
||||
import componentCypressSpecGenerator from '../component-cypress-spec/component-cypress-spec';
|
||||
import componentStoryGenerator from '../component-story/component-story';
|
||||
import { getComponentsInfo } from './lib/component-info';
|
||||
import {
|
||||
getComponentsInfo,
|
||||
getStandaloneComponentsInfo,
|
||||
} from './lib/component-info';
|
||||
import { getE2EProject } from './lib/get-e2e-project';
|
||||
import { getModuleFilePaths } from './lib/module-info';
|
||||
import type { StoriesGeneratorOptions } from './schema';
|
||||
@ -16,7 +19,11 @@ export function angularStoriesGenerator(
|
||||
const e2eProject = getE2EProject(tree, e2eProjectName);
|
||||
const projectPath = getProjectRootPath(tree, options.name);
|
||||
const moduleFilePaths = getModuleFilePaths(tree, projectPath);
|
||||
const componentsInfo = getComponentsInfo(tree, moduleFilePaths, options.name);
|
||||
const componentsInfo = [
|
||||
...getComponentsInfo(tree, moduleFilePaths, options.name),
|
||||
// TODO(leo): uncomment once Storybook supports standalone components https://github.com/storybookjs/storybook/pull/18272
|
||||
// ...getStandaloneComponentsInfo(tree, projectPath),
|
||||
];
|
||||
|
||||
if (options.generateCypressSpecs && !e2eProject) {
|
||||
logger.info(
|
||||
|
||||
@ -0,0 +1,86 @@
|
||||
import {
|
||||
addProjectConfiguration,
|
||||
readProjectConfiguration,
|
||||
Tree,
|
||||
} from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import removeShowCircularDependencies from './remove-show-circular-dependencies-option';
|
||||
|
||||
describe('remove-show-circular-dependencies-option migration', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyWorkspace(2);
|
||||
});
|
||||
|
||||
it.each([
|
||||
'@angular-devkit/build-angular:browser',
|
||||
'@angular-devkit/build-angular:server',
|
||||
'@nrwl/angular:webpack-browser',
|
||||
])(
|
||||
'should remove "showCircularDependencies" option from target using the "%s" executor',
|
||||
async (executor) => {
|
||||
addProjectConfiguration(tree, 'app1', {
|
||||
root: 'apps/app1',
|
||||
sourceRoot: 'apps/app1/src',
|
||||
projectType: 'application',
|
||||
targets: {
|
||||
build: {
|
||||
executor,
|
||||
options: { extractCss: false, showCircularDependencies: true },
|
||||
configurations: {
|
||||
one: { showCircularDependencies: false, aot: true },
|
||||
two: { showCircularDependencies: false, aot: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await removeShowCircularDependencies(tree);
|
||||
|
||||
const project = readProjectConfiguration(tree, 'app1');
|
||||
expect(
|
||||
project.targets.build.options.showCircularDependencies
|
||||
).toBeUndefined();
|
||||
expect(project.targets.build.configurations).toBeDefined();
|
||||
expect(
|
||||
project.targets.build.configurations.one.showCircularDependencies
|
||||
).toBeUndefined();
|
||||
expect(
|
||||
project.targets.build.configurations.two.showCircularDependencies
|
||||
).toBeUndefined();
|
||||
}
|
||||
);
|
||||
|
||||
it('should not remove "showCircularDependencies" from target not using the relevant executors', async () => {
|
||||
addProjectConfiguration(tree, 'app1', {
|
||||
root: 'apps/app1',
|
||||
sourceRoot: 'apps/app1/src',
|
||||
projectType: 'application',
|
||||
targets: {
|
||||
build: {
|
||||
executor: '@org/awesome-plugin:executor',
|
||||
options: { extractCss: false, showCircularDependencies: true },
|
||||
configurations: {
|
||||
one: { showCircularDependencies: false, aot: true },
|
||||
two: { showCircularDependencies: false, aot: true },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await removeShowCircularDependencies(tree);
|
||||
|
||||
const project = readProjectConfiguration(tree, 'app1');
|
||||
expect(
|
||||
project.targets.build.options.showCircularDependencies
|
||||
).toBeDefined();
|
||||
expect(project.targets.build.configurations).toBeDefined();
|
||||
expect(
|
||||
project.targets.build.configurations.one.showCircularDependencies
|
||||
).toBeDefined();
|
||||
expect(
|
||||
project.targets.build.configurations.two.showCircularDependencies
|
||||
).toBeDefined();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,37 @@
|
||||
import {
|
||||
formatFiles,
|
||||
readProjectConfiguration,
|
||||
Tree,
|
||||
updateProjectConfiguration,
|
||||
} from '@nrwl/devkit';
|
||||
import { forEachExecutorOptions } from '@nrwl/workspace/src/utilities/executor-options-utils';
|
||||
|
||||
const executors = [
|
||||
'@angular-devkit/build-angular:browser',
|
||||
'@angular-devkit/build-angular:server',
|
||||
'@nrwl/angular:webpack-browser',
|
||||
];
|
||||
|
||||
export default async function (tree: Tree) {
|
||||
executors.forEach((executor) => {
|
||||
forEachExecutorOptions(
|
||||
tree,
|
||||
executor,
|
||||
(_options, projectName, targetName, configurationName) => {
|
||||
const projectConfiguration = readProjectConfiguration(
|
||||
tree,
|
||||
projectName
|
||||
);
|
||||
const config = configurationName
|
||||
? projectConfiguration.targets[targetName].configurations[
|
||||
configurationName
|
||||
]
|
||||
: projectConfiguration.targets[targetName].options;
|
||||
delete config.showCircularDependencies;
|
||||
updateProjectConfiguration(tree, projectName, projectConfiguration);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
await formatFiles(tree);
|
||||
}
|
||||
@ -0,0 +1,42 @@
|
||||
import { readJson, Tree, writeJson } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import updateAngularCli from './update-angular-cli';
|
||||
|
||||
describe('update-angular-cli migration', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyWorkspace(2);
|
||||
});
|
||||
|
||||
it('should update @angular/cli version when defined as a dev dependency', async () => {
|
||||
writeJson(tree, 'package.json', {
|
||||
devDependencies: { '@angular/cli': '~13.3.0' },
|
||||
});
|
||||
|
||||
await updateAngularCli(tree);
|
||||
|
||||
const { devDependencies } = readJson(tree, 'package.json');
|
||||
expect(devDependencies['@angular/cli']).toEqual('~14.0.0-rc.2');
|
||||
});
|
||||
|
||||
it('should update @angular/cli version when defined as a dependency', async () => {
|
||||
writeJson(tree, 'package.json', {
|
||||
dependencies: { '@angular/cli': '~13.3.0' },
|
||||
});
|
||||
|
||||
await updateAngularCli(tree);
|
||||
|
||||
const { dependencies } = readJson(tree, 'package.json');
|
||||
expect(dependencies['@angular/cli']).toEqual('~14.0.0-rc.2');
|
||||
});
|
||||
|
||||
it('should add @angular/cli to package.json when it is not set', async () => {
|
||||
const initialPackageJson = readJson(tree, 'package.json');
|
||||
|
||||
await updateAngularCli(tree);
|
||||
|
||||
const packageJson = readJson(tree, 'package.json');
|
||||
expect(packageJson).toStrictEqual(initialPackageJson);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,21 @@
|
||||
import { formatFiles, Tree, updateJson } from '@nrwl/devkit';
|
||||
|
||||
export default async function (tree: Tree) {
|
||||
let shouldFormat = false;
|
||||
|
||||
updateJson(tree, 'package.json', (json) => {
|
||||
if (json.devDependencies?.['@angular/cli']) {
|
||||
json.devDependencies['@angular/cli'] = '~14.0.0-rc.2';
|
||||
shouldFormat = true;
|
||||
} else if (json.dependencies?.['@angular/cli']) {
|
||||
json.dependencies['@angular/cli'] = '~14.0.0-rc.2';
|
||||
shouldFormat = true;
|
||||
}
|
||||
|
||||
return json;
|
||||
});
|
||||
|
||||
if (shouldFormat) {
|
||||
await formatFiles(tree);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
import {
|
||||
addProjectConfiguration,
|
||||
readJson,
|
||||
Tree,
|
||||
writeJson,
|
||||
} from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import updateLibrariesSecondaryEntrypoints from './update-libraries-secondary-entrypoints';
|
||||
|
||||
const libraryExecutors = [
|
||||
'@angular-devkit/build-angular:ng-packagr',
|
||||
'@nrwl/angular:ng-packagr-lite',
|
||||
'@nrwl/angular:package',
|
||||
];
|
||||
|
||||
describe('update-libraries-secondary-entrypoints migration', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyWorkspace(2);
|
||||
});
|
||||
|
||||
it.each(libraryExecutors)(
|
||||
'should not delete "package.json" of the primary entrypoint (%s)',
|
||||
async (executor) => {
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
root: 'libs/lib1',
|
||||
targets: { build: { executor } },
|
||||
});
|
||||
writeJson(tree, 'libs/lib1/package.json', { version: '0.0.0' });
|
||||
|
||||
await updateLibrariesSecondaryEntrypoints(tree);
|
||||
|
||||
expect(tree.exists('libs/lib1/package.json')).toBe(true);
|
||||
}
|
||||
);
|
||||
|
||||
it.each(libraryExecutors)(
|
||||
'should delete "package.json" of the secondary entrypoint (%s)',
|
||||
async (executor) => {
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
root: 'libs/lib1',
|
||||
targets: { build: { executor } },
|
||||
});
|
||||
writeJson(tree, 'libs/lib1/package.json', { version: '0.0.0' });
|
||||
writeJson(tree, 'libs/lib1/secondary/package.json', {
|
||||
version: '0.0.0',
|
||||
ngPackage: { lib: { entryFile: 'src/index.ts' } },
|
||||
});
|
||||
|
||||
await updateLibrariesSecondaryEntrypoints(tree);
|
||||
|
||||
expect(tree.exists('libs/lib1/secondary/package.json')).toBe(false);
|
||||
}
|
||||
);
|
||||
|
||||
it.each(libraryExecutors)(
|
||||
'should move ng-packagr configuration from "package.json" to "ng-package.json" (%s)',
|
||||
async (executor) => {
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
root: 'libs/lib1',
|
||||
targets: { build: { executor } },
|
||||
});
|
||||
writeJson(tree, 'libs/lib1/package.json', { version: '0.0.0' });
|
||||
writeJson(tree, 'libs/lib1/secondary/package.json', {
|
||||
version: '0.0.0',
|
||||
ngPackage: { lib: { entryFile: 'src/index.ts' } },
|
||||
});
|
||||
|
||||
await updateLibrariesSecondaryEntrypoints(tree);
|
||||
|
||||
expect(
|
||||
readJson(tree, 'libs/lib1/secondary/ng-package.json')
|
||||
).toStrictEqual({
|
||||
lib: { entryFile: 'src/index.ts' },
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
it('should do nothing when not using any of the relevant executors', async () => {
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
root: 'libs/lib1',
|
||||
targets: { test: { executor: '@nrwl/jest:jest' } },
|
||||
});
|
||||
writeJson(tree, 'libs/lib1/package.json', { version: '0.0.0' });
|
||||
writeJson(tree, 'libs/lib1/secondary/package.json', {
|
||||
version: '0.0.0',
|
||||
ngPackage: { lib: { entryFile: 'src/index.ts' } },
|
||||
});
|
||||
|
||||
await updateLibrariesSecondaryEntrypoints(tree);
|
||||
|
||||
expect(tree.exists('libs/lib1/package.json')).toBe(true);
|
||||
expect(tree.exists('libs/lib1/secondary/package.json')).toBe(true);
|
||||
expect(tree.exists('libs/lib1/secondary/ng-package.json')).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,54 @@
|
||||
import {
|
||||
formatFiles,
|
||||
getProjects,
|
||||
joinPathFragments,
|
||||
readJson,
|
||||
Tree,
|
||||
visitNotIgnoredFiles,
|
||||
writeJson,
|
||||
} from '@nrwl/devkit';
|
||||
import { basename, dirname } from 'path';
|
||||
|
||||
const libraryExecutors = [
|
||||
'@angular-devkit/build-angular:ng-packagr',
|
||||
'@nrwl/angular:ng-packagr-lite',
|
||||
'@nrwl/angular:package',
|
||||
];
|
||||
|
||||
export default async function (tree: Tree) {
|
||||
const projects = getProjects(tree);
|
||||
|
||||
for (const [, project] of projects) {
|
||||
if (
|
||||
!Object.values(project.targets ?? {}).some((target) =>
|
||||
libraryExecutors.includes(target.executor)
|
||||
)
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
visitNotIgnoredFiles(tree, project.root, (filePath) => {
|
||||
if (
|
||||
basename(filePath) !== 'package.json' ||
|
||||
filePath === joinPathFragments(project.root, 'package.json')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const json = readJson(tree, filePath);
|
||||
if (json.ngPackage) {
|
||||
// Migrate ng-packagr config to an ng-packagr config file.
|
||||
const configFilePath = joinPathFragments(
|
||||
dirname(filePath),
|
||||
'ng-package.json'
|
||||
);
|
||||
writeJson(tree, configFilePath, json.ngPackage);
|
||||
}
|
||||
|
||||
// Delete package.json as it is no longer needed in APF 14.
|
||||
tree.delete(filePath);
|
||||
});
|
||||
}
|
||||
|
||||
await formatFiles(tree);
|
||||
}
|
||||
@ -0,0 +1,60 @@
|
||||
import { readJson } from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import updateNgccTarget from './update-ngcc-target';
|
||||
|
||||
describe('update-ngcc-postinstall-target migration', () => {
|
||||
[
|
||||
{
|
||||
test: 'node ./decorate-angular-cli.js && ngcc --properties es2015 browser module main',
|
||||
expected:
|
||||
'node ./decorate-angular-cli.js && ngcc --properties es2020 browser module main',
|
||||
},
|
||||
{
|
||||
test: 'node ./decorate-angular-cli.js && ngcc --properties es2015 browser module main && echo "hi"',
|
||||
expected:
|
||||
'node ./decorate-angular-cli.js && ngcc --properties es2020 browser module main && echo "hi"',
|
||||
},
|
||||
{
|
||||
test: 'ngcc --properties es2015 browser module main && node ./decorate-angular-cli.js && echo "hi"',
|
||||
expected:
|
||||
'ngcc --properties es2020 browser module main && node ./decorate-angular-cli.js && echo "hi"',
|
||||
},
|
||||
].forEach((testEntry) => {
|
||||
it(`should adjust ngcc target for: "${testEntry.test}"`, async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
tree.write(
|
||||
'/package.json',
|
||||
JSON.stringify({ scripts: { postinstall: testEntry.test } })
|
||||
);
|
||||
|
||||
await updateNgccTarget(tree);
|
||||
|
||||
const packageJson = readJson(tree, 'package.json');
|
||||
expect(packageJson.scripts.postinstall).toEqual(testEntry.expected);
|
||||
});
|
||||
});
|
||||
|
||||
[
|
||||
{
|
||||
test: 'node ngcc.js',
|
||||
expected: 'node ngcc.js',
|
||||
},
|
||||
{
|
||||
test: 'any random postinstall script',
|
||||
expected: 'any random postinstall script',
|
||||
},
|
||||
].forEach((testEntry) => {
|
||||
it(`should not update postinstall script: "${testEntry.test}"`, async () => {
|
||||
const tree = createTreeWithEmptyWorkspace();
|
||||
tree.write(
|
||||
'/package.json',
|
||||
JSON.stringify({ scripts: { postinstall: testEntry.test } })
|
||||
);
|
||||
|
||||
await updateNgccTarget(tree);
|
||||
|
||||
const packageJson = readJson(tree, 'package.json');
|
||||
expect(packageJson.scripts.postinstall).toEqual(testEntry.expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,21 @@
|
||||
import { formatFiles, Tree, updateJson } from '@nrwl/devkit';
|
||||
|
||||
export default async function (tree: Tree) {
|
||||
let shouldFormat = false;
|
||||
|
||||
updateJson(tree, 'package.json', (json) => {
|
||||
if (json.scripts?.postinstall?.includes('ngcc ')) {
|
||||
json.scripts.postinstall = json.scripts.postinstall.replace(
|
||||
/(.*)(ngcc --properties es2015 )(.*)/,
|
||||
'$1ngcc --properties es2020 $3'
|
||||
);
|
||||
shouldFormat = true;
|
||||
}
|
||||
|
||||
return json;
|
||||
});
|
||||
|
||||
if (shouldFormat) {
|
||||
await formatFiles(tree);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,608 @@
|
||||
import { logger, ProjectGraph, Tree } from '@nrwl/devkit';
|
||||
import {
|
||||
addProjectConfiguration,
|
||||
DependencyType,
|
||||
readJson,
|
||||
writeJson,
|
||||
} from '@nrwl/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nrwl/devkit/testing';
|
||||
import updateTsConfigTarget from './update-tsconfig-target';
|
||||
|
||||
let projectGraph: ProjectGraph;
|
||||
jest.mock('@nrwl/devkit', () => ({
|
||||
...jest.requireActual<any>('@nrwl/devkit'),
|
||||
createProjectGraphAsync: jest
|
||||
.fn()
|
||||
.mockImplementation(async () => projectGraph),
|
||||
}));
|
||||
|
||||
describe('update-tsconfig-target migration', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyWorkspace(2);
|
||||
});
|
||||
|
||||
it('should update target in "tsconfig.json" at the project root when it is an Angular project', async () => {
|
||||
addProjectConfiguration(tree, 'app1', {
|
||||
root: 'apps/app1',
|
||||
sourceRoot: 'apps/app1/src',
|
||||
projectType: 'application',
|
||||
targets: {
|
||||
build: {
|
||||
executor: '@nrwl/angular:webpack-browser',
|
||||
options: { tsConfig: 'apps/app1/tsconfig.app.json' },
|
||||
},
|
||||
},
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
app1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'app1',
|
||||
target: 'npm:@angular/core',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
writeJson(tree, 'apps/app1/tsconfig.json', {
|
||||
compilerOptions: { target: 'es2017' },
|
||||
});
|
||||
writeJson(tree, 'apps/app1/tsconfig.app.json', {
|
||||
compilerOptions: { target: 'es2017' },
|
||||
});
|
||||
|
||||
await updateTsConfigTarget(tree);
|
||||
|
||||
const { compilerOptions } = readJson(tree, 'apps/app1/tsconfig.json');
|
||||
expect(compilerOptions.target).toBe('es2020');
|
||||
const optionTsConfig = readJson(tree, 'apps/app1/tsconfig.app.json');
|
||||
expect(optionTsConfig.compilerOptions.target).toBe('es2020');
|
||||
});
|
||||
|
||||
it('should not update target in a tsconfig file referenced by a target option when it does not have the target set and there is a "tsconfig.json" at the project root', async () => {
|
||||
addProjectConfiguration(tree, 'app1', {
|
||||
root: 'apps/app1',
|
||||
sourceRoot: 'apps/app1/src',
|
||||
projectType: 'application',
|
||||
targets: {
|
||||
build: {
|
||||
executor: '@nrwl/angular:webpack-browser',
|
||||
options: { tsConfig: 'apps/app1/tsconfig.app.json' },
|
||||
},
|
||||
},
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
app1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'app1',
|
||||
target: 'npm:@angular/core',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
writeJson(tree, 'apps/app1/tsconfig.json', {
|
||||
compilerOptions: { target: 'es2017' },
|
||||
});
|
||||
writeJson(tree, 'apps/app1/tsconfig.app.json', {
|
||||
compilerOptions: {},
|
||||
});
|
||||
|
||||
await updateTsConfigTarget(tree);
|
||||
|
||||
const { compilerOptions } = readJson(tree, 'apps/app1/tsconfig.json');
|
||||
expect(compilerOptions.target).toBe('es2020');
|
||||
const optionTsConfig = readJson(tree, 'apps/app1/tsconfig.app.json');
|
||||
expect(optionTsConfig.compilerOptions).toStrictEqual({});
|
||||
});
|
||||
|
||||
it.each([
|
||||
['@angular-devkit/build-angular:browser', 'tsconfig.app.json'],
|
||||
['@angular-devkit/build-angular:karma', 'tsconfig.spec.json'],
|
||||
['@nrwl/angular:webpack-browser', 'tsconfig.app.json'],
|
||||
['@nrwl/angular:delegate-build', 'tsconfig.app.json'],
|
||||
])(
|
||||
'should update target in the tsconfig file referenced by the target configuration when using the "%s" executor and there is no "tsconfig.json" at the project root',
|
||||
async (executor, tsConfig) => {
|
||||
const tsConfigPath = `apps/app1/${tsConfig}`;
|
||||
addProjectConfiguration(tree, 'app1', {
|
||||
root: 'apps/app1',
|
||||
sourceRoot: 'apps/app1/src',
|
||||
projectType: 'application',
|
||||
targets: {
|
||||
build: { executor, options: { tsConfig: tsConfigPath } },
|
||||
},
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
app1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'app1',
|
||||
target: 'npm:@angular/core',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
writeJson(tree, tsConfigPath, {
|
||||
compilerOptions: { target: 'es2017' },
|
||||
});
|
||||
|
||||
await updateTsConfigTarget(tree);
|
||||
|
||||
const { compilerOptions } = readJson(tree, tsConfigPath);
|
||||
expect(compilerOptions.target).toBe('es2020');
|
||||
}
|
||||
);
|
||||
|
||||
it.each([
|
||||
'@angular-devkit/build-angular:ng-packagr',
|
||||
'@nrwl/angular:ng-packagr-lite',
|
||||
'@nrwl/angular:package',
|
||||
])(
|
||||
'should update target in the tsconfig file referenced by the target configuration when using the "%s" executor and there is no "tsconfig.json" at the project root',
|
||||
async (executor) => {
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
root: 'libs/lib1',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
projectType: 'library',
|
||||
targets: {
|
||||
build: {
|
||||
executor,
|
||||
options: { tsConfig: 'libs/lib1/tsconfig.lib.json' },
|
||||
configurations: {
|
||||
production: { tsConfig: 'libs/lib1/tsconfig.lib.prod.json' },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
lib1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'npm:@angular/core',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
writeJson(tree, 'libs/lib1/tsconfig.lib.json', {
|
||||
compilerOptions: { target: 'es2017' },
|
||||
});
|
||||
writeJson(tree, 'libs/lib1/tsconfig.lib.prod.json', {});
|
||||
|
||||
await updateTsConfigTarget(tree);
|
||||
|
||||
const { compilerOptions } = readJson(tree, 'libs/lib1/tsconfig.lib.json');
|
||||
expect(compilerOptions.target).toBe('es2020');
|
||||
const tsConfigProd = readJson(tree, 'libs/lib1/tsconfig.lib.prod.json');
|
||||
expect(tsConfigProd.compilerOptions.target).toBe('es2020');
|
||||
}
|
||||
);
|
||||
|
||||
it('should not error and log a warning when the tsconfig file specified in target does not exist', async () => {
|
||||
jest.spyOn(logger, 'warn');
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
root: 'libs/lib1',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
projectType: 'library',
|
||||
targets: {
|
||||
build: {
|
||||
executor: '@nrwl/angular:package',
|
||||
options: { tsConfig: 'libs/lib1/tsconfig.lib.json' },
|
||||
},
|
||||
},
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
lib1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'npm:@angular/core',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
|
||||
await expect(updateTsConfigTarget(tree)).resolves.not.toThrow();
|
||||
|
||||
expect(logger.warn).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
`The "libs/lib1/tsconfig.lib.json" file specified in the "build" target of the "lib1" project could not be found.`
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('should update target in tsconfig file specified in the jest config when it is an Angular project', async () => {
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
root: 'libs/lib1',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
projectType: 'library',
|
||||
targets: {
|
||||
build: {
|
||||
executor: '@nrwl/jest:jest',
|
||||
options: { jestConfig: 'libs/lib1/jest.config.ts' },
|
||||
},
|
||||
},
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
lib1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'npm:@angular/core',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
tree.write(
|
||||
'libs/lib1/jest.config.ts',
|
||||
`export default {
|
||||
displayName: 'lib1',
|
||||
preset: '../../jest.preset.js',
|
||||
setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsconfig: '<rootDir>/tsconfig.spec.json',
|
||||
stringifyContentPathRegex: '\\.(html|svg)$',
|
||||
},
|
||||
},
|
||||
coverageDirectory: '../../coverage/libs/lib1',
|
||||
transform: {
|
||||
'^.+\\.(ts|mjs|js|html)$': 'jest-preset-angular',
|
||||
},
|
||||
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$)'],
|
||||
snapshotSerializers: [
|
||||
'jest-preset-angular/build/serializers/no-ng-attributes',
|
||||
'jest-preset-angular/build/serializers/ng-snapshot',
|
||||
'jest-preset-angular/build/serializers/html-comment',
|
||||
],
|
||||
};`
|
||||
);
|
||||
writeJson(tree, 'libs/lib1/tsconfig.spec.json', {
|
||||
compilerOptions: { target: 'es2017' },
|
||||
});
|
||||
|
||||
await updateTsConfigTarget(tree);
|
||||
|
||||
const { compilerOptions } = readJson(tree, 'libs/lib1/tsconfig.spec.json');
|
||||
expect(compilerOptions.target).toBe('es2020');
|
||||
});
|
||||
|
||||
it('should not error and log a warning when the tsconfig file specified in the jest configuration does not exist', async () => {
|
||||
jest.spyOn(logger, 'warn');
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
root: 'libs/lib1',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
projectType: 'library',
|
||||
targets: {
|
||||
test: {
|
||||
executor: '@nrwl/jest:jest',
|
||||
options: { jestConfig: 'libs/lib1/jest.config.ts' },
|
||||
},
|
||||
},
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
lib1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'npm:@angular/core',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
tree.write(
|
||||
'libs/lib1/jest.config.ts',
|
||||
`export default {
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
tsconfig: '<rootDir>/tsconfig.spec.json',
|
||||
stringifyContentPathRegex: '\\.(html|svg)$',
|
||||
},
|
||||
},
|
||||
};`
|
||||
);
|
||||
|
||||
await expect(updateTsConfigTarget(tree)).resolves.not.toThrow();
|
||||
|
||||
expect(logger.warn).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
`The "<rootDir>/tsconfig.spec.json" file specified in the Jest configuration file "libs/lib1/jest.config.ts" of the "test" target of the "lib1" project could not be found.`
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('should not error and log a warning when the jest configuration does not specify the "tsconfig"', async () => {
|
||||
jest.spyOn(logger, 'warn');
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
root: 'libs/lib1',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
projectType: 'library',
|
||||
targets: {
|
||||
test: {
|
||||
executor: '@nrwl/jest:jest',
|
||||
options: { jestConfig: 'libs/lib1/jest.config.ts' },
|
||||
},
|
||||
},
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
lib1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'npm:@angular/core',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
tree.write('libs/lib1/jest.config.ts', `export default {};`);
|
||||
|
||||
await expect(updateTsConfigTarget(tree)).resolves.not.toThrow();
|
||||
|
||||
expect(logger.warn).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
`Couldn't find the "tsconfig" property for "ts-jest" in the Jest configuration file "libs/lib1/jest.config.ts" specified in the "test" target of the "lib1" project.`
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('should not error and log a warning when the jest configuration file does not exist', async () => {
|
||||
jest.spyOn(logger, 'warn');
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
root: 'libs/lib1',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
projectType: 'library',
|
||||
targets: {
|
||||
test: {
|
||||
executor: '@nrwl/jest:jest',
|
||||
options: { jestConfig: 'libs/lib1/jest.config.ts' },
|
||||
},
|
||||
},
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
lib1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'npm:@angular/core',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
|
||||
await expect(updateTsConfigTarget(tree)).resolves.not.toThrow();
|
||||
|
||||
expect(logger.warn).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
`The "libs/lib1/jest.config.ts" file specified in the "test" target of the "lib1" project could not be found.`
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('should not error and log a warning when the jest configuration file is not specified', async () => {
|
||||
jest.spyOn(logger, 'warn');
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
root: 'libs/lib1',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
projectType: 'library',
|
||||
targets: { test: { executor: '@nrwl/jest:jest', options: {} } },
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
lib1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'npm:@angular/core',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
|
||||
await expect(updateTsConfigTarget(tree)).resolves.not.toThrow();
|
||||
|
||||
expect(logger.warn).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
`The "test" target of the "lib1" project is using the "@nrwl/jest:jest" executor but no "jestConfig" property was specified.`
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it.each(['es2021', 'es2022', 'esnext'])(
|
||||
'should not update target when it is already set to a target greater than es2020 ("%s")',
|
||||
async (target) => {
|
||||
addProjectConfiguration(tree, 'app1', {
|
||||
root: 'apps/app1',
|
||||
sourceRoot: 'apps/app1/src',
|
||||
projectType: 'library',
|
||||
targets: {
|
||||
build: {
|
||||
executor: '@angular-devkit/build-angular:browser',
|
||||
options: { tsConfig: 'apps/app1/tsconfig.other.json' },
|
||||
},
|
||||
},
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
app1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'app1',
|
||||
target: 'npm:@angular/core',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
writeJson(tree, 'apps/app1/tsconfig.json', {
|
||||
compilerOptions: { target },
|
||||
});
|
||||
|
||||
await updateTsConfigTarget(tree);
|
||||
|
||||
const { compilerOptions } = readJson(tree, 'apps/app1/tsconfig.json');
|
||||
expect(compilerOptions.target).toBe(target);
|
||||
}
|
||||
);
|
||||
|
||||
it('should not update target in "tsconfig.json" at the project root when it is not an angular project', async () => {
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
root: 'libs/lib1',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
projectType: 'library',
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
lib1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'npm:lodash',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
writeJson(tree, 'libs/lib1/tsconfig.json', {
|
||||
compilerOptions: { target: 'es2017' },
|
||||
});
|
||||
|
||||
await updateTsConfigTarget(tree);
|
||||
|
||||
const { compilerOptions } = readJson(tree, 'libs/lib1/tsconfig.json');
|
||||
expect(compilerOptions.target).toBe('es2017');
|
||||
});
|
||||
|
||||
it('should not update target in a tsconfig file referenced by a target option when not using the relevant executors', async () => {
|
||||
jest.spyOn(logger, 'warn');
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
root: 'libs/lib1',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
projectType: 'library',
|
||||
targets: {
|
||||
build: {
|
||||
executor: '@org/awesome-plugin:executor',
|
||||
options: { tsConfig: 'libs/lib1/tsconfig.other.json' },
|
||||
},
|
||||
},
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
lib1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'npm:@angular/core',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
writeJson(tree, 'libs/lib1/tsconfig.other.json', {
|
||||
compilerOptions: { target: 'es2017' },
|
||||
});
|
||||
|
||||
await updateTsConfigTarget(tree);
|
||||
|
||||
const { compilerOptions } = readJson(tree, 'libs/lib1/tsconfig.other.json');
|
||||
expect(compilerOptions.target).toBe('es2017');
|
||||
expect(logger.warn).toHaveBeenCalledWith(
|
||||
expect.stringContaining(
|
||||
'The "build" target of the "lib1" project is using an executor not supported by the migration.'
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('should not update target in a tsconfig file referenced by a target configuration when not using the relevant executors', async () => {
|
||||
addProjectConfiguration(tree, 'lib1', {
|
||||
root: 'libs/lib1',
|
||||
sourceRoot: 'libs/lib1/src',
|
||||
projectType: 'library',
|
||||
targets: {
|
||||
build: {
|
||||
executor: '@org/awesome-plugin:executor',
|
||||
configurations: {
|
||||
production: { tsConfig: 'libs/lib1/tsconfig.other.json' },
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
lib1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'lib1',
|
||||
target: 'npm:@angular/core',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
writeJson(tree, 'libs/lib1/tsconfig.other.json', {
|
||||
compilerOptions: { target: 'es2017' },
|
||||
});
|
||||
|
||||
await updateTsConfigTarget(tree);
|
||||
|
||||
const { compilerOptions } = readJson(tree, 'libs/lib1/tsconfig.other.json');
|
||||
expect(compilerOptions.target).toBe('es2017');
|
||||
});
|
||||
|
||||
it('should not update target in workspace "tsconfig.base.json"', async () => {
|
||||
addProjectConfiguration(tree, 'app1', {
|
||||
root: 'apps/app1',
|
||||
sourceRoot: 'apps/app1/src',
|
||||
projectType: 'application',
|
||||
targets: {
|
||||
build: {
|
||||
executor: '@nrwl/angular:webpack-browser',
|
||||
options: { tsConfig: 'apps/app1/tsconfig.json' },
|
||||
},
|
||||
},
|
||||
});
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
app1: [
|
||||
{
|
||||
type: DependencyType.static,
|
||||
source: 'app1',
|
||||
target: 'npm:@angular/core',
|
||||
},
|
||||
],
|
||||
},
|
||||
nodes: {},
|
||||
};
|
||||
writeJson(tree, 'apps/app1/tsconfig.json', {
|
||||
compilerOptions: { target: 'es2017' },
|
||||
});
|
||||
writeJson(tree, 'tsconfig.base.json', {
|
||||
compilerOptions: { target: 'es2017' },
|
||||
});
|
||||
|
||||
await updateTsConfigTarget(tree);
|
||||
|
||||
const { compilerOptions } = readJson(tree, 'tsconfig.base.json');
|
||||
expect(compilerOptions.target).toBe('es2017');
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,247 @@
|
||||
import {
|
||||
ProjectConfiguration,
|
||||
readJson,
|
||||
TargetConfiguration,
|
||||
Tree,
|
||||
} from '@nrwl/devkit';
|
||||
import {
|
||||
createProjectGraphAsync,
|
||||
formatFiles,
|
||||
joinPathFragments,
|
||||
logger,
|
||||
readProjectConfiguration,
|
||||
updateJson,
|
||||
} from '@nrwl/devkit';
|
||||
import { tsquery } from '@phenomnomnominal/tsquery';
|
||||
import { dirname } from 'path';
|
||||
import type { StringLiteral } from 'typescript';
|
||||
|
||||
const jestExecutor = '@nrwl/jest:jest';
|
||||
const executors = [
|
||||
'@angular-devkit/build-angular:browser',
|
||||
'@angular-devkit/build-angular:karma',
|
||||
'@angular-devkit/build-angular:ng-packagr',
|
||||
'@nrwl/angular:webpack-browser',
|
||||
'@nrwl/angular:delegate-build',
|
||||
'@nrwl/angular:ng-packagr-lite',
|
||||
'@nrwl/angular:package',
|
||||
];
|
||||
const skipTargets = ['es2020', 'es2021', 'es2022', 'esnext'];
|
||||
|
||||
export default async function (tree: Tree) {
|
||||
const tsConfigPaths = await collectTsConfigPaths(tree);
|
||||
|
||||
for (const tsConfigPath of tsConfigPaths) {
|
||||
updateJson(tree, tsConfigPath, (json) => {
|
||||
if (
|
||||
!json.compilerOptions?.target ||
|
||||
(json.compilerOptions?.target &&
|
||||
!skipTargets.includes(json.compilerOptions.target.toLowerCase()))
|
||||
) {
|
||||
json.compilerOptions ??= {};
|
||||
json.compilerOptions.target = 'es2020';
|
||||
}
|
||||
return json;
|
||||
});
|
||||
}
|
||||
|
||||
await formatFiles(tree);
|
||||
}
|
||||
|
||||
async function collectTsConfigPaths(tree: Tree): Promise<string[]> {
|
||||
const uniqueTsConfigs = new Set([]);
|
||||
|
||||
const projectGraph = await createProjectGraphAsync();
|
||||
const angularProjects = Object.entries(projectGraph.dependencies)
|
||||
.filter(([, dep]) =>
|
||||
dep.some(({ target }) => target === 'npm:@angular/core')
|
||||
)
|
||||
.map(([projectName]) => ({
|
||||
projectName,
|
||||
project: readProjectConfiguration(tree, projectName),
|
||||
}));
|
||||
|
||||
for (const { projectName, project } of angularProjects) {
|
||||
const tsConfigPath = joinPathFragments(project.root, 'tsconfig.json');
|
||||
if (tree.exists(tsConfigPath)) {
|
||||
uniqueTsConfigs.add(tsConfigPath);
|
||||
|
||||
const targetTsConfigPaths = getProjectTsConfigPaths(
|
||||
tree,
|
||||
project,
|
||||
projectName,
|
||||
false
|
||||
);
|
||||
targetTsConfigPaths.forEach((tsConfigPath) => {
|
||||
const tsConfig = readJson(tree, tsConfigPath);
|
||||
if (tsConfig.compilerOptions?.target) {
|
||||
uniqueTsConfigs.add(tsConfigPath);
|
||||
}
|
||||
});
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const tsConfigPaths = getProjectTsConfigPaths(tree, project, projectName);
|
||||
for (const tsConfigPath of tsConfigPaths) {
|
||||
uniqueTsConfigs.add(tsConfigPath);
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(uniqueTsConfigs);
|
||||
}
|
||||
|
||||
function getProjectTsConfigPaths(
|
||||
tree: Tree,
|
||||
project: ProjectConfiguration,
|
||||
projectName: string,
|
||||
shouldWarn: boolean = true
|
||||
): string[] {
|
||||
const tsConfigPaths = new Set<string>();
|
||||
|
||||
for (const [targetName, target] of Object.entries(project.targets || {})) {
|
||||
if (executors.includes(target.executor)) {
|
||||
const tsConfigPathsFromTarget = getPathValuesFromTarget(
|
||||
target,
|
||||
'tsConfig'
|
||||
);
|
||||
tsConfigPathsFromTarget.forEach((tsConfigPath) => {
|
||||
if (tree.exists(tsConfigPath)) {
|
||||
tsConfigPaths.add(tsConfigPath);
|
||||
} else if (shouldWarn) {
|
||||
logger.warn(
|
||||
`The "${tsConfigPath}" file specified in the "${targetName}" target of the "${projectName}" project could not be found. ` +
|
||||
'Skipping setting the target to ES2020.'
|
||||
);
|
||||
}
|
||||
});
|
||||
} else if (target.executor === jestExecutor) {
|
||||
const tsConfigPathsFromJestTarget = getTsConfigPathsFromJestTarget(
|
||||
tree,
|
||||
target,
|
||||
targetName,
|
||||
projectName,
|
||||
shouldWarn
|
||||
);
|
||||
tsConfigPathsFromJestTarget.forEach((tsConfigPath) => {
|
||||
tsConfigPaths.add(tsConfigPath);
|
||||
});
|
||||
} else if (shouldWarn) {
|
||||
logger.warn(
|
||||
`The "${targetName}" target of the "${projectName}" project is using an executor not supported by the migration. ` +
|
||||
'Skipping setting the TS target to ES2020 for the project.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(tsConfigPaths);
|
||||
}
|
||||
|
||||
function getTsConfigPathsFromJestTarget(
|
||||
tree: Tree,
|
||||
target: TargetConfiguration,
|
||||
targetName: string,
|
||||
projectName: string,
|
||||
shouldWarn: boolean
|
||||
): string[] {
|
||||
const tsConfigPaths: string[] = [];
|
||||
|
||||
const jestConfigPaths = getPathValuesFromTarget(target, 'jestConfig');
|
||||
if (!jestConfigPaths.length && shouldWarn) {
|
||||
logger.warn(
|
||||
`The "${targetName}" target of the "${projectName}" project is using the "${jestExecutor}" executor but no "jestConfig" property was specified. ` +
|
||||
'Skipping setting the TS compilation target to ES2020 for the project.'
|
||||
);
|
||||
}
|
||||
|
||||
for (const jestConfigPath of jestConfigPaths) {
|
||||
const tsConfigPath = getTsConfigFromJestConfig(
|
||||
tree,
|
||||
jestConfigPath,
|
||||
targetName,
|
||||
projectName,
|
||||
shouldWarn
|
||||
);
|
||||
if (tsConfigPath) {
|
||||
tsConfigPaths.push(tsConfigPath);
|
||||
}
|
||||
}
|
||||
|
||||
return tsConfigPaths;
|
||||
}
|
||||
|
||||
function getTsConfigFromJestConfig(
|
||||
tree: Tree,
|
||||
jestConfigPath: string,
|
||||
targetName: string,
|
||||
projectName: string,
|
||||
shouldWarn: boolean
|
||||
): string {
|
||||
if (!tree.exists(jestConfigPath)) {
|
||||
if (shouldWarn) {
|
||||
logger.warn(
|
||||
`The "${jestConfigPath}" file specified in the "${targetName}" target of the "${projectName}" project could not be found. ` +
|
||||
`The TS config file used by the target can't be determined. Skipping setting the target to ES2020.`
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const jestConfig = tree.read(jestConfigPath, 'utf-8');
|
||||
const jestConfigAst = tsquery.ast(jestConfig);
|
||||
const tsJestTsConfigStringLiteral = tsquery(
|
||||
jestConfigAst,
|
||||
'PropertyAssignment:has(Identifier[name=globals]) PropertyAssignment:has(StringLiteral[value=ts-jest]) PropertyAssignment Identifier[name=tsconfig] ~ StringLiteral',
|
||||
{ visitAllChildren: true }
|
||||
)[0] as StringLiteral;
|
||||
|
||||
if (!tsJestTsConfigStringLiteral) {
|
||||
if (shouldWarn) {
|
||||
logger.warn(
|
||||
`Couldn't find the "tsconfig" property for "ts-jest" in the Jest configuration file "${jestConfigPath}" specified in the ` +
|
||||
`"${targetName}" target of the "${projectName}" project. The TS config file used by the target can't be determined. ` +
|
||||
'Skipping setting the target to ES2020.'
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const tsJestTsConfigValue = tsJestTsConfigStringLiteral
|
||||
.getText()
|
||||
.replace(/['"]/g, '');
|
||||
const tsConfigPath = tsJestTsConfigValue.replace(
|
||||
'<rootDir>',
|
||||
dirname(jestConfigPath)
|
||||
);
|
||||
|
||||
if (!tree.exists(tsConfigPath)) {
|
||||
if (shouldWarn) {
|
||||
logger.warn(
|
||||
`The "${tsJestTsConfigValue}" file specified in the Jest configuration file "${jestConfigPath}" of the "${targetName}" target ` +
|
||||
`of the "${projectName}" project could not be found. Skipping setting the target to ES2020.`
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return tsConfigPath;
|
||||
}
|
||||
|
||||
function getPathValuesFromTarget(
|
||||
target: TargetConfiguration,
|
||||
option: string
|
||||
): string[] {
|
||||
const values: string[] = [];
|
||||
|
||||
if (target.options?.[option]) {
|
||||
values.push(target.options[option]);
|
||||
}
|
||||
|
||||
Object.values(target.configurations ?? {}).forEach((options) => {
|
||||
if (options[option]) {
|
||||
values.push(options[option]);
|
||||
}
|
||||
});
|
||||
|
||||
return values;
|
||||
}
|
||||
@ -232,6 +232,78 @@ describe('MFE Webpack Utils', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should collect secondary entry points from exports and fall back to lookinp up for package.json', () => {
|
||||
// ARRANGE
|
||||
(fs.existsSync as jest.Mock).mockImplementation(
|
||||
(path) => !path.endsWith('/secondary/package.json')
|
||||
);
|
||||
jest.spyOn(devkit, 'readJsonFile').mockImplementation((file) => {
|
||||
if (file.endsWith('pkg1/package.json')) {
|
||||
return {
|
||||
name: 'pkg1',
|
||||
version: '1.0.0',
|
||||
exports: {
|
||||
'.': './index.js',
|
||||
'./package.json': './package.json',
|
||||
'./secondary': './secondary/index.js',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// @angular/core/package.json won't have exports, so it looks up for package.json
|
||||
return {
|
||||
name: file
|
||||
.replace(/\\/g, '/')
|
||||
.replace(/^.*node_modules[/]/, '')
|
||||
.replace('/package.json', ''),
|
||||
dependencies: { pkg1: '1.0.0', '@angular/core': '~13.2.0' },
|
||||
};
|
||||
});
|
||||
(fs.readdirSync as jest.Mock).mockImplementation(
|
||||
(directoryPath: string) => {
|
||||
const packages = {
|
||||
pkg1: ['secondary'],
|
||||
'@angular/core': ['testing'],
|
||||
};
|
||||
|
||||
for (const key of Object.keys(packages)) {
|
||||
if (directoryPath.endsWith(key)) {
|
||||
return packages[key];
|
||||
}
|
||||
}
|
||||
return [];
|
||||
}
|
||||
);
|
||||
(fs.lstatSync as jest.Mock).mockReturnValue({ isDirectory: () => true });
|
||||
|
||||
// ACT
|
||||
const packages = sharePackages(['pkg1', '@angular/core']);
|
||||
|
||||
// ASSERT
|
||||
expect(packages).toStrictEqual({
|
||||
pkg1: {
|
||||
singleton: true,
|
||||
strictVersion: true,
|
||||
requiredVersion: '1.0.0',
|
||||
},
|
||||
'pkg1/secondary': {
|
||||
singleton: true,
|
||||
strictVersion: true,
|
||||
requiredVersion: '1.0.0',
|
||||
},
|
||||
'@angular/core': {
|
||||
singleton: true,
|
||||
strictVersion: true,
|
||||
requiredVersion: '~13.2.0',
|
||||
},
|
||||
'@angular/core/testing': {
|
||||
singleton: true,
|
||||
strictVersion: true,
|
||||
requiredVersion: '~13.2.0',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('should not throw when the main entry point package.json cannot be required', () => {
|
||||
// ARRANGE
|
||||
(fs.existsSync as jest.Mock).mockImplementation(
|
||||
|
||||
@ -102,27 +102,36 @@ function recursivelyCollectSecondaryEntryPointsFromDirectory(
|
||||
pkgName: string,
|
||||
pkgVersion: string,
|
||||
pkgRoot: string,
|
||||
mainEntryPointExports: any | undefined,
|
||||
directories: string[],
|
||||
collectedPackages: { name: string; version: string }[]
|
||||
): void {
|
||||
for (const directory of directories) {
|
||||
const packageJsonPath = join(directory, 'package.json');
|
||||
const relativeEntryPointPath = relative(pkgRoot, directory);
|
||||
const entryPointName = joinPathFragments(pkgName, relativeEntryPointPath);
|
||||
if (existsSync(packageJsonPath)) {
|
||||
const importName = joinPathFragments(
|
||||
pkgName,
|
||||
relative(pkgRoot, directory)
|
||||
);
|
||||
|
||||
try {
|
||||
// require the secondary entry point to try to rule out sample code
|
||||
require.resolve(importName, { paths: [workspaceRoot] });
|
||||
require.resolve(entryPointName, { paths: [workspaceRoot] });
|
||||
const { name } = readJsonFile(packageJsonPath);
|
||||
// further check to make sure what we were able to require is the
|
||||
// same as the package name
|
||||
if (name === importName) {
|
||||
if (name === entryPointName) {
|
||||
collectedPackages.push({ name, version: pkgVersion });
|
||||
}
|
||||
} catch {}
|
||||
} else if (mainEntryPointExports) {
|
||||
// if the package.json doesn't exist, check if the directory is
|
||||
// exported by the main entry point
|
||||
const entryPointExportKey = `./${relativeEntryPointPath}`;
|
||||
const entryPointInfo = mainEntryPointExports[entryPointExportKey];
|
||||
if (entryPointInfo) {
|
||||
collectedPackages.push({
|
||||
name: entryPointName,
|
||||
version: pkgVersion,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const subDirs = getNonNodeModulesSubDirs(directory);
|
||||
@ -130,6 +139,7 @@ function recursivelyCollectSecondaryEntryPointsFromDirectory(
|
||||
pkgName,
|
||||
pkgVersion,
|
||||
pkgRoot,
|
||||
mainEntryPointExports,
|
||||
subDirs,
|
||||
collectedPackages
|
||||
);
|
||||
@ -142,8 +152,9 @@ function collectPackageSecondaryEntryPoints(
|
||||
collectedPackages: { name: string; version: string }[]
|
||||
): void {
|
||||
let pathToPackage: string;
|
||||
let packageJsonPath: string;
|
||||
try {
|
||||
const packageJsonPath = require.resolve(`${pkgName}/package.json`, {
|
||||
packageJsonPath = require.resolve(`${pkgName}/package.json`, {
|
||||
paths: [workspaceRoot],
|
||||
});
|
||||
pathToPackage = dirname(packageJsonPath);
|
||||
@ -152,17 +163,20 @@ function collectPackageSecondaryEntryPoints(
|
||||
// entry and is not exporting the package.json file, fall back to trying
|
||||
// to find it from the top-level node_modules
|
||||
pathToPackage = join(workspaceRoot, 'node_modules', pkgName);
|
||||
if (!existsSync(join(pathToPackage, 'package.json'))) {
|
||||
packageJsonPath = join(pathToPackage, 'package.json');
|
||||
if (!existsSync(packageJsonPath)) {
|
||||
// might not exist if it's nested in another package, just return here
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const { exports } = readJsonFile(packageJsonPath);
|
||||
const subDirs = getNonNodeModulesSubDirs(pathToPackage);
|
||||
recursivelyCollectSecondaryEntryPointsFromDirectory(
|
||||
pkgName,
|
||||
pkgVersion,
|
||||
pathToPackage,
|
||||
exports,
|
||||
subDirs,
|
||||
collectedPackages
|
||||
);
|
||||
|
||||
@ -32,7 +32,7 @@ const migrationTestRunner = new SchematicTestRunner(
|
||||
join(__dirname, '../../migrations.json')
|
||||
);
|
||||
|
||||
export function runMigration<SchemaOptions = any>(
|
||||
export function runMigration<SchemaOptions extends object = any>(
|
||||
schematicName: string,
|
||||
options: SchemaOptions,
|
||||
tree: Tree
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
export const nxVersion = require('../../package.json').version;
|
||||
export const angularVersion = '~13.3.0';
|
||||
export const angularDevkitVersion = '~13.3.0';
|
||||
export const angularVersion = '~14.0.0-rc.2';
|
||||
export const angularDevkitVersion = '~14.0.0-rc.2';
|
||||
export const ngPackagrVersion = '~14.0.0-rc.0';
|
||||
export const angularJsVersion = '1.7.9';
|
||||
export const ngrxVersion = '~13.0.0';
|
||||
export const ngrxVersion = '~13.2.0';
|
||||
export const rxjsVersion = '~7.4.0';
|
||||
export const jestPresetAngularVersion = '11.1.1';
|
||||
export const angularEslintVersion = '~13.1.0';
|
||||
export const jestPresetAngularVersion = '~11.1.2';
|
||||
export const angularEslintVersion = '~13.2.1';
|
||||
export const tailwindVersion = '^3.0.2';
|
||||
export const postcssVersion = '^8.4.5';
|
||||
export const autoprefixerVersion = '^10.4.0';
|
||||
|
||||
@ -6,9 +6,9 @@ Object {
|
||||
"devDependencies": Object {
|
||||
"@nrwl/eslint-plugin-nx": "0.0.1",
|
||||
"@nrwl/linter": "0.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "~5.18.0",
|
||||
"@typescript-eslint/parser": "~5.18.0",
|
||||
"eslint": "~8.12.0",
|
||||
"@typescript-eslint/eslint-plugin": "~5.24.0",
|
||||
"@typescript-eslint/parser": "~5.24.0",
|
||||
"eslint": "~8.15.0",
|
||||
"eslint-config-prettier": "8.1.0",
|
||||
"eslint-plugin-cypress": "^2.10.3",
|
||||
"eslint-plugin-import": "latest",
|
||||
|
||||
@ -23,7 +23,7 @@
|
||||
},
|
||||
"homepage": "https://nx.dev",
|
||||
"peerDependencies": {
|
||||
"@typescript-eslint/parser": "~5.18.0",
|
||||
"@typescript-eslint/parser": "~5.24.0",
|
||||
"eslint-config-prettier": "^8.1.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
@ -34,7 +34,7 @@
|
||||
"dependencies": {
|
||||
"@nrwl/devkit": "file:../devkit",
|
||||
"@nrwl/workspace": "file:../workspace",
|
||||
"@typescript-eslint/experimental-utils": "~5.18.0",
|
||||
"@typescript-eslint/experimental-utils": "~5.24.0",
|
||||
"chalk": "4.1.0",
|
||||
"confusing-browser-globals": "^1.0.9"
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ const migrationTestRunner = new SchematicTestRunner(
|
||||
join(__dirname, '../../migrations.json')
|
||||
);
|
||||
|
||||
export function runSchematic<T = any>(
|
||||
export function runSchematic<T extends object = any>(
|
||||
schematicName: string,
|
||||
options: T,
|
||||
tree: Tree
|
||||
@ -26,9 +26,9 @@ export function callRule(rule: Rule, tree: Tree) {
|
||||
return testRunner.callRule(rule, tree).toPromise();
|
||||
}
|
||||
|
||||
export function runMigration(
|
||||
export function runMigration<T extends object = any>(
|
||||
migrationName: string,
|
||||
options: unknown,
|
||||
options: T,
|
||||
tree: Tree
|
||||
) {
|
||||
return migrationTestRunner
|
||||
|
||||
@ -208,6 +208,23 @@
|
||||
"version": "~8.12.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"14.2.0": {
|
||||
"version": "14.2.0-beta.0",
|
||||
"packages": {
|
||||
"@typescript-eslint/parser": {
|
||||
"version": "~5.24.0"
|
||||
},
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"version": "~5.24.0"
|
||||
},
|
||||
"@typescript-eslint/experimental-utils": {
|
||||
"version": "~5.24.0"
|
||||
},
|
||||
"eslint": {
|
||||
"version": "~8.15.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ const migrationTestRunner = new SchematicTestRunner(
|
||||
join(__dirname, '../../migrations.json')
|
||||
);
|
||||
|
||||
export function runMigration<T = any>(
|
||||
export function runMigration<T extends object = any>(
|
||||
migrationName: string,
|
||||
options: T,
|
||||
tree: Tree
|
||||
|
||||
@ -2,8 +2,8 @@ export const nxVersion = require('../../package.json').version;
|
||||
|
||||
export const tslintVersion = '~6.1.0';
|
||||
export const tslintToEslintConfigVersion = '^2.4.0';
|
||||
export const buildAngularVersion = '~13.3.0';
|
||||
export const buildAngularVersion = '~14.0.0-rc.2';
|
||||
|
||||
export const typescriptESLintVersion = '~5.18.0';
|
||||
export const eslintVersion = '~8.12.0';
|
||||
export const typescriptESLintVersion = '~5.24.0';
|
||||
export const eslintVersion = '~8.15.0';
|
||||
export const eslintConfigPrettierVersion = '8.1.0';
|
||||
|
||||
@ -6,9 +6,9 @@ Object {
|
||||
"devDependencies": Object {
|
||||
"@nrwl/eslint-plugin-nx": "0.0.1",
|
||||
"@nrwl/linter": "0.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "~5.18.0",
|
||||
"@typescript-eslint/parser": "~5.18.0",
|
||||
"eslint": "~8.12.0",
|
||||
"@typescript-eslint/eslint-plugin": "~5.24.0",
|
||||
"@typescript-eslint/parser": "~5.24.0",
|
||||
"eslint": "~8.15.0",
|
||||
"eslint-config-prettier": "8.1.0",
|
||||
"eslint-plugin-import": "latest",
|
||||
},
|
||||
@ -299,9 +299,9 @@ Object {
|
||||
"devDependencies": Object {
|
||||
"@nrwl/eslint-plugin-nx": "0.0.1",
|
||||
"@nrwl/linter": "0.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "~5.18.0",
|
||||
"@typescript-eslint/parser": "~5.18.0",
|
||||
"eslint": "~8.12.0",
|
||||
"@typescript-eslint/eslint-plugin": "~5.24.0",
|
||||
"@typescript-eslint/parser": "~5.24.0",
|
||||
"eslint": "~8.15.0",
|
||||
"eslint-config-prettier": "8.1.0",
|
||||
"eslint-plugin-import": "latest",
|
||||
},
|
||||
|
||||
@ -71,8 +71,6 @@ function getProjects(projectGraph: ProjectGraph, project: string): any {
|
||||
const targetAliases = {
|
||||
b: 'build',
|
||||
e: 'e2e',
|
||||
'i18n-extract': 'extract-i18n',
|
||||
xi18n: 'extract-i18n',
|
||||
l: 'lint',
|
||||
s: 'serve',
|
||||
t: 'test',
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
export const nxVersion = require('../../package.json').version;
|
||||
|
||||
export const angularCliVersion = '~13.2.0';
|
||||
export const typescriptVersion = '~4.5.2';
|
||||
export const angularCliVersion = '~14.0.0-rc.2';
|
||||
export const typescriptVersion = '~4.6.2';
|
||||
export const prettierVersion = '^2.5.1';
|
||||
export const tslintVersion = '~6.1.0';
|
||||
export const typescriptESLintVersion = '~5.18.0';
|
||||
export const eslintVersion = '~8.12.0';
|
||||
export const typescriptESLintVersion = '~5.24.0';
|
||||
export const eslintVersion = '~8.15.0';
|
||||
export const eslintConfigPrettierVersion = '8.1.0';
|
||||
export const swcNodeVersion = '^1.4.2';
|
||||
export const swcCoreVersion = '^1.2.173';
|
||||
|
||||
@ -63,7 +63,7 @@ const migrationTestRunner = new SchematicTestRunner(
|
||||
join(__dirname, '../../migrations.json')
|
||||
);
|
||||
|
||||
export function runExternalSchematic<T = any>(
|
||||
export function runExternalSchematic<T extends object = any>(
|
||||
collectionName: string,
|
||||
schematicName: string,
|
||||
options: T,
|
||||
@ -74,7 +74,7 @@ export function runExternalSchematic<T = any>(
|
||||
.toPromise();
|
||||
}
|
||||
|
||||
export function runSchematic<T = any>(
|
||||
export function runSchematic<T extends object = any>(
|
||||
schematicName: string,
|
||||
options: T,
|
||||
tree: Tree
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
export const nxVersion = require('../../package.json').version;
|
||||
|
||||
export const angularCliVersion = '~13.3.0';
|
||||
export const angularCliVersion = '~14.0.0-rc.2';
|
||||
export const typescriptVersion = '~4.6.2';
|
||||
export const prettierVersion = '^2.5.1';
|
||||
export const tslintVersion = '~6.1.0';
|
||||
export const typescriptESLintVersion = '~5.18.0';
|
||||
export const eslintVersion = '~8.12.0';
|
||||
export const typescriptESLintVersion = '~5.24.0';
|
||||
export const eslintVersion = '~8.15.0';
|
||||
export const eslintConfigPrettierVersion = '8.1.0';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user