nodejs-resolver 0.1.1

nodejs resolve
Documentation
use super::Plugin;
use crate::{
    context::Context,
    description::DescriptionData,
    log::color,
    log::depth,
    map::{Field, ImportsField},
    Error, Info, PathKind, Resolver, State,
};

pub struct ImportsFieldPlugin<'a> {
    pkg_info: &'a DescriptionData,
}

impl<'a> ImportsFieldPlugin<'a> {
    pub fn new(pkg_info: &'a DescriptionData) -> Self {
        Self { pkg_info }
    }

    fn check_target(&self, resolver: &Resolver, info: Info) -> State {
        let path = info.to_resolved_path();
        if resolver.load_entry(&path).is_file() {
            if let Err(msg) = ImportsField::check_target(info.request().target()) {
                let msg = format!("{msg} in {:?}/package.json", &self.pkg_info.dir().as_ref());
                State::Error(Error::UnexpectedValue(msg))
            } else {
                State::Resolving(info)
            }
        } else {
            State::Error(Error::UnexpectedValue(format!(
                "Package path {} can't imported in {:?}",
                info.request().target(),
                info.normalized_path().as_ref()
            )))
        }
    }
}

impl<'a> Plugin for ImportsFieldPlugin<'a> {
    fn apply(&self, resolver: &Resolver, info: Info, context: &mut Context) -> State {
        if !info.request().target().starts_with('#') {
            return State::Resolving(info);
        }

        let root = match self.pkg_info.data().raw().get("imports") {
            Some(tree) => tree,
            None => return State::Resolving(info),
        };

        let list = match ImportsField::field_process(
            root,
            info.request().target(),
            &resolver.options.condition_names,
        ) {
            Ok(list) => list,
            Err(err) => return State::Error(err),
        };

        if let Some(item) = list.first() {
            tracing::debug!(
                "ImportsField in '{}' works, trigger by '{}', mapped to '{}'({})",
                color::blue(&format!("{:?}/package.json", self.pkg_info.dir().as_ref())),
                color::blue(&info.request().target()),
                color::blue(&item),
                depth(&context.depth)
            );
            let request = Resolver::parse(item);
            let is_relative = !matches!(request.kind(), PathKind::Normal | PathKind::Internal);
            let info = Info::from(self.pkg_info.dir().clone()).with_request(request);
            if is_relative {
                self.check_target(resolver, info)
            } else {
                let fully_specified = context.fully_specified.get();
                if fully_specified {
                    context.fully_specified.set(false);
                }
                let state = resolver._resolve(info, context);
                if fully_specified {
                    context.fully_specified.set(true);
                }
                state
            }
        } else {
            State::Error(Error::UnexpectedValue(format!(
                "Package path {} can't imported in {:?}",
                info.request().target(),
                info.normalized_path().as_ref()
            )))
        }
    }
}