From b3c5931cf0aa99f3d6bd3ed5ca7377426268a341 Mon Sep 17 00:00:00 2001 From: Tim Deschryver <28659384+timdeschryver@users.noreply.github.com> Date: Thu, 26 Jan 2023 15:24:32 +0100 Subject: [PATCH] feat(store): add createFeature migration (#3759) --- modules/store/migrations/15_2_0/index.spec.ts | 66 +++++++++++++++++++ modules/store/migrations/15_2_0/index.ts | 62 +++++++++++++++++ modules/store/migrations/migration.json | 5 ++ 3 files changed, 133 insertions(+) create mode 100644 modules/store/migrations/15_2_0/index.spec.ts create mode 100644 modules/store/migrations/15_2_0/index.ts diff --git a/modules/store/migrations/15_2_0/index.spec.ts b/modules/store/migrations/15_2_0/index.spec.ts new file mode 100644 index 0000000000..5c1199c530 --- /dev/null +++ b/modules/store/migrations/15_2_0/index.spec.ts @@ -0,0 +1,66 @@ +import { Tree } from '@angular-devkit/schematics'; +import { + SchematicTestRunner, + UnitTestTree, +} from '@angular-devkit/schematics/testing'; +import * as path from 'path'; + +describe('Store Migration 15_2_0', () => { + const collectionPath = path.join(__dirname, '../migration.json'); + const pkgName = 'store'; + + it(`should replace remove the State type argument`, async () => { + const input = ` + import {createFeature} from '@ngrx/store'; + interface AppState { + users: State; + } + export const usersFeature = createFeature({ + name: 'users', + reducer: createReducer(initialState, /* case reducers */), + }); +`; + + const expected = ` + import {createFeature} from '@ngrx/store'; + interface AppState { + users: State; + } + export const usersFeature = createFeature({ + name: 'users', + reducer: createReducer(initialState, /* case reducers */), + }); +`; + const appTree = new UnitTestTree(Tree.empty()); + appTree.create('./fixture.ts', input); + const runner = new SchematicTestRunner('schematics', collectionPath); + + const newTree = await runner + .runSchematicAsync(`ngrx-${pkgName}-migration-15-2-0`, {}, appTree) + .toPromise(); + const file = newTree.readContent('fixture.ts'); + + expect(file).toBe(expected); + }); + + it(`should not update createFeature when correctly used`, async () => { + const input = ` + import {createFeature} from '@ngrx/store'; + export const usersFeature = createFeature({ + name: 'users', + reducer: createReducer(initialState, /* case reducers */), + }); +`; + + const appTree = new UnitTestTree(Tree.empty()); + appTree.create('./fixture.ts', input); + const runner = new SchematicTestRunner('schematics', collectionPath); + + const newTree = await runner + .runSchematicAsync(`ngrx-${pkgName}-migration-15-2-0`, {}, appTree) + .toPromise(); + const file = newTree.readContent('fixture.ts'); + + expect(file).toBe(input); + }); +}); diff --git a/modules/store/migrations/15_2_0/index.ts b/modules/store/migrations/15_2_0/index.ts new file mode 100644 index 0000000000..629d8ea942 --- /dev/null +++ b/modules/store/migrations/15_2_0/index.ts @@ -0,0 +1,62 @@ +import * as ts from 'typescript'; +import { Rule, chain, Tree } from '@angular-devkit/schematics'; +import { + visitTSSourceFiles, + RemoveChange, + commitChanges, + InsertChange, +} from '../../schematics-core'; + +function updatecreateFeature(): Rule { + return (tree: Tree) => { + visitTSSourceFiles(tree, (sourceFile) => { + const runMigration = sourceFile.statements + .filter(ts.isImportDeclaration) + .filter( + (importDeclaration) => + importDeclaration.moduleSpecifier.getText(sourceFile) === + "'@ngrx/store'" || + importDeclaration.moduleSpecifier.getText(sourceFile) === + '"@ngrx/store"' + ) + .some((importDeclaration) => { + return importDeclaration.importClause?.namedBindings + ?.getText(sourceFile) + .includes('createFeature'); + }); + + if (!runMigration) return; + + const changes: (RemoveChange | InsertChange)[] = []; + ts.forEachChild(sourceFile, crawl); + return commitChanges(tree, sourceFile.fileName, changes); + + function crawl(node: ts.Node) { + ts.forEachChild(node, crawl); + + if (!ts.isCallExpression(node)) return; + + const { typeArguments } = node; + + if (!typeArguments?.length) return; + + if (!ts.isIdentifier(node.expression)) return; + if (node.expression.text !== 'createFeature') return; + + changes.push( + new RemoveChange( + sourceFile.fileName, + // to include < + typeArguments.pos - 1, + // to include > + typeArguments.end + 1 + ) + ); + } + }); + }; +} + +export default function (): Rule { + return chain([updatecreateFeature]); +} diff --git a/modules/store/migrations/migration.json b/modules/store/migrations/migration.json index 6023c1314b..e51f286898 100644 --- a/modules/store/migrations/migration.json +++ b/modules/store/migrations/migration.json @@ -25,6 +25,11 @@ "description": "The road to v13 RC", "version": "13-rc.1", "factory": "./13_0_0-rc/index" + }, + "ngrx-store-migration-15-2-0": { + "description": "The road to v15.2", + "version": "15.2.0", + "factory": "./15_2_0/index" } } }