Exemplo n.º 1
0
  return (host: Tree, context: SchematicContext) => {
    context.logger.debug('Updating appmodule');

    // find app module
    const projectTargets = getProjectTargets(host, options.project);
    if (!projectTargets.build) {
      throw targetBuildNotFoundError();
    }

    const mainPath = projectTargets.build.options.main;
    const modulePath = getAppModulePath(host, mainPath);
    context.logger.debug(`module path: ${modulePath}`);

    // add import
    let moduleSource = getTsSourceFile(host, modulePath);
    let importModule = 'ServiceWorkerModule';
    let importPath = '@angular/service-worker';
    if (!isImported(moduleSource, importModule, importPath)) {
      const change = insertImport
      (moduleSource, modulePath, importModule, importPath);
      if (change) {
        const recorder = host.beginUpdate(modulePath);
        recorder.insertLeft((change as InsertChange).pos, (change as InsertChange).toAdd);
        host.commitUpdate(recorder);
      }
    }

    // add import for environments
    // import { environment } from '../environments/environment';
    moduleSource = getTsSourceFile(host, modulePath);
    importModule = 'environment';
    // TODO: dynamically find environments relative path
    importPath = '../environments/environment';
    if (!isImported(moduleSource, importModule, importPath)) {
      const change = insertImport
      (moduleSource, modulePath, importModule, importPath);
      if (change) {
        const recorder = host.beginUpdate(modulePath);
        recorder.insertLeft((change as InsertChange).pos, (change as InsertChange).toAdd);
        host.commitUpdate(recorder);
      }
    }

    // register SW in app module
    const importText =
      `ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production })`;
    moduleSource = getTsSourceFile(host, modulePath);
    const metadataChanges = addSymbolToNgModuleMetadata(
      moduleSource, modulePath, 'imports', importText);
    if (metadataChanges) {
      const recorder = host.beginUpdate(modulePath);
      metadataChanges.forEach((change: InsertChange) => {
        recorder.insertRight(change.pos, change.toAdd);
      });
      host.commitUpdate(recorder);
    }

    return host;
  };
Exemplo n.º 2
0
Arquivo: index.ts Projeto: iwe7/devkit
  return (host: Tree) => {
    if (options.skipImport || !options.module) {
      return host;
    }

    const modulePath = options.module;
    const text = host.read(modulePath);
    if (text === null) {
      throw new SchematicsException(`File ${modulePath} does not exist.`);
    }
    const sourceText = text.toString('utf-8');
    const source = ts.createSourceFile(modulePath, sourceText, ts.ScriptTarget.Latest, true);

    const componentPath = `/${options.path}/`
                          + (options.flat ? '' : strings.dasherize(options.name) + '/')
                          + strings.dasherize(options.name)
                          + '.component';
    const relativePath = buildRelativePath(modulePath, componentPath);
    const classifiedName = strings.classify(`${options.name}Component`);
    const declarationChanges = addDeclarationToModule(source,
                                                      modulePath,
                                                      classifiedName,
                                                      relativePath);

    const declarationRecorder = host.beginUpdate(modulePath);
    for (const change of declarationChanges) {
      if (change instanceof InsertChange) {
        declarationRecorder.insertLeft(change.pos, change.toAdd);
      }
    }
    host.commitUpdate(declarationRecorder);

    if (options.export) {
      // Need to refresh the AST because we overwrote the file in the host.
      const text = host.read(modulePath);
      if (text === null) {
        throw new SchematicsException(`File ${modulePath} does not exist.`);
      }
      const sourceText = text.toString('utf-8');
      const source = ts.createSourceFile(modulePath, sourceText, ts.ScriptTarget.Latest, true);

      const exportRecorder = host.beginUpdate(modulePath);
      const exportChanges = addExportToModule(source, modulePath,
                                              strings.classify(`${options.name}Component`),
                                              relativePath);

      for (const change of exportChanges) {
        if (change instanceof InsertChange) {
          exportRecorder.insertLeft(change.pos, change.toAdd);
        }
      }
      host.commitUpdate(exportRecorder);
    }


    return host;
  };
