Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ improve(patch): improve facades #2504

Merged
merged 3 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/babel/bud.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-check
/**
* @param {import('@roots/bud').Bud} bud
*/
Expand Down
7 changes: 6 additions & 1 deletion examples/config-yml/bud.config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@ runtime: true
assets:
- ['src/**/*.html']

# Inner properties of bud are fair game
# You can access inner properties
babel:
setPluginOptions:
- '@babel/plugin-transform-runtime'
- {helpers: true}

# You can use dot notation
babel.setPluginOptions:
- '@babel/plugin-transform-runtime'
- {helpers: true}

# prefix bud properties with _
# to reference the value
splitChunks: _bud.isProduction
Expand Down
32 changes: 32 additions & 0 deletions sources/@roots/bud-api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,39 @@ declare module '@roots/bud-framework' {
/**
* ## bud.hash
*
* Hash output filenames
*
* {@link https://bud.js.org/docs/bud.hash 📕 Documentation}
*
* @example
* Enable:
* ```js
* bud.hash()
* ```
*
* @example
* Disable:
* ```js
* bud.hash(false)
* ```
*
* @example
* Enable with custom format:
* ```js
* bud.hash('contenthash:8')
* ```
*
* @example
* Enable with a bud.js callback:
* ```js
* bud.when(bud.isProduction, bud.hash)
* ```
*
* @example
* Transform the existing value:
* ```js
* bud.hash((value) => !value)
* ```
*/
hash(...params: Hash.Parameters): Bud

Expand Down
3 changes: 2 additions & 1 deletion sources/@roots/bud-api/src/methods/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import isFunction from '@roots/bud-support/lodash/isFunction'

export type Parameters = [
| ((config: Partial<Configuration>) => Partial<Configuration>)
| ((config: Partial<Configuration>) => Promise<Partial<Configuration>>)
| Partial<Configuration>,
]

Expand All @@ -27,7 +28,7 @@ export const config: config = function (this: Bud, input): Bud {
if (!app) return

app.build.config = isFunction(input)
? input(app.build.config)
? await input(app.build.config)
: {...app.build.config, ...input}
})

