index.js 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. import process from 'node:process';
  2. import path from 'node:path';
  3. import fs from 'node:fs';
  4. import commonPathPrefix from 'common-path-prefix';
  5. import {packageDirectorySync} from 'pkg-dir';
  6. const {env, cwd} = process;
  7. const isWritable = path => {
  8. try {
  9. fs.accessSync(path, fs.constants.W_OK);
  10. return true;
  11. } catch {
  12. return false;
  13. }
  14. };
  15. function useDirectory(directory, options) {
  16. if (options.create) {
  17. fs.mkdirSync(directory, {recursive: true});
  18. }
  19. return directory;
  20. }
  21. function getNodeModuleDirectory(directory) {
  22. const nodeModules = path.join(directory, 'node_modules');
  23. if (
  24. !isWritable(nodeModules)
  25. && (fs.existsSync(nodeModules) || !isWritable(path.join(directory)))
  26. ) {
  27. return;
  28. }
  29. return nodeModules;
  30. }
  31. export default function findCacheDirectory(options = {}) {
  32. if (env.CACHE_DIR && !['true', 'false', '1', '0'].includes(env.CACHE_DIR)) {
  33. return useDirectory(path.join(env.CACHE_DIR, options.name), options);
  34. }
  35. let {cwd: directory = cwd(), files} = options;
  36. if (files) {
  37. if (!Array.isArray(files)) {
  38. throw new TypeError(`Expected \`files\` option to be an array, got \`${typeof files}\`.`);
  39. }
  40. directory = commonPathPrefix(files.map(file => path.resolve(directory, file)));
  41. }
  42. directory = packageDirectorySync({cwd: directory});
  43. if (!directory) {
  44. return;
  45. }
  46. const nodeModules = getNodeModuleDirectory(directory);
  47. if (!nodeModules) {
  48. return;
  49. }
  50. return useDirectory(path.join(directory, 'node_modules', '.cache', options.name), options);
  51. }