rspack_binding_api 0.101.2

Rspack shared binding API
Documentation
mod raw_snapshot;
mod raw_storage;

use core::panic;

use napi::{
  Either,
  bindgen_prelude::{FromNapiValue, JsObjectValue, Object, TypeName, ValidateNapiValue},
};
use napi_derive::napi;
use raw_snapshot::RawSnapshotOptions;
use raw_storage::RawStorageOptions;
use rspack_core::{CacheOptions, cache::persistent::PersistentCacheOptions};

#[derive(Debug)]
#[napi(object)]
pub struct RawCacheOptionsPersistent {
  pub build_dependencies: Option<Vec<String>>,
  pub version: Option<String>,
  pub max_age: u32,
  pub max_versions: u32,
  pub snapshot: Option<RawSnapshotOptions>,
  pub storage: Option<RawStorageOptions>,
  pub portable: Option<bool>,
  pub readonly: Option<bool>,
}

impl TryFrom<RawCacheOptionsPersistent> for PersistentCacheOptions {
  type Error = rspack_error::Error;

  fn try_from(value: RawCacheOptionsPersistent) -> rspack_error::Result<Self> {
    let storage = value.storage.unwrap_or_default().normalize()?;
    Ok(Self {
      build_dependencies: value
        .build_dependencies
        .unwrap_or_default()
        .into_iter()
        .map(Into::into)
        .collect(),
      version: value.version.unwrap_or_default(),
      snapshot: value.snapshot.unwrap_or_default().into(),
      storage,
      portable: value.portable.unwrap_or_default(),
      readonly: value.readonly.unwrap_or_default(),
      max_age: value.max_age.into(),
      max_versions: value.max_versions,
    })
  }
}

#[derive(Debug)]
#[napi(object)]
pub struct RawCacheOptionsMemory {
  pub max_generations: Option<u32>,
}

#[derive(Debug)]
pub enum InnerCacheOptions {
  Memory(RawCacheOptionsMemory),
  Persistent(RawCacheOptionsPersistent),
}

impl TypeName for InnerCacheOptions {
  fn type_name() -> &'static str {
    "InnerCacheOptions"
  }

  fn value_type() -> napi::ValueType {
    napi::ValueType::Object
  }
}

impl ValidateNapiValue for InnerCacheOptions {}

impl FromNapiValue for InnerCacheOptions {
  unsafe fn from_napi_value(
    env: napi::sys::napi_env,
    napi_val: napi::sys::napi_value,
  ) -> napi::Result<Self> {
    unsafe {
      let o = Object::from_napi_value(env, napi_val)?;
      let t = o.get_named_property::<String>("type")?;

      let v = match &*t {
        "persistent" => {
          let o = RawCacheOptionsPersistent::from_napi_value(env, napi_val)?;
          Self::Persistent(o)
        }
        "memory" => {
          let o = RawCacheOptionsMemory::from_napi_value(env, napi_val)?;
          Self::Memory(o)
        }
        _ => panic!("Unexpected cache type: {t}, expected 'persistent' or 'memory'"),
      };

      Ok(v)
    }
  }
}

pub type RawCacheOptions = Either<bool, InnerCacheOptions>;

pub fn normalize_raw_cache(options: RawCacheOptions) -> rspack_error::Result<CacheOptions> {
  Ok(match options {
    Either::A(options) => {
      if options {
        CacheOptions::Memory { max_generations: 1 }
      } else {
        CacheOptions::Disabled
      }
    }
    Either::B(options) => match options {
      InnerCacheOptions::Persistent(options) => CacheOptions::Persistent(options.try_into()?),
      InnerCacheOptions::Memory(options) => CacheOptions::Memory {
        max_generations: options.max_generations.unwrap_or(1),
      },
    },
  })
}