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