'use strict';

var Module = require('node:module');
var vendor = require('./vendor.js');
var path = require('node:path');
var path$1 = require('../external/@socketsecurity/registry/lib/path');
var constants = require('./constants.js');
var utils = require('./utils.js');
var logger = require('../external/@socketsecurity/registry/lib/logger');
var registry = require('../external/@socketsecurity/registry');
var objects = require('../external/@socketsecurity/registry/lib/objects');

var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
let _arboristPkgPath;
function getArboristPackagePath() {
  if (_arboristPkgPath === undefined) {
    const pkgName = '@npmcli/arborist';
    const mainPathWithForwardSlashes = path$1.normalizePath(utils.getNpmRequire().resolve(pkgName));
    const arboristPkgPathWithForwardSlashes = mainPathWithForwardSlashes.slice(0, mainPathWithForwardSlashes.lastIndexOf(pkgName) + pkgName.length);
    // Lazily access constants.WIN32.
    _arboristPkgPath = constants.WIN32 ? path.normalize(arboristPkgPathWithForwardSlashes) : arboristPkgPathWithForwardSlashes;
  }
  return _arboristPkgPath;
}
let _arboristClassPath;
function getArboristClassPath() {
  if (_arboristClassPath === undefined) {
    _arboristClassPath = path.join(getArboristPackagePath(), 'lib/arborist/index.js');
  }
  return _arboristClassPath;
}
let _arboristEdgeClassPath;
function getArboristEdgeClassPath() {
  if (_arboristEdgeClassPath === undefined) {
    _arboristEdgeClassPath = path.join(getArboristPackagePath(), 'lib/edge.js');
  }
  return _arboristEdgeClassPath;
}
let _arboristNodeClassPath;
function getArboristNodeClassPath() {
  if (_arboristNodeClassPath === undefined) {
    _arboristNodeClassPath = path.join(getArboristPackagePath(), 'lib/node.js');
  }
  return _arboristNodeClassPath;
}
let _arboristOverrideSetClassPath;
function getArboristOverrideSetClassPath() {
  if (_arboristOverrideSetClassPath === undefined) {
    _arboristOverrideSetClassPath = path.join(getArboristPackagePath(), 'lib/override-set.js');
  }
  return _arboristOverrideSetClassPath;
}

const DiffAction = utils.createEnum({
  add: 'ADD',
  change: 'CHANGE',
  remove: 'REMOVE'
});

