1 | "use strict";
|
2 |
|
3 | const pathUtil = require("path");
|
4 | const treeWalker = require("./utils/tree_walker");
|
5 | const inspect = require("./inspect");
|
6 | const matcher = require("./utils/matcher");
|
7 | const validate = require("./utils/validate");
|
8 |
|
9 | const 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 |
|
21 | const normalizeOptions = options => {
|
22 | const opts = options || {};
|
23 |
|
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 |
|
39 | const processFoundObjects = (foundObjects, cwd) => {
|
40 | return foundObjects.map(inspectObj => {
|
41 | return pathUtil.relative(cwd, inspectObj.absolutePath);
|
42 | });
|
43 | };
|
44 |
|
45 | const 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 |
|
51 | const 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 |
|
61 |
|
62 |
|
63 | const 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 |
|
100 | const 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 |
|
113 |
|
114 |
|
115 | const 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 |
|
161 | const 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 |
|
174 |
|
175 |
|
176 | exports.validateInput = validateInput;
|
177 | exports.sync = findSyncInit;
|
178 | exports.async = findAsyncInit;
|