getDescriptionFile = (
	fs,
	directory,
	descriptionFiles,
	callback,
	satisfiesDescriptionFileData,
	checkedFilePaths = new Set()
) => {
	let i = 0;

	const satisfiesDescriptionFileDataInternal = {
		check: satisfiesDescriptionFileData,
		checkedFilePaths
	};

	const tryLoadCurrent = () => {
		if (i >= descriptionFiles.length) {
			const parentDirectory = dirname(fs, directory);
			if (!parentDirectory || parentDirectory === directory) {
				return callback(
					null,
					undefined,
					Array.from(satisfiesDescriptionFileDataInternal.checkedFilePaths)
				);
			}
			return getDescriptionFile(
				fs,
				parentDirectory,
				descriptionFiles,
				callback,
				satisfiesDescriptionFileDataInternal.check,
				satisfiesDescriptionFileDataInternal.checkedFilePaths
			);
		}
		const filePath = join(fs, directory, descriptionFiles[i]);
		readJson(fs, filePath, (err, data) => {
			if (err) {
				if ("code" in err && err.code === "ENOENT") {
					i++;
					return tryLoadCurrent();
				}
				return callback(err);
			}
			if (!data || typeof data !== "object" || Array.isArray(data)) {
				return callback(
					new Error(`Description file ${filePath} is not an object`)
				);
			}
			if (
				typeof satisfiesDescriptionFileDataInternal.check === "function" &&
				!satisfiesDescriptionFileDataInternal.check({ data, path: filePath })
			) {
				i++;
				satisfiesDescriptionFileDataInternal.checkedFilePaths.add(filePath);
				return tryLoadCurrent();
			}
			callback(null, { data, path: filePath });
		});
	};
	tryLoadCurrent();
}
@param {InputFileSystem} fs file system
@param {string} directory directory to start looking into
@param {string[]} descriptionFiles possible description filenames
@param {(err?: Error | null, descriptionFile?: DescriptionFile, paths?: string[]) => void} callback callback
@param {(descriptionFile?: DescriptionFile) => boolean} satisfiesDescriptionFileData file data compliance check
@param {Set<string>} checkedFilePaths set of file paths that have been checked