const {
  LOOP_SENTINEL,
  NPM: NPM$1,
  NPM_REGISTRY_URL
} = constants;
function getUrlOrigin(input) {
  try {
    // TODO: URL.parse is available in Node 22.1.0. We can use it when we drop Node 18.
    // https://nodejs.org/docs/latest-v22.x/api/url.html#urlparseinput-base
    // return URL.parse(input)?.origin ?? ''
    return new URL(input).origin ?? '';
  } catch {}
  return '';
}
function findBestPatchVersion(node, availableVersions, vulnerableVersionRange, _firstPatchedVersionIdentifier) {
  const manifestData = registry.getManifestData(NPM$1, node.name);
  let eligibleVersions;
  if (manifestData && manifestData.name === manifestData.package) {
    const major = utils.getMajor(manifestData.version);
    if (typeof major !== 'number') {
      return null;
    }
    eligibleVersions = availableVersions.filter(v => utils.getMajor(v) === major);
  } else {
    const major = utils.getMajor(node.version);
    if (typeof major !== 'number') {
      return null;
    }
    eligibleVersions = availableVersions.filter(v =>
    // Filter for versions that are within the current major version and
    // are NOT in the vulnerable range.
    utils.getMajor(v) === major && (!vulnerableVersionRange || !vendor.semverExports.satisfies(v, vulnerableVersionRange)));
  }
  return eligibleVersions ? vendor.semverExports.maxSatisfying(eligibleVersions, '*') : null;
}
function findPackageNode(tree, name, version) {
  const queue = [tree];
  const visited = new Set();
  let sentinel = 0;
  while (queue.length) {
    if (sentinel++ === LOOP_SENTINEL) {
      throw new Error('Detected infinite loop in findPackageNode');
    }
    const nodeOrLink = queue.pop();
    const node = getTargetNode(nodeOrLink);
    if (visited.has(node)) {
      continue;
    }
    visited.add(node);
    if (node.name === name && (typeof version !== 'string' || node.version === version)) {
      return node;
    }
    for (const child of node.children.values()) {
      queue.push(child);
    }
    for (const edge of node.edgesOut.values()) {
      const {
        to
      } = edge;
      if (to) {
        queue.push(to);
      }
    }
  }
  return undefined;
}
function findPackageNodes(tree, name, version) {
  const matches = [];
  const queue = [tree];
  const visited = new Set();
  let sentinel = 0;
  while (queue.length) {
    if (sentinel++ === LOOP_SENTINEL) {
      throw new Error('Detected infinite loop in findPackageNodes');
    }
    const nodeOrLink = queue.pop();
    const node = getTargetNode(nodeOrLink);
    if (visited.has(node)) {
      continue;
    }
    visited.add(node);
    if (node.name === name && ("undefined" !== 'string')) {
      matches.push(node);
    }
    for (const child of node.children.values()) {
      queue.push(child);
    }
    for (const edge of node.edgesOut.values()) {
      const {
        to
      } = edge;
      if (to) {
        queue.push(to);
      }
    }
  }
  return matches;
}
async function getAlertsMapFromArborist(arb, options_) {
  const options = {
    __proto__: null,
    consolidate: false,
    include: undefined,
    limit: Infinity,
    nothrow: false,
    ...options_
  };
  options.include = {
    __proto__: null,
    // Leave 'actions' unassigned so it can be given a default value in
    // subsequent functions where `options` is passed.
    // actions: undefined,
    blocked: true,
    critical: true,
    cve: true,
    existing: false,
    unfixable: true,
    upgradable: false,
    ...options.include
  };
  const needInfoOn = getDetailsFromDiff(arb.diff, {
    include: {
      unchanged: options.include.existing
    }
  });
  const purls = needInfoOn.map(d => utils.idToPurl(d.node.pkgid));
  let overrides;
  const overridesMap = (arb.actualTree ?? arb.idealTree ?? (await arb.loadActual()))?.overrides?.children;
  if (overridesMap) {
    overrides = Object.fromEntries([...overridesMap.entries()].map(([key, overrideSet]) => {
      return [key, overrideSet.value];
    }));
  }
  return await utils.getAlertsMapFromPurls(purls, {
    overrides,
    ...options
  });
}
function getDetailsFromDiff(diff_, options) {
  const details = [];
  // `diff_` is `null` when `npm install --package-lock-only` is passed.
  if (!diff_) {
    return details;
  }
  const include = {
    __proto__: null,
    unchanged: false,
    unknownOrigin: false,
    ...{
      __proto__: null,
      ...options
    }.include
  };
  const queue = [...diff_.children];
  let pos = 0;
  let {
    length: queueLength
  } = queue;
  while (pos < queueLength) {
    if (pos === LOOP_SENTINEL) {
      throw new Error('Detected infinite loop while walking Arborist diff');
    }
    const diff = queue[pos++];
    const {
      action
    } = diff;
    if (action) {
      // The `pkgNode`, i.e. the `ideal` node, will be `undefined` if the diff
      // action is 'REMOVE'
      // The `oldNode`, i.e. the `actual` node, will be `undefined` if the diff
      // action is 'ADD'.
      const {
        actual: oldNode,
        ideal: pkgNode
      } = diff;
      let existing;
      let keep = false;
      if (action === DiffAction.change) {
        if (pkgNode?.package.version !== oldNode?.package.version) {
          keep = true;
          if (oldNode?.package.name && oldNode.package.name === pkgNode?.package.name) {
            existing = oldNode;
          }
        }
      } else {
        keep = action !== DiffAction.remove;
      }
      if (keep && pkgNode?.resolved && (!oldNode || oldNode.resolved)) {
        if (include.unknownOrigin || getUrlOrigin(pkgNode.resolved) === NPM_REGISTRY_URL) {
          details.push({
            node: pkgNode,
            existing
          });
        }
      }
    }
    for (const child of diff.children) {
      queue[queueLength++] = child;
    }
  }
  if (include.unchanged) {
    const {
      unchanged
    } = diff_;
    for (let i = 0, {
        length
      } = unchanged; i < length; i += 1) {
      const pkgNode = unchanged[i];
      if (include.unknownOrigin || getUrlOrigin(pkgNode.resolved) === NPM_REGISTRY_URL) {
        details.push({
          node: pkgNode,
          existing: pkgNode
        });
      }
    }
  }
  return details;
}
function getTargetNode(nodeOrLink) {
  return nodeOrLink?.isLink ? nodeOrLink.target : nodeOrLink ?? null;
}
function isTopLevel(tree, node) {
  return getTargetNode(tree.children.get(node.name)) === node;
}
function updateNode(node, newVersion, newVersionPackument) {
  // Object.defineProperty is needed to set the version property and replace
  // the old value with newVersion.
  Object.defineProperty(node, 'version', {
    configurable: true,
    enumerable: true,
    get: () => newVersion
  });
  // Update package.version associated with the node.
  node.package.version = newVersion;
  // Update node.resolved.
  const purlObj = vendor.packageurlJsExports.PackageURL.fromString(utils.idToPurl(node.name));
  node.resolved = `${NPM_REGISTRY_URL}/${node.name}/-/${purlObj.name}-${newVersion}.tgz`;
  // Update node.integrity with the targetPackument.dist.integrity value if available
  // else delete node.integrity so a new value is resolved for the target version.
  const {
    integrity
  } = newVersionPackument.dist;
  if (integrity) {
    node.integrity = integrity;
  } else {
    delete node.integrity;
  }
  // Update node.package.deprecated based on targetPackument.deprecated.
  if (objects.hasOwn(newVersionPackument, 'deprecated')) {
    node.package['deprecated'] = newVersionPackument.deprecated;
  } else {
    delete node.package['deprecated'];
  }
  // Update node.package.dependencies.
  const newDeps = {
    ...newVersionPackument.dependencies
  };
  const {
    dependencies: oldDeps
  } = node.package;
  node.package.dependencies = newDeps;
  if (oldDeps) {
    for (const oldDepName of Object.keys(oldDeps)) {
      if (!objects.hasOwn(newDeps, oldDepName)) {
        // Detach old edges for dependencies that don't exist on the updated
        // node.package.dependencies.
        node.edgesOut.get(oldDepName)?.detach();
      }
    }
  }
  for (const newDepName of Object.keys(newDeps)) {
    if (!objects.hasOwn(oldDeps, newDepName)) {
      // Add new edges for dependencies that don't exist on the old
      // node.package.dependencies.
      node.addEdgeOut(new Edge({
        from: node,
        name: newDepName,
        spec: newDeps[newDepName],
        type: 'prod'
      }));
    }
  }
}
function updatePackageJsonFromNode(editablePkgJson, tree, node, newVersion, rangeStyle) {
  let result = false;
  if (!isTopLevel(tree, node)) {
    return result;
  }
  const {
    name
  } = node;
  for (const depField of ['dependencies', 'optionalDependencies', 'peerDependencies']) {
    const depObject = editablePkgJson.content[depField];
    const depValue = objects.hasOwn(depObject, name) ? depObject[name] : undefined;
    if (typeof depValue !== 'string' || depValue.startsWith('catalog:')) {
      continue;
    }
    let oldRange = depValue;
    // Use npa if depValue looks like more than just a semver range.
    if (depValue.includes(':')) {
      const npaResult = utils.npa(depValue);
      if (!npaResult || npaResult.subSpec) {
        continue;
      }
      oldRange = npaResult.rawSpec;
    }
    const oldMin = utils.getMinVersion(oldRange);
    const newRange = oldMin &&
    // Ensure we're on the same major version...
    utils.getMajor(newVersion) === oldMin.major &&
    // and not a downgrade.
    vendor.semverExports.gte(newVersion, oldMin.version) ? utils.applyRange(oldRange, newVersion, rangeStyle) : oldRange;
    if (oldRange !== newRange) {
      result = true;
      editablePkgJson.update({
        [depField]: {
          ...depObject,
          [name]: newRange
        }
      });
    }
  }
  return result;
}

