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 source_pos::SourcePos,
19};
20
21#[derive(PartialEq, Eq, ValueDebugFormat, TraceRawVcs, NonLocalValue)]
25pub struct PackageJson(ReadRef<FileJsonContent>);
26
27impl Deref for PackageJson {
28 type Target = JsonValue;
29 fn deref(&self) -> &Self::Target {
30 match &*self.0 {
31 FileJsonContent::Content(json) => json,
32 _ => unreachable!("PackageJson is guaranteed to hold Content"),
33 }
34 }
35}
36
37#[turbo_tasks::value(transparent, serialization = "none")]
38pub struct OptionPackageJson(Option<PackageJson>);
39
40#[turbo_tasks::function]
43pub async fn read_package_json(path: ResolvedVc<Box<dyn Source>>) -> Result<Vc<OptionPackageJson>> {
44 let read = path.content().parse_json().await?;
45 match &*read {
46 FileJsonContent::Content(_) => Ok(OptionPackageJson(Some(PackageJson(read))).cell()),
47 FileJsonContent::NotFound => Ok(OptionPackageJson(None).cell()),
48 FileJsonContent::Unparsable(e) => {
49 let error_message = RcStr::from(format!(
50 "package.json is not parseable: invalid JSON: {}",
51 e.message
52 ));
53
54 let source = match (e.start_location, e.end_location) {
55 (None, None) => IssueSource::from_source_only(path),
56 (Some((line, column)), None) | (None, Some((line, column))) => {
57 IssueSource::from_line_col(
58 path,
59 SourcePos { line, column },
60 SourcePos { line, column },
61 )
62 }
63 (Some((start_line, start_column)), Some((end_line, end_column))) => {
64 IssueSource::from_line_col(
65 path,
66 SourcePos {
67 line: start_line,
68 column: start_column,
69 },
70 SourcePos {
71 line: end_line,
72 column: end_column,
73 },
74 )
75 }
76 };
77 PackageJsonIssue {
78 error_message,
79 source,
80 }
81 .resolved_cell()
82 .emit();
83 Ok(OptionPackageJson(None).cell())
84 }
85 }
86}
87
88#[turbo_tasks::value(shared)]
90pub struct PackageJsonIssue {
91 pub error_message: RcStr,
92 pub source: IssueSource,
93}
94
95#[turbo_tasks::value_impl]
96impl Issue for PackageJsonIssue {
97 #[turbo_tasks::function]
98 fn title(&self) -> Vc<StyledString> {
99 StyledString::Text(rcstr!("Error parsing package.json file")).cell()
100 }
101
102 #[turbo_tasks::function]
103 fn stage(&self) -> Vc<IssueStage> {
104 IssueStage::Parse.cell()
105 }
106
107 #[turbo_tasks::function]
108 fn file_path(&self) -> Vc<FileSystemPath> {
109 self.source.file_path()
110 }
111
112 #[turbo_tasks::function]
113 fn description(&self) -> Vc<OptionStyledString> {
114 Vc::cell(Some(
115 StyledString::Text(self.error_message.clone()).resolved_cell(),
116 ))
117 }
118
119 #[turbo_tasks::function]
120 fn source(&self) -> Vc<OptionIssueSource> {
121 Vc::cell(Some(self.source))
122 }
123}