Exemplo n.º 3
0
  return (host: Tree) => {
    const clientProject = getProject(host, options.clientProject);
    const architect = getProjectTargets(clientProject);
    // const mainPath = universalArchitect.build.options.main;
    const modulePath = getServerModulePath(host, clientProject, architect);
    if (modulePath === null) {
      throw new SchematicsException('Universal/server module not found.');
    }

    let moduleSource = getSourceFile(host, modulePath);
    if (!isImported(moduleSource, 'Routes', '@angular/router')) {
      const recorder = host.beginUpdate(modulePath);
      const routesChange = insertImport(moduleSource,
                                        modulePath,
                                        'Routes',
                                        '@angular/router') as InsertChange;
      if (routesChange.toAdd) {
        recorder.insertLeft(routesChange.pos, routesChange.toAdd);
      }

      const imports = getSourceNodes(moduleSource)
        .filter(node => node.kind === ts.SyntaxKind.ImportDeclaration)
        .sort((a, b) => a.getStart() - b.getStart());
      const insertPosition = imports[imports.length - 1].getEnd();
      const routeText =
        `\n\nconst routes: Routes = [ { path: '${options.route}', component: AppShellComponent }];`;
      recorder.insertRight(insertPosition, routeText);
      host.commitUpdate(recorder);
    }

    moduleSource = getSourceFile(host, modulePath);
    if (!isImported(moduleSource, 'RouterModule', '@angular/router')) {
      const recorder = host.beginUpdate(modulePath);
      const routerModuleChange = insertImport(moduleSource,
                                              modulePath,
                                              'RouterModule',
                                              '@angular/router') as InsertChange;

      if (routerModuleChange.toAdd) {
        recorder.insertLeft(routerModuleChange.pos, routerModuleChange.toAdd);
      }

      const metadataChange = addSymbolToNgModuleMetadata(
          moduleSource, modulePath, 'imports', 'RouterModule.forRoot(routes)');
      if (metadataChange) {
        metadataChange.forEach((change: InsertChange) => {
          recorder.insertRight(change.pos, change.toAdd);
        });
      }
      host.commitUpdate(recorder);
    }


    return host;
  };
Exemplo n.º 4
0
  return (host: Tree) => {
    if (options.skipImport || !options.module) {
      return host;
    }

    const modulePath = options.module;
    const text = host.read(modulePath);
    if (text === null) {
      throw new SchematicsException(`File ${modulePath} does not exist.`);
    }
    const sourceText = text.toString('utf-8');
    const source = ts.createSourceFile(modulePath, sourceText, ts.ScriptTarget.Latest, true);

    const pipePath = `/${options.path}/`
                     + (options.flat ? '' : strings.dasherize(options.name) + '/')
                     + strings.dasherize(options.name)
                     + '.pipe';
    const relativePath = buildRelativePath(modulePath, pipePath);
    const changes = addDeclarationToModule(source, modulePath,
                                           strings.classify(`${options.name}Pipe`),
                                           relativePath);
    const recorder = host.beginUpdate(modulePath);
    for (const change of changes) {
      if (change instanceof InsertChange) {
        recorder.insertLeft(change.pos, change.toAdd);
      }
    }
    host.commitUpdate(recorder);

    if (options.export) {
      const text = host.read(modulePath);
      if (text === null) {
        throw new SchematicsException(`File ${modulePath} does not exist.`);
      }
      const sourceText = text.toString('utf-8');
      const source = ts.createSourceFile(modulePath, sourceText, ts.ScriptTarget.Latest, true);

      const exportRecorder = host.beginUpdate(modulePath);
      const exportChanges = addExportToModule(source, modulePath,
                                              strings.classify(`${options.name}Pipe`),
                                              relativePath);

      for (const change of exportChanges) {
        if (change instanceof InsertChange) {
          exportRecorder.insertLeft(change.pos, change.toAdd);
        }
      }
      host.commitUpdate(exportRecorder);
    }

    return host;
  };
