import type { HeftConfiguration , HeftSession , IBuildStageContext , IHeftPlugin , IPreCompileSubstage , ScopedLogger } from '@rushstack/heft' ; import { ConfigurationFile , PathResolutionMethod } from '@rushstack/heft-config-file' ; import { JsonSchema } from '@rushstack/node-core-library' ; import { ISassConfiguration , SassTypingsGenerator } from './SassTypingsGenerator' ; import { Async } from './utilities/Async' ; export interface ISassConfigurationJson extends ISassConfiguration { } const PLUGIN_NAME = 'SassTypingsPlugin' ; const PLUGIN_SCHEMA_PATH = `${ __dirname }/schemas/heft-sass-plugin.schema.json` ; const SASS_CONFIGURATION_LOCATION = 'config/sass.json' ; export class SassTypingsPlugin implements IHeftPlugin { private static _sassConfigurationLoader : ConfigurationFile < ISassConfigurationJson > | undefined ; public readonly pluginName : string = PLUGIN_NAME ; public readonly optionsSchema : JsonSchema = JsonSchema . fromFile ( PLUGIN_SCHEMA_PATH ) ; /**
     * Generate typings for Sass files before TypeScript compilation.
     */ public apply ( heftSession , heftConfiguration ) { heftSession . hooks . build . tap ( PLUGIN_NAME , ( build ) => { build . hooks . preCompile . tap ( PLUGIN_NAME , ( preCompile ) => { preCompile . hooks . run . tapPromise ( PLUGIN_NAME , async ( ) => { await this . _runSassTypingsGeneratorAsync ( heftSession , heftConfiguration , build . properties . watchMode ) ; } ) ; } ) ; } ) ; } private async _runSassTypingsGeneratorAsync ( heftSession , heftConfiguration , isWatchMode ) { const logger = heftSession . requestScopedLogger ( 'sass-typings-generator' ) ; const sassConfiguration = await this . _loadSassConfigurationAsync ( heftConfiguration , logger ) ; const sassTypingsGenerator = new SassTypingsGenerator ( { buildFolder : heftConfiguration . buildFolder , sassConfiguration } ) ; await sassTypingsGenerator . generateTypingsAsync ( ) ; if ( isWatchMode ) { Async . runWatcherWithErrorHandling ( async ( ) => await sassTypingsGenerator . runWatcherAsync ( ) , logger ) ; } } private async _loadSassConfigurationAsync ( heftConfiguration , logger ) { const { buildFolder } = heftConfiguration ; const sassConfigurationJson = await SassTypingsPlugin . _getSassConfigurationLoader ( ) . tryLoadConfigurationFileForProjectAsync ( logger . terminal , buildFolder , heftConfiguration . rigConfig ) ; return { ... sassConfigurationJson } ; } private static _getSassConfigurationLoader ( ) { if ( ! SassTypingsPlugin . _sassConfigurationLoader ) { SassTypingsPlugin . _sassConfigurationLoader = new ConfigurationFile < ISassConfigurationJson > ( { projectRelativeFilePath : SASS_CONFIGURATION_LOCATION , jsonSchemaPath : PLUGIN_SCHEMA_PATH , jsonPathMetadata : { '$.importIncludePaths.*' : { pathResolutionMethod : PathResolutionMethod . resolvePathRelativeToProjectRoot } , '$.generatedTsFolder.*' : { pathResolutionMethod : PathResolutionMethod . resolvePathRelativeToProjectRoot } , '$.srcFolder.*' : { pathResolutionMethod : PathResolutionMethod . resolvePathRelativeToProjectRoot } , '$.cssOutputFolders.*' : { pathResolutionMethod : PathResolutionMethod . resolvePathRelativeToProjectRoot } } } ) ; } return SassTypingsPlugin . _sassConfigurationLoader ; } }