import CJS_COMPAT_NODE_URL_fkaa0x0zihe from 'node:url';
import CJS_COMPAT_NODE_PATH_fkaa0x0zihe from 'node:path';
import CJS_COMPAT_NODE_MODULE_fkaa0x0zihe from "node:module";

var __filename = CJS_COMPAT_NODE_URL_fkaa0x0zihe.fileURLToPath(import.meta.url);
var __dirname = CJS_COMPAT_NODE_PATH_fkaa0x0zihe.dirname(__filename);
var require = CJS_COMPAT_NODE_MODULE_fkaa0x0zihe.createRequire(import.meta.url);

// ------------------------------------------------------------
// end of CJS compatibility banner, injected by Storybook's esbuild configuration
// ------------------------------------------------------------
import {
  basename,
  dirname,
  isAbsolute,
  join,
  normalize,
  resolve
} from "./chunk-QUBI53SI.js";

// src/core-server/mocking-utils/resolve.ts
import { readFileSync as readFileSync2, realpathSync } from "node:fs";
import { createRequire } from "node:module";
import { findMockRedirect } from "@vitest/mocker/redirect";

// ../node_modules/resolve.exports/dist/index.mjs
function e(e2, n2, r2) {
  throw new Error(r2 ? `No known conditions for "${n2}" specifier in "${e2}" package` : `Missing "${n2}" specifier in "${e2}" package`);
}
function n(n2, i, o2, f) {
  let s, u, l = r(n2, o2), c = (function(e2) {
    let n3 = /* @__PURE__ */ new Set(["default", ...e2.conditions || []]);
    return e2.unsafe || n3.add(e2.require ? "require" : "import"), e2.unsafe || n3.add(e2.browser ? "browser" : "node"), n3;
  })(f || {}), a = i[l];
  if (a === void 0) {
    let e2, n3, r2, t3;
    for (t3 in i) n3 && t3.length < n3.length || (t3[t3.length - 1] === "/" && l.startsWith(t3) ? (u = l.substring(t3.length), n3 = t3) : t3.length > 1 && (r2 = t3.indexOf("*", 1), ~r2 && (e2 = RegExp("^" + t3.substring(0, r2) + "(.*)" + t3.substring(1 + r2) + "$").exec(l), e2 && e2[1] && (u = e2[1], n3 = t3))));
    a = i[n3];
  }
  return a || e(n2, l), s = t(a, c), s || e(n2, l, 1), u && (function(e2, n3) {
    let r2, t3 = 0, i2 = e2.length, o3 = /[*]/g, f2 = /[/]$/;
    for (; t3 < i2; t3++) e2[t3] = o3.test(r2 = e2[t3]) ? r2.replace(o3, n3) : f2.test(r2) ? r2 + n3 : r2;
  })(s, u), s;
}
function r(e2, n2, r2) {
  if (e2 === n2 || n2 === ".") return ".";
  let t3 = e2 + "/", i = t3.length, o2 = n2.slice(0, i) === t3, f = o2 ? n2.slice(i) : n2;
  return f[0] === "#" ? f : o2 || !r2 ? f.slice(0, 2) === "./" ? f : "./" + f : f;
}
function t(e2, n2, r2) {
  if (e2) {
    if (typeof e2 == "string") return r2 && r2.add(e2), [e2];
    let i, o2;
    if (Array.isArray(e2)) {
      for (o2 = r2 || /* @__PURE__ */ new Set(), i = 0; i < e2.length; i++) t(e2[i], n2, o2);
      if (!r2 && o2.size) return [...o2];
    } else for (i in e2) if (n2.has(i)) return t(e2[i], n2, r2);
  }
}
function o(e2, r2, t3) {
  let i, o2 = e2.exports;
  if (o2) {
    if (typeof o2 == "string") o2 = { ".": o2 };
    else for (i in o2) {
      i[0] !== "." && (o2 = { ".": o2 });
      break;
    }
    return n(e2.name, o2, r2 || ".", t3);
  }
}

// src/core-server/mocking-utils/extract.ts
import { readFileSync } from "node:fs";
import { generate, parser, types as t2 } from "storybook/internal/babel";
import { logger } from "storybook/internal/node-logger";
import { telemetry } from "storybook/internal/telemetry";
import { transformSync } from "esbuild";