Exemplo n.º 5
0
 return (host: Tree, context: SchematicContext) => {
   const packageJson = 'package.json';
   if (!host.exists(packageJson)) {
     throw new Error(`Could not find ${packageJson}`);
   }
   const content = host.read(packageJson).toString();
   const jsonAst = parseJsonAst(content);
   if (!isJsonAstObject(jsonAst)) {
     throw new Error(`Failed to parse JSON for ${packageJson}`);
   }
   const deps = findPropertyInAstObject(jsonAst, 'dependencies');
   if (!isJsonAstObject(deps)) {
     throw new Error(`Failed to find dependencies in ${packageJson}`);
   }
   const rxjs = findPropertyInAstObject(deps, 'rxjs');
   if (!rxjs) {
     throw new Error(`Failed to find rxjs in dependencies of ${packageJson}`);
   }
   const value = rxjs.value as string;  // value can be version or range
   const match = value.match(/(\d)+\.(\d)+.(\d)+$/);
   if (match) {
     const [_, major, minor] = match;
     if (major < '6' || (major === '6' && minor < '4')) {
       const recorder = host.beginUpdate(packageJson);
       replacePropertyInAstObject(recorder, deps, 'rxjs', '~6.4.0');
       host.commitUpdate(recorder);
     }
   } else {
     context.logger.info(
         'Could not determine version of rxjs. \n' +
         'Please make sure that version is at least 6.4.0.');
   }
   return host;
 };
Exemplo n.º 6
0
  return (host: Tree) => {
    const pkgJsonPath = '/package.json';
    const buffer = host.read(pkgJsonPath);
    if (!buffer) {
      throw new SchematicsException('Could not read package.json.');
    }

    const packageJsonAst = parseJsonAst(buffer.toString(), JsonParseMode.Strict);
    if (packageJsonAst.kind !== 'object') {
      throw new SchematicsException('Invalid package.json. Was expecting an object.');
    }

    const scriptsNode = findPropertyInAstObject(packageJsonAst, 'scripts');
    if (scriptsNode && scriptsNode.kind === 'object') {
      const recorder = host.beginUpdate(pkgJsonPath);
      const postInstall = findPropertyInAstObject(scriptsNode, 'postinstall');

      if (!postInstall) {
        // postinstall script not found, add it.
        insertPropertyInAstObjectInOrder(
          recorder,
          scriptsNode,
          'postinstall',
          'ivy-ngcc',
          4,
        );
      }

      host.commitUpdate(recorder);
    }
  };
Exemplo n.º 7
0
  return (host: Tree) => {
    const tsConfigPath = '/tsconfig.json';
    const buffer = host.read(tsConfigPath);
    if (!buffer) {
      return host;
    }

    const tsCfgAst = parseJsonAst(buffer.toString(), JsonParseMode.Loose);
    if (tsCfgAst.kind !== 'object') {
      return host;
    }

    const compilerOptions = findPropertyInAstObject(tsCfgAst, 'compilerOptions');
    if (!compilerOptions || compilerOptions.kind !== 'object') {
      return host;
    }

    const importHelpers = findPropertyInAstObject(compilerOptions, 'importHelpers');
    if (importHelpers && importHelpers.value === true) {
      return host;
    }

    const recorder = host.beginUpdate(tsConfigPath);
    if (importHelpers) {
      const { start, end } = importHelpers;
      recorder.remove(start.offset, end.offset - start.offset);
      recorder.insertLeft(start.offset, 'true');
    } else {
      insertPropertyInAstObjectInOrder(recorder, compilerOptions, 'importHelpers', true, 4);
    }
    host.commitUpdate(recorder);

    return host;
  };