// @ts-ignore
const {
  NPM,
  NPX,
  SOCKET_CLI_ACCEPT_RISKS,
  SOCKET_CLI_SAFE_BIN,
  SOCKET_CLI_SAFE_PROGRESS,
  SOCKET_CLI_VIEW_ALL_RISKS,
  kInternalsSymbol,
  [kInternalsSymbol]: {
    getIpc
  }
} = constants;
const SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES$1 = {
  __proto__: null,
  audit: false,
  dryRun: true,
  fund: false,
  ignoreScripts: true,
  progress: false,
  save: false,
  saveBundle: false,
  silent: true
};
const kCtorArgs = Symbol('ctorArgs');
const kRiskyReify = Symbol('riskyReify');
const Arborist = vendor.arboristExports;

// Implementation code not related to our custom behavior is based on
// https://github.com/npm/cli/blob/v11.0.0/workspaces/arborist/lib/arborist/index.js:
class SafeArborist extends Arborist {
  constructor(...ctorArgs) {
    super({
      path: (ctorArgs.length ? ctorArgs[0]?.path : undefined) ?? process.cwd(),
      ...(ctorArgs.length ? ctorArgs[0] : undefined),
      ...SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES$1
    }, ...ctorArgs.slice(1));
    this[kCtorArgs] = ctorArgs;
  }
  async [kRiskyReify](...args) {
    const ctorArgs = this[kCtorArgs];
    const arb = new Arborist({
      ...(ctorArgs.length ? ctorArgs[0] : undefined),
      progress: false
    }, ...ctorArgs.slice(1));
    const ret = await arb.reify({
      ...(args.length ? args[0] : undefined),
      progress: false
    }, ...args.slice(1));
    Object.assign(this, arb);
    return ret;
  }

