@dozerg/find-up
Version:
Find files or directories by walking up parent directories.
244 lines (243 loc) • 11.7 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }
var __asyncValues = (this && this.__asyncValues) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};
var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
var i, p;
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; }
};
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), i, q = [];
return i = Object.create((typeof AsyncIterator === "function" ? AsyncIterator : Object).prototype), verb("next"), verb("throw"), verb("return", awaitReturn), i[Symbol.asyncIterator] = function () { return this; }, i;
function awaitReturn(f) { return function (v) { return Promise.resolve(v).then(f, reject); }; }
function verb(n, f) { if (g[n]) { i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; if (f) i[n] = f(i[n]); } }
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = findUp;
const fs_1 = __importStar(require("fs"));
const path_1 = __importDefault(require("path"));
const url_1 = require("url");
const condition_1 = require("@dozerg/condition");
function findUp(name_1) {
return __awaiter(this, arguments, void 0, function* (name, options = {}) {
const { directory, stopAt, root, limit } = normalise(options);
const { found, runMatcher } = yield getRunMatcher(name, Object.assign(Object.assign({}, options), { cwd: directory }));
const unique = new Set(found);
for (let cwd = directory; found.length < limit; cwd = path_1.default.dirname(cwd)) {
const { result, stop } = yield runMatcher(Object.assign(Object.assign({}, options), { cwd }));
if (result && !unique.has(result)) {
found.push(result);
unique.add(result);
}
if (stop || cwd === stopAt || cwd === root)
break;
}
return found.slice(0, limit);
});
}
findUp.sync = (name, options = {}) => {
const { directory, stopAt, root, limit } = normalise(options);
const { found, runMatcher } = getRunMatcher.sync(name, Object.assign(Object.assign({}, options), { cwd: directory }));
const unique = new Set(found);
for (let cwd = directory; found.length < limit; cwd = path_1.default.dirname(cwd)) {
const { result, stop } = runMatcher(Object.assign(Object.assign({}, options), { cwd }));
if (result && !unique.has(result)) {
found.push(result);
unique.add(result);
}
if (stop || cwd === stopAt || cwd === root)
break;
}
return found.slice(0, limit);
};
findUp.gen = function (name_1) {
return __asyncGenerator(this, arguments, function* (name, options = {}) {
const { directory, stopAt, root, limit } = normalise(options);
const { found, runMatcher } = yield __await(getRunMatcher(name, Object.assign(Object.assign({}, options), { cwd: directory })));
yield __await(yield* __asyncDelegator(__asyncValues(found.slice(0, limit))));
const unique = new Set(found);
for (let cwd = directory; found.length < limit; cwd = path_1.default.dirname(cwd)) {
const { result, stop } = yield __await(runMatcher(Object.assign(Object.assign({}, options), { cwd })));
if (result && !unique.has(result)) {
found.push(result);
unique.add(result);
yield yield __await(result);
}
if (stop || cwd === stopAt || cwd === root)
break;
}
});
};
function toPath(urlOrPath) {
return urlOrPath instanceof URL ? (0, url_1.fileURLToPath)(urlOrPath) : urlOrPath;
}
function normalise(options) {
var _a, _b, _c;
const directory = path_1.default.resolve((_a = toPath(options.cwd)) !== null && _a !== void 0 ? _a : '');
const { root } = path_1.default.parse(directory);
const stopAt = path_1.default.resolve(directory, (_b = toPath(options.stopAtPath)) !== null && _b !== void 0 ? _b : root);
const limit = (_c = options.stopAtLimit) !== null && _c !== void 0 ? _c : Number.POSITIVE_INFINITY;
return { directory, stopAt, root, limit };
}
function getRunMatcher(name, options) {
return __awaiter(this, void 0, void 0, function* () {
const { absolute, relative, matcher } = normaliseName(name);
const found = [];
if (absolute)
for (const n of absolute) {
const p = yield locatePath([n], options);
if (p)
found.push(p);
}
const runMatcher = (opt) => __awaiter(this, void 0, void 0, function* () {
if (matcher) {
(0, condition_1.assertIsString)(opt.cwd);
const p = matcher(opt.cwd);
return typeof p === 'string' ? { result: yield locatePath([p], opt) } : {};
}
return { result: yield locatePath(relative, opt), stop: relative.length < 1 };
});
return { found, runMatcher };
});
}
getRunMatcher.sync = (name, options) => {
var _a;
const { absolute, relative, matcher } = normaliseName(name);
const found = (_a = absolute === null || absolute === void 0 ? void 0 : absolute.map(n => locatePath.sync([n], options)).filter(condition_1.isNonNull)) !== null && _a !== void 0 ? _a : [];
const runMatcher = (opt) => {
if (matcher) {
(0, condition_1.assertIsString)(opt.cwd);
const p = matcher(opt.cwd);
return typeof p === 'string' ? { result: locatePath.sync([p], opt) } : {};
}
return { result: locatePath.sync(relative, opt), stop: relative.length < 1 };
};
return { found, runMatcher };
};
function normaliseName(name) {
if (typeof name !== 'function') {
const [absolute, relative] = [name].flat().reduce((r, n) => {
if (path_1.default.isAbsolute(n))
r[0].add(path_1.default.normalize(n));
else
r[1].add(n);
return r;
}, [new Set(), new Set()]);
return { absolute: [...absolute], relative: [...relative] };
}
return { matcher: name };
}
function locatePath(names_1, _a) {
return __awaiter(this, arguments, void 0, function* (names, { cwd, allowSymlinks, type }) {
(0, condition_1.assertIsString)(cwd);
const fstat = getFstat(allowSymlinks !== false);
for (const name of names) {
const fname = path_1.default.resolve(cwd, name);
const stat = yield fstat(fname);
if (checkType(stat, type !== null && type !== void 0 ? type : 'file'))
return fname;
}
return undefined;
});
}
locatePath.sync = (names, { cwd, allowSymlinks, type }) => {
(0, condition_1.assertIsString)(cwd);
const fstat = getFstat.sync(allowSymlinks !== false);
for (const name of names) {
const fname = path_1.default.resolve(cwd, name);
const stat = fstat(fname);
if (checkType(stat, type !== null && type !== void 0 ? type : 'file'))
return fname;
}
return undefined;
};
function getFstat(allowSymlinks) {
const fstat = allowSymlinks ? fs_1.promises.stat : fs_1.promises.lstat;
return (fname) => __awaiter(this, void 0, void 0, function* () {
try {
return yield fstat(fname); // Need to await if there is an error
}
catch (_a) {
return undefined;
}
});
}
getFstat.sync = (allowSymlinks) => {
const fstat = allowSymlinks ? fs_1.default.statSync : fs_1.default.lstatSync;
return (fname) => {
try {
return fstat(fname);
}
catch (_a) {
return undefined;
}
};
};
function checkType(stat, type) {
if (!stat)
return false;
switch (type) {
case 'file':
return stat.isFile();
case 'directory':
return stat.isDirectory();
}
throw Error(`Invalid type: ${type}`);
}