feat(angular): update ngrx packages to v16 (#16763)
This commit is contained in:
parent
d853ba2081
commit
f2e48e429a
@ -58,9 +58,9 @@
|
||||
"@nestjs/schematics": "^9.1.0",
|
||||
"@nestjs/swagger": "^6.0.0",
|
||||
"@nestjs/testing": "^9.0.0",
|
||||
"@ngrx/effects": "~15.3.0",
|
||||
"@ngrx/router-store": "~15.3.0",
|
||||
"@ngrx/store": "~15.3.0",
|
||||
"@ngrx/effects": "~16.0.0",
|
||||
"@ngrx/router-store": "~16.0.0",
|
||||
"@ngrx/store": "~16.0.0",
|
||||
"@nguniversal/builders": "~16.0.0",
|
||||
"@nx/cypress": "16.1.0-rc.0",
|
||||
"@nx/devkit": "16.1.0-rc.0",
|
||||
|
||||
@ -236,6 +236,15 @@
|
||||
},
|
||||
"description": "Update the @angular/cli package version to ~16.0.0.",
|
||||
"factory": "./src/migrations/update-16-1-0/update-angular-cli"
|
||||
},
|
||||
"switch-data-persistence-operators-imports-to-ngrx-router-store": {
|
||||
"cli": "nx",
|
||||
"version": "16.2.0-beta.0",
|
||||
"requires": {
|
||||
"@ngrx/store": ">=16.0.0"
|
||||
},
|
||||
"description": "Switch the data persistence operator imports to '@ngrx/router-store/data-persistence'.",
|
||||
"factory": "./src/migrations/update-16-2-0/switch-data-persistence-operators-imports-to-ngrx-router-store"
|
||||
}
|
||||
},
|
||||
"packageJsonUpdates": {
|
||||
@ -1126,6 +1135,18 @@
|
||||
"alwaysAddToPackageJson": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"16.2.0-ngrx": {
|
||||
"version": "16.2.0-beta.0",
|
||||
"requires": {
|
||||
"@angular/core": "^16.0.0"
|
||||
},
|
||||
"packages": {
|
||||
"@ngrx/store": {
|
||||
"version": "~16.0.0",
|
||||
"alwaysAddToPackageJson": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,309 @@
|
||||
import { ProjectGraph, Tree, addProjectConfiguration } from '@nx/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||
import migration from './switch-data-persistence-operators-imports-to-ngrx-router-store';
|
||||
|
||||
let projectGraph: ProjectGraph;
|
||||
jest.mock('@nx/devkit', () => ({
|
||||
...jest.requireActual('@nx/devkit'),
|
||||
createProjectGraphAsync: jest
|
||||
.fn()
|
||||
.mockImplementation(async () => projectGraph),
|
||||
}));
|
||||
|
||||
describe('switch-data-persistence-operators-imports-to-ngrx-router-store migration', () => {
|
||||
let tree: Tree;
|
||||
const file = 'apps/app1/src/app/+state/users.effects.ts';
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
addProjectConfiguration(tree, 'app1', { root: 'apps/app1' });
|
||||
projectGraph = {
|
||||
dependencies: {
|
||||
app1: [{ source: 'app1', target: 'npm:@nx/angular', type: 'static' }],
|
||||
},
|
||||
nodes: {
|
||||
app1: {
|
||||
data: {
|
||||
files: [
|
||||
{
|
||||
file,
|
||||
hash: '',
|
||||
dependencies: [
|
||||
{
|
||||
source: 'app1',
|
||||
target: 'npm:@nx/angular',
|
||||
type: 'static',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
root: 'apps/app1',
|
||||
},
|
||||
name: 'app1',
|
||||
type: 'app',
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
it('should do nothing when there are no imports from the angular plugin', async () => {
|
||||
tree.write(
|
||||
file,
|
||||
`import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
`
|
||||
);
|
||||
|
||||
await migration(tree);
|
||||
|
||||
expect(tree.read(file, 'utf-8')).toMatchInlineSnapshot(`
|
||||
"import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should not replace the import path when no operator is imported', async () => {
|
||||
tree.write(
|
||||
file,
|
||||
`import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { foo } from '@nx/angular';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
`
|
||||
);
|
||||
|
||||
await migration(tree);
|
||||
|
||||
expect(tree.read(file, 'utf-8')).toMatchInlineSnapshot(`
|
||||
"import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { foo } from '@nx/angular';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should not match imports from angular plugin secondary entry points', async () => {
|
||||
tree.write(
|
||||
file,
|
||||
`import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch } from '@nx/angular/mf';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
`
|
||||
);
|
||||
|
||||
await migration(tree);
|
||||
|
||||
expect(tree.read(file, 'utf-8')).toMatchInlineSnapshot(`
|
||||
"import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch } from '@nx/angular/mf';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should replace the import path in-place when it is importing an operator', async () => {
|
||||
tree.write(
|
||||
file,
|
||||
`import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch } from '@nx/angular';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
`
|
||||
);
|
||||
|
||||
await migration(tree);
|
||||
|
||||
expect(tree.read(file, 'utf-8')).toMatchInlineSnapshot(`
|
||||
"import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch } from '@ngrx/router-store/data-persistence';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should match imports using @nrwl/angular', async () => {
|
||||
tree.write(
|
||||
file,
|
||||
`import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch } from '@nrwl/angular';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
`
|
||||
);
|
||||
|
||||
await migration(tree);
|
||||
|
||||
expect(tree.read(file, 'utf-8')).toMatchInlineSnapshot(`
|
||||
"import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch } from '@ngrx/router-store/data-persistence';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should support multiple operators imports', async () => {
|
||||
tree.write(
|
||||
file,
|
||||
`import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch, navigation } from '@nx/angular';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
`
|
||||
);
|
||||
|
||||
await migration(tree);
|
||||
|
||||
expect(tree.read(file, 'utf-8')).toMatchInlineSnapshot(`
|
||||
"import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch, navigation } from '@ngrx/router-store/data-persistence';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should add a separate import statement when there are operator and non-operator imports', async () => {
|
||||
tree.write(
|
||||
file,
|
||||
`import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch, foo, navigation } from '@nx/angular';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
`
|
||||
);
|
||||
|
||||
await migration(tree);
|
||||
|
||||
expect(tree.read(file, 'utf-8')).toMatchInlineSnapshot(`
|
||||
"import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch, navigation } from '@ngrx/router-store/data-persistence';
|
||||
import { foo } from '@nx/angular';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should support multiple import statements and import paths', async () => {
|
||||
tree.write(
|
||||
file,
|
||||
`import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch } from '@nx/angular';
|
||||
import { navigation } from '@nrwl/angular';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
`
|
||||
);
|
||||
|
||||
await migration(tree);
|
||||
|
||||
expect(tree.read(file, 'utf-8')).toMatchInlineSnapshot(`
|
||||
"import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch } from '@ngrx/router-store/data-persistence';
|
||||
import { navigation } from '@ngrx/router-store/data-persistence';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should support renamed import symbols', async () => {
|
||||
tree.write(
|
||||
file,
|
||||
`import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch as customFetch } from '@nx/angular';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
`
|
||||
);
|
||||
|
||||
await migration(tree);
|
||||
|
||||
expect(tree.read(file, 'utf-8')).toMatchInlineSnapshot(`
|
||||
"import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch as customFetch } from '@ngrx/router-store/data-persistence';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should support multiple imports with renamed and non-renamed symbols', async () => {
|
||||
tree.write(
|
||||
file,
|
||||
`import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch as customFetch, navigation } from '@nx/angular';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
`
|
||||
);
|
||||
|
||||
await migration(tree);
|
||||
|
||||
expect(tree.read(file, 'utf-8')).toMatchInlineSnapshot(`
|
||||
"import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import {
|
||||
fetch as customFetch,
|
||||
navigation,
|
||||
} from '@ngrx/router-store/data-persistence';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
"
|
||||
`);
|
||||
});
|
||||
|
||||
it('should add a separate import statement even with renamed symbols', async () => {
|
||||
tree.write(
|
||||
file,
|
||||
`import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import { fetch as customFetch, foo, navigation } from '@nx/angular';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
`
|
||||
);
|
||||
|
||||
await migration(tree);
|
||||
|
||||
expect(tree.read(file, 'utf-8')).toMatchInlineSnapshot(`
|
||||
"import { Actions, createEffect, ofType } from '@ngrx/effects';
|
||||
import {
|
||||
fetch as customFetch,
|
||||
navigation,
|
||||
} from '@ngrx/router-store/data-persistence';
|
||||
import { foo } from '@nx/angular';
|
||||
|
||||
@Injectable()
|
||||
class UsersEffects {}
|
||||
"
|
||||
`);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,184 @@
|
||||
import type { FileData, Tree } from '@nx/devkit';
|
||||
import {
|
||||
addDependenciesToPackageJson,
|
||||
formatFiles,
|
||||
readJson,
|
||||
} from '@nx/devkit';
|
||||
import { ensureTypescript } from '@nx/js/src/utils/typescript/ensure-typescript';
|
||||
import type { ImportDeclaration, ImportSpecifier, Node } from 'typescript';
|
||||
import { FileChangeRecorder } from '../../utils/file-change-recorder';
|
||||
import { ngrxVersion } from '../../utils/versions';
|
||||
import { getProjectsFilteredByDependencies } from '../utils/projects';
|
||||
|
||||
let tsquery: typeof import('@phenomnomnominal/tsquery').tsquery;
|
||||
|
||||
const angularPluginTargetNames = ['npm:@nx/angular', 'npm:@nrwl/angular'];
|
||||
const dataPersistenceOperators = [
|
||||
'fetch',
|
||||
'navigation',
|
||||
'optimisticUpdate',
|
||||
'pessimisticUpdate',
|
||||
];
|
||||
const newImportPath = '@ngrx/router-store/data-persistence';
|
||||
|
||||
export default async function (tree: Tree): Promise<void> {
|
||||
const projects = await getProjectsFilteredByDependencies(
|
||||
tree,
|
||||
angularPluginTargetNames
|
||||
);
|
||||
|
||||
if (!projects.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
ensureTypescript();
|
||||
tsquery = require('@phenomnomnominal/tsquery').tsquery;
|
||||
|
||||
const filesWithNxAngularImports: FileData[] = [];
|
||||
for (const { graphNode } of projects) {
|
||||
const files = filterFilesWithNxAngularDep(graphNode.data.files);
|
||||
filesWithNxAngularImports.push(...files);
|
||||
}
|
||||
|
||||
let isAnyFileUsingDataPersistence = false;
|
||||
for (const { file } of filesWithNxAngularImports) {
|
||||
const updated = replaceDataPersistenceInFile(tree, file);
|
||||
isAnyFileUsingDataPersistence ||= updated;
|
||||
}
|
||||
|
||||
if (isAnyFileUsingDataPersistence) {
|
||||
addNgrxRouterStoreIfNotInstalled(tree);
|
||||
|
||||
await formatFiles(tree);
|
||||
}
|
||||
}
|
||||
|
||||
function replaceDataPersistenceInFile(tree: Tree, file: string): boolean {
|
||||
const fileContents = tree.read(file, 'utf-8');
|
||||
const fileAst = tsquery.ast(fileContents);
|
||||
|
||||
// "\\u002F" is the unicode code for "/", there's an issue with the query parser
|
||||
// that prevents using "/" directly in regex queries
|
||||
// https://github.com/estools/esquery/issues/68#issuecomment-415597670
|
||||
const NX_ANGULAR_IMPORT_SELECTOR =
|
||||
'ImportDeclaration:has(StringLiteral[value=/@(nx|nrwl)\\u002Fangular$/])';
|
||||
const nxAngularImports = tsquery<ImportDeclaration>(
|
||||
fileAst,
|
||||
NX_ANGULAR_IMPORT_SELECTOR,
|
||||
{ visitAllChildren: true }
|
||||
);
|
||||
|
||||
if (!nxAngularImports.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const recorder = new FileChangeRecorder(tree, file);
|
||||
|
||||
const IMPORT_SPECIFIERS_SELECTOR =
|
||||
'ImportClause NamedImports ImportSpecifier';
|
||||
for (const importDeclaration of nxAngularImports) {
|
||||
const importSpecifiers = tsquery<ImportSpecifier>(
|
||||
importDeclaration,
|
||||
IMPORT_SPECIFIERS_SELECTOR,
|
||||
{ visitAllChildren: true }
|
||||
);
|
||||
|
||||
if (!importSpecifiers.length) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// no imported symbol is a data persistence operator, skip
|
||||
if (importSpecifiers.every((i) => !isOperatorImport(i))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// all imported symbols are data persistence operators, change import path
|
||||
if (importSpecifiers.every((i) => isOperatorImport(i))) {
|
||||
const IMPORT_PATH_SELECTOR = `${NX_ANGULAR_IMPORT_SELECTOR} > StringLiteral`;
|
||||
const importPathNode = tsquery(importDeclaration, IMPORT_PATH_SELECTOR, {
|
||||
visitAllChildren: true,
|
||||
});
|
||||
recorder.replace(importPathNode[0], `'${newImportPath}'`);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// mixed imports, split data persistence operators to a separate import
|
||||
const operatorImportSpecifiers: string[] = [];
|
||||
for (const importSpecifier of importSpecifiers) {
|
||||
if (isOperatorImport(importSpecifier)) {
|
||||
operatorImportSpecifiers.push(importSpecifier.getText());
|
||||
recorder.remove(
|
||||
importSpecifier.getStart(),
|
||||
importSpecifier.getEnd() +
|
||||
(hasTrailingComma(recorder.originalContent, importSpecifier)
|
||||
? 1
|
||||
: 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
recorder.insertLeft(
|
||||
importDeclaration.getStart(),
|
||||
`import { ${operatorImportSpecifiers.join(
|
||||
', '
|
||||
)} } from '${newImportPath}';`
|
||||
);
|
||||
}
|
||||
|
||||
if (recorder.hasChanged()) {
|
||||
recorder.applyChanges();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function hasTrailingComma(content: string, node: Node): boolean {
|
||||
return content[node.getEnd()] === ',';
|
||||
}
|
||||
|
||||
function isOperatorImport(importSpecifier: ImportSpecifier): boolean {
|
||||
return dataPersistenceOperators.includes(
|
||||
getOriginalIdentifierTextFromImportSpecifier(importSpecifier)
|
||||
);
|
||||
}
|
||||
|
||||
function getOriginalIdentifierTextFromImportSpecifier(
|
||||
importSpecifier: ImportSpecifier
|
||||
): string {
|
||||
const children = importSpecifier.getChildren();
|
||||
if (!children.length) {
|
||||
return importSpecifier.getText();
|
||||
}
|
||||
|
||||
return children[0].getText();
|
||||
}
|
||||
|
||||
function addNgrxRouterStoreIfNotInstalled(tree: Tree): void {
|
||||
const { dependencies, devDependencies } = readJson(tree, 'package.json');
|
||||
if (
|
||||
dependencies?.['@ngrx/router-store'] ||
|
||||
devDependencies?.['@ngrx/router-store']
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
addDependenciesToPackageJson(tree, { '@ngrx/router-store': ngrxVersion }, {});
|
||||
}
|
||||
|
||||
function filterFilesWithNxAngularDep(files: FileData[]): FileData[] {
|
||||
const filteredFiles: FileData[] = [];
|
||||
|
||||
for (const file of files) {
|
||||
if (
|
||||
file.dependencies?.some((dep) =>
|
||||
angularPluginTargetNames.includes(dep.target)
|
||||
)
|
||||
) {
|
||||
filteredFiles.push(file);
|
||||
}
|
||||
}
|
||||
|
||||
return filteredFiles;
|
||||
}
|
||||
@ -3,7 +3,7 @@ export const nxVersion = require('../../package.json').version;
|
||||
export const angularVersion = '~16.0.0';
|
||||
export const angularDevkitVersion = '~16.0.0';
|
||||
export const ngPackagrVersion = '~16.0.0';
|
||||
export const ngrxVersion = '~15.3.0';
|
||||
export const ngrxVersion = '~16.0.0';
|
||||
export const rxjsVersion = '~7.8.0';
|
||||
export const zoneJsVersion = '~0.13.0';
|
||||
export const angularJsVersion = '1.7.9';
|
||||
|
||||
42
pnpm-lock.yaml
generated
42
pnpm-lock.yaml
generated
@ -233,14 +233,14 @@ devDependencies:
|
||||
specifier: ^9.0.0
|
||||
version: 9.1.6(@nestjs/common@9.1.6)(@nestjs/core@9.1.6)(@nestjs/platform-express@9.1.6)
|
||||
'@ngrx/effects':
|
||||
specifier: ~15.3.0
|
||||
version: 15.3.0(@angular/core@16.0.0)(@ngrx/store@15.3.0)(rxjs@7.8.1)
|
||||
specifier: ~16.0.0
|
||||
version: 16.0.0(@angular/core@16.0.0)(@ngrx/store@16.0.0)(rxjs@7.8.1)
|
||||
'@ngrx/router-store':
|
||||
specifier: ~15.3.0
|
||||
version: 15.3.0(@angular/common@16.0.0)(@angular/core@16.0.0)(@angular/router@16.0.0)(@ngrx/store@15.3.0)(rxjs@7.8.1)
|
||||
specifier: ~16.0.0
|
||||
version: 16.0.0(@angular/common@16.0.0)(@angular/core@16.0.0)(@angular/router@16.0.0)(@ngrx/store@16.0.0)(rxjs@7.8.1)
|
||||
'@ngrx/store':
|
||||
specifier: ~15.3.0
|
||||
version: 15.3.0(@angular/core@16.0.0)(rxjs@7.8.1)
|
||||
specifier: ~16.0.0
|
||||
version: 16.0.0(@angular/core@16.0.0)(rxjs@7.8.1)
|
||||
'@nguniversal/builders':
|
||||
specifier: ~16.0.0
|
||||
version: 16.0.0(@angular-devkit/build-angular@16.0.0)(@angular/common@16.0.0)(@angular/core@16.0.0)(@types/express@4.17.14)(chokidar@3.5.3)(typescript@5.0.2)
|
||||
@ -4868,40 +4868,40 @@ packages:
|
||||
requiresBuild: true
|
||||
optional: true
|
||||
|
||||
/@ngrx/effects@15.3.0(@angular/core@16.0.0)(@ngrx/store@15.3.0)(rxjs@7.8.1):
|
||||
resolution: {integrity: sha512-L+Ie4XFrzYBJOV7hNQvR5hUvG1PSCDd6niwOOJg5nm9zEjSnAxveJ/a3B52pRwge6EYOnrQne97jyArxOzPCJA==}
|
||||
/@ngrx/effects@16.0.0(@angular/core@16.0.0)(@ngrx/store@16.0.0)(rxjs@7.8.1):
|
||||
resolution: {integrity: sha512-l3H/yCwVl8DPmUasOEDthdv9lZMhCSJwBxfSXjUW7gKJVEamP3PSuvExp0ZpW9RULPblgcfTM1TH8VcPAHelQw==}
|
||||
peerDependencies:
|
||||
'@angular/core': ^15.0.0
|
||||
'@ngrx/store': 15.3.0
|
||||
'@angular/core': ^16.0.0
|
||||
'@ngrx/store': 16.0.0
|
||||
rxjs: ^6.5.3 || ^7.5.0
|
||||
dependencies:
|
||||
'@angular/core': 16.0.0(rxjs@7.8.1)(zone.js@0.13.0)
|
||||
'@ngrx/store': 15.3.0(@angular/core@16.0.0)(rxjs@7.8.1)
|
||||
'@ngrx/store': 16.0.0(@angular/core@16.0.0)(rxjs@7.8.1)
|
||||
rxjs: 7.8.1
|
||||
tslib: 2.5.0
|
||||
dev: true
|
||||
|
||||
/@ngrx/router-store@15.3.0(@angular/common@16.0.0)(@angular/core@16.0.0)(@angular/router@16.0.0)(@ngrx/store@15.3.0)(rxjs@7.8.1):
|
||||
resolution: {integrity: sha512-rAaKm6oToXF9pj/IRwsEdv/EYgQscHBfDpiAmPufFwRi/nM/NSfxtV0viZLyOw4buZi0xFwucd3aTFtaqY//vQ==}
|
||||
/@ngrx/router-store@16.0.0(@angular/common@16.0.0)(@angular/core@16.0.0)(@angular/router@16.0.0)(@ngrx/store@16.0.0)(rxjs@7.8.1):
|
||||
resolution: {integrity: sha512-i36reUxFSkpnEr01yZufe8H5J6Na0q/5Ul3HmT1HSG5cw0y2xIHWk2MpvCLIJjr3WeGSLvVpkQUYEdkkgmJOdw==}
|
||||
peerDependencies:
|
||||
'@angular/common': ^15.0.0
|
||||
'@angular/core': ^15.0.0
|
||||
'@angular/router': ^15.0.0
|
||||
'@ngrx/store': 15.3.0
|
||||
'@angular/common': ^16.0.0
|
||||
'@angular/core': ^16.0.0
|
||||
'@angular/router': ^16.0.0
|
||||
'@ngrx/store': 16.0.0
|
||||
rxjs: ^6.5.3 || ^7.5.0
|
||||
dependencies:
|
||||
'@angular/common': 16.0.0(@angular/core@16.0.0)(rxjs@7.8.1)
|
||||
'@angular/core': 16.0.0(rxjs@7.8.1)(zone.js@0.13.0)
|
||||
'@angular/router': 16.0.0(@angular/common@16.0.0)(@angular/core@16.0.0)(@angular/platform-browser@16.0.0)(rxjs@7.8.1)
|
||||
'@ngrx/store': 15.3.0(@angular/core@16.0.0)(rxjs@7.8.1)
|
||||
'@ngrx/store': 16.0.0(@angular/core@16.0.0)(rxjs@7.8.1)
|
||||
rxjs: 7.8.1
|
||||
tslib: 2.5.0
|
||||
dev: true
|
||||
|
||||
/@ngrx/store@15.3.0(@angular/core@16.0.0)(rxjs@7.8.1):
|
||||
resolution: {integrity: sha512-8cd0zWkOZ3TedDQHyOzUxZD1HHa0fU8fgzVX/2eIq6wmnleUxHVOKSJvA+DdE4GRoryFqVhAp17L1r5eC2QYHA==}
|
||||
/@ngrx/store@16.0.0(@angular/core@16.0.0)(rxjs@7.8.1):
|
||||
resolution: {integrity: sha512-bmr0KLITh9u1DJO51USTc4OAKX+su06efhTdNiQV/wagifpbC4kA8zr2hdstKMNG3Z5EKTX3XLFanIiREkd6JQ==}
|
||||
peerDependencies:
|
||||
'@angular/core': ^15.0.0
|
||||
'@angular/core': ^16.0.0
|
||||
rxjs: ^6.5.3 || ^7.5.0
|
||||
dependencies:
|
||||
'@angular/core': 16.0.0(rxjs@7.8.1)(zone.js@0.13.0)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user