/*!
 * @nuxt/core v2.16.0 (c) 2016-2023
 * Released under the MIT License
 * Repository: https://github.com/nuxt/nuxt.js
 * Website: https://nuxtjs.org
*/
'use strict';

const path = require('path');
const fs = require('fs');
const hash = require('hash-sum');
const consola = require('consola');
const utils = require('@nuxt/utils');
const lodash = require('lodash');
const Hookable = require('hable');
const config = require('@nuxt/config');
const server = require('@nuxt/server');
const fs$1 = require('fs-extra');

class ModuleContainer {
  constructor(nuxt) {
    this.nuxt = nuxt;
    this.options = nuxt.options;
    this.requiredModules = {};
    for (const method of Object.getOwnPropertyNames(ModuleContainer.prototype)) {
      if (typeof this[method] === "function") {
        this[method] = this[method].bind(this);
      }
    }
  }
  async ready() {
    await this.nuxt.callHook("modules:before", this, this.options.modules);
    if (this.options.buildModules && !this.options._start) {
      await utils.sequence(this.options.buildModules, this.addModule);
    }
    await utils.sequence(this.options.modules, this.addModule);
    await utils.sequence(this.options._modules, this.addModule);
    await this.nuxt.callHook("modules:done", this);
  }
  addVendor() {
    consola.warn("addVendor has been deprecated due to webpack4 optimization");
  }
  addTemplate(template) {
    if (!template) {
      throw new Error("Invalid template: " + JSON.stringify(template));
    }
    const src = template.src || template;
    const srcPath = path.parse(src);
    if (typeof src !== "string" || !fs.existsSync(src)) {
      throw new Error("Template src not found: " + src);
    }
    const fileName = template.fileName || template.filename;
    const dst = fileName || `${path.basename(srcPath.dir)}.${srcPath.name}.${hash(src)}${srcPath.ext}`;
    const templateObj = {
      src,
      dst,
      options: template.options
    };
    this.options.build.templates.push(templateObj);
    return templateObj;
  }
  addPlugin(template) {
    const { dst } = this.addTemplate(template);
    this.options.plugins.unshift({
      src: path.join(this.options.buildDir, dst),
      // TODO: remove deprecated option in Nuxt 3
      ssr: template.ssr,
      mode: template.mode
    });
  }
  addLayout(template, name) {
    const { dst, src } = this.addTemplate(template);
    const layoutName = name || path.parse(src).name;
    const layout = this.options.layouts[layoutName];
    if (layout) {
      consola.warn(`Duplicate layout registration, "${layoutName}" has been registered as "${layout}"`);
    }
    this.options.layouts[layoutName] = `./${dst}`;
    if (name === "error") {
      this.addErrorLayout(dst);
    }
  }
  addErrorLayout(dst) {
    const relativeBuildDir = path.relative(this.options.rootDir, this.options.buildDir);
    this.options.ErrorPage = `~/${relativeBuildDir}/${dst}`;
  }
  addServerMiddleware(middleware) {
    this.options.serverMiddleware.push(middleware);
  }
  extendBuild(fn) {
    this.options.build.extend = utils.chainFn(this.options.build.extend, fn);
  }
  extendRoutes(fn) {
    this.options.router.extendRoutes = utils.chainFn(
      this.options.router.extendRoutes,
      fn
    );
  }
  requireModule(moduleOpts, { paths } = {}) {
    return this.addModule(moduleOpts, void 0, { paths });
  }
  async addModule(moduleOpts, arg2, arg3) {
    const { paths } = { ...arg2, ...arg3 };
    let src;
    let options;
    let handler;
    if (typeof moduleOpts === "string" || typeof moduleOpts === "function") {
      src = moduleOpts;
    } else if (Array.isArray(moduleOpts)) {
      [src, options] = moduleOpts;
    } else if (typeof moduleOpts === "object") {
      ({ src, options, handler } = moduleOpts);
    }
    if (typeof src === "function") {
      handler = src;
    }
    if (this.options.buildModules.includes(handler) && this.options._start) {
      return;
    }
    if (!handler) {
      try {
        handler = this.nuxt.resolver.requireModule(src, { paths });
        try {
          (global.__NUXT_PATHS__ || []).push(this.nuxt.resolver.resolvePath(src, { paths }));
        } catch (_err) {
        }
      } catch (error) {
        if (error.code !== "MODULE_NOT_FOUND") {
          throw error;
        }
        if (error.message.includes(src) && !/^[~.]|^@\//.test(src)) {
          let message = "Module `{name}` not found.";
          if (this.options.buildModules.includes(src)) {
            message += " Please ensure `{name}` is in `devDependencies` and installed. HINT: During build step, for npm/yarn, `NODE_ENV=production` or `--production` should NOT be used.".replace("{name}", src);
          } else if (this.options.modules.includes(src)) {
            message += " Please ensure `{name}` is in `dependencies` and installed.";
          }
          message = message.replace(/{name}/g, src);
          consola.warn(message);
        }
        if (this.options._cli) {
          throw error;
        } else {
          consola.warn("Silently ignoring module as programatic usage detected.");
          return;
        }
      }
    }
    if (typeof handler !== "function") {
      throw new TypeError("Module should export a function: " + src);
    }
    const metaKey = handler.meta && handler.meta.name;
    const key = metaKey || src;
    if (typeof key === "string") {
      if (this.requiredModules[key]) {
        if (!metaKey) {
          consola.warn("Modules should be only specified once:", key);
        } else {
          return;
        }
      }
      this.requiredModules[key] = { src, options, handler };
    }
    if (options === void 0) {
      options = {};
    }
    const result = await handler.call(this, options);
    return result;
  }
}