Expand Down
2 changes: 1 addition & 1 deletion sources/@roots/bud-api/src/methods/devtool/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export const devtool: devtool = async function (
if (input instanceof Bud) {
this.hooks.on(`build.devtool`, FALLBACK_SOURCEMAP)

this.api.logger.success(`bud.devtool`, `devtool set to`, input)
this.api.logger.success(`bud.devtool:`, `devtool set to`, input)

return this
}
Expand Down
80 changes: 59 additions & 21 deletions sources/@roots/bud-api/src/methods/hash/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import {Bud} from '@roots/bud-framework'
import type {Bud} from '@roots/bud-framework'

import {InputError} from '@roots/bud-support/errors'

export type Value =
| ((hash: boolean | undefined) => boolean)
| ((hash?: boolean) => boolean | string)
| boolean
| Bud
| string
Expand All @@ -12,34 +14,70 @@ export interface hash {
(value: Value): Bud
}

export const hash: hash = function (this: Bud, value) {
if (value instanceof Bud || value === undefined) {
this.context.hash = true
export const hash: hash = function (this: Bud, value = true) {
if (typeof value === `boolean`) {
return setHash(this, value)
}

if (value instanceof this.constructor) {
return setHash(this, true)
}

this.api.logger.success(`bud.hash: hash set to`, this.context.hash)
if (typeof value === `function`) {
value = value(this.context.hash)

return this
if (typeof value !== `boolean` && typeof value !== `string`)
throw new InputError(`bud.hash: invalid input`, {
details: `callbacks supplied to bud.hash should return a boolean or a string value`,
docs: new URL(`https://bud.js.org/reference/bud.hash`),
thrownBy: `@roots/bud-api/methods/hash`,
})

if (typeof value === `string`) {
setHash(this, true)
setFormat(this, value)
return this
}

return setHash(this, value)
}

if (typeof value === `string`) {
if (!value.startsWith(`[`)) value = `[${value}]`
setHash(this, true)
return setFormat(this, value)
}

this.context.hash = true
this.hooks.on(`value.hashFormat`, value)
throw new InputError(`bud.hash: invalid input`, {
details: `bud.hash accepts a boolean, string, or callback function as input.`,
docs: new URL(`https://bud.js.org/reference/bud.hash`),
thrownBy: `@roots/bud-api/methods/hash`,
})
}

this.api.logger
.success(`bud.hash: hash set to`, this.context.hash)
.success(
`bud.hash: hash format set to`,
this.hooks.filter(`value.hashFormat`),
)
const formatHashString = (value: string): string => {
if (!value.startsWith(`[`)) value = `[${value}`
if (!value.endsWith(`]`)) value = `${value}]`
return value
}

return this
}
const setFormat = (bud: Bud, value: string): Bud => {
value = formatHashString(value)

bud.hooks
.on(`value.hashFormat`, value)
.api.logger.success(`bud.hash: hash format set to`, value)

return bud
}

this.context.hash = this.maybeCall(value, this.context.hash)
const setHash = (bud: Bud, value: boolean): Bud => {
bud.context.hash = value

this.api.logger.success(`bud.hash: hash set to`, this.context.hash)
bud.api.logger.success(
`bud.hash:`,
`hash`,
value ? `enabled` : `disabled`,
)

return this
return bud
}
52 changes: 42 additions & 10 deletions sources/@roots/bud-api/src/methods/minimize/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,54 @@ export interface minimize {
}

export const minimize: minimize = function (this: Bud, value = true) {
/**
* Handle {@link Bud} instances (when used as a callback for something like bud.tap, bud.promise, etc)
*/
if (value instanceof Bud) {
this.minimizers.enable(true)
this.minimizers.js.enable(true)
this.minimizers.css.enable(true)
;[this.minimizers, this.minimizers.js, this.minimizers.css].map(
minimizer => minimizer.enable(true),
)
return this
}

/**
* Handle true, false
*/
if (typeof value == `boolean`) {
this.minimizers.enable(value)
this.minimizers.js.enable(value)
this.minimizers.css.enable(value)
;[this.minimizers, this.minimizers.js, this.minimizers.css].map(
minimizer => minimizer.enable(value),
)
return this
}

/**
* For everything else, enable minimization and reset any state by disabling all minimizers
*/
this.minimizers.enable(true)
this.minimizers.js.enable(false)
this.minimizers.css.enable(false)

/**
* Handle string (`css`, `js`)
*/
if (typeof value == `string`) {
this.minimizers.enable(true)
if (!(value in this.minimizers)) {
throwUndefinedMinimizer()
}

this.minimizers[value].enable(true)
return this
}

/**
* Handle array of strings ([`css`, `js`])
*/
if (Array.isArray(value)) {
this.minimizers.enable(true)
value.map(key => {
this.minimizers[key].enable(true)
if (value.some(prop => !(prop in this.minimizers))) {
throwUndefinedMinimizer()
}
value.map(prop => {
this.minimizers[prop].enable(true)
})
return this
}
Expand All @@ -47,3 +71,11 @@ export const minimize: minimize = function (this: Bud, value = true) {
thrownBy: `@roots/bud-api/methods/minimize`,
})
}

const throwUndefinedMinimizer = (): never => {
throw ConfigError.normalize(`Error in bud.minimize`, {
details: `Invalid argument passed to bud.minimize. Minimizer does not exist.`,
docs: new URL(`https://bud.js.org/reference/bud.minimize`),
thrownBy: `@roots/bud-api/methods/minimize`,
})
}
6 changes: 0 additions & 6 deletions sources/@roots/bud-api/src/methods/persist/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ export interface persist {
}

export const persist: persist = function (this: Bud, type = `filesystem`) {
if (type instanceof Bud) {
this.cache.enabled = true
this.api.logger.success(`bud.cache:`, `set to`, type.cache.type)
return this
}

if (type === false) {
this.cache.enabled = false
this.api.logger.success(`bud.cache:`, `disabled`)
Expand Down
15 changes: 11 additions & 4 deletions sources/@roots/bud-api/src/methods/runtime/index.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type {Bud} from '@roots/bud-framework'
import type {Optimization} from '@roots/bud-framework/config'

import {Bud} from '@roots/bud-framework'

export type Parameters = [
| ((
runtime: Optimization.RuntimeChunk | undefined,
) => Optimization.RuntimeChunk)
| Bud
| Optimization.RuntimeChunk
| undefined,
]

export interface runtime {
Expand All @@ -17,8 +18,14 @@ export const runtime: runtime = async function (
this: Bud,
runtime = `single`,
) {
return this.hooks.on(
const value = runtime instanceof Bud || runtime === true ? `single` : runtime

this.hooks.on(
`build.optimization.runtimeChunk`,
runtime === true ? `single` : runtime,
value,
)

this.api.logger.success(`bud.runtime:`, `set to`, value)

return this
}
4 changes: 2 additions & 2 deletions sources/@roots/bud-api/test/minimize.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ describe(`bud.minimize`, () => {
minimize(value)

expect(spies.pop()).toHaveBeenCalledWith(true)
expect(spies.pop()).not.toHaveBeenCalled()
expect(spies.pop()).toHaveBeenCalledWith(false)
expect(spies.pop()).toHaveBeenCalledWith(true)
})

Expand All @@ -64,7 +64,7 @@ describe(`bud.minimize`, () => {

expect(spies.pop()).toHaveBeenCalledWith(true)
expect(spies.pop()).toHaveBeenCalledWith(true)
expect(spies.pop()).not.toHaveBeenCalled()
expect(spies.pop()).toHaveBeenCalledWith(false)
})

it(`should return bud`, () => {
Expand Down
3 changes: 2 additions & 1 deletion sources/@roots/bud-framework/src/bud/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,9 @@ export class Bud {
* Await all promised tasks
*/
@bind
public promise(promise: (bud: Bud) => Promise<unknown>) {
public promise(promise: (bud: Bud) => Promise<unknown>): Bud {
this.promised.push(promise)
return this
}

@bind
Expand Down
2 changes: 0 additions & 2 deletions sources/@roots/bud-framework/src/configuration/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ class Configuration {
})
})

this.bud.log(`config`, config)

if (!config) {
throw ConfigError.normalize(`No configuration found`, {
file: source,
Expand Down
23 changes: 14 additions & 9 deletions sources/@roots/bud-framework/src/methods/bindFacade.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type {Bud} from '@roots/bud-framework'

import {Bud} from '@roots/bud-framework'
import {BudError} from '@roots/bud-support/errors'
import isFunction from '@roots/bud-support/lodash/isFunction'
import logger from '@roots/bud-support/logger'
Expand All @@ -23,16 +22,15 @@ export const bindFacade: bindFacade = function (key, fn, binding?) {
if (`bind` in fn) fn = fn.bind(binding ?? this)

this.set(key, (...args: Array<any>) => {
logger
.scope(`bud.${key}`)
.log(
`called with args:`,
...args.map(arg => this.fs.json.stringify(arg)),
)
logger.enabled &&
logger
.scope(`bud.${key}`)
.log(`called with args:`, args.map(parseArgs(this)).join(`, `))

this.promise(async () => {
try {
await this.resolvePromises().then(async () => await fn(...args))
await this.resolvePromises()
await fn(...args)
} catch (error) {
throw error
}
Expand All @@ -43,3 +41,10 @@ export const bindFacade: bindFacade = function (key, fn, binding?) {

return this
}

const parseArgs = (bud: Bud) => (arg: any) =>
arg instanceof Bud
? `(bud)`
: typeof arg === `function`
? `(function)`
: bud.fs.json.stringify(arg)
Loading
Loading