index.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. 'use strict';
  2. var fs = require('fs');
  3. var path = require('path');
  4. var isString = require('lodash.isstring');
  5. var isPlainObject = require('lodash.isplainobject');
  6. var isEmpty = require('lodash.isempty');
  7. var pick = require('lodash.pick');
  8. var assignWith = require('lodash.assignwith');
  9. var expandTilde = require('expand-tilde');
  10. var parsePath = require('parse-filepath');
  11. function assignNullish(objValue, srcValue) {
  12. return (srcValue == null ? objValue : srcValue);
  13. }
  14. function defaults(mainObj, defaultObj) {
  15. return assignWith({}, defaultObj, mainObj, assignNullish);
  16. }
  17. function fined(pathObj, defaultObj) {
  18. var expandedPath = expandPath(pathObj, defaultObj);
  19. return expandedPath ? findWithExpandedPath(expandedPath) : null;
  20. }
  21. function expandPath(pathObj, defaultObj) {
  22. if (!isPlainObject(defaultObj)) {
  23. defaultObj = {};
  24. }
  25. if (isString(pathObj)) {
  26. pathObj = { path: pathObj };
  27. }
  28. if (!isPlainObject(pathObj)) {
  29. pathObj = {};
  30. }
  31. pathObj = defaults(pathObj, defaultObj);
  32. var filePath;
  33. if (!isString(pathObj.path)) {
  34. return null;
  35. }
  36. // Execution of toString is for a String object.
  37. if (isString(pathObj.name) && pathObj.name) {
  38. if (pathObj.path) {
  39. filePath = expandTilde(pathObj.path.toString());
  40. filePath = path.join(filePath, pathObj.name.toString());
  41. } else {
  42. filePath = pathObj.name.toString();
  43. }
  44. } else {
  45. filePath = expandTilde(pathObj.path.toString());
  46. }
  47. var extArr = createExtensionArray(pathObj.extensions);
  48. var extMap = createExtensionMap(pathObj.extensions);
  49. var basedir = isString(pathObj.cwd) ? pathObj.cwd.toString() : '.';
  50. basedir = path.resolve(expandTilde(basedir));
  51. var findUp = !!pathObj.findUp;
  52. var parsed = parsePath(filePath);
  53. if (parsed.isAbsolute) {
  54. filePath = filePath.slice(parsed.root.length);
  55. findUp = false;
  56. basedir = parsed.root;
  57. } else if (parsed.root) { // Expanded path has a drive letter on Windows.
  58. filePath = filePath.slice(parsed.root.length);
  59. basedir = path.resolve(parsed.root);
  60. }
  61. return {
  62. path: filePath,
  63. basedir: basedir,
  64. findUp: findUp,
  65. extArr: extArr,
  66. extMap: extMap,
  67. };
  68. }
  69. function findWithExpandedPath(expanded) {
  70. var found = expanded.findUp ?
  71. findUpFile(expanded.basedir, expanded.path, expanded.extArr) :
  72. findFile(expanded.basedir, expanded.path, expanded.extArr);
  73. if (!found) {
  74. return null;
  75. }
  76. if (expanded.extMap) {
  77. found.extension = pick(expanded.extMap, found.extension);
  78. }
  79. return found;
  80. }
  81. function findFile(basedir, relpath, extArr) {
  82. var noExtPath = path.resolve(basedir, relpath);
  83. for (var i = 0, n = extArr.length; i < n; i++) {
  84. var filepath = noExtPath + extArr[i];
  85. try {
  86. fs.statSync(filepath);
  87. return { path: filepath, extension: extArr[i] };
  88. } catch (e) {}
  89. }
  90. return null;
  91. }
  92. function findUpFile(basedir, filepath, extArr) {
  93. var lastdir;
  94. do {
  95. var found = findFile(basedir, filepath, extArr);
  96. if (found) {
  97. return found;
  98. }
  99. lastdir = basedir;
  100. basedir = path.dirname(basedir);
  101. } while (lastdir !== basedir);
  102. return null;
  103. }
  104. function createExtensionArray(exts) {
  105. if (isString(exts)) {
  106. return [exts];
  107. }
  108. if (Array.isArray(exts)) {
  109. exts = exts.filter(isString);
  110. return (exts.length > 0) ? exts : [''];
  111. }
  112. if (isPlainObject(exts)) {
  113. exts = Object.keys(exts);
  114. return (exts.length > 0) ? exts : [''];
  115. }
  116. return [''];
  117. }
  118. function createExtensionMap(exts) {
  119. if (!isPlainObject(exts)) {
  120. return null;
  121. }
  122. if (isEmpty(exts)) {
  123. return { '': null };
  124. }
  125. return exts;
  126. }
  127. module.exports = fined;