@angular-devkit/core#dirname TypeScript Examples

The following examples show how to use @angular-devkit/core#dirname. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: parsers.ts    From form-schematic with MIT License 6 votes vote down vote up
parseName = (
	path: string,
	name: string
): { name: string; path: Path } => {
	const nameWithoutPath = basename(name as Path);
	const namePath = dirname((path + '/' + name) as Path);

	return {
		name: dasherize(nameWithoutPath),
		path: normalize('/' + namePath)
	};
}
Example #2
Source File: find-module.ts    From edit-in-place with MIT License 5 votes vote down vote up
/**
 * Find the module referred by a set of options passed to the schematics.
 */
export function findModuleFromOptions(host: Tree, options: any, projectPath: any): Path | undefined {
  if (options.hasOwnProperty('skipImport') && options.skipImport) {
    return undefined;
  }

  const moduleExt = options.moduleExt || MODULE_EXT;
  const routingModuleExt = options.routingModuleExt || ROUTING_MODULE_EXT;

  if (!options.module) {
    const pathToCheck = (projectPath || '') + '/' + options.name;
    const module = findModule(host, pathToCheck, moduleExt, routingModuleExt);
    return module ? normalize(module) : undefined;
  } else {
    const modulePath = normalize(`/${projectPath}/${options.module}`);
    const componentPath = normalize(`/${projectPath}/${options.name}`);
    const moduleBaseName = normalize(modulePath)
      .split('/')
      .pop();

    const candidateSet = new Set<Path>([normalize(projectPath || '/')]);

    for (let dir = modulePath; dir !== NormalizedRoot; dir = dirname(dir)) {
      candidateSet.add(dir);
    }
    for (let dir = componentPath; dir !== NormalizedRoot; dir = dirname(dir)) {
      candidateSet.add(dir);
    }

    const candidatesDirs = [...candidateSet].sort((a, b) => b.length - a.length);
    for (const c of candidatesDirs) {
      const candidateFiles = ['', `${moduleBaseName}.ts`, `${moduleBaseName}${moduleExt}`].map(x => join(c, x));

      for (const sc of candidateFiles) {
        if (host.exists(sc)) {
          return normalize(sc);
        }
      }
    }
    throw new Error(
      `Specified module '${options.module}' does not exist.\n` +
        `Looked in the following directories:\n    ${candidatesDirs.join('\n    ')}`
    );
  }
}
Example #3
Source File: library.loader.ts    From angular-miniprogram with MIT License 4 votes vote down vote up
export default async function (
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  this: webpack.LoaderContext<any>,
  data: string,
  map: string
) {
  const callback = this.async();
  const selector = createCssSelectorForTs(data);
  const list = selector.queryAll(`BinaryExpression[left$=ɵcmp]`);
  if (!list.length) {
    callback(undefined, data, map);
    return;
  }
  const context: ComponentTemplateLoaderContext = (this._compilation! as any)[
    ExportMiniProgramAssetsPluginSymbol
  ];
  const templateScopeOutside = (this._compilation as any)[
    TemplateScopeSymbol
  ] as TemplateScopeOutside;
  const scopeLibraryObj: Record<string, ExtraTemplateData[]> = {};
  for (let i = 0; i < list.length; i++) {
    const element = list[i] as ts.BinaryExpression;
    const componentName = (
      element.left as ts.PropertyAccessExpression
    ).expression.getText();
    const extraNode = selector.queryOne(
      `VariableDeclaration[name="${componentName}_${LIBRARY_COMPONENT_METADATA_SUFFIX}"]`
    ) as ts.VariableDeclaration;
    if (!extraNode) {
      continue;
    }
    const content = extraNode.initializer!.getText();
    const meta: ExportLibraryComponentMeta = literalResolve(content);
    (this._compilation as any)[LibrarySymbol] =
      (this._compilation as any)[LibrarySymbol] || {};
    const libraryLoaderContext: LibraryLoaderContext = (
      this._compilation as any
    )[LibrarySymbol];
    libraryLoaderContext.libraryMetaList =
      libraryLoaderContext.libraryMetaList || [];
    libraryLoaderContext.libraryMetaList.push({
      ...meta,
      context: this.context,
      importPath: this.resourcePath,
      contextPath: this.utils.contextify(this.rootContext, this.resourcePath),
    });
    const fileExtname = libraryLoaderContext.buildPlatform.fileExtname;
    libraryLoaderContext.libraryMetaList.forEach((item) => {
      const globalTemplatePath = join(
        normalize('/library-template'),
        strings.classify(item.moduleId) +
          libraryLoaderContext.buildPlatform.fileExtname.contentTemplate
      );
      const LIBRARY_SCOPE_ID = libraryTemplateScopeName(item.moduleId);
      const configPath = join(
        normalize(LIBRARY_OUTPUT_ROOTDIR),
        item.libraryPath + fileExtname.config
      );
      const list = scopeLibraryObj[LIBRARY_SCOPE_ID] || [];
      list.push({
        configPath: configPath,
        useComponents: item.useComponents,
        templateList: [],
        templatePath: globalTemplatePath,
      });

      scopeLibraryObj[LIBRARY_SCOPE_ID] = list;
      const libraryTemplateLiteralConvertOptions: LibraryTemplateLiteralConvertOptions =
        {
          directivePrefix:
            libraryLoaderContext.buildPlatform.templateTransform.getData()
              .directivePrefix,
          eventListConvert:
            libraryLoaderContext.buildPlatform.templateTransform
              .eventListConvert,
          templateInterpolation:
            libraryLoaderContext.buildPlatform.templateTransform
              .templateInterpolation,
          fileExtname: libraryLoaderContext.buildPlatform.fileExtname,
        };
      this.emitFile(
        join(
          normalize(LIBRARY_OUTPUT_ROOTDIR),
          item.libraryPath + fileExtname.content
        ),
        `<import src="${globalTemplatePath}"/>` +
          literalResolve(
            `\`${item.content}\``,
            libraryTemplateLiteralConvertOptions
          )
      );
      if (item.contentTemplate) {
        this.emitFile(
          join(
            normalize(LIBRARY_OUTPUT_ROOTDIR),
            dirname(normalize(item.libraryPath)),
            'template' + fileExtname.contentTemplate
          ),
          `<import src="${globalTemplatePath}"/>` +
            literalResolve(
              `\`${item.contentTemplate}\``,
              libraryTemplateLiteralConvertOptions
            )
        );
      }
      if (item.style) {
        this.emitFile(
          join(
            normalize(LIBRARY_OUTPUT_ROOTDIR),
            item.libraryPath + fileExtname.style
          ),
          item.style
        );
      }
    });
  }
  for (const key in scopeLibraryObj) {
    if (Object.prototype.hasOwnProperty.call(scopeLibraryObj, key)) {
      const element = scopeLibraryObj[key];
      templateScopeOutside.setScopeLibraryUseComponents(key, element);
    }
  }
  callback(undefined, data, map);
}
Example #4
Source File: compile-source-files.ts    From angular-miniprogram with MIT License 4 votes vote down vote up
export async function compileSourceFiles(
  graph: BuildGraph,
  tsConfig: ParsedConfiguration,
  moduleResolutionCache: ts.ModuleResolutionCache,
  extraOptions?: Partial<CompilerOptions>,
  stylesheetProcessor?: StylesheetProcessor,
  ngccProcessor?: NgccProcessor,
  watch?: boolean
) {
  const { NgtscProgram, formatDiagnostics } = await ngCompilerCli();

  const tsConfigOptions: CompilerOptions = {
    ...tsConfig.options,
    ...extraOptions,
  };
  const entryPoint: EntryPointNode = graph.find(
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    isEntryPointInProgress() as any
  )!;
  const ngPackageNode: PackageNode = graph.find(isPackage)!;
  const inlineStyleLanguage = ngPackageNode.data.inlineStyleLanguage;

  const tsCompilerHost = ngccTransformCompilerHost(
    cacheCompilerHost(
      graph,
      entryPoint,
      tsConfigOptions,
      moduleResolutionCache,
      stylesheetProcessor,
      inlineStyleLanguage
    ),
    tsConfigOptions,
    ngccProcessor!,
    moduleResolutionCache
  );
  // inject
  augmentLibraryMetadata(tsCompilerHost);
  const cache = entryPoint.cache;
  const sourceFileCache = cache.sourcesFileCache;

  // Create the Angular specific program that contains the Angular compiler
  const angularProgram = new NgtscProgram(
    tsConfig.rootNames,
    tsConfigOptions,
    tsCompilerHost,
    cache.oldNgtscProgram
  );

  const angularCompiler = angularProgram.compiler;
  const { ignoreForDiagnostics, ignoreForEmit } = angularCompiler;

  // SourceFile versions are required for builder programs.
  // The wrapped host inside NgtscProgram adds additional files that will not have versions.
  const typeScriptProgram = angularProgram.getTsProgram();
  augmentProgramWithVersioning(typeScriptProgram);

  let builder: ts.BuilderProgram | ts.EmitAndSemanticDiagnosticsBuilderProgram;
  if (watch) {
    builder = cache.oldBuilder =
      ts.createEmitAndSemanticDiagnosticsBuilderProgram(
        typeScriptProgram,
        tsCompilerHost,
        cache.oldBuilder
      );
    cache.oldNgtscProgram = angularProgram;
  } else {
    // When not in watch mode, the startup cost of the incremental analysis can be avoided by
    // using an abstract builder that only wraps a TypeScript program.
    builder = ts.createAbstractBuilder(typeScriptProgram, tsCompilerHost);
  }

  // Update semantic diagnostics cache
  const affectedFiles = new Set<ts.SourceFile>();

  // Analyze affected files when in watch mode for incremental type checking
  if ('getSemanticDiagnosticsOfNextAffectedFile' in builder) {
    // eslint-disable-next-line no-constant-condition
    while (true) {
      const result = builder.getSemanticDiagnosticsOfNextAffectedFile(
        undefined,
        (sourceFile) => {
          // If the affected file is a TTC shim, add the shim's original source file.
          // This ensures that changes that affect TTC are typechecked even when the changes
          // are otherwise unrelated from a TS perspective and do not result in Ivy codegen changes.
          // For example, changing @Input property types of a directive used in another component's
          // template.
          if (
            ignoreForDiagnostics.has(sourceFile) &&
            sourceFile.fileName.endsWith('.ngtypecheck.ts')
          ) {
            // This file name conversion relies on internal compiler logic and should be converted
            // to an official method when available. 15 is length of `.ngtypecheck.ts`
            const originalFilename = sourceFile.fileName.slice(0, -15) + '.ts';
            const originalSourceFile = builder.getSourceFile(originalFilename);
            if (originalSourceFile) {
              affectedFiles.add(originalSourceFile);
            }

            return true;
          }

          return false;
        }
      );

      if (!result) {
        break;
      }

      affectedFiles.add(result.affected as ts.SourceFile);
    }
  }

  // Collect program level diagnostics
  const allDiagnostics: ts.Diagnostic[] = [
    ...angularCompiler.getOptionDiagnostics(),
    ...builder.getOptionsDiagnostics(),
    ...builder.getGlobalDiagnostics(),
  ];
  // inject
  let injector = Injector.create({
    providers: [
      ...getBuildPlatformInjectConfig(PlatformType.library),
      {
        provide: MiniProgramCompilerService,
        useFactory: (injector: Injector, buildPlatform: BuildPlatform) => {
          return new MiniProgramCompilerService(
            angularProgram,
            injector,
            buildPlatform
          );
        },
        deps: [Injector, BuildPlatform],
      },
      {
        provide: ENTRY_FILE_TOKEN,
        useValue: join(
          dirname(normalize(tsConfig.rootNames[0])),
          normalize(tsConfigOptions.flatModuleOutFile!)
        ),
      },
      {
        provide: ENTRY_POINT_TOKEN,
        useValue: entryPoint.data.entryPoint.moduleId,
      },
    ],
  });
  const miniProgramCompilerService = injector.get(MiniProgramCompilerService);
  // Required to support asynchronous resource loading
  // Must be done before creating transformers or getting template diagnostics
  await angularCompiler.analyzeAsync();
  // inject
  miniProgramCompilerService.init();
  const metaMap =
    await miniProgramCompilerService.exportComponentBuildMetaMap();
  injector = Injector.create({
    parent: injector,
    providers: [
      { provide: RESOLVED_DATA_GROUP_TOKEN, useValue: metaMap },
      { provide: AddDeclarationMetaDataService },
      { provide: OutputTemplateMetadataService },
      { provide: SetupComponentDataService },
    ],
  });
  // Collect source file specific diagnostics
  for (const sourceFile of builder.getSourceFiles()) {
    if (!ignoreForDiagnostics.has(sourceFile)) {
      allDiagnostics.push(
        ...builder.getSyntacticDiagnostics(sourceFile),
        ...builder.getSemanticDiagnostics(sourceFile)
      );
    }

    if (sourceFile.isDeclarationFile) {
      continue;
    }

    // Collect sources that are required to be emitted
    if (
      !ignoreForEmit.has(sourceFile) &&
      !angularCompiler.incrementalDriver.safeToSkipEmit(sourceFile)
    ) {
      // If required to emit, diagnostics may have also changed
      if (!ignoreForDiagnostics.has(sourceFile)) {
        affectedFiles.add(sourceFile);
      }
    } else if (
      sourceFileCache &&
      !affectedFiles.has(sourceFile) &&
      !ignoreForDiagnostics.has(sourceFile)
    ) {
      // Use cached Angular diagnostics for unchanged and unaffected files
      const angularDiagnostics =
        sourceFileCache.getAngularDiagnostics(sourceFile);
      if (angularDiagnostics?.length) {
        allDiagnostics.push(...angularDiagnostics);
      }
    }
  }

  // Collect new Angular diagnostics for files affected by changes
  for (const affectedFile of affectedFiles) {
    const angularDiagnostics = angularCompiler.getDiagnosticsForFile(
      affectedFile,
      /** OptimizeFor.WholeProgram */ 1
    );

    allDiagnostics.push(...angularDiagnostics);
    sourceFileCache.updateAngularDiagnostics(affectedFile, angularDiagnostics);
  }

  const otherDiagnostics = [];
  const errorDiagnostics = [];
  for (const diagnostic of allDiagnostics) {
    if (diagnostic.category === ts.DiagnosticCategory.Error) {
      errorDiagnostics.push(diagnostic);
    } else {
      otherDiagnostics.push(diagnostic);
    }
  }

  if (otherDiagnostics.length) {
    log.msg(formatDiagnostics(errorDiagnostics));
  }

  if (errorDiagnostics.length) {
    throw new Error(formatDiagnostics(errorDiagnostics));
  }

  const transformers = angularCompiler.prepareEmit().transformers;
  for (const sourceFile of builder.getSourceFiles()) {
    if (!ignoreForEmit.has(sourceFile)) {
      builder.emit(sourceFile, undefined, undefined, undefined, transformers);
    }
  }
  function augmentLibraryMetadata(compilerHost: ts.CompilerHost) {
    const oldWriteFile = compilerHost.writeFile;
    compilerHost.writeFile = function (
      fileName: string,
      data: string,
      writeByteOrderMark,
      onError,
      sourceFiles
    ) {
      const entryFileName = injector.get(ENTRY_FILE_TOKEN);
      if (fileName.endsWith('.map')) {
        return oldWriteFile.call(
          this,
          fileName,
          data,
          writeByteOrderMark,
          onError,
          sourceFiles
        );
      }
      if (fileName.endsWith('.d.ts')) {
        const service = injector.get(AddDeclarationMetaDataService);
        const result = service.run(fileName, data);
        return oldWriteFile.call(
          this,
          fileName,
          result,
          writeByteOrderMark,
          onError,
          sourceFiles
        );
      }
      const sourceFile = sourceFiles && sourceFiles[0];
      if (sourceFile) {
        if (
          entryFileName ===
          normalize(sourceFile.fileName.replace(/\.ts$/, '.js'))
        ) {
          const service = injector.get(OutputTemplateMetadataService);
          const result = service.run(fileName, data, sourceFiles![0]);
          return oldWriteFile.call(
            this,
            fileName,
            result,
            writeByteOrderMark,
            onError,
            sourceFiles
          );
        }
        const originFileName = path.normalize(sourceFile.fileName);
        const setupComponentDataService = injector.get(
          SetupComponentDataService
        );
        const result = setupComponentDataService.run(
          data,
          originFileName,
          stylesheetProcessor! as CustomStyleSheetProcessor
        );
        return oldWriteFile.call(
          this,
          fileName,
          result,
          writeByteOrderMark,
          onError,
          sourceFiles
        );
      }
      return oldWriteFile.call(
        this,
        fileName,
        data,
        writeByteOrderMark,
        onError,
        sourceFiles
      );
    };
  }
}