'use strict' import path from 'path' import fs from 'fs' import {uniq} from 'lodash' import hash from 'hash-sum' import {chainFn} from './utils' class Module { constructor (nuxt) { this.nuxt = nuxt this.options = nuxt.options } addVendor (vendor) { if (!vendor) { return } this.options.build.vendor = uniq(this.options.build.vendor.concat(vendor)) } addTemplate (template) { if (!template) { return } // Validate & parse source const src = template.src || template const srcPath = path.parse(src) if (!src || typeof src !== 'string' || !fs.existsSync(src)) { // eslint-disable-next-line no-console console.warn('[Nuxt] invalid template', template) return } // Generate unique and human readable dst filename const dst = template.fileName || (path.basename(srcPath.dir) + '.' + srcPath.name + '.' + hash(src) + '.' + srcPath.ext) // Add to templates list const templateObj = { src, dst, options: template.options } this.options.build.templates.push(templateObj) // Watch template for changes this.addWatch(src) return templateObj } addWatch (pattern) { this.options.build.watch.push(pattern) } addPlugin (template) { const {dst} = this.addTemplate(template) // Add to nuxt plugins this.options.plugins.push({ src: '~/.nuxt/' + dst, ssr: template.ssr, injectAs: template.injectAs }) } addServerMiddleware (middleware) { this.options.serverMiddlewares.push(middleware) } extendBuild (fn) { this.options.build.extend = chainFn(this.options.build.extend, fn) } extendRoutes (fn) { this.options.router.extendRoutes = chainFn(this.options.router.extendRoutes, fn) } installModule (moduleOpts) { if (!moduleOpts) { return } // Allows passing runtime options to each module const options = moduleOpts.options || {} let src = moduleOpts.src || moduleOpts // Resolve module let module try { if (typeof src === 'string') { // Using ~ shorthand modules are resolved from project srcDir if (src.indexOf('~') === 0) { src = path.resolve(this.options.srcDir, src.substr(1)) } // eslint-disable-next-line no-eval module = eval('require')(src) } } catch (e) { // eslint-disable-next-line no-console console.error('[Nuxt] Unable to resolve module', src) // eslint-disable-next-line no-console console.error(e) return } // Validate module if (!(module instanceof Function)) { // eslint-disable-next-line no-console console.error('[Nuxt] Module should be a function', module) } // Call module with `this` context and pass options return new Promise((resolve, reject) => { const result = module.call(this, options, err => { if (err) { return reject(err) } resolve(module) }) if (result && result.then instanceof Function) { return result.then(resolve) } }) } } export default Module