turbopack_core/
package_json.rs1use std::{fmt::Write, ops::Deref};
2
3use anyhow::Result;
4use serde_json::Value as JsonValue;
5use turbo_rcstr::RcStr;
6use turbo_tasks::{
7 NonLocalValue, ReadRef, ResolvedVc, Vc, debug::ValueDebugFormat, trace::TraceRawVcs,
8};
9use turbo_tasks_fs::{FileContent, FileJsonContent, FileSystemPath};
10
11use super::issue::Issue;
12use crate::issue::{IssueExt, IssueStage, OptionStyledString, StyledString};
13
14#[derive(PartialEq, Eq, ValueDebugFormat, TraceRawVcs, NonLocalValue)]
18pub struct PackageJson(ReadRef<FileJsonContent>);
19
20impl Deref for PackageJson {
21 type Target = JsonValue;
22 fn deref(&self) -> &Self::Target {
23 match &*self.0 {
24 FileJsonContent::Content(json) => json,
25 _ => unreachable!("PackageJson is guaranteed to hold Content"),
26 }
27 }
28}
29
30#[turbo_tasks::value(transparent, serialization = "none")]
31pub struct OptionPackageJson(Option<PackageJson>);
32
33#[turbo_tasks::function]
36pub async fn read_package_json(path: ResolvedVc<FileSystemPath>) -> Result<Vc<OptionPackageJson>> {
37 let read = path.read_json().await?;
38 match &*read {
39 FileJsonContent::Content(_) => Ok(OptionPackageJson(Some(PackageJson(read))).cell()),
40 FileJsonContent::NotFound => Ok(OptionPackageJson(None).cell()),
41 FileJsonContent::Unparseable(e) => {
42 let mut message = "package.json is not parseable: invalid JSON: ".to_string();
43 if let FileContent::Content(content) = &*path.read().await? {
44 let text = content.content().to_str()?;
45 e.write_with_content(&mut message, &text)?;
46 } else {
47 write!(message, "{e}")?;
48 }
49 PackageJsonIssue {
50 error_message: message.into(),
51 path,
52 }
53 .resolved_cell()
54 .emit();
55 Ok(OptionPackageJson(None).cell())
56 }
57 }
58}
59
60#[turbo_tasks::value(shared)]
62pub struct PackageJsonIssue {
63 pub path: ResolvedVc<FileSystemPath>,
64 pub error_message: RcStr,
65}
66
67#[turbo_tasks::value_impl]
68impl Issue for PackageJsonIssue {
69 #[turbo_tasks::function]
70 fn title(&self) -> Vc<StyledString> {
71 StyledString::Text("Error parsing package.json file".into()).cell()
72 }
73
74 #[turbo_tasks::function]
75 fn stage(&self) -> Vc<IssueStage> {
76 IssueStage::Parse.cell()
77 }
78
79 #[turbo_tasks::function]
80 fn file_path(&self) -> Vc<FileSystemPath> {
81 *self.path
82 }
83
84 #[turbo_tasks::function]
85 fn description(&self) -> Vc<OptionStyledString> {
86 Vc::cell(Some(
87 StyledString::Text(self.error_message.clone()).resolved_cell(),
88 ))
89 }
90}