index.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /*!
  2. * detect-file <https://github.com/doowb/detect-file>
  3. *
  4. * Copyright (c) 2016-2017, Brian Woodward.
  5. * Released under the MIT License.
  6. */
  7. 'use strict';
  8. var fs = require('fs');
  9. var path = require('path');
  10. /**
  11. * Detect the given `filepath` if it exists.
  12. *
  13. * ```js
  14. * var res = detect('package.json');
  15. * console.log(res);
  16. * //=> "package.json"
  17. *
  18. * var res = detect('fake-file.json');
  19. * console.log(res)
  20. * //=> null
  21. * ```
  22. *
  23. * @param {String} `filepath` filepath to detect.
  24. * @param {Object} `options` Additional options.
  25. * @param {Boolean} `options.nocase` Set this to `true` to force case-insensitive filename checks. This is useful on case sensitive file systems.
  26. * @return {String} Returns the detected filepath if it exists, otherwise returns `null`.
  27. * @api public
  28. */
  29. module.exports = function detect(filepath, options) {
  30. if (!filepath || (typeof filepath !== 'string')) {
  31. return null;
  32. }
  33. if (fs.existsSync(filepath)) {
  34. return path.resolve(filepath);
  35. }
  36. options = options || {};
  37. if (options.nocase === true) {
  38. return nocase(filepath);
  39. }
  40. return null;
  41. };
  42. /**
  43. * Check if the filepath exists by falling back to reading in the entire directory.
  44. * Returns the real filepath (for case sensitive file systems) if found.
  45. *
  46. * @param {String} `filepath` filepath to check.
  47. * @return {String} Returns found filepath if exists, otherwise null.
  48. */
  49. function nocase(filepath) {
  50. filepath = path.resolve(filepath);
  51. var res = tryReaddir(filepath);
  52. if (res === null) {
  53. return null;
  54. }
  55. // "filepath" is a directory, an error would be
  56. // thrown if it doesn't exist. if we're here, it exists
  57. if (res.path === filepath) {
  58. return res.path;
  59. }
  60. // "filepath" is not a directory
  61. // compare against upper case later
  62. // see https://nodejs.org/en/docs/guides/working-with-different-filesystems/
  63. var upper = filepath.toUpperCase();
  64. var len = res.files.length;
  65. var idx = -1;
  66. while (++idx < len) {
  67. var fp = path.resolve(res.path, res.files[idx]);
  68. if (filepath === fp || upper === fp) {
  69. return fp;
  70. }
  71. var fpUpper = fp.toUpperCase();
  72. if (filepath === fpUpper || upper === fpUpper) {
  73. return fp;
  74. }
  75. }
  76. return null;
  77. }
  78. /**
  79. * Try to read the filepath as a directory first, then fallback to the filepath's dirname.
  80. *
  81. * @param {String} `filepath` path of the directory to read.
  82. * @return {Object} Object containing `path` and `files` if succesful. Otherwise, null.
  83. */
  84. function tryReaddir(filepath) {
  85. var ctx = { path: filepath, files: [] };
  86. try {
  87. ctx.files = fs.readdirSync(filepath);
  88. return ctx;
  89. } catch (err) {}
  90. try {
  91. ctx.path = path.dirname(filepath);
  92. ctx.files = fs.readdirSync(ctx.path);
  93. return ctx;
  94. } catch (err) {}
  95. return null;
  96. }