@nx/angular 21.0.0-beta.4 → 21.0.0-beta.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/nx-angular.mjs +0 -352
- package/fesm2022/nx-angular.mjs.map +1 -1
- package/generators.json +2 -2
- package/index.d.ts +1 -1
- package/migrations.json +18 -69
- package/package.json +9 -14
- package/src/builders/dev-server/schema.d.ts +3 -0
- package/src/builders/dev-server/schema.json +1 -1
- package/src/builders/webpack-browser/schema.d.ts +0 -5
- package/src/builders/webpack-browser/webpack-browser.impl.js +3 -4
- package/src/executors/module-federation-dev-server/schema.d.ts +3 -0
- package/src/executors/module-federation-dev-server/schema.json +1 -1
- package/src/generators/add-linting/lib/create-eslint-configuration.d.ts +2 -2
- package/src/generators/add-linting/lib/create-eslint-configuration.js +2 -2
- package/src/generators/application/application.js +6 -0
- package/src/generators/application/files/rspack-ssr/server.ts__tmpl__ +72 -0
- package/src/generators/application/lib/add-e2e.js +0 -7
- package/src/generators/convert-to-rspack/convert-to-rspack.js +20 -10
- package/src/generators/convert-to-rspack/lib/create-config.js +14 -17
- package/src/generators/convert-to-rspack/lib/get-custom-webpack-config.js +5 -3
- package/src/generators/move/move.d.ts +3 -0
- package/src/generators/move/move.js +3 -0
- package/src/generators/ngrx/ngrx.d.ts +3 -0
- package/src/generators/ngrx/ngrx.js +3 -0
- package/src/generators/ngrx/schema.json +1 -1
- package/src/migrations/update-16-2-0/switch-data-persistence-operators-imports-to-ngrx-router-store.js +4 -4
- package/src/migrations/{update-16-1-0/remove-ngcc-invocation.d.ts → update-21-0-0/change-data-persistence-operators-imports-to-ngrx-router-store-data-persistence.d.ts} +1 -1
- package/src/migrations/update-21-0-0/change-data-persistence-operators-imports-to-ngrx-router-store-data-persistence.js +122 -0
- package/src/utils/nx-devkit/ast-utils.d.ts +0 -8
- package/src/utils/nx-devkit/ast-utils.js +7 -12
- package/src/utils/versions.d.ts +1 -1
- package/src/utils/versions.js +1 -1
- package/fesm2022/nx-angular-testing.mjs +0 -45
- package/fesm2022/nx-angular-testing.mjs.map +0 -1
- package/src/migrations/update-16-0-0/remove-karma-defaults.d.ts +0 -2
- package/src/migrations/update-16-0-0/remove-karma-defaults.js +0 -52
- package/src/migrations/update-16-0-0/remove-library-generator-simple-module-name-option.d.ts +0 -2
- package/src/migrations/update-16-0-0/remove-library-generator-simple-module-name-option.js +0 -40
- package/src/migrations/update-16-0-0/remove-protractor-defaults.d.ts +0 -2
- package/src/migrations/update-16-0-0/remove-protractor-defaults.js +0 -52
- package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.d.ts +0 -2
- package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.js +0 -9
- package/src/migrations/update-16-1-0/extract-standalone-config-from-bootstrap.d.ts +0 -2
- package/src/migrations/update-16-1-0/extract-standalone-config-from-bootstrap.js +0 -127
- package/src/migrations/update-16-1-0/remove-ngcc-invocation.js +0 -22
- package/src/migrations/update-16-1-0/remove-render-module-platform-server-exports.d.ts +0 -2
- package/src/migrations/update-16-1-0/remove-render-module-platform-server-exports.js +0 -62
- package/src/migrations/update-16-1-0/update-angular-cli.d.ts +0 -3
- package/src/migrations/update-16-1-0/update-angular-cli.js +0 -23
- package/src/migrations/update-16-1-0/update-server-executor-config.d.ts +0 -2
- package/src/migrations/update-16-1-0/update-server-executor-config.js +0 -26
- package/src/runtime/nx/data-persistence.d.ts +0 -276
- package/testing/index.d.ts +0 -1
- package/testing/ng-package.json +0 -6
- package/testing/src/testing-utils.d.ts +0 -33
@@ -5,7 +5,7 @@ exports.createEsLintConfiguration = createEsLintConfiguration;
|
|
5
5
|
const devkit_1 = require("@nx/devkit");
|
6
6
|
const string_utils_1 = require("@nx/devkit/src/utils/string-utils");
|
7
7
|
/**
|
8
|
-
* @deprecated Use tools from `@nx/eslint/src/generators/utils/eslint-file` instead
|
8
|
+
* @deprecated Use tools from `@nx/eslint/src/generators/utils/eslint-file` instead. It will be removed in Nx v22.
|
9
9
|
*/
|
10
10
|
const extendAngularEslintJson = (json, options) => {
|
11
11
|
const overrides = [
|
@@ -53,7 +53,7 @@ const extendAngularEslintJson = (json, options) => {
|
|
53
53
|
};
|
54
54
|
exports.extendAngularEslintJson = extendAngularEslintJson;
|
55
55
|
/**
|
56
|
-
* @deprecated Use {@link extendAngularEslintJson} instead
|
56
|
+
* @deprecated Use {@link extendAngularEslintJson} instead. It will be removed in Nx v22.
|
57
57
|
*/
|
58
58
|
function createEsLintConfiguration(tree, options) {
|
59
59
|
const rootConfig = `${(0, devkit_1.offsetFromRoot)(options.projectRoot)}.eslintrc.json`;
|
@@ -76,6 +76,12 @@ async function applicationGenerator(tree, schema) {
|
|
76
76
|
skipInstall: options.skipPackageJson,
|
77
77
|
skipFormat: true,
|
78
78
|
});
|
79
|
+
if (options.ssr) {
|
80
|
+
(0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, './files/rspack-ssr'), options.appProjectSourceRoot, {
|
81
|
+
pathToDistFolder: (0, devkit_1.joinPathFragments)((0, devkit_1.offsetFromRoot)(options.appProjectRoot), options.outputPath, 'browser'),
|
82
|
+
tmpl: '',
|
83
|
+
});
|
84
|
+
}
|
79
85
|
}
|
80
86
|
if (!options.skipFormat) {
|
81
87
|
await (0, devkit_1.formatFiles)(tree);
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import 'zone.js/node';
|
2
|
+
|
3
|
+
import { APP_BASE_HREF } from '@angular/common';
|
4
|
+
import { CommonEngine } from '@angular/ssr/node';
|
5
|
+
import * as express from 'express';
|
6
|
+
import { existsSync } from 'node:fs';
|
7
|
+
import { join } from 'node:path';
|
8
|
+
import bootstrap from './main.server';
|
9
|
+
|
10
|
+
// The Express app is exported so that it can be used by serverless Functions.
|
11
|
+
export function app(): express.Express {
|
12
|
+
const server = express();
|
13
|
+
const distFolder = join(process.cwd(), "<%= pathToDistFolder %>");
|
14
|
+
const indexHtml = existsSync(join(distFolder, 'index.original.html'))
|
15
|
+
? join(distFolder, 'index.original.html')
|
16
|
+
: join(distFolder, 'index.html');
|
17
|
+
|
18
|
+
const commonEngine = new CommonEngine();
|
19
|
+
|
20
|
+
server.set('view engine', 'html');
|
21
|
+
server.set('views', distFolder);
|
22
|
+
|
23
|
+
// Example Express Rest API endpoints
|
24
|
+
// server.get('/api/**', (req, res) => { });
|
25
|
+
// Serve static files from /browser
|
26
|
+
server.get(
|
27
|
+
'*.*',
|
28
|
+
express.static(distFolder, {
|
29
|
+
maxAge: '1y',
|
30
|
+
})
|
31
|
+
);
|
32
|
+
|
33
|
+
// All regular routes use the Angular engine
|
34
|
+
server.get('*', (req, res, next) => {
|
35
|
+
const { protocol, originalUrl, baseUrl, headers } = req;
|
36
|
+
|
37
|
+
commonEngine
|
38
|
+
.render({
|
39
|
+
bootstrap,
|
40
|
+
documentFilePath: indexHtml,
|
41
|
+
url: `${protocol}://${headers.host}${originalUrl}`,
|
42
|
+
publicPath: distFolder,
|
43
|
+
providers: [{ provide: APP_BASE_HREF, useValue: baseUrl }],
|
44
|
+
})
|
45
|
+
.then((html) => res.send(html))
|
46
|
+
.catch((err) => next(err));
|
47
|
+
});
|
48
|
+
|
49
|
+
return server;
|
50
|
+
}
|
51
|
+
|
52
|
+
function run(): void {
|
53
|
+
const port = process.env['PORT'] || 4000;
|
54
|
+
|
55
|
+
// Start up the Node server
|
56
|
+
const server = app();
|
57
|
+
server.listen(port, () => {
|
58
|
+
console.log(`Node Express server listening on http://localhost:${port}`);
|
59
|
+
});
|
60
|
+
}
|
61
|
+
|
62
|
+
// Webpack will replace 'require' with '__webpack_require__'
|
63
|
+
// '__non_webpack_require__' is a proxy to Node 'require'
|
64
|
+
// The below code is to ensure that the server is run only when not requiring the bundle.
|
65
|
+
declare const __non_webpack_require__: NodeRequire;
|
66
|
+
const mainModule = __non_webpack_require__.main;
|
67
|
+
const moduleFilename = (mainModule && mainModule.filename) || '';
|
68
|
+
if (moduleFilename === __filename || moduleFilename.includes('iisnode')) {
|
69
|
+
run();
|
70
|
+
}
|
71
|
+
|
72
|
+
export default bootstrap;
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.addE2e = addE2e;
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
5
5
|
const versions_1 = require("../../../utils/versions");
|
6
|
-
const target_defaults_utils_1 = require("@nx/devkit/src/generators/target-defaults-utils");
|
7
6
|
async function addE2e(tree, options) {
|
8
7
|
// since e2e are separate projects, default to adding plugins
|
9
8
|
const nxJson = (0, devkit_1.readNxJson)(tree);
|
@@ -37,9 +36,6 @@ async function addE2e(tree, options) {
|
|
37
36
|
rootProject: options.rootProject,
|
38
37
|
addPlugin,
|
39
38
|
});
|
40
|
-
if (addPlugin) {
|
41
|
-
await (0, target_defaults_utils_1.addE2eCiTargetDefaults)(tree, '@nx/cypress/plugin', '^build', (0, devkit_1.joinPathFragments)(options.e2eProjectRoot, 'cypress.config.ts'));
|
42
|
-
}
|
43
39
|
}
|
44
40
|
else if (options.e2eTestRunner === 'playwright') {
|
45
41
|
const { configurationGenerator } = (0, devkit_1.ensurePackage)('@nx/playwright', versions_1.nxVersion);
|
@@ -63,9 +59,6 @@ async function addE2e(tree, options) {
|
|
63
59
|
rootProject: options.rootProject,
|
64
60
|
addPlugin,
|
65
61
|
});
|
66
|
-
if (addPlugin) {
|
67
|
-
await (0, target_defaults_utils_1.addE2eCiTargetDefaults)(tree, '@nx/playwright/plugin', '^build', (0, devkit_1.joinPathFragments)(options.e2eProjectRoot, 'playwright.config.ts'));
|
68
|
-
}
|
69
62
|
}
|
70
63
|
return e2eWebServerInfo.e2ePort;
|
71
64
|
}
|
@@ -14,7 +14,9 @@ const enquirer_1 = require("enquirer");
|
|
14
14
|
const SUPPORTED_EXECUTORS = [
|
15
15
|
'@angular-devkit/build-angular:browser',
|
16
16
|
'@angular-devkit/build-angular:dev-server',
|
17
|
+
'@angular-devkit/build-angular:server',
|
17
18
|
'@nx/angular:webpack-browser',
|
19
|
+
'@nx/angular:webpack-server',
|
18
20
|
'@nx/angular:dev-server',
|
19
21
|
'@nx/angular:module-federation-dev-server',
|
20
22
|
];
|
@@ -22,20 +24,12 @@ const RENAMED_OPTIONS = {
|
|
22
24
|
main: 'browser',
|
23
25
|
ngswConfigPath: 'serviceWorker',
|
24
26
|
};
|
27
|
+
const DEFAULT_PORT = 4200;
|
25
28
|
const REMOVED_OPTIONS = [
|
26
|
-
'publicHost',
|
27
|
-
'disableHostCheck',
|
28
|
-
'resourcesOutputPath',
|
29
|
-
'routesFile',
|
30
|
-
'routes',
|
31
|
-
'discoverRoutes',
|
32
|
-
'appModuleBundle',
|
33
|
-
'inputIndexPath',
|
34
|
-
'outputIndexPath',
|
35
29
|
'buildOptimizer',
|
36
|
-
'deployUrl',
|
37
30
|
'buildTarget',
|
38
31
|
'browserTarget',
|
32
|
+
'publicHost',
|
39
33
|
];
|
40
34
|
function normalizeFromProjectRoot(tree, path, projectRoot) {
|
41
35
|
if (projectRoot === '.') {
|
@@ -256,6 +250,7 @@ async function convertToRspack(tree, schema) {
|
|
256
250
|
const serveTargetNames = [];
|
257
251
|
let customWebpackConfigPath;
|
258
252
|
(0, validate_supported_executor_1.validateSupportedBuildExecutor)(Object.values(project.targets));
|
253
|
+
let projectServePort = DEFAULT_PORT;
|
259
254
|
for (const [targetName, target] of Object.entries(project.targets)) {
|
260
255
|
if (target.executor === '@angular-devkit/build-angular:browser' ||
|
261
256
|
target.executor === '@nx/angular:webpack-browser') {
|
@@ -268,12 +263,22 @@ async function convertToRspack(tree, schema) {
|
|
268
263
|
}
|
269
264
|
buildTargetNames.push(targetName);
|
270
265
|
}
|
266
|
+
else if (target.executor === '@angular-devkit/build-angular:server' ||
|
267
|
+
target.executor === '@nx/angular:webpack-server') {
|
268
|
+
createConfigOptions.ssr ??= {};
|
269
|
+
createConfigOptions.ssr.entry ??= normalizeFromProjectRoot(tree, target.options.main, project.root);
|
270
|
+
createConfigOptions.server = './src/main.server.ts';
|
271
|
+
buildTargetNames.push(targetName);
|
272
|
+
}
|
271
273
|
else if (target.executor === '@angular-devkit/build-angular:dev-server' ||
|
272
274
|
target.executor === '@nx/angular:dev-server' ||
|
273
275
|
target.executor === '@nx/angular:module-federation-dev-server') {
|
274
276
|
createConfigOptions.devServer = {};
|
275
277
|
if (target.options) {
|
276
278
|
handleDevServerTargetOptions(tree, target.options, createConfigOptions.devServer, project.root);
|
279
|
+
if (target.options.port !== DEFAULT_PORT) {
|
280
|
+
projectServePort = target.options.port;
|
281
|
+
}
|
277
282
|
}
|
278
283
|
if (target.configurations) {
|
279
284
|
for (const [configurationName, configuration] of Object.entries(target.configurations)) {
|
@@ -293,6 +298,11 @@ async function convertToRspack(tree, schema) {
|
|
293
298
|
for (const targetName of [...buildTargetNames, ...serveTargetNames]) {
|
294
299
|
delete project.targets[targetName];
|
295
300
|
}
|
301
|
+
if (projectServePort !== DEFAULT_PORT) {
|
302
|
+
project.targets.serve ??= {};
|
303
|
+
project.targets.serve.options ??= {};
|
304
|
+
project.targets.serve.options.port = projectServePort;
|
305
|
+
}
|
296
306
|
(0, devkit_1.updateProjectConfiguration)(tree, projectName, project);
|
297
307
|
const { rspackInitGenerator } = (0, devkit_1.ensurePackage)('@nx/rspack', versions_1.nxVersion);
|
298
308
|
await rspackInitGenerator(tree, {
|
@@ -9,7 +9,7 @@ function createConfig(tree, opts, configurationOptions = {}, existingWebpackConf
|
|
9
9
|
? Object.entries(configurationOptions)
|
10
10
|
.map(([configurationName, configurationOptions]) => {
|
11
11
|
return `
|
12
|
-
${configurationName}: {
|
12
|
+
"${configurationName}": {
|
13
13
|
options: {
|
14
14
|
${JSON.stringify(configurationOptions, undefined, 2).slice(1, -1)}
|
15
15
|
}
|
@@ -17,6 +17,12 @@ function createConfig(tree, opts, configurationOptions = {}, existingWebpackConf
|
|
17
17
|
})
|
18
18
|
.join(',\n')
|
19
19
|
: '';
|
20
|
+
const createConfigContents = `createConfig({
|
21
|
+
options: {
|
22
|
+
root: __dirname,
|
23
|
+
${JSON.stringify(createConfigOptions, undefined, 2).slice(1, -1)}
|
24
|
+
}
|
25
|
+
}${hasConfigurations ? `, {${expandedConfigurationOptions}}` : ''});`;
|
20
26
|
const configContents = `
|
21
27
|
import { createConfig }from '@nx/angular-rspack';
|
22
28
|
${existingWebpackConfigPath
|
@@ -26,23 +32,14 @@ function createConfig(tree, opts, configurationOptions = {}, existingWebpackConf
|
|
26
32
|
: `import webpackMerge from 'webpack-merge';`}`
|
27
33
|
: ''}
|
28
34
|
|
29
|
-
${existingWebpackConfigPath ? 'const baseConfig = ' : 'export default '}createConfig({
|
30
|
-
options: {
|
31
|
-
root: __dirname,
|
32
|
-
${JSON.stringify(createConfigOptions, undefined, 2).slice(1, -1)}
|
33
|
-
}
|
34
|
-
}${hasConfigurations ? `, {${expandedConfigurationOptions}}` : ''});
|
35
35
|
${existingWebpackConfigPath
|
36
|
-
? `
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
? `export default async () => {
|
37
|
+
const baseConfig = await ${createConfigContents}
|
38
|
+
${isExistingWebpackConfigFunction
|
39
|
+
? `const oldConfig = await baseWebpackConfig;
|
40
40
|
const browserConfig = baseConfig[0];
|
41
|
-
return oldConfig(browserConfig)
|
42
|
-
|
43
|
-
|
44
|
-
`
|
45
|
-
: ''}
|
46
|
-
`;
|
41
|
+
return oldConfig(browserConfig);`
|
42
|
+
: 'return webpackMerge(baseConfig[0], baseWebpackConfig);'}};`
|
43
|
+
: `export default ${createConfigContents}`}`;
|
47
44
|
tree.write((0, devkit_1.joinPathFragments)(root, 'rspack.config.ts'), configContents);
|
48
45
|
}
|
@@ -30,7 +30,7 @@ function convertWebpackConfigToUseNxModuleFederationPlugin(webpackConfigContents
|
|
30
30
|
const withModuleFederationImportNodes = (0, tsquery_1.tsquery)(ast, 'ImportDeclaration:has(StringLiteral[value=@nx/module-federation/angular])');
|
31
31
|
if (withModuleFederationImportNodes.length > 0) {
|
32
32
|
const withModuleFederationImportNode = withModuleFederationImportNodes[0];
|
33
|
-
newWebpackConfigContents = `${webpackConfigContents.slice(0, withModuleFederationImportNode.getStart())}import { NxModuleFederationPlugin } from '@nx/module-federation/rspack';${webpackConfigContents.slice(withModuleFederationImportNode.getEnd())}`;
|
33
|
+
newWebpackConfigContents = `${webpackConfigContents.slice(0, withModuleFederationImportNode.getStart())}import { NxModuleFederationPlugin, NxModuleFederationDevServerPlugin } from '@nx/module-federation/rspack';${webpackConfigContents.slice(withModuleFederationImportNode.getEnd())}`;
|
34
34
|
ast = tsquery_1.tsquery.ast(newWebpackConfigContents);
|
35
35
|
const exportedWithModuleFederationNodes = (0, tsquery_1.tsquery)(ast, 'ExportAssignment:has(CallExpression > Identifier[name=withModuleFederation])');
|
36
36
|
if (exportedWithModuleFederationNodes.length > 0) {
|
@@ -38,9 +38,10 @@ function convertWebpackConfigToUseNxModuleFederationPlugin(webpackConfigContents
|
|
38
38
|
newWebpackConfigContents = `${newWebpackConfigContents.slice(0, exportedWithModuleFederationNode.getStart())}${newWebpackConfigContents.slice(exportedWithModuleFederationNode.getEnd())}
|
39
39
|
export default {
|
40
40
|
plugins: [
|
41
|
-
new NxModuleFederationPlugin(config, {
|
41
|
+
new NxModuleFederationPlugin({ config }, {
|
42
42
|
dts: false,
|
43
43
|
}),
|
44
|
+
new NxModuleFederationDevServerPlugin({ config }),
|
44
45
|
]
|
45
46
|
}
|
46
47
|
`;
|
@@ -52,7 +53,7 @@ function convertWebpackConfigToUseNxModuleFederationPlugin(webpackConfigContents
|
|
52
53
|
const withModuleFederationRequireNodes = (0, tsquery_1.tsquery)(ast, 'VariableStatement:has(CallExpression > Identifier[name=withModuleFederation], StringLiteral[value=@nx/module-federation/angular])');
|
53
54
|
if (withModuleFederationRequireNodes.length > 0) {
|
54
55
|
const withModuleFederationRequireNode = withModuleFederationRequireNodes[0];
|
55
|
-
newWebpackConfigContents = `${webpackConfigContents.slice(0, withModuleFederationRequireNode.getStart())}const { NxModuleFederationPlugin } = require('@nx/module-federation/rspack');${webpackConfigContents.slice(withModuleFederationRequireNode.getEnd())}`;
|
56
|
+
newWebpackConfigContents = `${webpackConfigContents.slice(0, withModuleFederationRequireNode.getStart())}const { NxModuleFederationPlugin, NxModuleFederationDevServerPlugin } = require('@nx/module-federation/rspack');${webpackConfigContents.slice(withModuleFederationRequireNode.getEnd())}`;
|
56
57
|
ast = tsquery_1.tsquery.ast(newWebpackConfigContents);
|
57
58
|
const exportedWithModuleFederationNodes = (0, tsquery_1.tsquery)(ast, 'ExpressionStatement:has(BinaryExpression > PropertyAccessExpression:has(Identifier[name=module], Identifier[name=exports]), CallExpression:has(Identifier[name=withModuleFederation]))');
|
58
59
|
if (exportedWithModuleFederationNodes.length > 0) {
|
@@ -63,6 +64,7 @@ function convertWebpackConfigToUseNxModuleFederationPlugin(webpackConfigContents
|
|
63
64
|
new NxModuleFederationPlugin({ config }, {
|
64
65
|
dts: false,
|
65
66
|
}),
|
67
|
+
new NxModuleFederationDevServerPlugin({ config }),
|
66
68
|
]
|
67
69
|
}
|
68
70
|
`;
|
@@ -1,3 +1,6 @@
|
|
1
1
|
import type { Tree } from '@nx/devkit';
|
2
2
|
import type { Schema } from './schema';
|
3
|
+
/**
|
4
|
+
* @deprecated Use the `@nx/workspace:move` generator instead. It will be removed in Nx v22.
|
5
|
+
*/
|
3
6
|
export declare function angularMoveGenerator(tree: Tree, schema: Schema): Promise<void>;
|
@@ -2,6 +2,9 @@
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.angularMoveGenerator = angularMoveGenerator;
|
4
4
|
const move_1 = require("@nx/workspace/src/generators/move/move");
|
5
|
+
/**
|
6
|
+
* @deprecated Use the `@nx/workspace:move` generator instead. It will be removed in Nx v22.
|
7
|
+
*/
|
5
8
|
async function angularMoveGenerator(tree, schema) {
|
6
9
|
process.env.NX_ANGULAR_MOVE_INVOKED = 'true';
|
7
10
|
await (0, move_1.moveGenerator)(tree, schema);
|
@@ -1,4 +1,7 @@
|
|
1
1
|
import type { GeneratorCallback, Tree } from '@nx/devkit';
|
2
2
|
import type { NgRxGeneratorOptions } from './schema';
|
3
|
+
/**
|
4
|
+
* @deprecated Use the 'ngrx-root-store' and 'ngrx-feature-store' generators instead. It will be removed in Nx v22.
|
5
|
+
*/
|
3
6
|
export declare function ngrxGenerator(tree: Tree, schema: NgRxGeneratorOptions): Promise<GeneratorCallback>;
|
4
7
|
export default ngrxGenerator;
|
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ngrxGenerator = ngrxGenerator;
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
5
5
|
const lib_1 = require("./lib");
|
6
|
+
/**
|
7
|
+
* @deprecated Use the 'ngrx-root-store' and 'ngrx-feature-store' generators instead. It will be removed in Nx v22.
|
8
|
+
*/
|
6
9
|
async function ngrxGenerator(tree, schema) {
|
7
10
|
(0, lib_1.validateOptions)(tree, schema);
|
8
11
|
const options = (0, lib_1.normalizeOptions)(tree, schema);
|
@@ -3,7 +3,7 @@
|
|
3
3
|
"$id": "NxNgrxGenerator",
|
4
4
|
"title": "Add NgRx support to an application or library.",
|
5
5
|
"description": "Adds NgRx support to an application or library.",
|
6
|
-
"x-deprecated": "
|
6
|
+
"x-deprecated": "Use the 'ngrx-root-store' and 'ngrx-feature-store' generators instead. It will be removed in Nx v22.",
|
7
7
|
"cli": "nx",
|
8
8
|
"type": "object",
|
9
9
|
"examples": [
|
@@ -3,11 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = default_1;
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
5
5
|
const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
|
6
|
+
const project_graph_1 = require("nx/src/config/project-graph");
|
7
|
+
const nx_deps_cache_1 = require("nx/src/project-graph/nx-deps-cache");
|
8
|
+
const version_utils_1 = require("../../generators/utils/version-utils");
|
6
9
|
const file_change_recorder_1 = require("../../utils/file-change-recorder");
|
7
|
-
const versions_1 = require("../../utils/versions");
|
8
10
|
const projects_1 = require("../utils/projects");
|
9
|
-
const nx_deps_cache_1 = require("nx/src/project-graph/nx-deps-cache");
|
10
|
-
const project_graph_1 = require("nx/src/config/project-graph");
|
11
11
|
let tsquery;
|
12
12
|
const angularPluginTargetNames = ['npm:@nx/angular', 'npm:@nrwl/angular'];
|
13
13
|
const dataPersistenceOperators = [
|
@@ -109,7 +109,7 @@ function addNgrxRouterStoreIfNotInstalled(tree) {
|
|
109
109
|
devDependencies?.['@ngrx/router-store']) {
|
110
110
|
return;
|
111
111
|
}
|
112
|
-
(0, devkit_1.addDependenciesToPackageJson)(tree, { '@ngrx/router-store':
|
112
|
+
(0, devkit_1.addDependenciesToPackageJson)(tree, { '@ngrx/router-store': (0, version_utils_1.versions)(tree).ngrxVersion }, {});
|
113
113
|
}
|
114
114
|
function filterFilesWithNxAngularDep(files) {
|
115
115
|
const filteredFiles = [];
|
@@ -1,2 +1,2 @@
|
|
1
|
-
import type
|
1
|
+
import { type Tree } from '@nx/devkit';
|
2
2
|
export default function (tree: Tree): Promise<void>;
|
@@ -0,0 +1,122 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.default = default_1;
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
5
|
+
const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
|
6
|
+
const project_graph_1 = require("nx/src/config/project-graph");
|
7
|
+
const nx_deps_cache_1 = require("nx/src/project-graph/nx-deps-cache");
|
8
|
+
const version_utils_1 = require("../../generators/utils/version-utils");
|
9
|
+
const file_change_recorder_1 = require("../../utils/file-change-recorder");
|
10
|
+
const projects_1 = require("../utils/projects");
|
11
|
+
let tsquery;
|
12
|
+
const angularPluginTargetNames = ['npm:@nx/angular', 'npm:@nrwl/angular'];
|
13
|
+
const dataPersistenceOperators = [
|
14
|
+
'fetch',
|
15
|
+
'navigation',
|
16
|
+
'optimisticUpdate',
|
17
|
+
'pessimisticUpdate',
|
18
|
+
];
|
19
|
+
const newImportPath = '@ngrx/router-store/data-persistence';
|
20
|
+
async function default_1(tree) {
|
21
|
+
const projects = await (0, projects_1.getProjectsFilteredByDependencies)(tree, angularPluginTargetNames);
|
22
|
+
if (!projects.length) {
|
23
|
+
return;
|
24
|
+
}
|
25
|
+
(0, ensure_typescript_1.ensureTypescript)();
|
26
|
+
tsquery = require('@phenomnomnominal/tsquery').tsquery;
|
27
|
+
const cachedFileMap = (0, nx_deps_cache_1.readFileMapCache)().fileMap.projectFileMap;
|
28
|
+
const filesWithNxAngularImports = [];
|
29
|
+
for (const { graphNode } of projects) {
|
30
|
+
const files = filterFilesWithNxAngularDep(cachedFileMap[graphNode.name] || []);
|
31
|
+
filesWithNxAngularImports.push(...files);
|
32
|
+
}
|
33
|
+
let isAnyFileUsingDataPersistence = false;
|
34
|
+
for (const { file } of filesWithNxAngularImports) {
|
35
|
+
const updated = replaceDataPersistenceInFile(tree, file);
|
36
|
+
isAnyFileUsingDataPersistence ||= updated;
|
37
|
+
}
|
38
|
+
if (isAnyFileUsingDataPersistence) {
|
39
|
+
addNgrxRouterStoreIfNotInstalled(tree);
|
40
|
+
await (0, devkit_1.formatFiles)(tree);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
function replaceDataPersistenceInFile(tree, file) {
|
44
|
+
const fileContents = tree.read(file, 'utf-8');
|
45
|
+
const fileAst = tsquery.ast(fileContents);
|
46
|
+
// "\\u002F" is the unicode code for "/", there's an issue with the query parser
|
47
|
+
// that prevents using "/" directly in regex queries
|
48
|
+
// https://github.com/estools/esquery/issues/68#issuecomment-415597670
|
49
|
+
const NX_ANGULAR_IMPORT_SELECTOR = 'ImportDeclaration:has(StringLiteral[value=/@(nx|nrwl)\\u002Fangular$/])';
|
50
|
+
const nxAngularImports = tsquery(fileAst, NX_ANGULAR_IMPORT_SELECTOR, { visitAllChildren: true });
|
51
|
+
if (!nxAngularImports.length) {
|
52
|
+
return false;
|
53
|
+
}
|
54
|
+
const recorder = new file_change_recorder_1.FileChangeRecorder(tree, file);
|
55
|
+
const IMPORT_SPECIFIERS_SELECTOR = 'ImportClause NamedImports ImportSpecifier';
|
56
|
+
for (const importDeclaration of nxAngularImports) {
|
57
|
+
const importSpecifiers = tsquery(importDeclaration, IMPORT_SPECIFIERS_SELECTOR, { visitAllChildren: true });
|
58
|
+
if (!importSpecifiers.length) {
|
59
|
+
continue;
|
60
|
+
}
|
61
|
+
// no imported symbol is a data persistence operator, skip
|
62
|
+
if (importSpecifiers.every((i) => !isOperatorImport(i))) {
|
63
|
+
continue;
|
64
|
+
}
|
65
|
+
// all imported symbols are data persistence operators, change import path
|
66
|
+
if (importSpecifiers.every((i) => isOperatorImport(i))) {
|
67
|
+
const IMPORT_PATH_SELECTOR = `${NX_ANGULAR_IMPORT_SELECTOR} > StringLiteral`;
|
68
|
+
const importPathNode = tsquery(importDeclaration, IMPORT_PATH_SELECTOR, {
|
69
|
+
visitAllChildren: true,
|
70
|
+
});
|
71
|
+
recorder.replace(importPathNode[0], `'${newImportPath}'`);
|
72
|
+
continue;
|
73
|
+
}
|
74
|
+
// mixed imports, split data persistence operators to a separate import
|
75
|
+
const operatorImportSpecifiers = [];
|
76
|
+
for (const importSpecifier of importSpecifiers) {
|
77
|
+
if (isOperatorImport(importSpecifier)) {
|
78
|
+
operatorImportSpecifiers.push(importSpecifier.getText());
|
79
|
+
recorder.remove(importSpecifier.getStart(), importSpecifier.getEnd() +
|
80
|
+
(hasTrailingComma(recorder.originalContent, importSpecifier)
|
81
|
+
? 1
|
82
|
+
: 0));
|
83
|
+
}
|
84
|
+
}
|
85
|
+
recorder.insertLeft(importDeclaration.getStart(), `import { ${operatorImportSpecifiers.join(', ')} } from '${newImportPath}';`);
|
86
|
+
}
|
87
|
+
if (recorder.hasChanged()) {
|
88
|
+
recorder.applyChanges();
|
89
|
+
return true;
|
90
|
+
}
|
91
|
+
return false;
|
92
|
+
}
|
93
|
+
function hasTrailingComma(content, node) {
|
94
|
+
return content[node.getEnd()] === ',';
|
95
|
+
}
|
96
|
+
function isOperatorImport(importSpecifier) {
|
97
|
+
return dataPersistenceOperators.includes(getOriginalIdentifierTextFromImportSpecifier(importSpecifier));
|
98
|
+
}
|
99
|
+
function getOriginalIdentifierTextFromImportSpecifier(importSpecifier) {
|
100
|
+
const children = importSpecifier.getChildren();
|
101
|
+
if (!children.length) {
|
102
|
+
return importSpecifier.getText();
|
103
|
+
}
|
104
|
+
return children[0].getText();
|
105
|
+
}
|
106
|
+
function addNgrxRouterStoreIfNotInstalled(tree) {
|
107
|
+
const { dependencies, devDependencies } = (0, devkit_1.readJson)(tree, 'package.json');
|
108
|
+
if (dependencies?.['@ngrx/router-store'] ||
|
109
|
+
devDependencies?.['@ngrx/router-store']) {
|
110
|
+
return;
|
111
|
+
}
|
112
|
+
(0, devkit_1.addDependenciesToPackageJson)(tree, { '@ngrx/router-store': (0, version_utils_1.versions)(tree).ngrxVersion }, {});
|
113
|
+
}
|
114
|
+
function filterFilesWithNxAngularDep(files) {
|
115
|
+
const filteredFiles = [];
|
116
|
+
for (const file of files) {
|
117
|
+
if (file.deps?.some((dep) => angularPluginTargetNames.includes((0, project_graph_1.fileDataDepTarget)(dep)))) {
|
118
|
+
filteredFiles.push(file);
|
119
|
+
}
|
120
|
+
}
|
121
|
+
return filteredFiles;
|
122
|
+
}
|
@@ -1,14 +1,6 @@
|
|
1
1
|
import { Tree } from '@nx/devkit';
|
2
2
|
import type * as ts from 'typescript';
|
3
3
|
type DecoratorName = 'Component' | 'Directive' | 'NgModule' | 'Pipe';
|
4
|
-
/**
|
5
|
-
* Check if the Component, Directive or Pipe is standalone
|
6
|
-
* @param sourceFile TS Source File containing the token to check
|
7
|
-
* @param decoratorName The type of decorator to check (Component, Directive, Pipe)
|
8
|
-
*
|
9
|
-
* @deprecated Use the function signature with a Tree. This signature will be removed in v21.
|
10
|
-
*/
|
11
|
-
export declare function isStandalone(sourceFile: ts.SourceFile, decoratorName: DecoratorName): boolean;
|
12
4
|
/**
|
13
5
|
* Check if the Component, Directive or Pipe is standalone
|
14
6
|
* @param tree The file system tree
|
@@ -77,18 +77,13 @@ function _angularImportsFromNode(node, _sourceFile) {
|
|
77
77
|
return {};
|
78
78
|
}
|
79
79
|
}
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
else {
|
88
|
-
tree = treeOrSourceFile;
|
89
|
-
sourceFile = sourceFileOrDecoratorName;
|
90
|
-
decoratorName = decoratorName;
|
91
|
-
}
|
80
|
+
/**
|
81
|
+
* Check if the Component, Directive or Pipe is standalone
|
82
|
+
* @param tree The file system tree
|
83
|
+
* @param sourceFile TS Source File containing the token to check
|
84
|
+
* @param decoratorName The type of decorator to check (Component, Directive, Pipe)
|
85
|
+
*/
|
86
|
+
function isStandalone(tree, sourceFile, decoratorName) {
|
92
87
|
const decoratorMetadata = getDecoratorMetadata(sourceFile, decoratorName, '@angular/core');
|
93
88
|
const hasStandaloneTrue = decoratorMetadata.some((node) => node.getText().includes('standalone: true'));
|
94
89
|
if (hasStandaloneTrue) {
|
package/src/utils/versions.d.ts
CHANGED
@@ -2,7 +2,7 @@ export declare const nxVersion: any;
|
|
2
2
|
export declare const angularVersion = "~19.2.0";
|
3
3
|
export declare const angularDevkitVersion = "~19.2.0";
|
4
4
|
export declare const ngPackagrVersion = "~19.2.0";
|
5
|
-
export declare const angularRspackVersion = "
|
5
|
+
export declare const angularRspackVersion = "^20.7.0";
|
6
6
|
export declare const ngrxVersion = "^19.0.0";
|
7
7
|
export declare const rxjsVersion = "~7.8.0";
|
8
8
|
export declare const zoneJsVersion = "~0.15.0";
|
package/src/utils/versions.js
CHANGED
@@ -5,7 +5,7 @@ exports.nxVersion = require('../../package.json').version;
|
|
5
5
|
exports.angularVersion = '~19.2.0';
|
6
6
|
exports.angularDevkitVersion = '~19.2.0';
|
7
7
|
exports.ngPackagrVersion = '~19.2.0';
|
8
|
-
exports.angularRspackVersion = '
|
8
|
+
exports.angularRspackVersion = '^20.7.0';
|
9
9
|
exports.ngrxVersion = '^19.0.0';
|
10
10
|
exports.rxjsVersion = '~7.8.0';
|
11
11
|
exports.zoneJsVersion = '~0.15.0';
|
@@ -1,45 +0,0 @@
|
|
1
|
-
import { toArray, first } from 'rxjs/operators';
|
2
|
-
|
3
|
-
/**
|
4
|
-
* @deprecated This will be removed in Nx v21. If using RxJS 7, use `firstValueFrom(obs$.pipe(toArray()))`
|
5
|
-
* or `lastValueFrom(obs$.pipe(toArray()))`. If using RxJS 6, use `obs$.pipe(toArray()).toPromise()`.
|
6
|
-
*
|
7
|
-
* @whatItDoes reads all the values from an observable and returns a promise
|
8
|
-
* with an array of all values. This should be used in combination with async/await.
|
9
|
-
*
|
10
|
-
* ## Example
|
11
|
-
*
|
12
|
-
* ```typescript
|
13
|
-
* const obs = of(1, 2, 3, 4);
|
14
|
-
* const res = await readAll(obs)
|
15
|
-
* expect(res).toEqual([1, 2, 3, 4]);
|
16
|
-
* ```
|
17
|
-
*/
|
18
|
-
function readAll(o) {
|
19
|
-
return o.pipe(toArray()).toPromise();
|
20
|
-
}
|
21
|
-
/**
|
22
|
-
* @deprecated This will be removed in Nx v21. Since RxJS 7, use `firstValueFrom(obs$)`. If using RxJS 6,
|
23
|
-
* use `obs$.pipe(first()).toPromise()`.
|
24
|
-
*
|
25
|
-
* @whatItDoes reads the first value from an observable and returns a promise
|
26
|
-
* with it. This should be used in combination with async/await.
|
27
|
-
*
|
28
|
-
* ## Example
|
29
|
-
*
|
30
|
-
* ```typescript
|
31
|
-
* const obs = of(1, 2, 3, 4);
|
32
|
-
* const res = await readFirst(obs)
|
33
|
-
* expect(res).toEqual(1);
|
34
|
-
* ```
|
35
|
-
*/
|
36
|
-
function readFirst(o) {
|
37
|
-
return o.pipe(first()).toPromise();
|
38
|
-
}
|
39
|
-
|
40
|
-
/**
|
41
|
-
* Generated bundle index. Do not edit.
|
42
|
-
*/
|
43
|
-
|
44
|
-
export { readAll, readFirst };
|
45
|
-
//# sourceMappingURL=nx-angular-testing.mjs.map
|
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"nx-angular-testing.mjs","sources":["../../../../packages/angular/testing/src/testing-utils.ts","../../../../packages/angular/testing/nx-angular-testing.ts"],"sourcesContent":["import type { Observable } from 'rxjs';\nimport { first, toArray } from 'rxjs/operators';\n\n/**\n * @deprecated This will be removed in Nx v21. If using RxJS 7, use `firstValueFrom(obs$.pipe(toArray()))`\n * or `lastValueFrom(obs$.pipe(toArray()))`. If using RxJS 6, use `obs$.pipe(toArray()).toPromise()`.\n *\n * @whatItDoes reads all the values from an observable and returns a promise\n * with an array of all values. This should be used in combination with async/await.\n *\n * ## Example\n *\n * ```typescript\n * const obs = of(1, 2, 3, 4);\n * const res = await readAll(obs)\n * expect(res).toEqual([1, 2, 3, 4]);\n * ```\n */\nexport function readAll<T>(o: Observable<T>): Promise<T[]> {\n return o.pipe(toArray()).toPromise();\n}\n\n/**\n * @deprecated This will be removed in Nx v21. Since RxJS 7, use `firstValueFrom(obs$)`. If using RxJS 6,\n * use `obs$.pipe(first()).toPromise()`.\n *\n * @whatItDoes reads the first value from an observable and returns a promise\n * with it. This should be used in combination with async/await.\n *\n * ## Example\n *\n * ```typescript\n * const obs = of(1, 2, 3, 4);\n * const res = await readFirst(obs)\n * expect(res).toEqual(1);\n * ```\n */\nexport function readFirst<T>(o: Observable<T>): Promise<T> {\n return o.pipe(first()).toPromise();\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":";;AAGA;;;;;;;;;;;;;;AAcG;AACG,SAAU,OAAO,CAAI,CAAgB,EAAA;IACzC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,SAAS,EAAE;AACtC;AAEA;;;;;;;;;;;;;;AAcG;AACG,SAAU,SAAS,CAAI,CAAgB,EAAA;IAC3C,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,SAAS,EAAE;AACpC;;ACvCA;;AAEG;;;;"}
|