// ../node_modules/estree-walker/src/walker.js
var WalkerBase = class {
  constructor() {
    this.should_skip = !1, this.should_remove = !1, this.replacement = null, this.context = {
      skip: () => this.should_skip = !0,
      remove: () => this.should_remove = !0,
      replace: (node) => this.replacement = node
    };
  }
  /**
   * @template {Node} Parent
   * @param {Parent | null | undefined} parent
   * @param {keyof Parent | null | undefined} prop
   * @param {number | null | undefined} index
   * @param {Node} node
   */
  replace(parent, prop, index, node) {
    parent && prop && (index != null ? parent[prop][index] = node : parent[prop] = node);
  }
  /**
   * @template {Node} Parent
   * @param {Parent | null | undefined} parent
   * @param {keyof Parent | null | undefined} prop
   * @param {number | null | undefined} index
   */
  remove(parent, prop, index) {
    parent && prop && (index != null ? parent[prop].splice(index, 1) : delete parent[prop]);
  }
};

// ../node_modules/estree-walker/src/sync.js
var SyncWalker = class extends WalkerBase {
  /**
   *
   * @param {SyncHandler} [enter]
   * @param {SyncHandler} [leave]
   */
  constructor(enter, leave) {
    super(), this.should_skip = !1, this.should_remove = !1, this.replacement = null, this.context = {
      skip: () => this.should_skip = !0,
      remove: () => this.should_remove = !0,
      replace: (node) => this.replacement = node
    }, this.enter = enter, this.leave = leave;
  }
  /**
   * @template {Node} Parent
   * @param {Node} node
   * @param {Parent | null} parent
   * @param {keyof Parent} [prop]
   * @param {number | null} [index]
   * @returns {Node | null}
   */
  visit(node, parent, prop, index) {
    if (node) {
      if (this.enter) {
        let _should_skip = this.should_skip, _should_remove = this.should_remove, _replacement = this.replacement;
        this.should_skip = !1, this.should_remove = !1, this.replacement = null, this.enter.call(this.context, node, parent, prop, index), this.replacement && (node = this.replacement, this.replace(parent, prop, index, node)), this.should_remove && this.remove(parent, prop, index);
        let skipped = this.should_skip, removed = this.should_remove;
        if (this.should_skip = _should_skip, this.should_remove = _should_remove, this.replacement = _replacement, skipped) return node;
        if (removed) return null;
      }
      let key;
      for (key in node) {
        let value = node[key];
        if (value && typeof value == "object")
          if (Array.isArray(value)) {
            let nodes = (
              /** @type {Array<unknown>} */
              value
            );
            for (let i = 0; i < nodes.length; i += 1) {
              let item = nodes[i];
              isNode(item) && (this.visit(item, node, key, i) || i--);
            }
          } else isNode(value) && this.visit(value, node, key, null);
      }
      if (this.leave) {
        let _replacement = this.replacement, _should_remove = this.should_remove;
        this.replacement = null, this.should_remove = !1, this.leave.call(this.context, node, parent, prop, index), this.replacement && (node = this.replacement, this.replace(parent, prop, index, node)), this.should_remove && this.remove(parent, prop, index);
        let removed = this.should_remove;
        if (this.replacement = _replacement, this.should_remove = _should_remove, removed) return null;
      }
    }
    return node;
  }
};
function isNode(value) {
  return value !== null && typeof value == "object" && "type" in value && typeof value.type == "string";
}

// ../node_modules/estree-walker/src/index.js
function walk(ast, { enter, leave }) {
  return new SyncWalker(enter, leave).visit(ast, null);
}