  // @ts-ignore Incorrectly typed.
  async reify(...args) {
    const options = {
      __proto__: null,
      ...(args.length ? args[0] : undefined)
    };
    const ipc = await getIpc();
    const binName = ipc[SOCKET_CLI_SAFE_BIN];
    if (!binName) {
      return await this[kRiskyReify](...args);
    }
    await super.reify({
      ...options,
      ...SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES$1,
      progress: false
    },
    // @ts-ignore: TypeScript gets grumpy about rest parameters.
    ...args.slice(1));
    // Lazily access constants.ENV.SOCKET_CLI_ACCEPT_RISKS.
    const acceptRisks = constants.ENV.SOCKET_CLI_ACCEPT_RISKS;
    const progress = ipc[SOCKET_CLI_SAFE_PROGRESS];
    const spinner = options['silent'] || !progress ? undefined :
    // Lazily access constants.spinner.
    constants.spinner;
    const isSafeNpm = binName === NPM;
    const isSafeNpx = binName === NPX;
    const alertsMap = await getAlertsMapFromArborist(this, {
      spinner,
      include: acceptRisks || options.dryRun || options['yes'] ? {
        actions: ['error'],
        blocked: true,
        critical: false,
        cve: false,
        existing: true,
        unfixable: false
      } : {
        existing: isSafeNpx,
        unfixable: isSafeNpm
      }
    });
    if (alertsMap.size) {
      process.exitCode = 1;
      // Lazily access constants.ENV.SOCKET_CLI_VIEW_ALL_RISKS.
      const viewAllRisks = constants.ENV.SOCKET_CLI_VIEW_ALL_RISKS;
      utils.logAlertsMap(alertsMap, {
        hideAt: viewAllRisks ? 'none' : 'middle',
        output: process.stderr
      });
      throw new Error(`
          Socket ${binName} exiting due to risks.${viewAllRisks ? '' : `\nView all risks - Rerun with environment variable ${SOCKET_CLI_VIEW_ALL_RISKS}=1.`}${acceptRisks ? '' : `\nAccept risks - Rerun with environment variable ${SOCKET_CLI_ACCEPT_RISKS}=1.`}
        `.trim());
    } else if (!options['silent']) {
      logger.logger.success(`Socket ${binName} ${acceptRisks ? 'accepted' : 'found no'} risks`);
      if (binName === NPX) {
        logger.logger.log(`Running ${options.add[0]}`);
      }
    }
    return await this[kRiskyReify](...args);
  }
}

const require$1 =Module.createRequire(require('u' + 'rl').pathToFileURL(__filename).href)
const SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES = {
  __proto__: null,
  audit: false,
  dryRun: true,
  fund: false,
  ignoreScripts: true,
  progress: false,
  save: false,
  saveBundle: false,
  silent: true
};
const Edge = vendor.edgeExports;
const Node = vendor.nodeExports;
const OverrideSet = vendor.overrideSetExports;
function installSafeArborist() {
  // Override '@npmcli/arborist' module exports with patched variants based on
  // https://github.com/npm/cli/pull/8089.
  const cache = require$1.cache;
  cache[getArboristClassPath()] = {
    exports: SafeArborist
  };
  cache[getArboristEdgeClassPath()] = {
    exports: Edge
  };
  cache[getArboristNodeClassPath()] = {
    exports: Node
  };
  cache[getArboristOverrideSetClassPath()] = {
    exports: OverrideSet
  };
}

installSafeArborist();

exports.Arborist = Arborist;
exports.SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES = SAFE_ARBORIST_REIFY_OPTIONS_OVERRIDES;
exports.findBestPatchVersion = findBestPatchVersion;
exports.findPackageNode = findPackageNode;
exports.findPackageNodes = findPackageNodes;
exports.getAlertsMapFromArborist = getAlertsMapFromArborist;
exports.updateNode = updateNode;
exports.updatePackageJsonFromNode = updatePackageJsonFromNode;
//# debugId=9d71e592-e12c-4065-8fcf-e4295154e643
//# sourceMappingURL=shadow-inject.js.map
