index.js 2.7 KB

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