use crate::collector::HookCollect;
use crate::parse::PathData;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use swc_atoms::JsWord;
use swc_ecmascript::ast::CallExpr;
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum EntryStrategy {
Single,
Hook,
Component,
Smart,
Manual(Vec<Vec<String>>),
}
pub trait EntryPolicy {
fn get_entry_for_sym(
&self,
symbol_name: &str,
location: &PathData,
context: &[String],
analytics: &HookCollect,
expr: &CallExpr,
) -> Option<String>;
}
#[derive(Default)]
pub struct SingleStrategy {}
impl EntryPolicy for SingleStrategy {
fn get_entry_for_sym(
&self,
_symbol: &str,
_path: &PathData,
_context: &[String],
_analytics: &HookCollect,
_expr: &CallExpr,
) -> Option<String> {
Some("entry_hooks".to_string())
}
}
#[derive(Default)]
pub struct PerHookStrategy {}
impl EntryPolicy for PerHookStrategy {
fn get_entry_for_sym(
&self,
_symbol: &str,
_path: &PathData,
_context: &[String],
_analytics: &HookCollect,
_expr: &CallExpr,
) -> Option<String> {
None
}
}
#[derive(Default)]
pub struct PerComponentStrategy {}
impl EntryPolicy for PerComponentStrategy {
fn get_entry_for_sym(
&self,
_symbol: &str,
_path: &PathData,
context: &[String],
_analytics: &HookCollect,
_expr: &CallExpr,
) -> Option<String> {
if let Some(root) = context.first() {
Some(["entry_", root].concat())
} else {
Some("entry-fallback".to_string())
}
}
}
#[derive(Default)]
pub struct SmartStrategy {}
impl EntryPolicy for SmartStrategy {
fn get_entry_for_sym(
&self,
_symbol: &str,
_path: &PathData,
context: &[String],
_analytics: &HookCollect,
_expr: &CallExpr,
) -> Option<String> {
if context.iter().any(|h| h == "onMount") {
return Some("entry-server".to_string());
}
if let Some(root) = context.first() {
Some(["entry_", root].concat())
} else {
Some("entry-fallback".to_string())
}
}
}
pub struct ManualStrategy {
map: HashMap<String, JsWord>,
fallback: String,
}
impl ManualStrategy {
pub fn new(groups: &[Vec<String>]) -> Self {
let mut map: HashMap<String, JsWord> = HashMap::new();
for (count, group) in groups.iter().enumerate() {
let group_name = JsWord::from(format!("entry_{}", count));
for sym in group {
map.insert(sym.clone(), group_name.clone());
}
}
Self {
map,
fallback: "entry-fallback".to_string(),
}
}
}
impl EntryPolicy for ManualStrategy {
fn get_entry_for_sym(
&self,
symbol: &str,
_path: &PathData,
_context: &[String],
_analytics: &HookCollect,
_expr: &CallExpr,
) -> Option<String> {
let entry = self.map.get(symbol);
Some(match entry {
Some(val) => val.to_string(),
None => self.fallback.clone(),
})
}
}
pub fn parse_entry_strategy(strategy: &EntryStrategy) -> Box<dyn EntryPolicy> {
match strategy {
EntryStrategy::Single => Box::new(SingleStrategy::default()),
EntryStrategy::Hook => Box::new(PerHookStrategy::default()),
EntryStrategy::Component => Box::new(PerComponentStrategy::default()),
EntryStrategy::Smart => Box::new(SmartStrategy::default()),
EntryStrategy::Manual(ref groups) => Box::new(ManualStrategy::new(groups)),
}
}