All files / src/migrations 2.7.2.ts

88.37% Statements 38/43
28.57% Branches 2/7
100% Functions 9/9
87.5% Lines 35/40

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 901x 1x 1x 1x 1x   1x                             2x 2x     1x 2x 5x     1x           2x   2x     2x       2x     1x 1x               1x       1x 1x 1x     1x   1x 1x   1x 1x     1x 1x 1x 1x   1x 1x 1x     1x        
import { join, normalize, workspaces } from '@angular-devkit/core';
import { Rule, SchematicsException, Tree } from '@angular-devkit/schematics';
import Project, { ImportDeclaration, ImportSpecifier, IndentationText, QuoteKind, SourceFile } from 'ts-simple-ast';
import { getApps, getWorkspace } from '../utils/backbase/package-utils';
import { tryRule } from './utils/rules';
 
const manualProcess = `
Update import statements in each application's "environments/type.ts" file.
 
## 1. Update importing of "Item"
 
Change import of "Item" to
 
import { Item } from '@backbase/foundation-ang/core';
 
## 2. Update importing of "ExternalServices"
 
Change import of "ExternalServices" to
 
import { ExternalServices } from '@backbase/foundation-ang/start';`;
 
const isNamedImportSpecifier = (namedImport: string) => (importSpecifier: ImportSpecifier) =>
  importSpecifier.getName() === namedImport;
 
const isNamedImportDeclaration =
  (moduleSpecifier: string, namedImport: string) =>
  (importDeclaration: ImportDeclaration): boolean =>
    importDeclaration.getModuleSpecifier().getLiteralValue() === moduleSpecifier &&
    undefined !== importDeclaration.getNamedImports().find(isNamedImportSpecifier(namedImport));
 
const updateNamedImport = (
  typeFile: SourceFile,
  moduleSpecifier: string,
  namedImport: string,
  newModuleSpecifier: string,
): void => {
  const importStatement = typeFile.getImportDeclaration(isNamedImportDeclaration(moduleSpecifier, namedImport));
 
  Iif (!importStatement) {
    return;
  }
  Iif (importStatement.getNamedImports().length > 1) {
    // If they're importing extra stuff, we don't know where they *should* be imported from.
    throw new SchematicsException(`Found unexpected imports from ${moduleSpecifier} in type.ts`);
  }
  importStatement.setModuleSpecifier(newModuleSpecifier);
};
 
export const updateTypeImports = (tree: Tree, project: workspaces.ProjectDefinition) => {
  const astProject = new Project({
    manipulationSettings: {
      indentationText: IndentationText.TwoSpaces,
      quoteKind: QuoteKind.Single,
    },
    useVirtualFileSystem: true,
  });
 
  Iif (!project.sourceRoot) {
    throw new SchematicsException('Project missing required "sourceRoot" property in angular.json');
  }
 
  const typeFilePath = join(normalize(project.sourceRoot), 'environments', 'type.ts');
  const existingTypeTs = tree.read(typeFilePath);
  Iif (!existingTypeTs) {
    throw new SchematicsException(`Project missing expected "type.ts" file at ${typeFilePath}`);
  }
  const typeFile = astProject.createSourceFile(typeFilePath, existingTypeTs.toString('utf-8'));
 
  updateNamedImport(typeFile, '@backbase/core-ang', 'Item', '@backbase/foundation-ang/core');
  updateNamedImport(typeFile, '@backbase/web-sdk-api-ang', 'ExternalServices', '@backbase/foundation-ang/start');
 
  tree.overwrite(typeFilePath, typeFile.getFullText());
  return;
};
 
export default function (): Rule {
  return tryRule(async (tree: Tree) => {
    const workspace = await getWorkspace(tree);
    const apps = getApps(workspace);
 
    for (const name of apps) {
      const project = workspace.projects.get(name);
      Iif (!project) {
        continue;
      }
      updateTypeImports(tree, project);
    }
  }, manualProcess);
}