text: /*!
   * @nuxt/builder v2.15.4 (c) 2016-2021
   * Released under the MIT License
   * Repository: https://github.com/nuxt/nuxt.js
   * Website: https://nuxtjs.org
  */
  'use strict';
  
  Object.defineProperty(exports, '__esModule', { value: true });
  
  const path = require('path');
  const chalk = require('chalk');
  const chokidar = require('chokidar');
  const consola = require('consola');
  const fsExtra = require('fs-extra');
  const Glob = require('glob');
  const hash = require('hash-sum');
  const pify = require('pify');
  const upath = require('upath');
  const lodash = require('lodash');
  const utils = require('@nuxt/utils');
  const vueApp = require('@nuxt/vue-app');
  const webpack = require('@nuxt/webpack');
  const ignore = require('ignore');
  const serialize = require('serialize-javascript');
  const devalue = require('@nuxt/devalue');
  
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
  
  const path__default = /*#__PURE__*/_interopDefaultLegacy(path);
  const chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk);
  const chokidar__default = /*#__PURE__*/_interopDefaultLegacy(chokidar);
  const consola__default = /*#__PURE__*/_interopDefaultLegacy(consola);
  const fsExtra__default = /*#__PURE__*/_interopDefaultLegacy(fsExtra);
  const Glob__default = /*#__PURE__*/_interopDefaultLegacy(Glob);
  const hash__default = /*#__PURE__*/_interopDefaultLegacy(hash);
  const pify__default = /*#__PURE__*/_interopDefaultLegacy(pify);
  const upath__default = /*#__PURE__*/_interopDefaultLegacy(upath);
  const ignore__default = /*#__PURE__*/_interopDefaultLegacy(ignore);
  const serialize__default = /*#__PURE__*/_interopDefaultLegacy(serialize);
  const devalue__default = /*#__PURE__*/_interopDefaultLegacy(devalue);
  
  class Ignore {
    constructor (options) {
      this.rootDir = options.rootDir;
      this.ignoreOptions = options.ignoreOptions;
      this.ignoreArray = options.ignoreArray;
      this.addIgnoresRules();
    }
  
    static get IGNORE_FILENAME () {
      return '.nuxtignore'
    }
  
    findIgnoreFile () {
      if (!this.ignoreFile) {
        const ignoreFile = path__default['default'].resolve(this.rootDir, Ignore.IGNORE_FILENAME);
        if (fsExtra__default['default'].existsSync(ignoreFile) && fsExtra__default['default'].statSync(ignoreFile).isFile()) {
          this.ignoreFile = ignoreFile;
          this.ignore = ignore__default['default'](this.ignoreOptions);
        }
      }
      return this.ignoreFile
    }
  
    readIgnoreFile () {
      if (this.findIgnoreFile()) {
        return fsExtra__default['default'].readFileSync(this.ignoreFile, 'utf8')
      }
    }
  
    addIgnoresRules () {
      const content = this.readIgnoreFile();
      if (content) {
        this.ignore.add(content);
      }
      if (this.ignoreArray && this.ignoreArray.length > 0) {
        if (!this.ignore) {
          this.ignore = ignore__default['default'](this.ignoreOptions);
        }
        this.ignore.add(this.ignoreArray);
      }
    }
  
    filter (paths) {
      if (this.ignore) {
        return this.ignore.filter([].concat(paths || []))
      }
      return paths
    }
  
    reload () {
      delete this.ignore;
      delete this.ignoreFile;
      this.addIgnoresRules();
    }
  }
  
  class BuildContext {
    constructor (builder) {
      this._builder = builder;
      this.nuxt = builder.nuxt;
      this.options = builder.nuxt.options;
      this.target = builder.nuxt.options.target;
    }
  
    get buildOptions () {
      return this.options.build
    }
  
    get plugins () {
      return this._builder.plugins
    }
  }
  
  class TemplateContext {
    constructor (builder, options) {
      this.templateFiles = Array.from(builder.template.files);
      this.templateVars = {
        nuxtOptions: options,
        features: options.features,
        extensions: options.extensions
          .map(ext => ext.replace(/^\./, ''))
          .join('|'),
        messages: options.messages,
        splitChunks: options.build.splitChunks,
        uniqBy: lodash.uniqBy,
        isDev: options.dev,
        isTest: options.test,
        isFullStatic: utils.isFullStatic(options),
        debug: options.debug,
        buildIndicator: options.dev && options.build.indicator,
        vue: { config: options.vue.config },
        fetch: options.fetch,
        mode: options.mode,
        router: options.router,
        env: options.env,
        head: options.head,
        store: options.features.store ? options.store : false,
        globalName: options.globalName,
        globals: builder.globals,
        css: options.css,
        plugins: builder.plugins,
        appPath: './App.js',
        layouts: Object.assign({}, options.layouts),
        loading:
          typeof options.loading === 'string'
            ? builder.relativeToBuild(options.srcDir, options.loading)
            : options.loading,
        pageTransition: options.pageTransition,
        layoutTransition: options.layoutTransition,
        rootDir: options.rootDir,
        srcDir: options.srcDir,
        dir: options.dir,
        components: {
          ErrorPage: options.ErrorPage
            ? builder.relativeToBuild(options.ErrorPage)
            : null
        }
      };
    }
  
    get templateOptions () {
      let lodash = null;
  
      return {
        imports: {
          serialize: serialize__default['default'],
          serializeFunction: utils.serializeFunction,
          devalue: devalue__default['default'],
          hash: hash__default['default'],
          r: utils.r,
          wp: utils.wp,
          wChunk: utils.wChunk,
          // Legacy support: https://github.com/nuxt/nuxt.js/issues/4350
          _: new Proxy({}, {
            get (target, prop) {
              if (!lodash) {
                consola__default['default'].warn('Avoid using _ inside templates');
                lodash = utils.requireModule('lodash');
              }
              return lodash[prop]
            }
          })
        },
        interpolate: /<%=([\s\S]+?)%>/g
      }
    }
  }
  
  const glob = pify__default['default'](Glob__default['default']);
  class Builder {
    constructor (nuxt, bundleBuilder) {
      this.nuxt = nuxt;
      this.plugins = [];
      this.options = nuxt.options;
      this.globals = utils.determineGlobals(nuxt.options.globalName, nuxt.options.globals);
      this.watchers = {
        files: null,
        custom: null,
        restart: null
      };
  
      this.supportedExtensions = ['vue', 'js', ...(this.options.build.additionalExtensions || [])];
  
      // Helper to resolve build paths
      this.relativeToBuild = (...args) => utils.relativeTo(this.options.buildDir, ...args);
  
      this._buildStatus = STATUS.INITIAL;
  
      // Hooks for watch lifecycle
      if (this.options.dev) {
        // Start watching after initial render
        this.nuxt.hook('build:done', () => {
          consola__default['default'].info('Waiting for file changes');
          this.watchClient();
          this.watchRestart();
        });
  
        // Enable HMR for serverMiddleware
        this.serverMiddlewareHMR();
  
        // Close hook
        this.nuxt.hook('close', () => this.close());
      }
  
      if (this.options.build.analyze) {
        this.nuxt.hook('build:done', () => {
          consola__default['default'].warn('Notice: Please do not deploy bundles built with "analyze" mode, they\'re for analysis purposes only.');
        });
      }
  
      // Resolve template
      this.template = this.options.build.template || vueApp.template;
      if (typeof this.template === 'string') {
        this.template = this.nuxt.resolver.requireModule(this.template).template;
      }
  
      // Create a new bundle builder
      this.bundleBuilder = this.getBundleBuilder(bundleBuilder);
  
      this.ignore = new Ignore({
        rootDir: this.options.srcDir,
        ignoreArray: this.options.ignore
      });
    }
  
    getBundleBuilder (BundleBuilder) {
      if (typeof BundleBuilder === 'object') {
        return BundleBuilder
      }
  
      const context = new BuildContext(this);
  
      if (typeof BundleBuilder !== 'function') {
        BundleBuilder = webpack.BundleBuilder;
      }
  
      return new BundleBuilder(context)
    }
  
    forGenerate () {
      this.options.target = utils.TARGETS.static;
      this.bundleBuilder.forGenerate();
    }
  
    async build () {
      // Avoid calling build() method multiple times when dev:true
      if (this._buildStatus === STATUS.BUILD_DONE && this.options.dev) {
        return this
      }
      // If building
      if (this._buildStatus === STATUS.BUILDING) {
        await utils.waitFor(1000);
        return this.build()
      }
      this._buildStatus = STATUS.BUILDING;
  
      if (this.options.dev) {
        consola__default['default'].info('Preparing project for development');
        consola__default['default'].info('Initial build may take a while');
      } else {
        consola__default['default'].info('Production build');
        if (this.options.render.ssr) {
          consola__default['default'].info(`Bundling for ${chalk__default['default'].bold.yellow('server')} and ${chalk__default['default'].bold.green('client')} side`);
        } else {
          consola__default['default'].info(`Bundling only for ${chalk__default['default'].bold.green('client')} side`);
        }
        consola__default['default'].info(`Target: ${chalk__default['default'].bold.cyan(this.options.target)}`);
      }
  
      // Wait for nuxt ready
      await this.nuxt.ready();
  
      // Call before hook
      await this.nuxt.callHook('build:before', this, this.options.build);
  
      await this.validatePages();
  
      consola__default['default'].success('Builder initialized');
  
      consola__default['default'].debug(`App root: ${this.options.srcDir}`);
  
      // Create or empty .nuxt/, .nuxt/components and .nuxt/dist folders
      await fsExtra__default['default'].emptyDir(utils.r(this.options.buildDir));
      const buildDirs = [utils.r(this.options.buildDir, 'components')];
      if (!this.options.dev) {
        buildDirs.push(
          utils.r(this.options.buildDir, 'dist', 'client'),
          utils.r(this.options.buildDir, 'dist', 'server')
        );
      }
      await Promise.all(buildDirs.map(dir => fsExtra__default['default'].emptyDir(dir)));
  
      // Call ready hook
      await this.nuxt.callHook('builder:prepared', this, this.options.build);
  
      // Generate routes and interpret the template files
      await this.generateRoutesAndFiles();
  
      // Add vue-app template dir to watchers
      this.options.build.watch.push(this.globPathWithExtensions(this.template.dir));
  
      await this.resolvePlugins();
  
      // Start bundle build: webpack, rollup, parcel...
      await this.bundleBuilder.build();
  
      // Flag to set that building is done
      this._buildStatus = STATUS.BUILD_DONE;
  
      // Call done hook
      await this.nuxt.callHook('build:done', this);
  
      return this
    }
  
    // Check if pages dir exists and warn if not
    async validatePages () {
      this._nuxtPages = typeof this.options.build.createRoutes !== 'function';
  
      if (
        !this._nuxtPages ||
        await fsExtra__default['default'].exists(path__default['default'].resolve(this.options.srcDir, this.options.dir.pages))
      ) {
        return
      }
  
      const dir = this.options.srcDir;
      if (await fsExtra__default['default'].exists(path__default['default'].join(this.options.srcDir, '..', this.options.dir.pages))) {
        throw new Error(
          `No \`${this.options.dir.pages}\` directory found in ${dir}. Did you mean to run \`nuxt\` in the parent (\`../\`) directory?`
        )
      }
  
      this._defaultPage = true;
      consola__default['default'].warn(`No \`${this.options.dir.pages}\` directory found in ${dir}. Using the default built-in page.`);
    }
  
    globPathWithExtensions (path) {
      return `${path}/**/*.{${this.supportedExtensions.join(',')}}`
    }
  
    createTemplateContext () {
      return new TemplateContext(this, this.options)
    }
  
    async generateRoutesAndFiles () {
      consola__default['default'].debug('Generating nuxt files');
  
      this.plugins = Array.from(await this.normalizePlugins());
  
      const templateContext = this.createTemplateContext();
  
      await Promise.all([
        this.resolveLayouts(templateContext),
        this.resolveRoutes(templateContext),
        this.resolveStore(templateContext),
        this.resolveMiddleware(templateContext)
      ]);
  
      this.addOptionalTemplates(templateContext);
  
      await this.resolveCustomTemplates(templateContext);
  
      await this.resolveLoadingIndicator(templateContext);
  
      await this.compileTemplates(templateContext);
  
      consola__default['default'].success('Nuxt files generated');
    }
  
    async normalizePlugins () {
      // options.extendPlugins allows for returning a new plugins array
      if (typeof this.options.extendPlugins === 'function') {
        const extendedPlugins = this.options.extendPlugins(this.options.plugins);
  
        if (Array.isArray(extendedPlugins)) {
          this.options.plugins = extendedPlugins;
        }
      }
  
      // extendPlugins hook only supports in-place modifying
      await this.nuxt.callHook('builder:extendPlugins', this.options.plugins);
  
      const modes = ['client', 'server'];
      const modePattern = new RegExp(`\\.(${modes.join('|')})(\\.\\w+)*$`);
      return lodash.uniqBy(
        this.options.plugins.map((p) => {
          if (typeof p === 'string') {
            p = { src: p };
          }
          const pluginBaseName = path__default['default'].basename(p.src, path__default['default'].extname(p.src)).replace(
            /[^a-zA-Z?\d\s:]/g,
            ''
          );
  
          if (p.ssr === false) {
            p.mode = 'client';
          } else if (p.mode === undefined) {
            p.mode = 'all';
            p.src.replace(modePattern, (_, mode) => {
              if (modes.includes(mode)) {
                p.mode = mode;
              }
            });
          } else if (!['client', 'server', 'all'].includes(p.mode)) {
            consola__default['default'].warn(`Invalid plugin mode (server/client/all): '${p.mode}'. Falling back to 'all'`);
            p.mode = 'all';
          }
  
          return {
            src: this.nuxt.resolver.resolveAlias(p.src),
            mode: p.mode,
            name: 'nuxt_plugin_' + pluginBaseName + '_' + hash__default['default'](p.src)
          }
        }),
        p => p.name
      )
    }
  
    addOptionalTemplates (templateContext) {
      if (this.options.build.indicator) {
        templateContext.templateFiles.push('components/nuxt-build-indicator.vue');
      }
  
      if (this.options.loading !== false) {
        templateContext.templateFiles.push('components/nuxt-loading.vue');
      }
    }
  
    async resolveFiles (dir, cwd = this.options.srcDir) {
      return this.ignore.filter(await glob(this.globPathWithExtensions(dir), {
        cwd,
        follow: this.options.build.followSymlinks
      }))
    }
  
    async resolveRelative (dir) {
      const dirPrefix = new RegExp(`^${dir}/`);
      return (await this.resolveFiles(dir)).map(file => ({ src: file.replace(dirPrefix, '') }))
    }
  
    async resolveLayouts ({ templateVars, templateFiles }) {
      if (!this.options.features.layouts) {
        return
      }
  
      if (await fsExtra__default['default'].exists(path__default['default'].resolve(this.options.srcDir, this.options.dir.layouts))) {
        for (const file of await this.resolveFiles(this.options.dir.layouts)) {
          const name = file
            .replace(new RegExp(`^${this.options.dir.layouts}/`), '')
            .replace(new RegExp(`\\.(${this.supportedExtensions.join('|')})$`), '');
  
          // Layout Priority: module.addLayout > .vue file > other extensions
          if (name === 'error') {
            if (!templateVars.components.ErrorPage) {
              templateVars.components.ErrorPage = this.relativeToBuild(
                this.options.srcDir,
                file
              );
            }
          } else if (this.options.layouts[name]) {
            consola__default['default'].warn(`Duplicate layout registration, "${name}" has been registered as "${this.options.layouts[name]}"`);
          } else if (!templateVars.layouts[name] || /\.vue$/.test(file)) {
            templateVars.layouts[name] = this.relativeToBuild(
              this.options.srcDir,
              file
            );
          }
        }
      }
  
      // If no default layout, create its folder and add the default folder
      if (!templateVars.layouts.default) {
        await fsExtra__default['default'].mkdirp(utils.r(this.options.buildDir, 'layouts'));
        templateFiles.push('layouts/default.vue');
        templateVars.layouts.default = './layouts/default.vue';
      }
    }
  
    async resolveRoutes ({ templateVars }) {
      consola__default['default'].debug('Generating routes...');
      const { routeNameSplitter, trailingSlash } = this.options.router;
  
      if (this._defaultPage) {
        templateVars.router.routes = utils.createRoutes({
          files: ['index.vue'],
          srcDir: this.template.dir + '/pages',
          routeNameSplitter,
          trailingSlash
        });
      } else if (this._nuxtPages) {
        // Use nuxt createRoutes bases on pages/
        const files = {};
        const ext = new RegExp(`\\.(${this.supportedExtensions.join('|')})$`);
        for (const page of await this.resolveFiles(this.options.dir.pages)) {
          const key = page.replace(ext, '');
          // .vue file takes precedence over other extensions
          if (/\.vue$/.test(page) || !files[key]) {
            files[key] = page.replace(/(['"])/g, '\\$1');
          }
        }
        templateVars.router.routes = utils.createRoutes({
          files: Object.values(files),
          srcDir: this.options.srcDir,
          pagesDir: this.options.dir.pages,
          routeNameSplitter,
          supportedExtensions: this.supportedExtensions,
          trailingSlash
        });
      } else { // If user defined a custom method to create routes
        templateVars.router.routes = await this.options.build.createRoutes(
          this.options.srcDir
        );
      }
  
      await this.nuxt.callHook(
        'build:extendRoutes',
        templateVars.router.routes,
        utils.r
      );
      // router.extendRoutes method
      if (typeof this.options.router.extendRoutes === 'function') {
        // let the user extend the routes
        const extendedRoutes = await this.options.router.extendRoutes(
          templateVars.router.routes,
          utils.r
        );
        // Only overwrite routes when something is returned for backwards compatibility
        if (extendedRoutes !== undefined) {
          templateVars.router.routes = extendedRoutes;
        }
      }
  
      // Make routes accessible for other modules and webpack configs
      this.routes = templateVars.router.routes;
    }
  
    async resolveStore ({ templateVars, templateFiles }) {
      // Add store if needed
      if (!this.options.features.store || !this.options.store) {
        return
      }
  
      templateVars.storeModules = (await this.resolveRelative(this.options.dir.store))
        .sort(({ src: p1 }, { src: p2 }) => {
          // modules are sorted from low to high priority (for overwriting properties)
          let res = p1.split('/').length - p2.split('/').length;
          if (res === 0 && p1.includes('/index.')) {
            res = -1;
          } else if (res === 0 && p2.includes('/index.')) {
            res = 1;
          }
          return res
        });
  
      templateFiles.push('store.js');
    }
  
    async resolveMiddleware ({ templateVars, templateFiles }) {
      if (!this.options.features.middleware) {
        return
      }
  
      const middleware = await this.resolveRelative(this.options.dir.middleware);
      const extRE = new RegExp(`\\.(${this.supportedExtensions.join('|')})$`);
      templateVars.middleware = middleware.map(({ src }) => {
        const name = src.replace(extRE, '');
        const dst = this.relativeToBuild(this.options.srcDir, this.options.dir.middleware, src);
        return { name, src, dst }
      });
  
      templateFiles.push('middleware.js');
    }
  
    async resolveCustomTemplates (templateContext) {
      // Sanitize custom template files
      this.options.build.templates = this.options.build.templates.map((t) => {
        const src = t.src || t;
        return {
          src: utils.r(this.options.srcDir, src),
          dst: t.dst || path__default['default'].basename(src),
          custom: true,
          ...(typeof t === 'object' ? t : undefined)
        }
      });
  
      const customTemplateFiles = this.options.build.templates.map(t => t.dst || path__default['default'].basename(t.src || t));
  
      const templatePaths = lodash.uniq([
        // Modules & user provided templates
        // first custom to keep their index
        ...customTemplateFiles,
        // @nuxt/vue-app templates
        ...templateContext.templateFiles
      ]);
  
      const appDir = path__default['default'].resolve(this.options.srcDir, this.options.dir.app);
  
      templateContext.templateFiles = await Promise.all(templatePaths.map(async (file) => {
        // Use custom file if provided in build.templates[]
        const customTemplateIndex = customTemplateFiles.indexOf(file);
        const customTemplate = customTemplateIndex !== -1 ? this.options.build.templates[customTemplateIndex] : null;
        let src = customTemplate ? (customTemplate.src || customTemplate) : utils.r(this.template.dir, file);
  
        // Allow override templates using a file with same name in ${srcDir}/app
        const customAppFile = path__default['default'].resolve(this.options.srcDir, this.options.dir.app, file);
        const customAppFileExists = customAppFile.startsWith(appDir) && await fsExtra__default['default'].exists(customAppFile);
        if (customAppFileExists) {
          src = customAppFile;
        }
  
        return {
          src,
          dst: file,
          custom: Boolean(customAppFileExists || customTemplate),
          options: (customTemplate && customTemplate.options) || {}
        }
      }));
    }
  
    async resolveLoadingIndicator ({ templateFiles }) {
      if (!this.options.loadingIndicator.name) {
        return
      }
      let indicatorPath = path__default['default'].resolve(
        this.template.dir,
        'views/loading',
        this.options.loadingIndicator.name + '.html'
      );
  
      let customIndicator = false;
      if (!await fsExtra__default['default'].exists(indicatorPath)) {
        indicatorPath = this.nuxt.resolver.resolveAlias(
          this.options.loadingIndicator.name
        );
  
        if (await fsExtra__default['default'].exists(indicatorPath)) {
          customIndicator = true;
        } else {
          indicatorPath = null;
        }
      }
  
      if (!indicatorPath) {
        consola__default['default'].error(
          `Could not fetch loading indicator: ${
            this.options.loadingIndicator.name
          }`
        );
        return
      }
  
      templateFiles.push({
        src: indicatorPath,
        dst: 'loading.html',
        custom: customIndicator,
        options: this.options.loadingIndicator
      });
    }
  
    async compileTemplates (templateContext) {
      // Prepare template options
      const { templateVars, templateFiles, templateOptions } = templateContext;
  
      await this.nuxt.callHook('build:templates', {
        templateVars,
        templatesFiles: templateFiles,
        resolve: utils.r
      });
  
      templateOptions.imports = {
        ...templateOptions.imports,
        resolvePath: this.nuxt.resolver.resolvePath,
        resolveAlias: this.nuxt.resolver.resolveAlias,
        relativeToBuild: this.relativeToBuild
      };
  
      // Interpret and move template files to .nuxt/
      await Promise.all(
        templateFiles.map(async (templateFile) => {
          const { src, dst, custom } = templateFile;
  
          // Add custom templates to watcher
          if (custom) {
            this.options.build.watch.push(src);
          }
  
          // Render template to dst
          const fileContent = await fsExtra__default['default'].readFile(src, 'utf8');
  
          let content;
          try {
            const templateFunction = lodash.template(fileContent, templateOptions);
            content = utils.stripWhitespace(
              templateFunction({
                ...templateVars,
                ...templateFile
              })
            );
          } catch (err) {
            throw new Error(`Could not compile template ${src}: ${err.message}`)
          }
  
          // Ensure parent dir exits and write file
          const relativePath = utils.r(this.options.buildDir, dst);
          await fsExtra__default['default'].outputFile(relativePath, content, 'utf8');
        })
      );
    }
  
    resolvePlugins () {
      // Check plugins exist then set alias to their real path
      return Promise.all(this.plugins.map(async (p) => {
        const ext = '{?(.+([^.])),/index.+([^.])}';
        const pluginFiles = await glob(`${p.src}${ext}`);
  
        if (!pluginFiles || pluginFiles.length === 0) {
          throw new Error(`Plugin not found: ${p.src}`)
        }
  
        if (pluginFiles.length > 1 && !utils.isIndexFileAndFolder(pluginFiles)) {
          consola__default['default'].warn({
            message: `Found ${pluginFiles.length} plugins that match the configuration, suggest to specify extension:`,
            additional: '\n' + pluginFiles.map(x => `- ${x}`).join('\n')
          });
        }
  
        p.src = this.relativeToBuild(p.src);
      }))
    }
  
    // TODO: Uncomment when generateConfig enabled again
    // async generateConfig() {
    //   const config = path.resolve(this.options.buildDir, 'build.config.js')
    //   const options = omit(this.options, Options.unsafeKeys)
    //   await fsExtra.writeFile(
    //     config,
    //     `export default ${JSON.stringify(options, null, '  ')}`,
    //     'utf8'
    //   )
    // }
  
    createFileWatcher (patterns, events, listener, watcherCreatedCallback) {
      const options = this.options.watchers.chokidar;
      const watcher = chokidar__default['default'].watch(patterns, options);
  
      for (const event of events) {
        watcher.on(event, listener);
      }
  
      // TODO: due to fixes in chokidar this isnt used anymore and could be removed in Nuxt v3
      const { rewatchOnRawEvents } = this.options.watchers;
      if (rewatchOnRawEvents && Array.isArray(rewatchOnRawEvents)) {
        watcher.on('raw', (_event) => {
          if (rewatchOnRawEvents.includes(_event)) {
            watcher.close();
  
            listener();
            this.createFileWatcher(patterns, events, listener, watcherCreatedCallback);
          }
        });
      }
  
      if (typeof watcherCreatedCallback === 'function') {
        watcherCreatedCallback(watcher);
      }
    }
  
    assignWatcher (key) {
      return (watcher) => {
        if (this.watchers[key]) {
          this.watchers[key].close();
        }
        this.watchers[key] = watcher;
      }
    }
  
    watchClient () {
      let patterns = [
        utils.r(this.options.srcDir, this.options.dir.layouts),
        utils.r(this.options.srcDir, this.options.dir.middleware)
      ];
  
      if (this.options.store) {
        patterns.push(utils.r(this.options.srcDir, this.options.dir.store));
      }
  
      if (this._nuxtPages && !this._defaultPage) {
        patterns.push(utils.r(this.options.srcDir, this.options.dir.pages));
      }
  
      patterns = patterns.map((path, ...args) => upath__default['default'].normalizeSafe(this.globPathWithExtensions(path), ...args));
  
      const refreshFiles = lodash.debounce(() => this.generateRoutesAndFiles(), 200);
  
      // Watch for src Files
      this.createFileWatcher(patterns, ['add', 'unlink'], refreshFiles, this.assignWatcher('files'));
  
      // Watch for custom provided files
      const customPatterns = lodash.uniq([
        ...this.options.build.watch,
        ...Object.values(lodash.omit(this.options.build.styleResources, ['options']))
      ]).map(upath__default['default'].normalizeSafe);
  
      if (customPatterns.length === 0) {
        return
      }
  
      this.createFileWatcher(customPatterns, ['change'], refreshFiles, this.assignWatcher('custom'));
  
      // Watch for app/ files
      this.createFileWatcher([utils.r(this.options.srcDir, this.options.dir.app)], ['add', 'change', 'unlink'], refreshFiles, this.assignWatcher('app'));
    }
  
    serverMiddlewareHMR () {
      // Check nuxt.server dependency
      if (!this.nuxt.server) {
        return
      }
  
      // Get registered server middleware with path
      const entries = this.nuxt.server.serverMiddlewarePaths();
  
      // Resolve dependency tree
      const deps = new Set();
      const dep2Entry = {};
  
      for (const entry of entries) {
        for (const dep of utils.scanRequireTree(entry)) {
          deps.add(dep);
          if (!dep2Entry[dep]) {
            dep2Entry[dep] = new Set();
          }
          dep2Entry[dep].add(entry);
        }
      }
  
      // Create watcher
      this.createFileWatcher(
        Array.from(deps),
        ['all'],
        lodash.debounce((event, fileName) => {
          if (!dep2Entry[fileName]) {
            return // #7097
          }
          for (const entry of dep2Entry[fileName]) {
            // Reload entry
            let newItem;
            try {
              newItem = this.nuxt.server.replaceMiddleware(entry, entry);
            } catch (error) {
              consola__default['default'].error(error);
              consola__default['default'].error(`[HMR Error]: ${error}`);
            }
  
            if (!newItem) {
              // Full reload if HMR failed
              return this.nuxt.callHook('watch:restart', { event, path: fileName })
            }
  
            // Log
            consola__default['default'].info(`[HMR] ${chalk__default['default'].cyan(newItem.route || '/')} (${chalk__default['default'].grey(fileName)})`);
          }
          // Tree may be changed so recreate watcher
          this.serverMiddlewareHMR();
        }, 200),
        this.assignWatcher('serverMiddleware')
      );
    }
  
    watchRestart () {
      const nuxtRestartWatch = [
        // Custom watchers
        ...this.options.watch
      ].map(this.nuxt.resolver.resolveAlias);
  
      if (this.ignore.ignoreFile) {
        nuxtRestartWatch.push(this.ignore.ignoreFile);
      }
  
      if (this.options._envConfig && this.options._envConfig.dotenv) {
        nuxtRestartWatch.push(this.options._envConfig.dotenv);
      }
  
      // If default page displayed, watch for first page creation
      if (this._nuxtPages && this._defaultPage) {
        nuxtRestartWatch.push(path__default['default'].join(this.options.srcDir, this.options.dir.pages));
      }
      // If store not activated, watch for a file in the directory
      if (!this.options.store) {
        nuxtRestartWatch.push(path__default['default'].join(this.options.srcDir, this.options.dir.store));
      }
  
      this.createFileWatcher(
        nuxtRestartWatch,
        ['all'],
        async (event, fileName) => {
          if (['add', 'change', 'unlink'].includes(event) === false) {
            return
          }
          await this.nuxt.callHook('watch:fileChanged', this, fileName); // Legacy
          await this.nuxt.callHook('watch:restart', { event, path: fileName });
        },
        this.assignWatcher('restart')
      );
    }
  
    unwatch () {
      for (const watcher in this.watchers) {
        this.watchers[watcher].close();
      }
    }
  
    async close () {
      if (this.__closed) {
        return
      }
      this.__closed = true;
  
      // Unwatch
      this.unwatch();
  
      // Close bundleBuilder
      if (typeof this.bundleBuilder.close === 'function') {
        await this.bundleBuilder.close();
      }
    }
  }
  
  const STATUS = {
    INITIAL: 1,
    BUILD_DONE: 2,
    BUILDING: 3
  };
  
  function getBuilder (nuxt) {
    return new Builder(nuxt)
  }
  
  function build (nuxt) {
    return getBuilder(nuxt).build()
  }
  
  exports.Builder = Builder;
  exports.build = build;
  exports.getBuilder = getBuilder;
  