import { createMinimalFS , Diagnostics , FileProcessor , postProcessor , process , processNamespace , replaceValueHook , StylableMeta , StylableResolver , StylableTransformer , createStylableFileProcessor , createDefaultResolver , Stylable , StylableConfig , } from '@stylable/core' ; import { isAbsolute } from 'path' ; import * as postcss from 'postcss' ; import { createMemoryFs } from '@file-services/memory' ; import type { IDirectoryContents } from '@file-services/types' ; export interface File { content : string ; mtime ? : Date ; namespace ? : string ; } export interface InfraConfig { files : Record < string , File > ; trimWS ? : boolean ; } export interface Config { entry ? : string ; files : Record < string , File > ; usedFiles ? : string [ ] ; trimWS ? : boolean ; optimize ? : boolean ; resolve ? : any ; mode ? : 'production' | 'development' ; } export type RequireType = ( path : string ) => any ; export function generateInfra ( config , diagnostics = new Diagnostics ( ) ) { const { fs , requireModule } = createMinimalFS ( config ) ; const fileProcessor = createStylableFileProcessor ( { fileSystem : fs , onProcess : ( meta , filePath ) => { meta . namespace = config . files [ filePath ] . namespace || meta . namespace ; return meta ; } , createDiagnostics : ( ) => diagnostics , } ) ; const resolveModule = createDefaultResolver ( fs , { } ) ; const resolvePath = ( context = '/' , moduleId ) => resolveModule ( context , moduleId ) ; const resolver = new StylableResolver ( fileProcessor , requireModule , resolvePath ) ; return { resolver , requireModule , fileProcessor , resolvePath } ; } interface CreateTransformerOptions { diagnostics ? : Diagnostics ; replaceValueHook ? : replaceValueHook ; postProcessor ? : postProcessor ; onResolve ? : ( resolved : string , _directoryPath : string , _request : string ) => string ; } export function createTransformer ( config , { diagnostics = new Diagnostics ( ) , replaceValueHook , postProcessor , onResolve = ( resolved ) => resolved , } = { } ) { const { requireModule , fileProcessor , resolvePath } = generateInfra ( config , diagnostics ) ; return new StylableTransformer ( { fileProcessor , moduleResolver : ( directoryPath , request ) => onResolve ( resolvePath ( directoryPath , request ) , directoryPath , request ) , requireModule , diagnostics , keepValues : false , replaceValueHook , postProcessor , mode : config . mode , } ) ; } export function processSource ( source , options = { } , resolveNamespace ? ) { return process ( postcss . parse ( source , options ) , undefined , resolveNamespace ) ; } export function createProcess ( fileProcessor ) { return ( path ) => fileProcessor . process ( path ) ; } export function generateStylableResult ( config , diagnostics = new Diagnostics ( ) ) { const { entry } = config ; if ( ! isAbsolute ( entry || '' ) ) { throw new Error ( `entry must be absolute path got: ${ entry }` ) ; } const transformer = createTransformer ( config , { diagnostics } ) ; return transformer . transform ( transformer . fileProcessor . process ( entry || '' ) ) ; } export function generateStylableRoot ( config ) { return generateStylableResult ( config ) . meta . outputAst ! ; } export function generateStylableExports ( config ) { return generateStylableResult ( config ) . exports ; } export function generateStylableEnvironment ( content , stylableConfig = { } ) { const fs = createMemoryFs ( content ) ; const stylable = Stylable . create ( { fileSystem : fs , projectRoot : '/' , resolveNamespace : ( ns ) => ns , ... stylableConfig , } ) ; return { stylable , fs , } ; }