lib_node_resolver/
errors.rs

1// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
2
3use std::borrow::Cow;
4use std::fmt::Write;
5use std::path::PathBuf;
6
7use boxed_error::Boxed;
8use thiserror::Error;
9use url::Url;
10
11use crate::NodeModuleKind;
12use crate::NodeResolutionMode;
13
14#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
15#[allow(non_camel_case_types)]
16pub enum NodeJsErrorCode {
17  ERR_INVALID_MODULE_SPECIFIER,
18  ERR_INVALID_PACKAGE_CONFIG,
19  ERR_INVALID_PACKAGE_TARGET,
20  ERR_MODULE_NOT_FOUND,
21  ERR_PACKAGE_IMPORT_NOT_DEFINED,
22  ERR_PACKAGE_PATH_NOT_EXPORTED,
23  ERR_UNKNOWN_FILE_EXTENSION,
24  ERR_UNSUPPORTED_DIR_IMPORT,
25  ERR_UNSUPPORTED_ESM_URL_SCHEME,
26  /// Deno specific since Node doesn't support TypeScript.
27  ERR_TYPES_NOT_FOUND,
28}
29
30impl std::fmt::Display for NodeJsErrorCode {
31  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32    write!(f, "{}", self.as_str())
33  }
34}
35
36impl NodeJsErrorCode {
37  pub fn as_str(&self) -> &'static str {
38    use NodeJsErrorCode::*;
39    match self {
40      ERR_INVALID_MODULE_SPECIFIER => "ERR_INVALID_MODULE_SPECIFIER",
41      ERR_INVALID_PACKAGE_CONFIG => "ERR_INVALID_PACKAGE_CONFIG",
42      ERR_INVALID_PACKAGE_TARGET => "ERR_INVALID_PACKAGE_TARGET",
43      ERR_MODULE_NOT_FOUND => "ERR_MODULE_NOT_FOUND",
44      ERR_PACKAGE_IMPORT_NOT_DEFINED => "ERR_PACKAGE_IMPORT_NOT_DEFINED",
45      ERR_PACKAGE_PATH_NOT_EXPORTED => "ERR_PACKAGE_PATH_NOT_EXPORTED",
46      ERR_UNKNOWN_FILE_EXTENSION => "ERR_UNKNOWN_FILE_EXTENSION",
47      ERR_UNSUPPORTED_DIR_IMPORT => "ERR_UNSUPPORTED_DIR_IMPORT",
48      ERR_UNSUPPORTED_ESM_URL_SCHEME => "ERR_UNSUPPORTED_ESM_URL_SCHEME",
49      ERR_TYPES_NOT_FOUND => "ERR_TYPES_NOT_FOUND",
50    }
51  }
52}
53
54pub trait NodeJsErrorCoded {
55  fn code(&self) -> NodeJsErrorCode;
56}
57
58// todo(https://github.com/denoland/deno_core/issues/810): make this a TypeError
59#[derive(Debug, Clone, Error)]
60#[error(
61  "[{}] Invalid module '{}' {}{}",
62  self.code(),
63  request,
64  reason,
65  maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default()
66)]
67pub struct InvalidModuleSpecifierError {
68  pub request: String,
69  pub reason: Cow<'static, str>,
70  pub maybe_referrer: Option<String>,
71}
72
73impl NodeJsErrorCoded for InvalidModuleSpecifierError {
74  fn code(&self) -> NodeJsErrorCode {
75    NodeJsErrorCode::ERR_INVALID_MODULE_SPECIFIER
76  }
77}
78
79#[derive(Debug, Boxed)]
80pub struct LegacyResolveError(pub Box<LegacyResolveErrorKind>);
81
82#[derive(Debug, Error)]
83pub enum LegacyResolveErrorKind {
84  #[error(transparent)]
85  TypesNotFound(#[from] TypesNotFoundError),
86  #[error(transparent)]
87  ModuleNotFound(#[from] ModuleNotFoundError),
88}
89
90impl NodeJsErrorCoded for LegacyResolveError {
91  fn code(&self) -> NodeJsErrorCode {
92    match self.as_kind() {
93      LegacyResolveErrorKind::TypesNotFound(e) => e.code(),
94      LegacyResolveErrorKind::ModuleNotFound(e) => e.code(),
95    }
96  }
97}
98
99#[derive(Debug, Error)]
100#[error(
101  "Could not find package '{}' from referrer '{}'{}.",
102  package_name,
103  referrer,
104  referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
105)]
106pub struct PackageNotFoundError {
107  pub package_name: String,
108  pub referrer: Url,
109  /// Extra information about the referrer.
110  pub referrer_extra: Option<String>,
111}
112
113impl NodeJsErrorCoded for PackageNotFoundError {
114  fn code(&self) -> NodeJsErrorCode {
115    NodeJsErrorCode::ERR_MODULE_NOT_FOUND
116  }
117}
118
119#[derive(Debug, Error)]
120#[error(
121  "Could not find referrer npm package '{}'{}.",
122  referrer,
123  referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
124)]
125pub struct ReferrerNotFoundError {
126  pub referrer: Url,
127  /// Extra information about the referrer.
128  pub referrer_extra: Option<String>,
129}
130
131impl NodeJsErrorCoded for ReferrerNotFoundError {
132  fn code(&self) -> NodeJsErrorCode {
133    NodeJsErrorCode::ERR_MODULE_NOT_FOUND
134  }
135}
136
137#[derive(Debug, Error)]
138#[error("Failed resolving '{package_name}' from referrer '{referrer}'.")]
139pub struct PackageFolderResolveIoError {
140  pub package_name: String,
141  pub referrer: Url,
142  #[source]
143  pub source: std::io::Error,
144}
145
146impl NodeJsErrorCoded for PackageFolderResolveIoError {
147  fn code(&self) -> NodeJsErrorCode {
148    NodeJsErrorCode::ERR_MODULE_NOT_FOUND
149  }
150}
151
152impl NodeJsErrorCoded for PackageFolderResolveError {
153  fn code(&self) -> NodeJsErrorCode {
154    match self.as_kind() {
155      PackageFolderResolveErrorKind::PackageNotFound(e) => e.code(),
156      PackageFolderResolveErrorKind::ReferrerNotFound(e) => e.code(),
157      PackageFolderResolveErrorKind::Io(e) => e.code(),
158    }
159  }
160}
161
162#[derive(Debug, Boxed)]
163pub struct PackageFolderResolveError(pub Box<PackageFolderResolveErrorKind>);
164
165#[derive(Debug, Error)]
166pub enum PackageFolderResolveErrorKind {
167  #[error(transparent)]
168  PackageNotFound(#[from] PackageNotFoundError),
169  #[error(transparent)]
170  ReferrerNotFound(#[from] ReferrerNotFoundError),
171  #[error(transparent)]
172  Io(#[from] PackageFolderResolveIoError),
173}
174
175impl NodeJsErrorCoded for PackageSubpathResolveError {
176  fn code(&self) -> NodeJsErrorCode {
177    match self.as_kind() {
178      PackageSubpathResolveErrorKind::PkgJsonLoad(e) => e.code(),
179      PackageSubpathResolveErrorKind::Exports(e) => e.code(),
180      PackageSubpathResolveErrorKind::LegacyResolve(e) => e.code(),
181    }
182  }
183}
184
185#[derive(Debug, Boxed)]
186pub struct PackageSubpathResolveError(pub Box<PackageSubpathResolveErrorKind>);
187
188#[derive(Debug, Error)]
189pub enum PackageSubpathResolveErrorKind {
190  #[error(transparent)]
191  PkgJsonLoad(#[from] PackageJsonLoadError),
192  #[error(transparent)]
193  Exports(PackageExportsResolveError),
194  #[error(transparent)]
195  LegacyResolve(LegacyResolveError),
196}
197
198#[derive(Debug, Error)]
199#[error(
200  "Target '{}' not found from '{}'{}{}.",
201  target,
202  pkg_json_path.display(),
203  maybe_referrer.as_ref().map(|r|
204    format!(
205      " from{} referrer {}",
206      match referrer_kind {
207        NodeModuleKind::Esm => "",
208        NodeModuleKind::Cjs => " cjs",
209      },
210      r
211    )
212  ).unwrap_or_default(),
213  match mode {
214    NodeResolutionMode::Execution => "",
215    NodeResolutionMode::Types => " for types",
216  }
217)]
218pub struct PackageTargetNotFoundError {
219  pub pkg_json_path: PathBuf,
220  pub target: String,
221  pub maybe_referrer: Option<Url>,
222  pub referrer_kind: NodeModuleKind,
223  pub mode: NodeResolutionMode,
224}
225
226impl NodeJsErrorCoded for PackageTargetNotFoundError {
227  fn code(&self) -> NodeJsErrorCode {
228    NodeJsErrorCode::ERR_MODULE_NOT_FOUND
229  }
230}
231
232impl NodeJsErrorCoded for PackageTargetResolveError {
233  fn code(&self) -> NodeJsErrorCode {
234    match self.as_kind() {
235      PackageTargetResolveErrorKind::NotFound(e) => e.code(),
236      PackageTargetResolveErrorKind::InvalidPackageTarget(e) => e.code(),
237      PackageTargetResolveErrorKind::InvalidModuleSpecifier(e) => e.code(),
238      PackageTargetResolveErrorKind::PackageResolve(e) => e.code(),
239      PackageTargetResolveErrorKind::TypesNotFound(e) => e.code(),
240    }
241  }
242}
243
244#[derive(Debug, Boxed)]
245pub struct PackageTargetResolveError(pub Box<PackageTargetResolveErrorKind>);
246
247#[derive(Debug, Error)]
248pub enum PackageTargetResolveErrorKind {
249  #[error(transparent)]
250  NotFound(#[from] PackageTargetNotFoundError),
251  #[error(transparent)]
252  InvalidPackageTarget(#[from] InvalidPackageTargetError),
253  #[error(transparent)]
254  InvalidModuleSpecifier(#[from] InvalidModuleSpecifierError),
255  #[error(transparent)]
256  PackageResolve(#[from] PackageResolveError),
257  #[error(transparent)]
258  TypesNotFound(#[from] TypesNotFoundError),
259}
260
261impl NodeJsErrorCoded for PackageExportsResolveError {
262  fn code(&self) -> NodeJsErrorCode {
263    match self.as_kind() {
264      PackageExportsResolveErrorKind::PackagePathNotExported(e) => e.code(),
265      PackageExportsResolveErrorKind::PackageTargetResolve(e) => e.code(),
266    }
267  }
268}
269
270#[derive(Debug, Boxed)]
271pub struct PackageExportsResolveError(pub Box<PackageExportsResolveErrorKind>);
272
273#[derive(Debug, Error)]
274pub enum PackageExportsResolveErrorKind {
275  #[error(transparent)]
276  PackagePathNotExported(#[from] PackagePathNotExportedError),
277  #[error(transparent)]
278  PackageTargetResolve(#[from] PackageTargetResolveError),
279}
280
281#[derive(Debug, Error)]
282#[error(
283    "[{}] Could not find types for '{}'{}",
284    self.code(),
285    self.0.code_specifier,
286    self.0.maybe_referrer.as_ref().map(|r| format!(" imported from '{}'", r)).unwrap_or_default(),
287  )]
288pub struct TypesNotFoundError(pub Box<TypesNotFoundErrorData>);
289
290#[derive(Debug)]
291pub struct TypesNotFoundErrorData {
292  pub code_specifier: Url,
293  pub maybe_referrer: Option<Url>,
294}
295
296impl NodeJsErrorCoded for TypesNotFoundError {
297  fn code(&self) -> NodeJsErrorCode {
298    NodeJsErrorCode::ERR_TYPES_NOT_FOUND
299  }
300}
301
302#[derive(Debug, Error)]
303#[error(
304  "[{}] Invalid package config. {}",
305  self.code(),
306  self.0
307)]
308pub struct PackageJsonLoadError(
309  #[source]
310  #[from]
311  pub deno_package_json::PackageJsonLoadError,
312);
313
314impl NodeJsErrorCoded for PackageJsonLoadError {
315  fn code(&self) -> NodeJsErrorCode {
316    NodeJsErrorCode::ERR_INVALID_PACKAGE_CONFIG
317  }
318}
319
320impl NodeJsErrorCoded for ClosestPkgJsonError {
321  fn code(&self) -> NodeJsErrorCode {
322    match self.as_kind() {
323      ClosestPkgJsonErrorKind::CanonicalizingDir(e) => e.code(),
324      ClosestPkgJsonErrorKind::Load(e) => e.code(),
325    }
326  }
327}
328
329#[derive(Debug, Boxed)]
330pub struct ClosestPkgJsonError(pub Box<ClosestPkgJsonErrorKind>);
331
332#[derive(Debug, Error)]
333pub enum ClosestPkgJsonErrorKind {
334  #[error(transparent)]
335  CanonicalizingDir(#[from] CanonicalizingPkgJsonDirError),
336  #[error(transparent)]
337  Load(#[from] PackageJsonLoadError),
338}
339
340#[derive(Debug, Error)]
341#[error("[{}] Failed canonicalizing package.json directory '{}'.", self.code(), dir_path.display())]
342pub struct CanonicalizingPkgJsonDirError {
343  pub dir_path: PathBuf,
344  #[source]
345  pub source: std::io::Error,
346}
347
348impl NodeJsErrorCoded for CanonicalizingPkgJsonDirError {
349  fn code(&self) -> NodeJsErrorCode {
350    NodeJsErrorCode::ERR_MODULE_NOT_FOUND
351  }
352}
353
354// todo(https://github.com/denoland/deno_core/issues/810): make this a TypeError
355#[derive(Debug, Error)]
356#[error(
357  "[{}] Package import specifier \"{}\" is not defined{}{}",
358  self.code(),
359  name,
360  package_json_path.as_ref().map(|p| format!(" in package {}", p.display())).unwrap_or_default(),
361  maybe_referrer.as_ref().map(|r| format!(" imported from '{}'", r)).unwrap_or_default(),
362)]
363pub struct PackageImportNotDefinedError {
364  pub name: String,
365  pub package_json_path: Option<PathBuf>,
366  pub maybe_referrer: Option<Url>,
367}
368
369impl NodeJsErrorCoded for PackageImportNotDefinedError {
370  fn code(&self) -> NodeJsErrorCode {
371    NodeJsErrorCode::ERR_PACKAGE_IMPORT_NOT_DEFINED
372  }
373}
374
375#[derive(Debug, Boxed)]
376pub struct PackageImportsResolveError(pub Box<PackageImportsResolveErrorKind>);
377
378#[derive(Debug, Error)]
379pub enum PackageImportsResolveErrorKind {
380  #[error(transparent)]
381  ClosestPkgJson(ClosestPkgJsonError),
382  #[error(transparent)]
383  InvalidModuleSpecifier(#[from] InvalidModuleSpecifierError),
384  #[error(transparent)]
385  NotDefined(#[from] PackageImportNotDefinedError),
386  #[error(transparent)]
387  Target(#[from] PackageTargetResolveError),
388}
389
390impl NodeJsErrorCoded for PackageImportsResolveErrorKind {
391  fn code(&self) -> NodeJsErrorCode {
392    match self {
393      Self::ClosestPkgJson(e) => e.code(),
394      Self::InvalidModuleSpecifier(e) => e.code(),
395      Self::NotDefined(e) => e.code(),
396      Self::Target(e) => e.code(),
397    }
398  }
399}
400
401impl NodeJsErrorCoded for PackageResolveError {
402  fn code(&self) -> NodeJsErrorCode {
403    match self.as_kind() {
404      PackageResolveErrorKind::ClosestPkgJson(e) => e.code(),
405      PackageResolveErrorKind::InvalidModuleSpecifier(e) => e.code(),
406      PackageResolveErrorKind::PackageFolderResolve(e) => e.code(),
407      PackageResolveErrorKind::ExportsResolve(e) => e.code(),
408      PackageResolveErrorKind::SubpathResolve(e) => e.code(),
409    }
410  }
411}
412
413#[derive(Debug, Boxed)]
414pub struct PackageResolveError(pub Box<PackageResolveErrorKind>);
415
416#[derive(Debug, Error)]
417pub enum PackageResolveErrorKind {
418  #[error(transparent)]
419  ClosestPkgJson(#[from] ClosestPkgJsonError),
420  #[error(transparent)]
421  InvalidModuleSpecifier(#[from] InvalidModuleSpecifierError),
422  #[error(transparent)]
423  PackageFolderResolve(#[from] PackageFolderResolveError),
424  #[error(transparent)]
425  ExportsResolve(#[from] PackageExportsResolveError),
426  #[error(transparent)]
427  SubpathResolve(#[from] PackageSubpathResolveError),
428}
429
430#[derive(Debug, Error)]
431#[error("Failed joining '{path}' from '{base}'.")]
432pub struct NodeResolveRelativeJoinError {
433  pub path: String,
434  pub base: Url,
435  #[source]
436  pub source: url::ParseError,
437}
438
439#[derive(Debug, Error)]
440#[error("Failed resolving specifier from data url referrer.")]
441pub struct DataUrlReferrerError {
442  #[source]
443  pub source: url::ParseError,
444}
445
446#[derive(Debug, Boxed)]
447pub struct NodeResolveError(pub Box<NodeResolveErrorKind>);
448
449#[derive(Debug, Error)]
450pub enum NodeResolveErrorKind {
451  #[error(transparent)]
452  RelativeJoin(#[from] NodeResolveRelativeJoinError),
453  #[error(transparent)]
454  PackageImportsResolve(#[from] PackageImportsResolveError),
455  #[error(transparent)]
456  UnsupportedEsmUrlScheme(#[from] UnsupportedEsmUrlSchemeError),
457  #[error(transparent)]
458  DataUrlReferrer(#[from] DataUrlReferrerError),
459  #[error(transparent)]
460  PackageResolve(#[from] PackageResolveError),
461  #[error(transparent)]
462  TypesNotFound(#[from] TypesNotFoundError),
463  #[error(transparent)]
464  FinalizeResolution(#[from] FinalizeResolutionError),
465}
466
467#[derive(Debug, Boxed)]
468pub struct FinalizeResolutionError(pub Box<FinalizeResolutionErrorKind>);
469
470#[derive(Debug, Error)]
471pub enum FinalizeResolutionErrorKind {
472  #[error(transparent)]
473  InvalidModuleSpecifierError(#[from] InvalidModuleSpecifierError),
474  #[error(transparent)]
475  ModuleNotFound(#[from] ModuleNotFoundError),
476  #[error(transparent)]
477  UnsupportedDirImport(#[from] UnsupportedDirImportError),
478}
479
480impl NodeJsErrorCoded for FinalizeResolutionError {
481  fn code(&self) -> NodeJsErrorCode {
482    match self.as_kind() {
483      FinalizeResolutionErrorKind::InvalidModuleSpecifierError(e) => e.code(),
484      FinalizeResolutionErrorKind::ModuleNotFound(e) => e.code(),
485      FinalizeResolutionErrorKind::UnsupportedDirImport(e) => e.code(),
486    }
487  }
488}
489
490#[derive(Debug, Error)]
491#[error(
492  "[{}] Cannot find {} '{}'{}",
493  self.code(),
494  typ,
495  specifier,
496  maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default()
497)]
498pub struct ModuleNotFoundError {
499  pub specifier: Url,
500  pub maybe_referrer: Option<Url>,
501  pub typ: &'static str,
502}
503
504impl NodeJsErrorCoded for ModuleNotFoundError {
505  fn code(&self) -> NodeJsErrorCode {
506    NodeJsErrorCode::ERR_MODULE_NOT_FOUND
507  }
508}
509
510#[derive(Debug, Error)]
511#[error(
512  "[{}] Directory import '{}' is not supported resolving ES modules{}",
513  self.code(),
514  dir_url,
515  maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default(),
516)]
517pub struct UnsupportedDirImportError {
518  pub dir_url: Url,
519  pub maybe_referrer: Option<Url>,
520}
521
522impl NodeJsErrorCoded for UnsupportedDirImportError {
523  fn code(&self) -> NodeJsErrorCode {
524    NodeJsErrorCode::ERR_UNSUPPORTED_DIR_IMPORT
525  }
526}
527
528#[derive(Debug)]
529pub struct InvalidPackageTargetError {
530  pub pkg_json_path: PathBuf,
531  pub sub_path: String,
532  pub target: String,
533  pub is_import: bool,
534  pub maybe_referrer: Option<Url>,
535}
536
537impl std::error::Error for InvalidPackageTargetError {}
538
539impl std::fmt::Display for InvalidPackageTargetError {
540  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
541    let rel_error = !self.is_import
542      && !self.target.is_empty()
543      && !self.target.starts_with("./");
544    f.write_char('[')?;
545    f.write_str(self.code().as_str())?;
546    f.write_char(']')?;
547
548    if self.sub_path == "." {
549      assert!(!self.is_import);
550      write!(
551        f,
552        " Invalid \"exports\" main target {} defined in the package config {}",
553        self.target,
554        self.pkg_json_path.display()
555      )?;
556    } else {
557      let ie = if self.is_import { "imports" } else { "exports" };
558      write!(
559        f,
560        " Invalid \"{}\" target {} defined for '{}' in the package config {}",
561        ie,
562        self.target,
563        self.sub_path,
564        self.pkg_json_path.display()
565      )?;
566    };
567
568    if let Some(referrer) = &self.maybe_referrer {
569      write!(f, " imported from '{}'", referrer)?;
570    }
571    if rel_error {
572      write!(f, "; target must start with \"./\"")?;
573    }
574    Ok(())
575  }
576}
577
578impl NodeJsErrorCoded for InvalidPackageTargetError {
579  fn code(&self) -> NodeJsErrorCode {
580    NodeJsErrorCode::ERR_INVALID_PACKAGE_TARGET
581  }
582}
583
584#[derive(Debug)]
585pub struct PackagePathNotExportedError {
586  pub pkg_json_path: PathBuf,
587  pub subpath: String,
588  pub maybe_referrer: Option<Url>,
589  pub mode: NodeResolutionMode,
590}
591
592impl NodeJsErrorCoded for PackagePathNotExportedError {
593  fn code(&self) -> NodeJsErrorCode {
594    NodeJsErrorCode::ERR_PACKAGE_PATH_NOT_EXPORTED
595  }
596}
597
598impl std::error::Error for PackagePathNotExportedError {}
599
600impl std::fmt::Display for PackagePathNotExportedError {
601  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
602    f.write_char('[')?;
603    f.write_str(self.code().as_str())?;
604    f.write_char(']')?;
605
606    let types_msg = match self.mode {
607      NodeResolutionMode::Execution => String::new(),
608      NodeResolutionMode::Types => " for types".to_string(),
609    };
610    if self.subpath == "." {
611      write!(
612        f,
613        " No \"exports\" main defined{} in '{}'",
614        types_msg,
615        self.pkg_json_path.display()
616      )?;
617    } else {
618      write!(
619        f,
620        " Package subpath '{}' is not defined{} by \"exports\" in '{}'",
621        self.subpath,
622        types_msg,
623        self.pkg_json_path.display()
624      )?;
625    };
626
627    if let Some(referrer) = &self.maybe_referrer {
628      write!(f, " imported from '{}'", referrer)?;
629    }
630    Ok(())
631  }
632}
633
634#[derive(Debug, Clone, Error)]
635#[error(
636  "[{}] Only file and data URLs are supported by the default ESM loader.{} Received protocol '{}'",
637  self.code(),
638  if cfg!(windows) && url_scheme.len() == 2 { " On Windows, absolute path must be valid file:// URLS."} else { "" },
639  url_scheme
640)]
641pub struct UnsupportedEsmUrlSchemeError {
642  pub url_scheme: String,
643}
644
645impl NodeJsErrorCoded for UnsupportedEsmUrlSchemeError {
646  fn code(&self) -> NodeJsErrorCode {
647    NodeJsErrorCode::ERR_UNSUPPORTED_ESM_URL_SCHEME
648  }
649}
650
651#[derive(Debug, Error)]
652pub enum ResolvePkgJsonBinExportError {
653  #[error(transparent)]
654  PkgJsonLoad(#[from] PackageJsonLoadError),
655  #[error("Failed resolving binary export. '{}' did not exist", pkg_json_path.display())]
656  MissingPkgJson { pkg_json_path: PathBuf },
657  #[error("Failed resolving binary export. {message}")]
658  InvalidBinProperty { message: String },
659}
660
661#[derive(Debug, Error)]
662pub enum ResolveBinaryCommandsError {
663  #[error(transparent)]
664  PkgJsonLoad(#[from] PackageJsonLoadError),
665  #[error("'{}' did not have a name", pkg_json_path.display())]
666  MissingPkgJsonName { pkg_json_path: PathBuf },
667}
668
669#[cfg(test)]
670mod test {
671  use super::*;
672
673  #[test]
674  fn types_resolution_package_path_not_exported() {
675    let separator_char = if cfg!(windows) { '\\' } else { '/' };
676    assert_eq!(
677      PackagePathNotExportedError {
678        pkg_json_path: PathBuf::from("test_path").join("package.json"),
679        subpath: "./jsx-runtime".to_string(), 
680        maybe_referrer: None,
681        mode: NodeResolutionMode::Types
682      }.to_string(),
683      format!("[ERR_PACKAGE_PATH_NOT_EXPORTED] Package subpath './jsx-runtime' is not defined for types by \"exports\" in 'test_path{separator_char}package.json'")
684    );
685    assert_eq!(
686      PackagePathNotExportedError {
687        pkg_json_path: PathBuf::from("test_path").join("package.json"),
688        subpath: ".".to_string(), 
689        maybe_referrer: None,
690        mode: NodeResolutionMode::Types
691      }.to_string(),
692      format!("[ERR_PACKAGE_PATH_NOT_EXPORTED] No \"exports\" main defined for types in 'test_path{separator_char}package.json'")
693    );
694  }
695}