turbopack_core/
file_source.rs

1use anyhow::Result;
2use turbo_rcstr::RcStr;
3use turbo_tasks::{ResolvedVc, Vc};
4use turbo_tasks_fs::{FileContent, FileSystemEntryType, FileSystemPath, LinkContent};
5
6use crate::{
7    asset::{Asset, AssetContent},
8    ident::AssetIdent,
9    source::Source,
10};
11
12/// The raw [Source]. It represents raw content from a path without any
13/// references to other [Source]s.
14#[turbo_tasks::value]
15pub struct FileSource {
16    pub path: ResolvedVc<FileSystemPath>,
17    pub query: ResolvedVc<RcStr>,
18}
19
20#[turbo_tasks::value_impl]
21impl FileSource {
22    #[turbo_tasks::function]
23    pub fn new(path: ResolvedVc<FileSystemPath>) -> Vc<Self> {
24        Self::cell(FileSource {
25            path,
26            query: ResolvedVc::cell(RcStr::default()),
27        })
28    }
29
30    #[turbo_tasks::function]
31    pub async fn new_with_query(
32        path: ResolvedVc<FileSystemPath>,
33        query: ResolvedVc<RcStr>,
34    ) -> Result<Vc<Self>> {
35        if query.await?.is_empty() {
36            Ok(Self::new(*path))
37        } else {
38            Ok(Self::cell(FileSource { path, query }))
39        }
40    }
41}
42
43#[turbo_tasks::value_impl]
44impl Source for FileSource {
45    #[turbo_tasks::function]
46    fn ident(&self) -> Vc<AssetIdent> {
47        AssetIdent::from_path(*self.path).with_query(*self.query)
48    }
49}
50
51#[turbo_tasks::value_impl]
52impl Asset for FileSource {
53    #[turbo_tasks::function]
54    async fn content(&self) -> Result<Vc<AssetContent>> {
55        let file_type = &*self.path.get_type().await?;
56        match file_type {
57            FileSystemEntryType::Symlink => match &*self.path.read_link().await? {
58                LinkContent::Link { target, link_type } => Ok(AssetContent::Redirect {
59                    target: target.clone(),
60                    link_type: *link_type,
61                }
62                .cell()),
63                _ => Err(anyhow::anyhow!("Invalid symlink")),
64            },
65            FileSystemEntryType::File => {
66                Ok(AssetContent::File(self.path.read().to_resolved().await?).cell())
67            }
68            FileSystemEntryType::NotFound => {
69                Ok(AssetContent::File(FileContent::NotFound.resolved_cell()).cell())
70            }
71            _ => Err(anyhow::anyhow!("Invalid file type {:?}", file_type)),
72        }
73    }
74}