// src/core-server/mocking-utils/extract.ts
var DEFAULT_MODULE_DIRECTORIES = ["/node_modules/"];
function isModuleDirectory(path) {
  let normalizedPath = normalize(path);
  return DEFAULT_MODULE_DIRECTORIES.some((dir) => normalizedPath.includes(dir));
}
var babelParser = (code) => parser.parse(code, {
  sourceType: "module",
  // Enable plugins to handle modern JavaScript features, including TSX.
  plugins: ["typescript", "jsx", "classProperties", "objectRestSpread"],
  errorRecovery: !0
}).program;
function rewriteSbMockImportCalls(code) {
  let ast = babelParser(code);
  return walk(ast, {
    enter(node) {
      node.type === "CallExpression" && node.callee.type === "MemberExpression" && node.callee.object.type === "Identifier" && node.callee.object.name === "sb" && node.callee.property.type === "Identifier" && node.callee.property.name === "mock" && node.arguments.length > 0 && node.arguments[0].type === "CallExpression" && node.arguments[0].callee.type === "Import" && node.arguments[0].arguments.length === 1 && node.arguments[0].arguments[0].type === "StringLiteral" && (node.arguments[0] = t2.stringLiteral(node.arguments[0].arguments[0].value));
    }
  }), generate(ast, {}, code);
}
function extractMockCalls(options, parse, root) {
  try {
    let hasSpyTrue2 = function(objectExpression) {
      if (!objectExpression || !objectExpression.properties)
        return !1;
      for (let prop of objectExpression.properties)
        if (prop.type === "ObjectProperty" && (prop.key.type === "Identifier" && prop.key.name === "spy" || prop.key.type === "StringLiteral" && prop.key.value === "spy") && prop.value.type === "BooleanLiteral" && prop.value.value === !0)
          return !0;
      return !1;
    };
    var hasSpyTrue = hasSpyTrue2;
    let previewConfigCode = readFileSync(options.previewConfigPath, "utf-8"), { code: jsCode } = transformSync(previewConfigCode, { loader: "tsx", format: "esm" }), ast = parse(jsCode), mocks = [];
    return walk(ast, {
      // @ts-expect-error - Node comes from babel
      async enter(node) {
        if (node.type !== "CallExpression" || node.callee.type !== "MemberExpression" || node.callee.object.type !== "Identifier" || node.callee.object.name !== "sb" || node.callee.property.type !== "Identifier" || node.callee.property.name !== "mock" || node.arguments.length === 0)
          return;
        let path;
        if (node.arguments[0].type === "StringLiteral")
          path = node.arguments[0].value;
        else if (node.arguments[0].type === "CallExpression" && node.arguments[0].callee.type === "Import" && node.arguments[0].arguments[0].type === "StringLiteral")
          path = node.arguments[0].arguments[0].value;
        else
          return;
        let spy = node.arguments.length > 1 && node.arguments[1].type === "ObjectExpression" && hasSpyTrue2(node.arguments[1]), { absolutePath, redirectPath } = resolveMock(path, root, options.previewConfigPath), pathWithoutExtension = path.replace(/\.[^/.]+$/, ""), basenameAbsolutePath = basename(absolutePath), basenamePath = basename(path), pathWithoutExtensionAndBasename = basenameAbsolutePath === basenamePath ? pathWithoutExtension : path;
        mocks.push({
          path: pathWithoutExtensionAndBasename,
          absolutePath,
          redirectPath,
          spy
        });
      }
    }), options.coreOptions?.disableTelemetry || telemetry(
      "mocking",
      {
        modulesMocked: mocks.length,
        modulesSpied: mocks.map((mock) => mock.spy).filter(Boolean).length,
        modulesManuallyMocked: mocks.map((mock) => !!mock.redirectPath).filter(Boolean).length
      },
      { configDir: options.configDir }
    ), mocks;
  } catch (error) {
    return logger.debug("Error extracting mock calls", error), [];
  }
}

// src/core-server/mocking-utils/resolve.ts
var require2 = createRequire(import.meta.url);
function findPackageJson(specifier, basedir) {
  let packageJsonPath = require2.resolve(`${specifier}/package.json`, { paths: [basedir] });
  return {
    path: packageJsonPath,
    data: JSON.parse(readFileSync2(packageJsonPath, "utf-8"))
  };
}
function resolveExternalModule(path, root) {
  let parts = path.split("/"), packageName = path.startsWith("@") ? `${parts[0]}/${parts[1]}` : parts[0], entry = `.${path.slice(packageName.length)}`, { path: packageJsonPath, data: pkg } = findPackageJson(packageName, root), packageDir = dirname(packageJsonPath);
  if (pkg.exports) {
    let result = o(pkg, entry, {
      browser: !0
    });
    if (result)
      return join(packageDir, result[0]);
  }
  return require2.resolve(path, { paths: [root] });
}
function getIsExternal(path, importer) {
  try {
    return !isAbsolute(path) && isModuleDirectory(require2.resolve(path, { paths: [importer] }));
  } catch {
    return !1;
  }
}
function resolveMock(path, root, importer) {
  let isExternal = getIsExternal(path, root), externalPath = isExternal ? path : null, absolutePath = isExternal ? resolveExternalModule(path, root) : require2.resolve(path, { paths: [dirname(importer)] }), normalizedAbsolutePath = resolve(absolutePath), redirectPath = findMockRedirect(root, normalizedAbsolutePath, externalPath);
  return {
    absolutePath: normalizedAbsolutePath,
    redirectPath
    // will be null if no __mocks__ file is found
  };
}
function getRealPath(path, preserveSymlinks) {
  try {
    return preserveSymlinks ? realpathSync(path) : path;
  } catch {
    return path;
  }
}
function resolveWithExtensions(path, from) {
  let extensions = [".js", ".ts", ".tsx", ".mjs", ".cjs", ".svelte", ".vue"];
  for (let extension of extensions)
    try {
      return require2.resolve(path + extension, { paths: [from] });
    } catch {
      continue;
    }
  return require2.resolve(path, { paths: [from] });
}

export {
  resolveExternalModule,
  getIsExternal,
  getRealPath,
  resolveWithExtensions,
  babelParser,
  rewriteSbMockImportCalls,
  extractMockCalls
};
