pnp/
manifest.rs

1use std::path::PathBuf;
2
3use rustc_hash::{FxHashMap, FxHashSet};
4use serde::{Deserialize, de::Deserializer};
5
6use crate::util::{RegexDef, Trie};
7
8#[derive(Clone, Debug, Deserialize)]
9#[serde(rename_all = "camelCase")]
10pub struct Manifest {
11    #[serde(skip_deserializing)]
12    pub manifest_dir: PathBuf,
13
14    #[serde(skip_deserializing)]
15    pub manifest_path: PathBuf,
16
17    #[serde(skip_deserializing)]
18    pub location_trie: Trie<PackageLocator>,
19
20    pub enable_top_level_fallback: bool,
21    pub ignore_pattern_data: Option<RegexDef>,
22
23    // dependencyTreeRoots: [{
24    //   "name": "@app/monorepo",
25    //   "workspace:."
26    // }]
27    pub dependency_tree_roots: FxHashSet<PackageLocator>,
28
29    // fallbackPool: [[
30    //   "@app/monorepo",
31    //   "workspace:.",
32    // ]]
33    #[serde(deserialize_with = "deserialize_package_dependencies")]
34    pub fallback_pool: FxHashMap<String, Option<PackageDependency>>,
35
36    // fallbackExclusionList: [[
37    //   "@app/server",
38    //  ["workspace:sources/server"],
39    // ]]
40    #[serde(deserialize_with = "deserialize_fallback_exclusion_list")]
41    pub fallback_exclusion_list: FxHashMap<String, FxHashSet<String>>,
42
43    // packageRegistryData: [
44    //   [null, [
45    //     [null, {
46    //       ...
47    //     }]
48    //   }]
49    // ]
50    #[serde(deserialize_with = "deserialize_package_registry_data")]
51    pub package_registry_data: FxHashMap<String, FxHashMap<String, PackageInformation>>,
52}
53
54#[derive(Clone, Debug, Default, Eq, PartialEq, Hash, Deserialize)]
55pub struct PackageLocator {
56    pub name: String,
57    pub reference: String,
58}
59
60#[derive(Clone, Debug, Deserialize)]
61#[serde(rename_all = "camelCase")]
62pub struct PackageInformation {
63    pub package_location: PathBuf,
64
65    #[serde(default)]
66    pub discard_from_lookup: bool,
67
68    #[serde(deserialize_with = "deserialize_package_dependencies")]
69    pub package_dependencies: FxHashMap<String, Option<PackageDependency>>,
70}
71
72#[derive(Clone, Debug, Deserialize)]
73#[serde(untagged)]
74pub enum PackageDependency {
75    Reference(String),
76    Alias(String, String),
77}
78
79fn deserialize_fallback_exclusion_list<'de, D>(
80    deserializer: D,
81) -> Result<FxHashMap<String, FxHashSet<String>>, D::Error>
82where
83    D: Deserializer<'de>,
84{
85    #[derive(Debug, Deserialize)]
86    struct Item(String, FxHashSet<String>);
87
88    let mut map = FxHashMap::default();
89    for item in Vec::<Item>::deserialize(deserializer)? {
90        map.insert(item.0, item.1);
91    }
92    Ok(map)
93}
94
95fn deserialize_package_dependencies<'de, D>(
96    deserializer: D,
97) -> Result<FxHashMap<String, Option<PackageDependency>>, D::Error>
98where
99    D: Deserializer<'de>,
100{
101    #[derive(Debug, Deserialize)]
102    struct Item(String, Option<PackageDependency>);
103
104    let mut map = FxHashMap::default();
105    for item in Vec::<Item>::deserialize(deserializer)? {
106        map.insert(item.0, item.1);
107    }
108    Ok(map)
109}
110
111fn deserialize_package_registry_data<'de, D>(
112    deserializer: D,
113) -> Result<FxHashMap<String, FxHashMap<String, PackageInformation>>, D::Error>
114where
115    D: Deserializer<'de>,
116{
117    #[derive(Debug, Deserialize)]
118    struct Item(Option<String>, Vec<(Option<String>, PackageInformation)>);
119
120    let mut map = FxHashMap::default();
121    for item in Vec::<Item>::deserialize(deserializer)? {
122        let key = item.0.unwrap_or_default();
123        let value =
124            FxHashMap::from_iter(item.1.into_iter().map(|(k, v)| (k.unwrap_or_default(), v)));
125        map.insert(key, value);
126    }
127    Ok(map)
128}