turbopack_core/
package_json.rs1use std::ops::Deref;
2
3use anyhow::Result;
4use serde_json::Value as JsonValue;
5use turbo_rcstr::{RcStr, rcstr};
6use turbo_tasks::{
7 NonLocalValue, ReadRef, ResolvedVc, Vc, debug::ValueDebugFormat, trace::TraceRawVcs,
8};
9use turbo_tasks_fs::{FileJsonContent, FileSystemPath};
10
11use super::issue::Issue;
12use crate::{
13 asset::Asset,
14 issue::{
15 IssueExt, IssueSource, IssueStage, OptionIssueSource, OptionStyledString, StyledString,
16 },
17 source::Source,
18};
19
20#[derive(PartialEq, Eq, ValueDebugFormat, TraceRawVcs, NonLocalValue)]
24pub struct PackageJson(ReadRef<FileJsonContent>);
25
26impl Deref for PackageJson {
27 type Target = JsonValue;
28 fn deref(&self) -> &Self::Target {
29 match &*self.0 {
30 FileJsonContent::Content(json) => json,
31 _ => unreachable!("PackageJson is guaranteed to hold Content"),
32 }
33 }
34}
35
36#[turbo_tasks::value(transparent, serialization = "none")]
37pub struct OptionPackageJson(Option<PackageJson>);
38
39#[turbo_tasks::function]
42pub async fn read_package_json(path: ResolvedVc<Box<dyn Source>>) -> Result<Vc<OptionPackageJson>> {
43 let read = path.content().parse_json().await?;
44 match &*read {
45 FileJsonContent::Content(_) => Ok(OptionPackageJson(Some(PackageJson(read))).cell()),
46 FileJsonContent::NotFound => Ok(OptionPackageJson(None).cell()),
47 FileJsonContent::Unparsable(e) => {
48 let error_message = RcStr::from(format!(
49 "package.json is not parseable: invalid JSON: {}",
50 e.message
51 ));
52
53 let source = IssueSource::from_unparsable_json(path, e);
54 PackageJsonIssue {
55 error_message,
56 source,
57 }
58 .resolved_cell()
59 .emit();
60 Ok(OptionPackageJson(None).cell())
61 }
62 }
63}
64
65#[turbo_tasks::value(shared)]
67pub struct PackageJsonIssue {
68 pub error_message: RcStr,
69 pub source: IssueSource,
70}
71
72#[turbo_tasks::value_impl]
73impl Issue for PackageJsonIssue {
74 #[turbo_tasks::function]
75 fn title(&self) -> Vc<StyledString> {
76 StyledString::Text(rcstr!("Error parsing package.json file")).cell()
77 }
78
79 #[turbo_tasks::function]
80 fn stage(&self) -> Vc<IssueStage> {
81 IssueStage::Parse.cell()
82 }
83
84 #[turbo_tasks::function]
85 fn file_path(&self) -> Vc<FileSystemPath> {
86 self.source.file_path()
87 }
88
89 #[turbo_tasks::function]
90 fn description(&self) -> Vc<OptionStyledString> {
91 Vc::cell(Some(
92 StyledString::Text(self.error_message.clone()).resolved_cell(),
93 ))
94 }
95
96 #[turbo_tasks::function]
97 fn source(&self) -> Vc<OptionIssueSource> {
98 Vc::cell(Some(self.source))
99 }
100}