@roots/bud-build
Version:
bud.js core module
157 lines (130 loc) • 3.27 kB
text/typescript
import type {Bud, Loaders} from '@roots/bud-framework'
import type * as Build from '@roots/bud-framework/services/build'
import {basename} from 'node:path'
import Registrable from '@roots/bud-build/helpers/registrable'
import Loader from '@roots/bud-build/loader'
import {bind} from '@roots/bud-support/decorators/bind'
import isString from '@roots/bud-support/isString'
import logger from '@roots/bud-support/logger'
export type ConstructorOptions = Build.Item.ConstructorOptions
/**
* Item class
*/
class Item extends Registrable implements Build.Item {
/**
* Identifier
*/
public ident: string
/**
* Loader
*/
public loader: `${keyof Loaders & string}` | Loader
/**
* Loader options
*/
public options: Build.Item['options']
/**
* Class constructor
*/
public constructor(
public override _app: () => Bud,
constructorParams?: {
ident?: string
loader?: `${keyof Loaders & string}` | Loader
options?: Item['options']
},
) {
super(_app)
constructorParams?.ident && this.setIdent(constructorParams.ident)
constructorParams?.loader && this.setLoader(constructorParams.loader)
!constructorParams?.ident &&
constructorParams?.loader &&
this.setIdent(
isString(constructorParams.loader)
? constructorParams.loader
: basename(constructorParams.loader.getSrc()),
)
constructorParams?.options &&
this.setOptions(constructorParams.options)
}
public getIdent(): Build.Item['ident'] {
return this.ident
}
/**
* Get rule set item loader
*/
public getLoader(): Loader {
return this.loader instanceof Loader
? this.loader
: this.app.build.loaders[this.loader]
}
/**
* Get rule set item options
*/
public getOptions(): Item['options'] {
return this.unwrap(this.options)
}
/**
* Merge rule set item options
*/
public mergeOptions(options: Build.Item.Options): this {
this.setOptions({
...(this.getOptions() ?? {}),
...options,
})
return this
}
public setIdent(ident: Build.Item['ident']): this {
this.ident = ident
return this
}
/**
* Set rule set item loader
*/
public setLoader(loader: `${keyof Loaders & string}` | Loader): this {
this.loader = loader
if (!this.ident)
this.setIdent(basename(isString(loader) ? loader : loader.getSrc()))
return this
}
/**
* Set rule set item options
*/
public setOptions(options: Item['options']) {
this.options = options
return this
}
/**
* Produce rule set item object for Webpack
*/
public toWebpack(): Build.Item.Output {
const output: Build.Item.Output = {
loader: this.getLoader()?.getSrc(),
}
if (this.options) {
output.options = this.getOptions()
}
if (this.ident) {
output.ident = this.getIdent()
}
if (!output.loader) {
logger.error(`error in ${this.ident}: no loader registered`)
}
return Object.entries(output).reduce(
(output, [key, value]) => ({
...(output ?? {}),
...(value ? {[key]: value} : {}),
}),
{},
)
}
}
export {Item as default}