UNPKG

4.71 kBJavaScriptView Raw
1"use strict";
2
3const pathUtil = require("path");
4const treeWalker = require("./utils/tree_walker");
5const inspect = require("./inspect");
6const matcher = require("./utils/matcher");
7const validate = require("./utils/validate");
8
9const validateInput = (methodName, path, options) => {
10 const methodSignature = `${methodName}([path], options)`;
11 validate.argument(methodSignature, "path", path, ["string"]);
12 validate.options(methodSignature, "options", options, {
13 matching: ["string", "array of string"],
14 files: ["boolean"],
15 directories: ["boolean"],
16 recursive: ["boolean"],
17 ignoreCase: ["boolean"]
18 });
19};
20
21const normalizeOptions = options => {
22 const opts = options || {};
23 // defaults:
24 if (opts.files === undefined) {
25 opts.files = true;
26 }
27 if (opts.ignoreCase === undefined) {
28 opts.ignoreCase = false;
29 }
30 if (opts.directories === undefined) {
31 opts.directories = false;
32 }
33 if (opts.recursive === undefined) {
34 opts.recursive = true;
35 }
36 return opts;
37};
38
39const processFoundObjects = (foundObjects, cwd) => {
40 return foundObjects.map(inspectObj => {
41 return pathUtil.relative(cwd, inspectObj.absolutePath);
42 });
43};
44
45const generatePathDoesntExistError = path => {
46 const err = new Error(`Path you want to find stuff in doesn't exist ${path}`);
47 err.code = "ENOENT";
48 return err;
49};
50
51const generatePathNotDirectoryError = path => {
52 const err = new Error(
53 `Path you want to find stuff in must be a directory ${path}`
54 );
55 err.code = "ENOTDIR";
56 return err;
57};
58
59// ---------------------------------------------------------
60// Sync
61// ---------------------------------------------------------
62
63const findSync = (path, options) => {
64 const foundInspectObjects = [];
65 const matchesAnyOfGlobs = matcher.create(
66 path,
67 options.matching,
68 options.ignoreCase
69 );
70
71 let maxLevelsDeep = Infinity;
72 if (options.recursive === false) {
73 maxLevelsDeep = 1;
74 }
75
76 treeWalker.sync(
77 path,
78 {
79 maxLevelsDeep,
80 inspectOptions: {
81 absolutePath: true,
82 symlinks: "follow"
83 }
84 },
85 (itemPath, item) => {
86 if (item && itemPath !== path && matchesAnyOfGlobs(itemPath)) {
87 if (
88 (item.type === "file" && options.files === true) ||
89 (item.type === "dir" && options.directories === true)
90 ) {
91 foundInspectObjects.push(item);
92 }
93 }
94 }
95 );
96
97 return processFoundObjects(foundInspectObjects, options.cwd);
98};
99
100const findSyncInit = (path, options) => {
101 const entryPointInspect = inspect.sync(path, { symlinks: "follow" });
102 if (entryPointInspect === undefined) {
103 throw generatePathDoesntExistError(path);
104 } else if (entryPointInspect.type !== "dir") {
105 throw generatePathNotDirectoryError(path);
106 }
107
108 return findSync(path, normalizeOptions(options));
109};
110
111// ---------------------------------------------------------
112// Async
113// ---------------------------------------------------------
114
115const findAsync = (path, options) => {
116 return new Promise((resolve, reject) => {
117 const foundInspectObjects = [];
118 const matchesAnyOfGlobs = matcher.create(
119 path,
120 options.matching,
121 options.ignoreCase
122 );
123
124 let maxLevelsDeep = Infinity;
125 if (options.recursive === false) {
126 maxLevelsDeep = 1;
127 }
128
129 const walker = treeWalker
130 .stream(path, {
131 maxLevelsDeep,
132 inspectOptions: {
133 absolutePath: true,
134 symlinks: "follow"
135 }
136 })
137 .on("readable", () => {
138 const data = walker.read();
139 if (
140 data &&
141 data.item &&
142 data.path !== path &&
143 matchesAnyOfGlobs(data.path)
144 ) {
145 const item = data.item;
146 if (
147 (item.type === "file" && options.files === true) ||
148 (item.type === "dir" && options.directories === true)
149 ) {
150 foundInspectObjects.push(item);
151 }
152 }
153 })
154 .on("error", reject)
155 .on("end", () => {
156 resolve(processFoundObjects(foundInspectObjects, options.cwd));
157 });
158 });
159};
160
161const findAsyncInit = (path, options) => {
162 return inspect.async(path, { symlinks: "follow" }).then(entryPointInspect => {
163 if (entryPointInspect === undefined) {
164 throw generatePathDoesntExistError(path);
165 } else if (entryPointInspect.type !== "dir") {
166 throw generatePathNotDirectoryError(path);
167 }
168 return findAsync(path, normalizeOptions(options));
169 });
170};
171
172// ---------------------------------------------------------
173// API
174// ---------------------------------------------------------
175
176exports.validateInput = validateInput;
177exports.sync = findSyncInit;
178exports.async = findAsyncInit;