import { readFile } from 'fs' ; import { extname , join , relative } from 'path' ; import { promisify } from 'util' ; import scanDirectory from 'scan-directory' ; import { StyleAst } from './parser/ast' ; import { buildAst } from './parser/toAst' ; import { StyleDefinition , StyleFiles , StylesLookupTable , SyncStyleDefinition } from './types' ; import { flattenOrder } from './utils/order' ; const RESOLVE_EXTENSIONS = [ '.css' ] ; const pReadFile = promisify ( readFile ) ; export const getFileContent = ( file ) => pReadFile ( file , 'utf8' ) ; const toFlattenArray = ( ast ) : StylesLookupTable => Object . keys ( ast ) . reduce ( ( acc , file ) => { ast [ file ] . selectors . forEach ( ( sel ) => { sel . pieces . forEach ( ( className ) => { if ( ! acc [ className ] ) { acc [ className ] = [ ] ; } acc [ className ] . push ( file ) ; } ) ; } ) ; return acc ; } , { } as StylesLookupTable ) ; const astFromFiles = ( fileDate ) : StyleAst => Object . keys ( fileDate ) . reduce ( ( acc , file ) => { acc [ file ] = buildAst ( fileDate [ file ] , file ) ; return acc ; } , { } as StyleAst ) ; param data export function parseProjectStyles ( data ) { const ast = astFromFiles ( data ) ; return { isReady : true , lookup : toFlattenArray ( ast ) , ast , } ; } const passAll = ( ) => true ; export interface FlattenFileOrder { file : string ; order : number ; } const createAwaitableResult = ( ) => { let resolve ; let reject ; const awaiter = new Promise < void > ( ( res , rej ) => { resolve = res ; reject = rej ; } ) ; const result = { isReady : false , then ( res , rej ) { return awaiter . then ( res , rej ) ; } , } as StyleDefinition ; return { result , resolve , reject , } ; } ; see discoverProjectStyles to automatically load styles from the build folder
 *  param getStyleNames param loader param fileFilter example export function loadStyleDefinitions ( getStyleNames , loader , fileFilter = passAll ) { const { resolve , reject , result } = createAwaitableResult ( ) ; async function scanner ( ) { const files = ( await getStyleNames ( ) ) . map ( ( file ) => ( { file , order : flattenOrder ( fileFilter ( file ) ) , } ) ) . filter ( ( { order } ) => ! Number . isNaN ( order ) ) . sort ( ( a , b ) => a . order - b . order ) . map ( ( { file } ) => file ) ; const styleFiles = { } ; files . map ( ( file ) => ( styleFiles [ file ] = undefined as any ) ) ; await Promise . all ( files . map ( async ( file ) => { styleFiles [ file ] = await loader ( file ) ; } ) ) ; return parseProjectStyles ( styleFiles ) ; } scanner ( ) . then ( ( styles ) => { Object . assign ( result , styles ) ; resolve ( ) ; } , ( e ) => { reject ( e ) ; console . error ( e ) ; throw new Error ( 'used-styles failed to start' ) ; } ) ; return result ; } see Use loadStyleDefinitions as a full customizable variant
 *  param rootDir param fileFilter export function discoverProjectStyles ( rootDir , fileFilter = passAll ) { return loadStyleDefinitions ( async ( ) => ( ( await scanDirectory ( rootDir , undefined , ( ) => false ) ) as string [ ] ) . filter ( ( name ) => RESOLVE_EXTENSIONS . indexOf ( extname ( name ) ) >= 0 ) . map ( ( file ) => relative ( rootDir , file ) ) . sort ( ) , ( fileName ) => getFileContent ( join ( rootDir , fileName ) ) , fileFilter ) ; }