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