summaryrefslogtreecommitdiff
path: root/ext/node/package_json.rs
blob: 877acfc7a7de295ad23f10b0cccf0d770ee0e17c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.

use deno_package_json::PackageJson;
use deno_package_json::PackageJsonRc;
use std::cell::RefCell;
use std::collections::HashMap;
use std::io::ErrorKind;
use std::path::Path;
use std::path::PathBuf;

use crate::errors::PackageJsonLoadError;

// use a thread local cache so that workers have their own distinct cache
thread_local! {
  static CACHE: RefCell<HashMap<PathBuf, PackageJsonRc>> = RefCell::new(HashMap::new());
}

pub struct PackageJsonThreadLocalCache;

impl PackageJsonThreadLocalCache {
  pub fn clear() {
    CACHE.with(|cache| cache.borrow_mut().clear());
  }
}

impl deno_package_json::PackageJsonCache for PackageJsonThreadLocalCache {
  fn get(&self, path: &Path) -> Option<PackageJsonRc> {
    CACHE.with(|cache| cache.borrow().get(path).cloned())
  }

  fn set(&self, path: PathBuf, package_json: PackageJsonRc) {
    CACHE.with(|cache| cache.borrow_mut().insert(path, package_json));
  }
}

pub struct DenoPkgJsonFsAdapter<'a>(pub &'a dyn deno_fs::FileSystem);

impl<'a> deno_package_json::fs::DenoPkgJsonFs for DenoPkgJsonFsAdapter<'a> {
  fn read_to_string_lossy(
    &self,
    path: &Path,
  ) -> Result<String, std::io::Error> {
    self
      .0
      .read_text_file_lossy_sync(path, None)
      .map_err(|err| err.into_io_error())
  }
}

/// Helper to load a package.json file using the thread local cache
/// in deno_node.
pub fn load_pkg_json(
  fs: &dyn deno_fs::FileSystem,
  path: &Path,
) -> Result<Option<PackageJsonRc>, PackageJsonLoadError> {
  let result = PackageJson::load_from_path(
    path,
    &DenoPkgJsonFsAdapter(fs),
    Some(&PackageJsonThreadLocalCache),
  );
  match result {
    Ok(pkg_json) => Ok(Some(pkg_json)),
    Err(deno_package_json::PackageJsonLoadError::Io { source, .. })
      if source.kind() == ErrorKind::NotFound =>
    {
      Ok(None)
    }
    Err(err) => Err(PackageJsonLoadError(err)),
  }
}