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}