import os from 'node:os'; import { applyMarkdown, applyStyle, Arg, Config } from '@boost/cli'; import { formatMs } from '@boost/common'; import { figures } from '@boost/terminal'; import { STATE_COLORS } from '../constants'; import { Package } from '../Package'; import type { BuildOptions } from '../types'; import { BaseCommand } from './Base'; @Config('build', 'Build a standardized package for distribution') export class BuildCommand extends BaseCommand> { @Arg.Flag('Add `engine` versions to each `package.json`') addEngines: boolean = false; @Arg.Flag('Add `exports` fields to each `package.json`') addExports: boolean = false; @Arg.Flag('Add `files` whitelist to each `package.json`') addFiles: boolean = true; @Arg.Number('Number of builds to run in parallel') concurrency: number = os.cpus().length; @Arg.Flag('Generate TypeScript declarations for each package') declaration: boolean = false; @Arg.Number('Timeout in milliseconds before a build is cancelled') timeout: number = 0; @Arg.Flag('Stamp all `package.json`s with a release timestamp') stamp: boolean = false; async run() { return this.build(await this.getPackage()); } protected async build(pkg: Package) { await this.packemon.build(pkg, { addEngines: this.addEngines, addExports: this.addExports, addFiles: this.addFiles, concurrency: this.concurrency, declaration: this.declaration, filterFormats: this.formats, filterPlatforms: this.platforms, loadConfigs: this.loadConfigs, quiet: this.quiet, skipPrivate: this.skipPrivate, stamp: this.stamp, timeout: this.timeout, }); const output = [applyMarkdown(`**${pkg.getName()}**`)]; const { filesize } = await import('filesize'); pkg.artifacts.forEach((artifact) => { const row: string[] = [' ']; artifact.builds.forEach((build, index) => { const icon = artifact.state === 'failed' ? figures.cross : figures.squareSmallFilled; const create = (tag: string) => applyStyle( applyMarkdown(`**${icon} ${tag}**`), STATE_COLORS[artifact.state] ?? 'default', ); row.push(create(build.format)); const { stats } = artifact.builds[index]; if (stats) { row.push(applyStyle(`(${String(filesize(stats.size))})`, 'muted')); } if (build.declaration) { row.push(create('dts')); } }); if (artifact.buildResult.time <= 100) { row.push(applyStyle('~', 'muted')); } else { row.push(formatMs(artifact.buildResult.time)); } output.push(row.join(' ')); }); output.push('\n'); this.log(output.join('\n').trim()); } protected async pack(pkg: Package) { await this.packemon.clean(pkg); await this.build(pkg); const validator = await this.packemon.validate(pkg, {}); this.renderValidator(validator); } }