var version = "2.16.0";

class Resolver {
  constructor(nuxt) {
    this.nuxt = nuxt;
    this.options = this.nuxt.options;
    this.resolvePath = this.resolvePath.bind(this);
    this.resolveAlias = this.resolveAlias.bind(this);
    this.resolveModule = this.resolveModule.bind(this);
    this.requireModule = this.requireModule.bind(this);
    this._createRequire = this.options.createRequire || utils.createRequire;
    this._require = this._createRequire(__filename);
  }
  resolveModule(path, { paths } = {}) {
    try {
      return this._require.resolve(path, {
        paths: [].concat(global.__NUXT_PREPATHS__ || [], paths || [], this.options.modulesDir, global.__NUXT_PATHS__ || [], process.cwd())
      });
    } catch (error) {
      if (error.code !== "MODULE_NOT_FOUND") {
        throw error;
      }
    }
  }
  resolveAlias(path$1) {
    if (utils.startsWithRootAlias(path$1)) {
      return path.join(this.options.rootDir, path$1.substr(2));
    }
    if (utils.startsWithSrcAlias(path$1)) {
      return path.join(this.options.srcDir, path$1.substr(1));
    }
    return path.resolve(this.options.srcDir, path$1);
  }
  resolvePath(path$1, { alias, isAlias = alias, module, isModule = module, isStyle, paths } = {}) {
    if (alias) {
      consola.warn("Using alias is deprecated and will be removed in Nuxt 3. Use `isAlias` instead.");
    }
    if (module) {
      consola.warn("Using module is deprecated and will be removed in Nuxt 3. Use `isModule` instead.");
    }
    if (fs$1.existsSync(path$1)) {
      return path$1;
    }
    let resolvedPath;
    if (isModule !== false) {
      resolvedPath = this.resolveModule(path$1, { paths });
    }
    if (!resolvedPath && isAlias !== false) {
      resolvedPath = this.resolveAlias(path$1);
    }
    if (!resolvedPath) {
      resolvedPath = path$1;
    }
    let isDirectory;
    if (fs$1.existsSync(resolvedPath)) {
      isDirectory = fs$1.lstatSync(resolvedPath).isDirectory();
      if (!isDirectory) {
        return resolvedPath;
      }
    }
    const extensions = isStyle ? this.options.styleExtensions : this.options.extensions;
    for (const ext of extensions) {
      if (!isDirectory && fs$1.existsSync(resolvedPath + "." + ext)) {
        return resolvedPath + "." + ext;
      }
      const resolvedPathwithIndex = path.join(resolvedPath, "index." + ext);
      if (isDirectory && fs$1.existsSync(resolvedPathwithIndex)) {
        return resolvedPathwithIndex;
      }
    }
    if (isDirectory) {
      return resolvedPath;
    }
    throw new Error(`Cannot resolve "${path$1}" from "${resolvedPath}"`);
  }
  requireModule(path, { alias, isAlias = alias, intropDefault, interopDefault = intropDefault, paths } = {}) {
    let resolvedPath = path;
    let requiredModule;
    if (intropDefault) {
      consola.warn("Using intropDefault is deprecated and will be removed in Nuxt 3. Use `interopDefault` instead.");
    }
    if (alias) {
      consola.warn("Using alias is deprecated and will be removed in Nuxt 3. Use `isAlias` instead.");
    }
    let lastError;
    try {
      resolvedPath = this.resolvePath(path, { isAlias, paths });
    } catch (e) {
      lastError = e;
    }
    const isExternal = utils.isExternalDependency(resolvedPath);
    if (this.options.dev && !isExternal) {
      utils.clearRequireCache(resolvedPath);
    }
    try {
      requiredModule = this._require(resolvedPath);
    } catch (e) {
      lastError = e;
    }
    if (interopDefault !== false && requiredModule && requiredModule.default) {
      requiredModule = requiredModule.default;
    }
    if (requiredModule === void 0 && lastError) {
      throw lastError;
    }
    return requiredModule;
  }
}