Exemplo n.º 8
0
  return (host: Tree, context: SchematicContext) => {
    context.logger.debug('updating project configuration.');

    // Add worker glob exclusion to tsconfig.app.json.
    const workerGlob = 'src/**/*.worker.ts';
    const buffer = host.read(tsConfigPath);
    if (buffer) {
      const tsCfgAst = parseJsonAst(buffer.toString(), JsonParseMode.Loose);
      if (tsCfgAst.kind != 'object') {
        throw new SchematicsException('Invalid tsconfig. Was expecting an object');
      }
      const filesAstNode = findPropertyInAstObject(tsCfgAst, 'exclude');
      if (filesAstNode && filesAstNode.kind != 'array') {
        throw new SchematicsException('Invalid tsconfig "exclude" property; expected an array.');
      }

      if (filesAstNode && !filesAstNode.value.includes(workerGlob)) {
        const recorder = host.beginUpdate(tsConfigPath);
        appendValueInAstArray(recorder, filesAstNode, workerGlob);
        host.commitUpdate(recorder);
      }
    }

    return mergeWith(
      apply(url('./files/worker-tsconfig'), [
        applyTemplates({
          ...options,
          relativePathToWorkspaceRoot: relativePathToWorkspaceRoot(root),
        }),
        move(root),
      ]),
    );
  };
Exemplo n.º 9
0
export function appendHtmlElementToHead(host: Tree, htmlFilePath: string, elementHtml: string) {
  const htmlFileBuffer = host.read(htmlFilePath);

  if (!htmlFileBuffer) {
    throw new SchematicsException(`Could not read file for path: ${htmlFilePath}`);
  }

  const htmlContent = htmlFileBuffer.toString();

  if (htmlContent.includes(elementHtml)) {
    return;
  }

  const headTag = getHtmlHeadTagElement(htmlContent);

  if (!headTag) {
    throw `Could not find '<head>' element in HTML file: ${htmlFileBuffer}`;
  }

  // We always have access to the source code location here because the `getHeadTagElement`
  // function explicitly has the `sourceCodeLocationInfo` option enabled.
  const endTagOffset = headTag.sourceCodeLocation!.endTag.startOffset;
  const indentationOffset = getChildElementIndentation(headTag);
  const insertion = `${' '.repeat(indentationOffset)}${elementHtml}`;

  const recordedChange = host
    .beginUpdate(htmlFilePath)
    .insertRight(endTagOffset, `${insertion}\n`);

  host.commitUpdate(recordedChange);
}
Exemplo n.º 10
0
  visitor.missingInjectablePipes.forEach(data => {
    const {classDeclaration, importDeclarationMissingImport} = data;
    const sourceFile = classDeclaration.getSourceFile();
    const update = tree.beginUpdate(relative(basePath, sourceFile.fileName));

    // Note that we don't need to go through the AST to insert the decorator, because the change
    // is pretty basic. Also this has a better chance of preserving the user's formatting.
    update.insertLeft(classDeclaration.getStart(), `@${INJECTABLE_DECORATOR_NAME}()\n`);

    // Add @Injectable to the imports if it isn't imported already. Note that this doesn't deal with
    // the case where there aren't any imports for `@angular/core` at all. We don't need to handle
    // it because the Pipe decorator won't be recognized if it hasn't been imported from Angular.
    if (importDeclarationMissingImport) {
      const namedImports = getNamedImports(importDeclarationMissingImport);

      if (namedImports) {
        update.remove(namedImports.getStart(), namedImports.getWidth());
        update.insertRight(
            namedImports.getStart(),
            printer.printNode(
                ts.EmitHint.Unspecified, addImport(namedImports, INJECTABLE_DECORATOR_NAME),
                sourceFile));
      }
    }

    tree.commitUpdate(update);
  });