Skip to main content

vite_static_shared/
lib.rs

1#![warn(clippy::pedantic)]
2
3use std::{borrow::Cow, collections::HashMap};
4
5use serde::{Deserialize, Serialize};
6
7pub mod parsing;
8
9/// Type of `.vite/manifest.json`.
10pub type ViteManifest<'a> = HashMap<Cow<'a, str>, ManifestChunk<'a>>;
11
12/// Dynamic boxed manifest.
13///
14/// Used as generic manifest to be plugged in integrations.
15///
16/// Created with [`Manifest::boxed()`] method.
17///
18/// ```rust
19/// MyViteManifest.boxed()
20/// ```
21pub type DynManifest<'a> = Box<dyn Manifest<'a> + Send + Sync>;
22
23/// Vite manifest chunk.
24///
25/// [See Vite documentation](https://vite.dev/guide/backend-integration)
26#[derive(Serialize, Deserialize, Clone, Default, Debug, PartialEq, Eq, Hash)]
27#[serde(rename_all = "camelCase")]
28pub struct ManifestChunk<'a> {
29    /// The key of this chunk in manifest.
30    ///
31    /// This field is added by `vite-static` and skipped during (de)serialization.
32    #[serde(skip)]
33    pub key: Cow<'a, str>,
34
35    /// The contents of manifest chunk.
36    ///
37    /// This field is added by `vite-static` and skipped during (de)serialization.
38    #[serde(skip)]
39    pub contents: Cow<'a, [u8]>,
40
41    /// [BLAKE3](https://github.com/BLAKE3-team/BLAKE3) hash of this chunk.
42    ///
43    /// BLAKE3 is used, because it's simple and fast.
44    ///
45    /// This field is added by `vite-static` and skipped during (de)serialization.
46    #[serde(skip)]
47    pub hash: Cow<'a, str>,
48
49    /// Mime type of this chunk.
50    ///
51    /// This field is added by `vite-static` and skipped during (de)serialization.
52    #[serde(skip)]
53    pub mime_type: Cow<'a, str>,
54
55    /// The input file name of this chunk/asset if known.
56    pub src: Option<Cow<'a, str>>,
57
58    /// The output file name of this chunk/asset.
59    pub file: Cow<'a, str>,
60
61    /// The list of CSS files imported by this chunk.
62    #[serde(default)]
63    pub css: Cow<'a, [Cow<'a, str>]>,
64
65    /// The list of asset files imported by this chunk, excluding CSS files.
66    #[serde(default)]
67    pub assets: Cow<'a, [Cow<'a, str>]>,
68
69    /// Whether this chunk or asset is an entry point
70    #[serde(default)]
71    pub is_entry: bool,
72
73    /// The name of this chunk/asset if known.
74    pub name: Option<Cow<'a, str>>,
75
76    /// Whether this chunk is a dynamic entry point
77    ///
78    /// This field is only present in JS chunks.
79    #[serde(default)]
80    pub is_dynamic_entry: bool,
81
82    /// The list of statically imported chunks by this chunk
83    ///
84    /// The values are the keys of the manifest. This field is only present in JS chunks.
85    #[serde(default)]
86    pub imports: Cow<'a, [Cow<'a, str>]>,
87
88    /// The list of dynamically imported chunks by this chunk
89    ///
90    /// The values are the keys of the manifest. This field is only present in JS chunks.
91    #[serde(default)]
92    pub dynamic_imports: Cow<'a, [Cow<'a, str>]>,
93}
94
95/// Trait, that helps query chunks in Vite manifest.
96///
97/// See [`Manifest` derive](https://docs.rs/vite-static/latest/vite_static/derive.Manifest.html)
98/// and [`ManifestChunk`].
99pub trait Manifest<'a> {
100    /// Returns generic boxed manifest.
101    ///
102    /// Usually used in integrations and functions, that require [`Manifest`].
103    fn boxed(&self) -> DynManifest<'a>;
104
105    /// Get base URL of [`Manifest`]. By default, it's `/`.
106    ///
107    /// Base URL - is an prefix before paths. This option is usually used in framework integrations
108    /// and `HtmlIntegration`.
109    fn base(&self) -> Cow<'a, str>;
110
111    /// Get `output_filename` from manifest key.
112    ///
113    /// ```rust
114    /// MyViteManifest.resolve_output("src/main.tsx") // returns "main.HASH.js"
115    /// ```
116    fn resolve_output(&self, key: &str) -> Option<Cow<'a, str>>;
117
118    /// Iterator over manifest keys (AKA input filenames, e.g. "src/main.tsx").
119    ///
120    /// ```rust
121    /// MyViteManifest.iter_keys()
122    /// // returns iterator over keys (e.g. "src/main.tsx", "src/component.tsx", ...)
123    /// ```
124    fn iter_keys(&self) -> Box<dyn Iterator<Item = &str> + '_>;
125
126    /// Iterator over manifest outputs (AKA output filenames, e.g. "main.HASH.js").
127    ///
128    /// ```rust
129    /// MyViteManifest.iter_outputs()
130    /// // returns iterator over output filenames (e.g. "main.HASH.js", "chunks/_shared.HASH.js", ...)
131    /// ```
132    fn iter_outputs(&self) -> Box<dyn Iterator<Item = &str> + '_>;
133
134    /// Get [`ManifestChunk`] from output filename.
135    ///
136    /// ```rust
137    /// dbg!(MyViteManifest.chunk("main.HASH.js"))
138    /// ```
139    fn chunk(&self, output: &str) -> Option<Cow<'a, ManifestChunk<'a>>>;
140
141    /// Get [`ManifestChunk`] from manifest key.
142    ///
143    /// ```rust
144    /// dbg!(MyViteManifest.chunk_by_key("src/main.tsx"))
145    /// ```
146    fn chunk_by_key(&self, key: &str) -> Option<Cow<'a, ManifestChunk<'a>>> {
147        match self.resolve_output(key) {
148            Some(output) => self.chunk(&output),
149            None => None,
150        }
151    }
152}