Home Reference Source

src/private/Options.js

import {join} from 'path'
import {exists} from './fs-util'

/**
Stores options from taken from package.json.
See descriptions [here](//dum-build.org/config).
*/
export default class Options {
	static async new(packageDir) {
		const packageConfig = require(join(packageDir, 'package.json'))
		const config = packageConfig.dum || {}

		const opts = applyDefaults(config, {
			inDir: null,
			outDir: null,
			port: 8000,
			bower: null,
			opts: {},
			sound: true
		})

		const defaultBower = {inDir: 'bower_components', outDir: 'lib'}
		if (opts.bower === null) {
			if (await exists(join(packageDir, 'bower_components')))
				opts.bower = defaultBower
		} else
			opts.bower = applyDefaults(opts.bower, defaultBower)
		await applyInOutDefaults(opts, packageDir)

		return new Options(Object.assign({config, packageDir, packageConfig}, opts))
	}

	/** @private */
	constructor(values) {
		Object.assign(this, values)
	}
}

async function applyInOutDefaults(opts, packageDir) {
	if (opts.inDir !== null) {
		if (opts.outDir !== null)
			throw new Error('Must define `outDir` if `inDir` is defined.')
	} else if (opts.outDir !== null)
		throw new Error('Must define `inDir` if `outDir` is defined.')
	else if (await exists(join(packageDir, 'assets'))) {
		opts.inDir = 'assets'
		opts.outDir = 'public'
	} else if (await exists(join(packageDir, 'src'))) {
		opts.inDir = 'src'
		opts.outDir = 'lib'
	} else
		throw new Error(
			'Dum config does not have `inDir`, and neither `assets` nor `src` directories exist.')
}

function applyDefaults(provided, defaults) {
	const out = {}
	for (const key in provided) {
		if (!(key in defaults))
			throw new Error(`No such option ${key}`)
		out[key] = provided[key]
	}
	for (const key in defaults)
		if (!(key in out)) {
			if (defaults[key] === undefined)
				throw new Error(`Option ${key} must be provided.`)
			out[key] = defaults[key]
		}
	return out
}