1use std::borrow::Cow;
4use std::fmt::Write;
5use std::path::PathBuf;
6
7use boxed_error::Boxed;
8use deno_error::JsError;
9use deno_path_util::UrlToFilePathError;
10use thiserror::Error;
11use url::Url;
12
13use crate::NodeResolutionKind;
14use crate::ResolutionMode;
15use crate::path::UrlOrPath;
16
17#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
18#[allow(non_camel_case_types)]
19pub enum NodeJsErrorCode {
20 ERR_INVALID_MODULE_SPECIFIER,
21 ERR_INVALID_PACKAGE_CONFIG,
22 ERR_INVALID_PACKAGE_TARGET,
23 ERR_MODULE_NOT_FOUND,
24 ERR_PACKAGE_IMPORT_NOT_DEFINED,
25 ERR_PACKAGE_PATH_NOT_EXPORTED,
26 ERR_UNKNOWN_FILE_EXTENSION,
27 ERR_UNSUPPORTED_DIR_IMPORT,
28 ERR_UNSUPPORTED_ESM_URL_SCHEME,
29 ERR_INVALID_FILE_URL_PATH,
30 ERR_UNKNOWN_BUILTIN_MODULE,
31 ERR_TYPES_NOT_FOUND,
33}
34
35impl std::fmt::Display for NodeJsErrorCode {
36 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37 write!(f, "{}", self.as_str())
38 }
39}
40
41impl NodeJsErrorCode {
42 pub fn as_str(&self) -> &'static str {
43 use NodeJsErrorCode::*;
44 match self {
45 ERR_INVALID_MODULE_SPECIFIER => "ERR_INVALID_MODULE_SPECIFIER",
46 ERR_INVALID_PACKAGE_CONFIG => "ERR_INVALID_PACKAGE_CONFIG",
47 ERR_INVALID_PACKAGE_TARGET => "ERR_INVALID_PACKAGE_TARGET",
48 ERR_MODULE_NOT_FOUND => "ERR_MODULE_NOT_FOUND",
49 ERR_PACKAGE_IMPORT_NOT_DEFINED => "ERR_PACKAGE_IMPORT_NOT_DEFINED",
50 ERR_PACKAGE_PATH_NOT_EXPORTED => "ERR_PACKAGE_PATH_NOT_EXPORTED",
51 ERR_UNKNOWN_FILE_EXTENSION => "ERR_UNKNOWN_FILE_EXTENSION",
52 ERR_UNSUPPORTED_DIR_IMPORT => "ERR_UNSUPPORTED_DIR_IMPORT",
53 ERR_UNSUPPORTED_ESM_URL_SCHEME => "ERR_UNSUPPORTED_ESM_URL_SCHEME",
54 ERR_TYPES_NOT_FOUND => "ERR_TYPES_NOT_FOUND",
55 ERR_INVALID_FILE_URL_PATH => "ERR_INVALID_FILE_URL_PATH",
56 ERR_UNKNOWN_BUILTIN_MODULE => "ERR_UNKNOWN_BUILTIN_MODULE",
57 }
58 }
59}
60
61impl From<NodeJsErrorCode> for deno_error::PropertyValue {
62 fn from(value: NodeJsErrorCode) -> Self {
63 deno_error::PropertyValue::String(value.as_str().into())
64 }
65}
66
67pub trait NodeJsErrorCoded {
68 fn code(&self) -> NodeJsErrorCode;
69}
70
71#[derive(Debug, Clone, Error, JsError)]
72#[error(
73 "[{}] Invalid module '{}' {}{}",
74 self.code(),
75 request,
76 reason,
77 maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default()
78)]
79#[class(type)]
80#[property("code" = self.code())]
81pub struct InvalidModuleSpecifierError {
82 pub request: String,
83 pub reason: Cow<'static, str>,
84 pub maybe_referrer: Option<String>,
85}
86
87impl NodeJsErrorCoded for InvalidModuleSpecifierError {
88 fn code(&self) -> NodeJsErrorCode {
89 NodeJsErrorCode::ERR_INVALID_MODULE_SPECIFIER
90 }
91}
92
93#[derive(Debug, Boxed, JsError)]
94pub struct LegacyResolveError(pub Box<LegacyResolveErrorKind>);
95
96impl LegacyResolveError {
97 pub fn specifier(&self) -> &UrlOrPath {
98 match self.as_kind() {
99 LegacyResolveErrorKind::TypesNotFound(err) => &err.0.code_specifier,
100 LegacyResolveErrorKind::ModuleNotFound(err) => &err.specifier,
101 }
102 }
103}
104
105#[derive(Debug, Error, JsError)]
106pub enum LegacyResolveErrorKind {
107 #[class(inherit)]
108 #[error(transparent)]
109 TypesNotFound(#[from] TypesNotFoundError),
110 #[class(inherit)]
111 #[error(transparent)]
112 ModuleNotFound(#[from] ModuleNotFoundError),
113}
114
115impl NodeJsErrorCoded for LegacyResolveError {
116 fn code(&self) -> NodeJsErrorCode {
117 match self.as_kind() {
118 LegacyResolveErrorKind::TypesNotFound(e) => e.code(),
119 LegacyResolveErrorKind::ModuleNotFound(e) => e.code(),
120 }
121 }
122}
123
124#[derive(Debug, Error, JsError)]
125#[error(
126 "Could not find package '{}' from referrer '{}'{}.",
127 package_name,
128 referrer,
129 referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
130)]
131#[class(generic)]
132#[property("code" = self.code())]
133pub struct PackageNotFoundError {
134 pub package_name: String,
135 pub referrer: UrlOrPath,
136 pub referrer_extra: Option<String>,
138}
139
140impl NodeJsErrorCoded for PackageNotFoundError {
141 fn code(&self) -> NodeJsErrorCode {
142 NodeJsErrorCode::ERR_MODULE_NOT_FOUND
143 }
144}
145
146#[derive(Debug, Error, JsError)]
147#[error(
148 "Could not find referrer npm package '{}'{}.",
149 referrer,
150 referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
151)]
152#[class(generic)]
153#[property("code" = self.code())]
154pub struct ReferrerNotFoundError {
155 pub referrer: UrlOrPath,
156 pub referrer_extra: Option<String>,
158}
159
160impl NodeJsErrorCoded for ReferrerNotFoundError {
161 fn code(&self) -> NodeJsErrorCode {
162 NodeJsErrorCode::ERR_MODULE_NOT_FOUND
163 }
164}
165
166#[derive(Debug, Error, JsError)]
167#[class(inherit)]
168#[error("Failed resolving '{package_name}' from referrer '{referrer}'.")]
169#[property("code" = self.code())]
170pub struct PackageFolderResolveIoError {
171 pub package_name: String,
172 pub referrer: UrlOrPath,
173 #[source]
174 #[inherit]
175 pub source: std::io::Error,
176}
177
178impl NodeJsErrorCoded for PackageFolderResolveIoError {
179 fn code(&self) -> NodeJsErrorCode {
180 NodeJsErrorCode::ERR_MODULE_NOT_FOUND
181 }
182}
183
184impl NodeJsErrorCoded for PackageFolderResolveErrorKind {
185 fn code(&self) -> NodeJsErrorCode {
186 match self {
187 PackageFolderResolveErrorKind::PackageNotFound(e) => e.code(),
188 PackageFolderResolveErrorKind::ReferrerNotFound(e) => e.code(),
189 PackageFolderResolveErrorKind::Io(e) => e.code(),
190 PackageFolderResolveErrorKind::PathToUrl(_) => {
191 NodeJsErrorCode::ERR_INVALID_FILE_URL_PATH
192 }
193 }
194 }
195}
196
197#[derive(Debug, Boxed, JsError)]
198pub struct PackageFolderResolveError(pub Box<PackageFolderResolveErrorKind>);
199
200#[derive(Debug, Error, JsError)]
201pub enum PackageFolderResolveErrorKind {
202 #[class(inherit)]
203 #[error(transparent)]
204 PackageNotFound(#[from] PackageNotFoundError),
205 #[class(inherit)]
206 #[error(transparent)]
207 ReferrerNotFound(#[from] ReferrerNotFoundError),
208 #[class(inherit)]
209 #[error(transparent)]
210 Io(#[from] PackageFolderResolveIoError),
211 #[class(inherit)]
212 #[error(transparent)]
213 #[property("code" = self.code())]
214 PathToUrl(#[from] deno_path_util::PathToUrlError),
215}
216
217#[derive(Debug, Boxed, JsError)]
218pub struct PackageSubpathFromDenoModuleResolveError(
219 pub Box<PackageSubpathFromDenoModuleResolveErrorKind>,
220);
221
222impl NodeJsErrorCoded for PackageSubpathFromDenoModuleResolveError {
223 fn code(&self) -> NodeJsErrorCode {
224 match self.as_kind() {
225 PackageSubpathFromDenoModuleResolveErrorKind::SubPath(e) => e.code(),
226 PackageSubpathFromDenoModuleResolveErrorKind::FinalizeResolution(e) => {
227 e.code()
228 }
229 }
230 }
231}
232
233impl PackageSubpathFromDenoModuleResolveError {
234 pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
235 match self.as_kind() {
236 PackageSubpathFromDenoModuleResolveErrorKind::SubPath(e) => {
237 e.as_types_not_found()
238 }
239 PackageSubpathFromDenoModuleResolveErrorKind::FinalizeResolution(e) => {
240 e.as_types_not_found()
241 }
242 }
243 }
244
245 pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
246 match self.as_kind() {
247 PackageSubpathFromDenoModuleResolveErrorKind::SubPath(e) => {
248 e.maybe_specifier()
249 }
250 PackageSubpathFromDenoModuleResolveErrorKind::FinalizeResolution(e) => {
251 e.maybe_specifier()
252 }
253 }
254 }
255
256 pub fn into_node_resolve_error(self) -> NodeResolveError {
257 match self.into_kind() {
258 PackageSubpathFromDenoModuleResolveErrorKind::SubPath(e) => {
259 NodeResolveErrorKind::PackageResolve(
260 PackageResolveErrorKind::SubpathResolve(e).into_box(),
261 )
262 }
263 PackageSubpathFromDenoModuleResolveErrorKind::FinalizeResolution(e) => {
264 NodeResolveErrorKind::FinalizeResolution(e)
265 }
266 }
267 .into_box()
268 }
269}
270
271#[derive(Debug, Error, JsError)]
272pub enum PackageSubpathFromDenoModuleResolveErrorKind {
273 #[class(inherit)]
274 #[error(transparent)]
275 SubPath(#[from] PackageSubpathResolveError),
276 #[class(inherit)]
277 #[error(transparent)]
278 FinalizeResolution(#[from] FinalizeResolutionError),
279}
280
281#[derive(Debug, Boxed, JsError)]
282pub struct PackageSubpathResolveError(pub Box<PackageSubpathResolveErrorKind>);
283
284impl NodeJsErrorCoded for PackageSubpathResolveError {
285 fn code(&self) -> NodeJsErrorCode {
286 match self.as_kind() {
287 PackageSubpathResolveErrorKind::PkgJsonLoad(e) => e.code(),
288 PackageSubpathResolveErrorKind::Exports(e) => e.code(),
289 PackageSubpathResolveErrorKind::LegacyResolve(e) => e.code(),
290 }
291 }
292}
293
294impl PackageSubpathResolveError {
295 pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
296 self.as_kind().as_types_not_found()
297 }
298
299 pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
300 match self.as_kind() {
301 PackageSubpathResolveErrorKind::PkgJsonLoad(_) => None,
302 PackageSubpathResolveErrorKind::Exports(err) => err.maybe_specifier(),
303 PackageSubpathResolveErrorKind::LegacyResolve(err) => {
304 Some(Cow::Borrowed(err.specifier()))
305 }
306 }
307 }
308}
309
310#[derive(Debug, Error, JsError)]
311pub enum PackageSubpathResolveErrorKind {
312 #[class(inherit)]
313 #[error(transparent)]
314 PkgJsonLoad(#[from] PackageJsonLoadError),
315 #[class(inherit)]
316 #[error(transparent)]
317 Exports(PackageExportsResolveError),
318 #[class(inherit)]
319 #[error(transparent)]
320 LegacyResolve(LegacyResolveError),
321}
322
323impl PackageSubpathResolveErrorKind {
324 pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
325 match self {
326 PackageSubpathResolveErrorKind::PkgJsonLoad(_) => None,
327 PackageSubpathResolveErrorKind::Exports(err) => match err.as_kind() {
328 PackageExportsResolveErrorKind::PackagePathNotExported(_) => None,
329 PackageExportsResolveErrorKind::PackageTargetResolve(err) => {
330 match err.as_kind() {
331 PackageTargetResolveErrorKind::TypesNotFound(not_found) => {
332 Some(not_found)
333 }
334 PackageTargetResolveErrorKind::NotFound(_)
335 | PackageTargetResolveErrorKind::InvalidPackageTarget(_)
336 | PackageTargetResolveErrorKind::InvalidModuleSpecifier(_)
337 | PackageTargetResolveErrorKind::PackageResolve(_)
338 | PackageTargetResolveErrorKind::UnknownBuiltInNodeModule(_)
339 | PackageTargetResolveErrorKind::UrlToFilePath(_) => None,
340 }
341 }
342 },
343 PackageSubpathResolveErrorKind::LegacyResolve(err) => match err.as_kind()
344 {
345 LegacyResolveErrorKind::TypesNotFound(not_found) => Some(not_found),
346 LegacyResolveErrorKind::ModuleNotFound(_) => None,
347 },
348 }
349 }
350}
351
352#[derive(Debug, Error, JsError)]
353#[class(generic)]
354#[error(
355 "Target '{}' not found from '{}'{}{}.",
356 target,
357 pkg_json_path.display(),
358 maybe_referrer.as_ref().map(|r|
359 format!(
360 " from{} referrer {}",
361 match resolution_mode {
362 ResolutionMode::Import => "",
363 ResolutionMode::Require => " cjs",
364 },
365 r
366 )
367 ).unwrap_or_default(),
368 match resolution_kind {
369 NodeResolutionKind::Execution => "",
370 NodeResolutionKind::Types => " for types",
371 }
372)]
373#[property("code" = self.code())]
374pub struct PackageTargetNotFoundError {
375 pub pkg_json_path: PathBuf,
376 pub target: String,
377 pub maybe_resolved: Option<UrlOrPath>,
378 pub maybe_referrer: Option<UrlOrPath>,
379 pub resolution_mode: ResolutionMode,
380 pub resolution_kind: NodeResolutionKind,
381}
382
383impl NodeJsErrorCoded for PackageTargetNotFoundError {
384 fn code(&self) -> NodeJsErrorCode {
385 NodeJsErrorCode::ERR_MODULE_NOT_FOUND
386 }
387}
388
389impl NodeJsErrorCoded for PackageTargetResolveErrorKind {
390 fn code(&self) -> NodeJsErrorCode {
391 match self {
392 PackageTargetResolveErrorKind::NotFound(e) => e.code(),
393 PackageTargetResolveErrorKind::InvalidPackageTarget(e) => e.code(),
394 PackageTargetResolveErrorKind::InvalidModuleSpecifier(e) => e.code(),
395 PackageTargetResolveErrorKind::PackageResolve(e) => e.code(),
396 PackageTargetResolveErrorKind::TypesNotFound(e) => e.code(),
397 PackageTargetResolveErrorKind::UnknownBuiltInNodeModule(e) => e.code(),
398 PackageTargetResolveErrorKind::UrlToFilePath(_) => {
399 NodeJsErrorCode::ERR_INVALID_FILE_URL_PATH
400 }
401 }
402 }
403}
404
405#[derive(Debug, Boxed, JsError)]
406pub struct PackageTargetResolveError(pub Box<PackageTargetResolveErrorKind>);
407
408impl PackageTargetResolveError {
409 pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
410 match self.as_kind() {
411 PackageTargetResolveErrorKind::NotFound(err) => {
412 err.maybe_resolved.as_ref().map(Cow::Borrowed)
413 }
414 PackageTargetResolveErrorKind::PackageResolve(err) => {
415 err.maybe_specifier()
416 }
417 PackageTargetResolveErrorKind::TypesNotFound(err) => {
418 Some(Cow::Borrowed(&err.0.code_specifier))
419 }
420 PackageTargetResolveErrorKind::UnknownBuiltInNodeModule(err) => {
421 err.maybe_specifier().map(|u| Cow::Owned(UrlOrPath::Url(u)))
422 }
423 PackageTargetResolveErrorKind::UrlToFilePath(e) => {
424 Some(Cow::Owned(UrlOrPath::Url(e.0.clone())))
425 }
426 PackageTargetResolveErrorKind::InvalidPackageTarget(_)
427 | PackageTargetResolveErrorKind::InvalidModuleSpecifier(_) => None,
428 }
429 }
430}
431
432#[derive(Debug, Error, JsError)]
433pub enum PackageTargetResolveErrorKind {
434 #[class(inherit)]
435 #[error(transparent)]
436 NotFound(#[from] PackageTargetNotFoundError),
437 #[class(inherit)]
438 #[error(transparent)]
439 InvalidPackageTarget(#[from] InvalidPackageTargetError),
440 #[class(inherit)]
441 #[error(transparent)]
442 InvalidModuleSpecifier(#[from] InvalidModuleSpecifierError),
443 #[class(inherit)]
444 #[error(transparent)]
445 PackageResolve(#[from] PackageResolveError),
446 #[class(inherit)]
447 #[error(transparent)]
448 TypesNotFound(#[from] TypesNotFoundError),
449 #[class(inherit)]
450 #[error(transparent)]
451 UnknownBuiltInNodeModule(#[from] UnknownBuiltInNodeModuleError),
452 #[class(inherit)]
453 #[error(transparent)]
454 #[property("code" = self.code())]
455 UrlToFilePath(#[from] deno_path_util::UrlToFilePathError),
456}
457
458impl PackageTargetResolveErrorKind {
459 pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
460 match self {
461 Self::TypesNotFound(not_found) => Some(not_found),
462 _ => None,
463 }
464 }
465}
466
467impl NodeJsErrorCoded for PackageExportsResolveErrorKind {
468 fn code(&self) -> NodeJsErrorCode {
469 match self {
470 PackageExportsResolveErrorKind::PackagePathNotExported(e) => e.code(),
471 PackageExportsResolveErrorKind::PackageTargetResolve(e) => e.code(),
472 }
473 }
474}
475
476#[derive(Debug, Boxed, JsError)]
477pub struct PackageExportsResolveError(pub Box<PackageExportsResolveErrorKind>);
478
479impl PackageExportsResolveError {
480 pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
481 match self.as_kind() {
482 PackageExportsResolveErrorKind::PackagePathNotExported(_) => None,
483 PackageExportsResolveErrorKind::PackageTargetResolve(err) => {
484 err.maybe_specifier()
485 }
486 }
487 }
488}
489
490#[derive(Debug, Error, JsError)]
491pub enum PackageExportsResolveErrorKind {
492 #[class(inherit)]
493 #[error(transparent)]
494 PackagePathNotExported(#[from] PackagePathNotExportedError),
495 #[class(inherit)]
496 #[error(transparent)]
497 PackageTargetResolve(#[from] PackageTargetResolveError),
498}
499
500#[derive(Debug, Error, JsError)]
501#[error(
502 "[{}] Could not find types for '{}'{}",
503 self.code(),
504 self.0.code_specifier,
505 self.0.maybe_referrer.as_ref().map(|r| format!(" imported from '{}'", r)).unwrap_or_default(),
506 )]
507#[class(generic)]
508#[property("code" = self.code())]
509pub struct TypesNotFoundError(pub Box<TypesNotFoundErrorData>);
510
511#[derive(Debug)]
512pub struct TypesNotFoundErrorData {
513 pub code_specifier: UrlOrPath,
514 pub maybe_referrer: Option<UrlOrPath>,
515}
516
517impl NodeJsErrorCoded for TypesNotFoundError {
518 fn code(&self) -> NodeJsErrorCode {
519 NodeJsErrorCode::ERR_TYPES_NOT_FOUND
520 }
521}
522
523#[derive(Debug, Error, JsError)]
524#[class(inherit)]
525#[error("[{}] Invalid package config. {}", self.code(), .0)]
526pub struct PackageJsonLoadError(pub deno_package_json::PackageJsonLoadError);
527
528impl NodeJsErrorCoded for PackageJsonLoadError {
529 fn code(&self) -> NodeJsErrorCode {
530 NodeJsErrorCode::ERR_INVALID_PACKAGE_CONFIG
531 }
532}
533
534#[derive(Debug, Error, JsError)]
535#[class(type)]
536#[error(
537 "[{}] Package import specifier \"{}\" is not defined{}{}",
538 self.code(),
539 name,
540 package_json_path.as_ref().map(|p| format!(" in package {}", p.display())).unwrap_or_default(),
541 maybe_referrer.as_ref().map(|r| format!(" imported from '{}'", r)).unwrap_or_default(),
542)]
543#[property("code" = self.code())]
544pub struct PackageImportNotDefinedError {
545 pub name: String,
546 pub package_json_path: Option<PathBuf>,
547 pub maybe_referrer: Option<UrlOrPath>,
548}
549
550impl NodeJsErrorCoded for PackageImportNotDefinedError {
551 fn code(&self) -> NodeJsErrorCode {
552 NodeJsErrorCode::ERR_PACKAGE_IMPORT_NOT_DEFINED
553 }
554}
555
556#[derive(Debug, Boxed, JsError)]
557pub struct PackageImportsResolveError(pub Box<PackageImportsResolveErrorKind>);
558
559impl PackageImportsResolveError {
560 pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
561 match self.as_kind() {
562 PackageImportsResolveErrorKind::Target(err) => err.maybe_specifier(),
563 PackageImportsResolveErrorKind::PkgJsonLoad(_)
564 | PackageImportsResolveErrorKind::InvalidModuleSpecifier(_)
565 | PackageImportsResolveErrorKind::NotDefined(_) => None,
566 }
567 }
568}
569
570#[derive(Debug, Error, JsError)]
571pub enum PackageImportsResolveErrorKind {
572 #[class(inherit)]
573 #[error(transparent)]
574 PkgJsonLoad(PackageJsonLoadError),
575 #[class(inherit)]
576 #[error(transparent)]
577 InvalidModuleSpecifier(#[from] InvalidModuleSpecifierError),
578 #[class(inherit)]
579 #[error(transparent)]
580 NotDefined(#[from] PackageImportNotDefinedError),
581 #[class(inherit)]
582 #[error(transparent)]
583 Target(#[from] PackageTargetResolveError),
584}
585
586impl PackageImportsResolveErrorKind {
587 pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
588 match self {
589 Self::Target(err) => err.as_types_not_found(),
590 _ => None,
591 }
592 }
593}
594
595impl NodeJsErrorCoded for PackageImportsResolveErrorKind {
596 fn code(&self) -> NodeJsErrorCode {
597 match self {
598 Self::PkgJsonLoad(e) => e.code(),
599 Self::InvalidModuleSpecifier(e) => e.code(),
600 Self::NotDefined(e) => e.code(),
601 Self::Target(e) => e.code(),
602 }
603 }
604}
605
606impl NodeJsErrorCoded for PackageResolveErrorKind {
607 fn code(&self) -> NodeJsErrorCode {
608 match self {
609 PackageResolveErrorKind::PkgJsonLoad(e) => e.code(),
610 PackageResolveErrorKind::InvalidModuleSpecifier(e) => e.code(),
611 PackageResolveErrorKind::PackageFolderResolve(e) => e.code(),
612 PackageResolveErrorKind::ExportsResolve(e) => e.code(),
613 PackageResolveErrorKind::SubpathResolve(e) => e.code(),
614 PackageResolveErrorKind::UrlToFilePath(_) => {
615 NodeJsErrorCode::ERR_INVALID_FILE_URL_PATH
616 }
617 }
618 }
619}
620
621#[derive(Debug, Boxed, JsError)]
622pub struct PackageResolveError(pub Box<PackageResolveErrorKind>);
623
624impl PackageResolveError {
625 pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
626 match self.as_kind() {
627 PackageResolveErrorKind::ExportsResolve(err) => err.maybe_specifier(),
628 PackageResolveErrorKind::SubpathResolve(err) => err.maybe_specifier(),
629 PackageResolveErrorKind::UrlToFilePath(err) => {
630 Some(Cow::Owned(UrlOrPath::Url(err.0.clone())))
631 }
632 PackageResolveErrorKind::PkgJsonLoad(_)
633 | PackageResolveErrorKind::InvalidModuleSpecifier(_)
634 | PackageResolveErrorKind::PackageFolderResolve(_) => None,
635 }
636 }
637}
638
639#[derive(Debug, Error, JsError)]
640pub enum PackageResolveErrorKind {
641 #[class(inherit)]
642 #[error(transparent)]
643 PkgJsonLoad(#[from] PackageJsonLoadError),
644 #[class(inherit)]
645 #[error(transparent)]
646 InvalidModuleSpecifier(#[from] InvalidModuleSpecifierError),
647 #[class(inherit)]
648 #[error(transparent)]
649 PackageFolderResolve(#[from] PackageFolderResolveError),
650 #[class(inherit)]
651 #[error(transparent)]
652 ExportsResolve(#[from] PackageExportsResolveError),
653 #[class(inherit)]
654 #[error(transparent)]
655 SubpathResolve(#[from] PackageSubpathResolveError),
656 #[class(inherit)]
657 #[error(transparent)]
658 #[property("code" = self.code())]
659 UrlToFilePath(#[from] UrlToFilePathError),
660}
661
662impl PackageResolveErrorKind {
663 pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
664 match self {
665 PackageResolveErrorKind::PkgJsonLoad(_)
666 | PackageResolveErrorKind::InvalidModuleSpecifier(_)
667 | PackageResolveErrorKind::PackageFolderResolve(_)
668 | PackageResolveErrorKind::ExportsResolve(_)
669 | PackageResolveErrorKind::UrlToFilePath(_) => None,
670 PackageResolveErrorKind::SubpathResolve(err) => err.as_types_not_found(),
671 }
672 }
673}
674
675#[derive(Debug, Error, JsError)]
676#[class(generic)]
677#[error("Failed joining '{path}' from '{base}'.")]
678pub struct NodeResolveRelativeJoinError {
679 pub path: String,
680 pub base: Url,
681 #[source]
682 pub source: url::ParseError,
683}
684
685#[derive(Debug, Error, JsError)]
686#[class(generic)]
687#[error("Failed resolving specifier from data url referrer.")]
688pub struct DataUrlReferrerError {
689 #[source]
690 pub source: url::ParseError,
691}
692
693#[derive(Debug, Boxed, JsError)]
694pub struct NodeResolveError(pub Box<NodeResolveErrorKind>);
695
696impl NodeResolveError {
697 pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
698 match self.as_kind() {
699 NodeResolveErrorKind::PathToUrl(err) => {
700 Some(Cow::Owned(UrlOrPath::Path(err.0.clone())))
701 }
702 NodeResolveErrorKind::UrlToFilePath(err) => {
703 Some(Cow::Owned(UrlOrPath::Url(err.0.clone())))
704 }
705 NodeResolveErrorKind::PackageImportsResolve(err) => err.maybe_specifier(),
706 NodeResolveErrorKind::PackageResolve(err) => err.maybe_specifier(),
707 NodeResolveErrorKind::TypesNotFound(err) => {
708 Some(Cow::Borrowed(&err.0.code_specifier))
709 }
710 NodeResolveErrorKind::UnknownBuiltInNodeModule(err) => {
711 err.maybe_specifier().map(|u| Cow::Owned(UrlOrPath::Url(u)))
712 }
713 NodeResolveErrorKind::FinalizeResolution(err) => err.maybe_specifier(),
714 NodeResolveErrorKind::UnsupportedEsmUrlScheme(_)
715 | NodeResolveErrorKind::DataUrlReferrer(_)
716 | NodeResolveErrorKind::RelativeJoin(_) => None,
717 }
718 }
719}
720
721#[derive(Debug, Error, JsError)]
722pub enum NodeResolveErrorKind {
723 #[class(inherit)]
724 #[error(transparent)]
725 RelativeJoin(#[from] NodeResolveRelativeJoinError),
726 #[class(inherit)]
727 #[error(transparent)]
728 PathToUrl(#[from] deno_path_util::PathToUrlError),
729 #[class(inherit)]
730 #[error(transparent)]
731 UrlToFilePath(#[from] deno_path_util::UrlToFilePathError),
732 #[class(inherit)]
733 #[error(transparent)]
734 PackageImportsResolve(#[from] PackageImportsResolveError),
735 #[class(inherit)]
736 #[error(transparent)]
737 UnsupportedEsmUrlScheme(#[from] UnsupportedEsmUrlSchemeError),
738 #[class(inherit)]
739 #[error(transparent)]
740 DataUrlReferrer(#[from] DataUrlReferrerError),
741 #[class(inherit)]
742 #[error(transparent)]
743 PackageResolve(#[from] PackageResolveError),
744 #[class(inherit)]
745 #[error(transparent)]
746 TypesNotFound(#[from] TypesNotFoundError),
747 #[class(inherit)]
748 #[error(transparent)]
749 UnknownBuiltInNodeModule(#[from] UnknownBuiltInNodeModuleError),
750 #[class(inherit)]
751 #[error(transparent)]
752 FinalizeResolution(#[from] FinalizeResolutionError),
753}
754
755impl NodeResolveErrorKind {
756 pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
757 match self {
758 NodeResolveErrorKind::TypesNotFound(not_found) => Some(not_found),
759 NodeResolveErrorKind::PackageImportsResolve(err) => {
760 err.as_kind().as_types_not_found()
761 }
762 NodeResolveErrorKind::PackageResolve(package_resolve_error) => {
763 package_resolve_error.as_types_not_found()
764 }
765 NodeResolveErrorKind::UnsupportedEsmUrlScheme(_)
766 | NodeResolveErrorKind::DataUrlReferrer(_)
767 | NodeResolveErrorKind::FinalizeResolution(_)
768 | NodeResolveErrorKind::RelativeJoin(_)
769 | NodeResolveErrorKind::PathToUrl(_)
770 | NodeResolveErrorKind::UnknownBuiltInNodeModule(_)
771 | NodeResolveErrorKind::UrlToFilePath(_) => None,
772 }
773 }
774
775 pub fn maybe_code(&self) -> Option<NodeJsErrorCode> {
776 match self {
777 NodeResolveErrorKind::RelativeJoin(_) => None,
778 NodeResolveErrorKind::PathToUrl(_) => None,
779 NodeResolveErrorKind::UrlToFilePath(_) => None,
780 NodeResolveErrorKind::PackageImportsResolve(e) => Some(e.code()),
781 NodeResolveErrorKind::UnsupportedEsmUrlScheme(e) => Some(e.code()),
782 NodeResolveErrorKind::DataUrlReferrer(_) => None,
783 NodeResolveErrorKind::PackageResolve(e) => Some(e.code()),
784 NodeResolveErrorKind::TypesNotFound(e) => Some(e.code()),
785 NodeResolveErrorKind::UnknownBuiltInNodeModule(e) => Some(e.code()),
786 NodeResolveErrorKind::FinalizeResolution(e) => Some(e.code()),
787 }
788 }
789}
790
791#[derive(Debug, Boxed, JsError)]
792pub struct FinalizeResolutionError(pub Box<FinalizeResolutionErrorKind>);
793
794impl FinalizeResolutionError {
795 pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
796 match self.as_kind() {
797 FinalizeResolutionErrorKind::ModuleNotFound(err) => {
798 Some(Cow::Borrowed(&err.specifier))
799 }
800 FinalizeResolutionErrorKind::TypesNotFound(err) => {
801 Some(Cow::Borrowed(&err.0.code_specifier))
802 }
803 FinalizeResolutionErrorKind::UnsupportedDirImport(err) => {
804 Some(Cow::Borrowed(&err.dir_url))
805 }
806 FinalizeResolutionErrorKind::PackageSubpathResolve(err) => {
807 err.maybe_specifier()
808 }
809 FinalizeResolutionErrorKind::InvalidModuleSpecifierError(_)
810 | FinalizeResolutionErrorKind::UrlToFilePath(_) => None,
811 }
812 }
813
814 pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
815 match self.as_kind() {
816 FinalizeResolutionErrorKind::TypesNotFound(err) => Some(err),
817 FinalizeResolutionErrorKind::PackageSubpathResolve(err) => {
818 err.as_types_not_found()
819 }
820 FinalizeResolutionErrorKind::ModuleNotFound(_)
821 | FinalizeResolutionErrorKind::UnsupportedDirImport(_)
822 | FinalizeResolutionErrorKind::InvalidModuleSpecifierError(_)
823 | FinalizeResolutionErrorKind::UrlToFilePath(_) => None,
824 }
825 }
826}
827
828#[derive(Debug, Error, JsError)]
829pub enum FinalizeResolutionErrorKind {
830 #[class(inherit)]
831 #[error(transparent)]
832 InvalidModuleSpecifierError(#[from] InvalidModuleSpecifierError),
833 #[class(inherit)]
834 #[error(transparent)]
835 ModuleNotFound(#[from] ModuleNotFoundError),
836 #[class(inherit)]
837 #[error(transparent)]
838 TypesNotFound(#[from] TypesNotFoundError),
839 #[class(inherit)]
840 #[error(transparent)]
841 PackageSubpathResolve(#[from] PackageSubpathResolveError),
842 #[class(inherit)]
843 #[error(transparent)]
844 UnsupportedDirImport(#[from] UnsupportedDirImportError),
845 #[class(inherit)]
846 #[error(transparent)]
847 #[property("code" = self.code())]
848 UrlToFilePath(#[from] deno_path_util::UrlToFilePathError),
849}
850
851impl NodeJsErrorCoded for FinalizeResolutionErrorKind {
852 fn code(&self) -> NodeJsErrorCode {
853 match self {
854 FinalizeResolutionErrorKind::InvalidModuleSpecifierError(e) => e.code(),
855 FinalizeResolutionErrorKind::ModuleNotFound(e) => e.code(),
856 FinalizeResolutionErrorKind::TypesNotFound(e) => e.code(),
857 FinalizeResolutionErrorKind::PackageSubpathResolve(e) => e.code(),
858 FinalizeResolutionErrorKind::UnsupportedDirImport(e) => e.code(),
859 FinalizeResolutionErrorKind::UrlToFilePath(_) => {
860 NodeJsErrorCode::ERR_INVALID_FILE_URL_PATH
861 }
862 }
863 }
864}
865
866#[derive(Debug, Error, JsError)]
867#[class(generic)]
868#[error(
869 "[{}] Cannot find module '{}'{}{}",
870 self.code(),
871 specifier,
872 maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default(),
873 suggested_ext.as_ref().map(|m| format!("\nDid you mean to import with the \".{}\" extension?", m)).unwrap_or_default()
874)]
875#[property("code" = self.code())]
876pub struct ModuleNotFoundError {
877 pub specifier: UrlOrPath,
878 pub maybe_referrer: Option<UrlOrPath>,
879 pub suggested_ext: Option<&'static str>,
880}
881
882impl NodeJsErrorCoded for ModuleNotFoundError {
883 fn code(&self) -> NodeJsErrorCode {
884 NodeJsErrorCode::ERR_MODULE_NOT_FOUND
885 }
886}
887
888#[derive(Debug, Error, JsError)]
889#[class(generic)]
890#[error(
891 "[{}] Directory import '{}' is not supported resolving ES modules{}{}",
892 self.code(),
893 dir_url,
894 maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default(),
895 suggestion.as_ref().map(|suggestion| format!("\nDid you mean to import '{suggestion}'?")).unwrap_or_default(),
896)]
897#[property("code" = self.code())]
898pub struct UnsupportedDirImportError {
899 pub dir_url: UrlOrPath,
900 pub maybe_referrer: Option<UrlOrPath>,
901 pub suggestion: Option<String>,
902}
903
904impl NodeJsErrorCoded for UnsupportedDirImportError {
905 fn code(&self) -> NodeJsErrorCode {
906 NodeJsErrorCode::ERR_UNSUPPORTED_DIR_IMPORT
907 }
908}
909
910#[derive(Debug, JsError)]
911#[class(generic)]
912#[property("code" = self.code())]
913pub struct InvalidPackageTargetError {
914 pub pkg_json_path: PathBuf,
915 pub sub_path: String,
916 pub target: String,
917 pub is_import: bool,
918 pub maybe_referrer: Option<UrlOrPath>,
919}
920
921impl std::error::Error for InvalidPackageTargetError {}
922
923impl std::fmt::Display for InvalidPackageTargetError {
924 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
925 let rel_error = !self.is_import
926 && !self.target.is_empty()
927 && !self.target.starts_with("./");
928 f.write_char('[')?;
929 f.write_str(self.code().as_str())?;
930 f.write_char(']')?;
931
932 if self.sub_path == "." {
933 assert!(!self.is_import);
934 write!(
935 f,
936 " Invalid \"exports\" main target {} defined in the package config {}",
937 self.target,
938 self.pkg_json_path.display()
939 )?;
940 } else {
941 let ie = if self.is_import { "imports" } else { "exports" };
942 write!(
943 f,
944 " Invalid \"{}\" target {} defined for '{}' in the package config {}",
945 ie,
946 self.target,
947 self.sub_path,
948 self.pkg_json_path.display()
949 )?;
950 };
951
952 if let Some(referrer) = &self.maybe_referrer {
953 write!(f, " imported from '{}'", referrer)?;
954 }
955 if rel_error {
956 write!(f, "; target must start with \"./\"")?;
957 }
958 Ok(())
959 }
960}
961
962impl NodeJsErrorCoded for InvalidPackageTargetError {
963 fn code(&self) -> NodeJsErrorCode {
964 NodeJsErrorCode::ERR_INVALID_PACKAGE_TARGET
965 }
966}
967
968#[derive(Debug, JsError)]
969#[class(generic)]
970#[property("code" = self.code())]
971pub struct PackagePathNotExportedError {
972 pub pkg_json_path: PathBuf,
973 pub subpath: String,
974 pub maybe_referrer: Option<UrlOrPath>,
975 pub resolution_kind: NodeResolutionKind,
976}
977
978impl NodeJsErrorCoded for PackagePathNotExportedError {
979 fn code(&self) -> NodeJsErrorCode {
980 NodeJsErrorCode::ERR_PACKAGE_PATH_NOT_EXPORTED
981 }
982}
983
984impl std::error::Error for PackagePathNotExportedError {}
985
986impl std::fmt::Display for PackagePathNotExportedError {
987 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
988 f.write_char('[')?;
989 f.write_str(self.code().as_str())?;
990 f.write_char(']')?;
991
992 let types_msg = match self.resolution_kind {
993 NodeResolutionKind::Execution => String::new(),
994 NodeResolutionKind::Types => " for types".to_string(),
995 };
996 if self.subpath == "." {
997 write!(
998 f,
999 " No \"exports\" main defined{} in '{}'",
1000 types_msg,
1001 self.pkg_json_path.display()
1002 )?;
1003 } else {
1004 write!(
1005 f,
1006 " Package subpath '{}' is not defined{} by \"exports\" in '{}'",
1007 self.subpath,
1008 types_msg,
1009 self.pkg_json_path.display()
1010 )?;
1011 };
1012
1013 if let Some(referrer) = &self.maybe_referrer {
1014 write!(f, " imported from '{}'", referrer)?;
1015 }
1016 Ok(())
1017 }
1018}
1019
1020#[derive(Debug, Clone, Error, JsError)]
1021#[class(type)]
1022#[error(
1023 "[{}] Only file and data URLs are supported by the default ESM loader.{} Received protocol '{}'",
1024 self.code(),
1025 if cfg!(windows) && url_scheme.len() == 2 { " On Windows, absolute path must be valid file:// URLS."} else { "" },
1026 url_scheme
1027)]
1028#[property("code" = self.code())]
1029pub struct UnsupportedEsmUrlSchemeError {
1030 pub url_scheme: String,
1031}
1032
1033impl NodeJsErrorCoded for UnsupportedEsmUrlSchemeError {
1034 fn code(&self) -> NodeJsErrorCode {
1035 NodeJsErrorCode::ERR_UNSUPPORTED_ESM_URL_SCHEME
1036 }
1037}
1038
1039#[derive(Debug, Error, JsError)]
1040pub enum ResolvePkgJsonBinExportError {
1041 #[class(inherit)]
1042 #[error(transparent)]
1043 PkgJsonLoad(#[from] PackageJsonLoadError),
1044 #[class(generic)]
1045 #[error("Failed resolving binary export. '{}' did not exist", pkg_json_path.display())]
1046 MissingPkgJson { pkg_json_path: PathBuf },
1047 #[class(generic)]
1048 #[error("Failed resolving binary export. {message}")]
1049 InvalidBinProperty { message: String },
1050}
1051
1052#[derive(Debug, Error, JsError)]
1053pub enum ResolveBinaryCommandsError {
1054 #[class(inherit)]
1055 #[error(transparent)]
1056 PkgJsonLoad(#[from] PackageJsonLoadError),
1057 #[class(generic)]
1058 #[error("'{}' did not have a name", pkg_json_path.display())]
1059 MissingPkgJsonName { pkg_json_path: PathBuf },
1060}
1061
1062#[derive(Error, Debug, Clone, deno_error::JsError)]
1063#[class("NotFound")]
1064#[error("No such built-in module: node:{module_name}")]
1065#[property("code" = self.code())]
1066pub struct UnknownBuiltInNodeModuleError {
1067 pub module_name: String,
1069}
1070
1071impl UnknownBuiltInNodeModuleError {
1072 pub fn maybe_specifier(&self) -> Option<Url> {
1073 Url::parse(&format!("node:{}", self.module_name)).ok()
1074 }
1075}
1076
1077impl NodeJsErrorCoded for UnknownBuiltInNodeModuleError {
1078 fn code(&self) -> NodeJsErrorCode {
1079 NodeJsErrorCode::ERR_UNKNOWN_BUILTIN_MODULE
1080 }
1081}
1082
1083#[cfg(test)]
1084mod test {
1085 use super::*;
1086
1087 #[test]
1088 fn types_resolution_package_path_not_exported() {
1089 let separator_char = if cfg!(windows) { '\\' } else { '/' };
1090 assert_eq!(
1091 PackagePathNotExportedError {
1092 pkg_json_path: PathBuf::from("test_path").join("package.json"),
1093 subpath: "./jsx-runtime".to_string(),
1094 maybe_referrer: None,
1095 resolution_kind: NodeResolutionKind::Types
1096 }
1097 .to_string(),
1098 format!(
1099 "[ERR_PACKAGE_PATH_NOT_EXPORTED] Package subpath './jsx-runtime' is not defined for types by \"exports\" in 'test_path{separator_char}package.json'"
1100 )
1101 );
1102 assert_eq!(
1103 PackagePathNotExportedError {
1104 pkg_json_path: PathBuf::from("test_path").join("package.json"),
1105 subpath: ".".to_string(),
1106 maybe_referrer: None,
1107 resolution_kind: NodeResolutionKind::Types
1108 }
1109 .to_string(),
1110 format!(
1111 "[ERR_PACKAGE_PATH_NOT_EXPORTED] No \"exports\" main defined for types in 'test_path{separator_char}package.json'"
1112 )
1113 );
1114 }
1115}