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}