class Nuxt extends Hookable {
  constructor(options = {}) {
    super(consola);
    this.options = config.getNuxtConfig(options);
    this.resolver = new Resolver(this);
    this.moduleContainer = new ModuleContainer(this);
    this.deprecateHooks({
      // #3294 - 7514db73b25c23b8c14ebdafbb4e129ac282aabd
      "render:context": {
        to: "_render:context",
        message: "`render:context(nuxt)` is deprecated, Please use `vue-renderer:ssr:context(context)`"
      },
      // #3773
      "render:routeContext": {
        to: "_render:context",
        message: "`render:routeContext(nuxt)` is deprecated, Please use `vue-renderer:ssr:context(context)`"
      },
      showReady: "webpack:done",
      // Introduced in 2.13
      "export:done": "generate:done",
      "export:before": "generate:before",
      "export:extendRoutes": "generate:extendRoutes",
      "export:distRemoved": "generate:distRemoved",
      "export:distCopied": "generate:distCopied",
      "export:route": "generate:route",
      "export:routeFailed": "generate:routeFailed",
      "export:page": "generate:page",
      "export:routeCreated": "generate:routeCreated"
    });
    utils.defineAlias(this, this.resolver, ["resolveAlias", "resolvePath"]);
    this.showReady = () => {
      this.callHook("webpack:done");
    };
    if (this.options.server !== false) {
      this._initServer();
    }
    if (this.options._ready !== false) {
      this.ready().catch((err) => {
        consola.fatal(err);
      });
    }
  }
  static get version() {
    return `v${version}` + (global.__NUXT_DEV__ ? "-development" : "");
  }
  ready() {
    if (!this._ready) {
      this._ready = this._init();
    }
    return this._ready;
  }
  async _init() {
    if (this._initCalled) {
      return this;
    }
    this._initCalled = true;
    if (lodash.isPlainObject(this.options.hooks)) {
      this.addHooks(this.options.hooks);
    } else if (typeof this.options.hooks === "function") {
      this.options.hooks(this.hook);
    }
    await this.moduleContainer.ready();
    if (this.server) {
      await this.server.ready();
    }
    await this.callHook("ready", this);
    return this;
  }
  _initServer() {
    if (this.server) {
      return;
    }
    this.server = new server.Server(this);
    this.renderer = this.server;
    this.render = this.server.app;
    utils.defineAlias(this, this.server, ["renderRoute", "renderAndGetWindow", "listen"]);
  }
  async close(callback) {
    await this.callHook("close", this);
    if (typeof callback === "function") {
      await callback();
    }
    this.clearHooks();
  }
}

const OVERRIDES = {
  dry: { dev: false, server: false },
  dev: { dev: true, _build: true },
  build: { dev: false, server: false, _build: true },
  start: { dev: false, _start: true }
};
async function loadNuxt(loadOptions) {
  if (typeof loadOptions === "string") {
    loadOptions = { for: loadOptions };
  }
  const { ready = true } = loadOptions;
  const _for = loadOptions.for || "dry";
  const override = OVERRIDES[_for];
  if (!override) {
    throw new Error("Unsupported for: " + _for);
  }
  const config$1 = await config.loadNuxtConfig(loadOptions);
  Object.assign(config$1, override);
  const nuxt = new Nuxt(config$1);
  if (ready) {
    await nuxt.ready();
  }
  return nuxt;
}

Object.defineProperty(exports, 'loadNuxtConfig', {
  enumerable: true,
  get: function () { return config.loadNuxtConfig; }
});
exports.Module = ModuleContainer;
exports.Nuxt = Nuxt;
exports.Resolver = Resolver;
exports.loadNuxt = loadNuxt;
