@expo/metro-file-map 55.0.0-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/README.md +1 -0
  2. package/build/Watcher.d.ts +53 -0
  3. package/build/Watcher.js +249 -0
  4. package/build/cache/DiskCacheManager.d.ts +25 -0
  5. package/build/cache/DiskCacheManager.js +110 -0
  6. package/build/constants.d.ts +23 -0
  7. package/build/constants.js +27 -0
  8. package/build/crawlers/node/fallback.d.ts +20 -0
  9. package/build/crawlers/node/fallback.js +148 -0
  10. package/build/crawlers/node/index.d.ts +10 -0
  11. package/build/crawlers/node/index.js +152 -0
  12. package/build/crawlers/watchman/index.d.ts +8 -0
  13. package/build/crawlers/watchman/index.js +288 -0
  14. package/build/crawlers/watchman/planQuery.d.ts +31 -0
  15. package/build/crawlers/watchman/planQuery.js +99 -0
  16. package/build/index.d.ts +140 -0
  17. package/build/index.js +836 -0
  18. package/build/lib/FileProcessor.d.ts +42 -0
  19. package/build/lib/FileProcessor.js +180 -0
  20. package/build/lib/FileSystemChangeAggregator.d.ts +18 -0
  21. package/build/lib/FileSystemChangeAggregator.js +114 -0
  22. package/build/lib/RootPathUtils.d.ts +24 -0
  23. package/build/lib/RootPathUtils.js +311 -0
  24. package/build/lib/TreeFS.d.ts +161 -0
  25. package/build/lib/TreeFS.js +1006 -0
  26. package/build/lib/checkWatchmanCapabilities.d.ts +9 -0
  27. package/build/lib/checkWatchmanCapabilities.js +50 -0
  28. package/build/lib/normalizePathSeparatorsToPosix.d.ts +8 -0
  29. package/build/lib/normalizePathSeparatorsToPosix.js +20 -0
  30. package/build/lib/normalizePathSeparatorsToSystem.d.ts +8 -0
  31. package/build/lib/normalizePathSeparatorsToSystem.js +20 -0
  32. package/build/lib/removeOverlappingRoots.d.ts +10 -0
  33. package/build/lib/removeOverlappingRoots.js +37 -0
  34. package/build/lib/rootRelativeCacheKeys.d.ts +11 -0
  35. package/build/lib/rootRelativeCacheKeys.js +56 -0
  36. package/build/lib/sorting.d.ts +8 -0
  37. package/build/lib/sorting.js +31 -0
  38. package/build/plugins/DependencyPlugin.d.ts +23 -0
  39. package/build/plugins/DependencyPlugin.js +61 -0
  40. package/build/plugins/FileDataPlugin.d.ts +28 -0
  41. package/build/plugins/FileDataPlugin.js +46 -0
  42. package/build/plugins/HastePlugin.d.ts +32 -0
  43. package/build/plugins/HastePlugin.js +358 -0
  44. package/build/plugins/MockPlugin.d.ts +27 -0
  45. package/build/plugins/MockPlugin.js +157 -0
  46. package/build/plugins/dependencies/dependencyExtractor.d.ts +7 -0
  47. package/build/plugins/dependencies/dependencyExtractor.js +66 -0
  48. package/build/plugins/dependencies/worker.d.ts +18 -0
  49. package/build/plugins/dependencies/worker.js +30 -0
  50. package/build/plugins/haste/DuplicateHasteCandidatesError.d.ts +14 -0
  51. package/build/plugins/haste/DuplicateHasteCandidatesError.js +51 -0
  52. package/build/plugins/haste/HasteConflictsError.d.ts +12 -0
  53. package/build/plugins/haste/HasteConflictsError.js +49 -0
  54. package/build/plugins/haste/computeConflicts.d.ts +19 -0
  55. package/build/plugins/haste/computeConflicts.js +74 -0
  56. package/build/plugins/haste/getPlatformExtension.d.ts +7 -0
  57. package/build/plugins/haste/getPlatformExtension.js +19 -0
  58. package/build/plugins/haste/worker.d.ts +16 -0
  59. package/build/plugins/haste/worker.js +48 -0
  60. package/build/plugins/mocks/getMockName.d.ts +8 -0
  61. package/build/plugins/mocks/getMockName.js +17 -0
  62. package/build/ts-declarations/fb-watchman.d.ts +20 -0
  63. package/build/ts-declarations/fb-watchman.js +2 -0
  64. package/build/types.d.ts +404 -0
  65. package/build/types.js +8 -0
  66. package/build/watchers/AbstractWatcher.d.ts +30 -0
  67. package/build/watchers/AbstractWatcher.js +97 -0
  68. package/build/watchers/FallbackWatcher.d.ts +18 -0
  69. package/build/watchers/FallbackWatcher.js +411 -0
  70. package/build/watchers/NativeWatcher.d.ts +39 -0
  71. package/build/watchers/NativeWatcher.js +156 -0
  72. package/build/watchers/RecrawlWarning.d.ts +18 -0
  73. package/build/watchers/RecrawlWarning.js +59 -0
  74. package/build/watchers/WatchmanWatcher.d.ts +22 -0
  75. package/build/watchers/WatchmanWatcher.js +263 -0
  76. package/build/watchers/common.d.ts +39 -0
  77. package/build/watchers/common.js +60 -0
  78. package/build/worker.d.ts +24 -0
  79. package/build/worker.js +80 -0
  80. package/build/workerExclusionList.d.ts +8 -0
  81. package/build/workerExclusionList.js +57 -0
  82. package/package.json +54 -0
@@ -0,0 +1,311 @@
1
+ "use strict";
2
+ /**
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.RootPathUtils = void 0;
13
+ exports.getAncestorOfRootIdx = getAncestorOfRootIdx;
14
+ exports.pathsToPattern = pathsToPattern;
15
+ const invariant_1 = __importDefault(require("invariant"));
16
+ const path_1 = __importDefault(require("path"));
17
+ const normalizePathSeparatorsToSystem_1 = __importDefault(require("./normalizePathSeparatorsToSystem"));
18
+ /**
19
+ * This module provides path utility functions - similar to `node:path` -
20
+ * optimised for Metro's use case (many paths, few roots) under assumptions
21
+ * typically safe to make within Metro - namely:
22
+ *
23
+ * - All input path separators must be system-native.
24
+ * - Double/redundant separators like '/foo//bar' are not supported.
25
+ * - All characters except separators are assumed to be valid in path segments.
26
+ *
27
+ * - A "well-formed" path is any path following the rules above.
28
+ * - A "normal" path is a root-relative well-formed path with no redundant
29
+ * indirections. Normal paths have no leading './`, and the normal path of
30
+ * the root is the empty string.
31
+ *
32
+ * Output and input paths are at least well-formed (normal where indicated by
33
+ * naming).
34
+ *
35
+ * Trailing path separators are preserved, except for fs roots in
36
+ * normalToAbsolute (fs roots always have a trailing separator), and the
37
+ * project root in absoluteToNormal and relativeToNormal (the project root is
38
+ * always the empty string, and is always a directory, so a trailing separator
39
+ * is redundant).
40
+ *
41
+ * As of Node 20, absoluteToNormal is ~8x faster than `path.relative` and
42
+ * `normalToAbsolute` is ~20x faster than `path.resolve`, benchmarked on the
43
+ * real inputs from building FB's product graph. Some well-formed inputs
44
+ * (e.g., /project/./foo/../bar), are handled but not optimised, and we fall
45
+ * back to `node:path` equivalents in those cases.
46
+ */
47
+ const UP_FRAGMENT_SEP = '..' + path_1.default.sep;
48
+ const SEP_UP_FRAGMENT = path_1.default.sep + '..';
49
+ const UP_FRAGMENT_SEP_LENGTH = UP_FRAGMENT_SEP.length;
50
+ const CURRENT_FRAGMENT = '.' + path_1.default.sep;
51
+ class RootPathUtils {
52
+ #rootDir;
53
+ #rootDirnames;
54
+ #rootParts;
55
+ #rootDepth;
56
+ constructor(rootDir) {
57
+ this.#rootDir = rootDir;
58
+ const rootDirnames = [];
59
+ for (let next = rootDir, previous = null; previous !== next; previous = next, next = path_1.default.dirname(next)) {
60
+ rootDirnames.push(next);
61
+ }
62
+ this.#rootDirnames = rootDirnames;
63
+ this.#rootDepth = rootDirnames.length - 1;
64
+ const rootParts = rootDir.split(path_1.default.sep);
65
+ // If rootDir is a filesystem root (C:\ or /), it will end in a separator and
66
+ // give a spurious empty entry at the end of rootParts.
67
+ if (this.#rootDepth === 0) {
68
+ rootParts.pop();
69
+ }
70
+ this.#rootParts = rootParts;
71
+ }
72
+ getBasenameOfNthAncestor(n) {
73
+ return this.#rootParts[this.#rootParts.length - 1 - n];
74
+ }
75
+ getParts() {
76
+ return this.#rootParts;
77
+ }
78
+ // absolutePath may be any well-formed absolute path.
79
+ absoluteToNormal(absolutePath) {
80
+ let endOfMatchingPrefix = 0;
81
+ let lastMatchingPartIdx = 0;
82
+ for (let nextPart = this.#rootParts[0], nextLength = nextPart.length; nextPart != null &&
83
+ // Check that absolutePath is equal to nextPart + '/' or ends with
84
+ // nextPart, starting from endOfMatchingPrefix.
85
+ absolutePath.startsWith(nextPart, endOfMatchingPrefix) &&
86
+ (absolutePath.length === endOfMatchingPrefix + nextLength ||
87
+ absolutePath[endOfMatchingPrefix + nextLength] === path_1.default.sep);) {
88
+ // Move our matching pointer forward and load the next part.
89
+ endOfMatchingPrefix += nextLength + 1;
90
+ nextPart = this.#rootParts[++lastMatchingPartIdx];
91
+ nextLength = nextPart?.length ?? 0;
92
+ }
93
+ // If our root is /project/root and we're given /project/bar/foo.js, we
94
+ // have matched up to '/project', and will need to return a path
95
+ // beginning '../' (one prepended indirection, to go up from 'root').
96
+ //
97
+ // If we're given /project/../project2/otherroot, we have one level of
98
+ // indirection up to prepend in the same way as above. There's another
99
+ // explicit indirection already present in the input - we'll account for
100
+ // that in tryCollapseIndirectionsInSuffix.
101
+ const upIndirectionsToPrepend = this.#rootParts.length - lastMatchingPartIdx;
102
+ return (this.#tryCollapseIndirectionsInSuffix(absolutePath, endOfMatchingPrefix, upIndirectionsToPrepend)?.collapsedPath ?? this.#slowAbsoluteToNormal(absolutePath));
103
+ }
104
+ #slowAbsoluteToNormal(absolutePath) {
105
+ const endsWithSep = absolutePath.endsWith(path_1.default.sep);
106
+ const result = path_1.default.relative(this.#rootDir, absolutePath);
107
+ return endsWithSep && !result.endsWith(path_1.default.sep) ? result + path_1.default.sep : result;
108
+ }
109
+ // `normalPath` is assumed to be normal (root-relative, no redundant
110
+ // indirection), per the definition above.
111
+ normalToAbsolute(normalPath) {
112
+ let left = this.#rootDir;
113
+ let i = 0;
114
+ let pos = 0;
115
+ while (normalPath.startsWith(UP_FRAGMENT_SEP, pos) ||
116
+ (normalPath.endsWith('..') && normalPath.length === 2 + pos)) {
117
+ left = this.#rootDirnames[i === this.#rootDepth ? this.#rootDepth : ++i];
118
+ pos += UP_FRAGMENT_SEP_LENGTH;
119
+ }
120
+ const right = pos === 0 ? normalPath : normalPath.slice(pos);
121
+ if (right.length === 0) {
122
+ return left;
123
+ }
124
+ // left may already end in a path separator only if it is a filesystem root,
125
+ // '/' or 'X:\'.
126
+ if (i === this.#rootDepth) {
127
+ return left + right;
128
+ }
129
+ return left + path_1.default.sep + right;
130
+ }
131
+ relativeToNormal(relativePath) {
132
+ return (this.#tryCollapseIndirectionsInSuffix(relativePath, 0, 0)?.collapsedPath ??
133
+ path_1.default.relative(this.#rootDir, path_1.default.join(this.#rootDir, relativePath)));
134
+ }
135
+ resolveSymlinkToNormal(symlinkNormalPath, readlinkResult) {
136
+ let target = (0, normalizePathSeparatorsToSystem_1.default)(readlinkResult);
137
+ // WARN: This only applies to Windows + Node 20 case, where the value is completely
138
+ // unnormalized and a trailing slash may be returned
139
+ if (target[target.length - 1] === path_1.default.sep) {
140
+ target = target.slice(0, -1);
141
+ }
142
+ if (path_1.default.isAbsolute(target)) {
143
+ return this.absoluteToNormal(target);
144
+ }
145
+ // Resolve relative to the symlink's containing directory, expressed as
146
+ // a root-relative (possibly non-normal) path, then normalize
147
+ const sepIdx = symlinkNormalPath.lastIndexOf(path_1.default.sep);
148
+ const rootRelativeTarget = sepIdx === -1 ? target : symlinkNormalPath.slice(0, sepIdx) + path_1.default.sep + target;
149
+ return this.relativeToNormal(rootRelativeTarget);
150
+ }
151
+ // If a path is a direct ancestor of the project root (or the root itself),
152
+ // return a number with the degrees of separation, e.g. root=0, parent=1,..
153
+ // or null otherwise.
154
+ getAncestorOfRootIdx(normalPath) {
155
+ if (normalPath === '') {
156
+ return 0;
157
+ }
158
+ if (normalPath === '..') {
159
+ return 1;
160
+ }
161
+ // Otherwise a *normal* path is only a root ancestor if it is a sequence of
162
+ // '../' segments followed by '..', so the length tells us the number of
163
+ // up fragments.
164
+ if (normalPath.endsWith(SEP_UP_FRAGMENT)) {
165
+ return (normalPath.length + 1) / 3;
166
+ }
167
+ return null;
168
+ }
169
+ // Takes a normal and relative path, and joins them efficiently into a normal
170
+ // path, including collapsing trailing '..' in the first part with leading
171
+ // project root segments in the relative part.
172
+ joinNormalToRelative(normalPath, relativePath) {
173
+ if (normalPath === '') {
174
+ return { collapsedSegments: 0, normalPath: relativePath };
175
+ }
176
+ if (relativePath === '') {
177
+ return { collapsedSegments: 0, normalPath };
178
+ }
179
+ const left = normalPath + path_1.default.sep;
180
+ const rawPath = left + relativePath;
181
+ if (normalPath === '..' || normalPath.endsWith(SEP_UP_FRAGMENT)) {
182
+ const collapsed = this.#tryCollapseIndirectionsInSuffix(rawPath, 0, 0);
183
+ (0, invariant_1.default)(collapsed != null, 'Failed to collapse');
184
+ return {
185
+ collapsedSegments: collapsed.collapsedSegments,
186
+ normalPath: collapsed.collapsedPath,
187
+ };
188
+ }
189
+ return {
190
+ collapsedSegments: 0,
191
+ normalPath: rawPath,
192
+ };
193
+ }
194
+ relative(from, to) {
195
+ return path_1.default.relative(from, to);
196
+ }
197
+ // Internal: Tries to collapse sequences like `../root/foo` for root
198
+ // `/project/root` down to the normal 'foo'.
199
+ #tryCollapseIndirectionsInSuffix(fullPath, // A string ending with the relative path to process
200
+ startOfRelativePart, // Index of the start of part to process
201
+ implicitUpIndirections // 0=root-relative, 1=dirname(root)-relative...
202
+ ) {
203
+ let totalUpIndirections = implicitUpIndirections;
204
+ let collapsedSegments = 0;
205
+ // Allow any sequence of indirection fragments at the start of the
206
+ // unmatched suffix e.g /project/[../../foo], but bail out to Node's
207
+ // path.relative if we find a possible indirection after any later segment,
208
+ // or on any "./" that isn't a "../".
209
+ for (let pos = startOfRelativePart;; pos += UP_FRAGMENT_SEP_LENGTH) {
210
+ const nextIndirection = fullPath.indexOf(CURRENT_FRAGMENT, pos);
211
+ if (nextIndirection === -1) {
212
+ // If we have any indirections, they may "collapse" if a subsequent
213
+ // segment re-enters a directory we had previously exited, e.g:
214
+ // /project/root/../root/foo should collapse to /project/root/foo' and
215
+ // return foo, not ../root/foo.
216
+ //
217
+ // We match each segment following redirections, in turn, against the
218
+ // part of the root path they may collapse into, and break on the first
219
+ // mismatch.
220
+ while (totalUpIndirections > 0) {
221
+ const segmentToMaybeCollapse = this.#rootParts[this.#rootParts.length - totalUpIndirections];
222
+ if (fullPath.startsWith(segmentToMaybeCollapse, pos) &&
223
+ // The following character should be either a separator or end of
224
+ // string
225
+ (fullPath.length === segmentToMaybeCollapse.length + pos ||
226
+ fullPath[segmentToMaybeCollapse.length + pos] === path_1.default.sep)) {
227
+ pos += segmentToMaybeCollapse.length + 1;
228
+ collapsedSegments++;
229
+ totalUpIndirections--;
230
+ }
231
+ else {
232
+ break;
233
+ }
234
+ }
235
+ // After collapsing we may have no more segments remaining (following
236
+ // '..' indirections). Ensure that we don't drop or add a trailing
237
+ // separator in this case by taking .slice(pos-1). In any other case,
238
+ // we know that fullPath[pos] is a separator.
239
+ if (pos >= fullPath.length) {
240
+ return {
241
+ collapsedPath: totalUpIndirections > 0
242
+ ? UP_FRAGMENT_SEP.repeat(totalUpIndirections - 1) + '..' + fullPath.slice(pos - 1)
243
+ : '',
244
+ collapsedSegments,
245
+ };
246
+ }
247
+ const right = pos > 0 ? fullPath.slice(pos) : fullPath;
248
+ if (right === '..' && totalUpIndirections >= this.#rootParts.length - 1) {
249
+ // If we have no right side (or an indirection that would take us
250
+ // below the root), just ensure we don't include a trailing separtor.
251
+ return {
252
+ collapsedPath: UP_FRAGMENT_SEP.repeat(totalUpIndirections).slice(0, -1),
253
+ collapsedSegments,
254
+ };
255
+ }
256
+ // Optimisation for the common case, saves a concatenation.
257
+ if (totalUpIndirections === 0) {
258
+ return { collapsedPath: right, collapsedSegments };
259
+ }
260
+ return {
261
+ collapsedPath: UP_FRAGMENT_SEP.repeat(totalUpIndirections) + right,
262
+ collapsedSegments,
263
+ };
264
+ }
265
+ // Cap the number of indirections at the total number of root segments.
266
+ // File systems treat '..' at the root as '.'.
267
+ if (totalUpIndirections < this.#rootParts.length - 1) {
268
+ totalUpIndirections++;
269
+ }
270
+ if (nextIndirection !== pos + 1 || // Fallback when ./ later in the path, or leading
271
+ fullPath[pos] !== '.' // and for anything other than a leading ../
272
+ ) {
273
+ return null;
274
+ }
275
+ }
276
+ }
277
+ }
278
+ exports.RootPathUtils = RootPathUtils;
279
+ function getAncestorOfRootIdx(normalPath) {
280
+ let pos = 0;
281
+ while (normalPath.startsWith(UP_FRAGMENT_SEP, pos)) {
282
+ pos += UP_FRAGMENT_SEP_LENGTH;
283
+ }
284
+ if (normalPath.length === pos + 2 &&
285
+ normalPath.charCodeAt(pos) === 46 &&
286
+ normalPath.charCodeAt(pos + 1) === 46) {
287
+ return pos / UP_FRAGMENT_SEP_LENGTH + 1;
288
+ }
289
+ return pos / UP_FRAGMENT_SEP_LENGTH;
290
+ }
291
+ function pathsToPattern(paths, pathUtils) {
292
+ if (paths.length === 0) {
293
+ return null;
294
+ }
295
+ const pathsPatterns = paths.map((input) => {
296
+ let pattern = pathUtils.absoluteToNormal(input);
297
+ // When pattern is '' (root === rootDir), match any normal path that
298
+ // doesn't escape the root via '..' indirections.
299
+ if (pattern === '') {
300
+ return `(?!\\.\\.(?:\\${path_1.default.sep}|$))`;
301
+ }
302
+ // Append separator so that 'src' matches 'src/foo' but not 'src2'.
303
+ if (!pattern.endsWith(path_1.default.sep)) {
304
+ pattern += path_1.default.sep;
305
+ }
306
+ // Escape all regex-special characters.
307
+ // eslint-disable-next-line no-useless-escape
308
+ return pattern.replace(/[\-\[\]\{\}\(\)\*\+\?\.\\\^\$\|\/]/g, '\\$&');
309
+ });
310
+ return new RegExp(`^(?:${pathsPatterns.join('|')})`);
311
+ }
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+ import type { CacheData, FallbackFilesystem, FileData, FileMetadata, FileStats, FileSystemListener, LookupResult, MutableFileSystem, Path, ProcessFileFunction } from '../types';
8
+ type DirectoryNode = Map<string, MixedNode | null>;
9
+ type FileNode = FileMetadata;
10
+ type MixedNode = FileNode | DirectoryNode;
11
+ interface DeserializedSnapshotInput {
12
+ rootDir: string;
13
+ fileSystemData: DirectoryNode;
14
+ processFile: ProcessFileFunction;
15
+ fallbackFilesystem?: FallbackFilesystem | null | undefined;
16
+ roots?: readonly string[];
17
+ serverRoot?: string | null | undefined;
18
+ }
19
+ interface TreeFSOptions {
20
+ rootDir: Path;
21
+ files?: FileData;
22
+ processFile: ProcessFileFunction;
23
+ fallbackFilesystem?: FallbackFilesystem | null | undefined;
24
+ roots?: readonly string[];
25
+ serverRoot?: string | null | undefined;
26
+ }
27
+ interface MatchFilesOptions {
28
+ readonly filter?: RegExp | null;
29
+ readonly filterCompareAbsolute?: boolean;
30
+ readonly filterComparePosix?: boolean;
31
+ readonly follow?: boolean;
32
+ readonly recursive?: boolean;
33
+ readonly rootDir?: Path | null;
34
+ }
35
+ interface MetadataIteratorOptions {
36
+ readonly includeSymlinks: boolean;
37
+ readonly includeNodeModules: boolean;
38
+ }
39
+ /**
40
+ * OVERVIEW:
41
+ *
42
+ * TreeFS is Metro's in-memory representation of the file system. It is
43
+ * structured as a tree of non-empty maps and leaves (tuples), with the root
44
+ * node representing the given `rootDir`, typically Metro's _project root_
45
+ * (not a filesystem root). Map keys are path segments, and branches outside
46
+ * the project root are accessed via `'..'`.
47
+ *
48
+ * EXAMPLE:
49
+ *
50
+ * For a root dir '/data/project', the file '/data/other/app/index.js' would
51
+ * have metadata at #rootNode.get('..').get('other').get('app').get('index.js')
52
+ *
53
+ * SERIALISATION:
54
+ *
55
+ * #rootNode is designed to be directly serialisable and directly portable (for
56
+ * a given project) between different root directories and operating systems.
57
+ *
58
+ * SYMLINKS:
59
+ *
60
+ * Symlinks are represented as nodes whose metadata contains their literal
61
+ * target. Literal targets are resolved to normal paths at runtime, and cached.
62
+ * If a symlink is encountered during traversal, we restart traversal at the
63
+ * root node targeting join(normal symlink target, remaining path suffix).
64
+ *
65
+ * NODE TYPES:
66
+ *
67
+ * - A directory (including a parent directory at '..') is represented by a
68
+ * `Map` of basenames to any other node type.
69
+ * - A file is represented by an `Array` (tuple) of metadata, of which:
70
+ * - A regular file has node[H.SYMLINK] === 0
71
+ * - A symlink has node[H.SYMLINK] === 1 or
72
+ * typeof node[H.SYMLINK] === 'string', where a string is the literal
73
+ * content of the symlink (i.e. from readlink), if known.
74
+ *
75
+ * TERMINOLOGY:
76
+ *
77
+ * - mixedPath
78
+ * A root-relative or absolute path
79
+ * - relativePath
80
+ * A root-relative path
81
+ * - normalPath
82
+ * A root-relative, normalised path (no extraneous '.' or '..'), may have a
83
+ * single trailing slash
84
+ * - canonicalPath
85
+ * A root-relative, normalised, real path (no symlinks in dirname), never has
86
+ * a trailing slash
87
+ */
88
+ export default class TreeFS implements MutableFileSystem {
89
+ #private;
90
+ constructor(opts: TreeFSOptions);
91
+ getSerializableSnapshot(): CacheData['fileSystemData'];
92
+ static fromDeserializedSnapshot(args: DeserializedSnapshotInput): TreeFS;
93
+ getSize(mixedPath: Path): number | null;
94
+ getDifference(files: FileData, options?: {
95
+ /**
96
+ * Only consider files under this normal subdirectory when computing
97
+ * removedFiles. If not provided, all files in the file system are
98
+ * considered.
99
+ */
100
+ readonly subpath?: string;
101
+ }): {
102
+ changedFiles: FileData;
103
+ removedFiles: Set<string>;
104
+ };
105
+ getMtimeByNormalPath(normalPath: Path): number | null;
106
+ getSha1(mixedPath: Path): string | null;
107
+ getOrComputeSha1(mixedPath: Path): Promise<{
108
+ sha1: string;
109
+ content?: Buffer;
110
+ } | null | undefined>;
111
+ exists(mixedPath: Path): boolean;
112
+ lookup(mixedPath: Path): LookupResult;
113
+ getAllFiles(): Path[];
114
+ linkStats(mixedPath: Path): FileStats | null;
115
+ /**
116
+ * Given a search context, return a list of file paths matching the query.
117
+ * The query matches against normalized paths which start with `./`,
118
+ * for example: `a/b.js` -> `./a/b.js`
119
+ */
120
+ matchFiles(opts: MatchFilesOptions): Generator<Path>;
121
+ addOrModify(mixedPath: Path, metadata: FileMetadata, changeListener?: FileSystemListener): void;
122
+ bulkAddOrModify(addedOrModifiedFiles: FileData, changeListener?: FileSystemListener): void;
123
+ remove(mixedPath: Path, changeListener?: FileSystemListener): void;
124
+ /**
125
+ * Given a start path (which need not exist), a subpath and type, and
126
+ * optionally a 'breakOnSegment', performs the following:
127
+ *
128
+ * X = mixedStartPath
129
+ * do
130
+ * if basename(X) === opts.breakOnSegment
131
+ * return null
132
+ * if X + subpath exists and has type opts.subpathType
133
+ * return {
134
+ * absolutePath: realpath(X + subpath)
135
+ * containerRelativePath: relative(mixedStartPath, X)
136
+ * }
137
+ * X = dirname(X)
138
+ * while X !== dirname(X)
139
+ *
140
+ * If opts.invalidatedBy is given, collects all absolute, real paths that if
141
+ * added or removed may invalidate this result.
142
+ *
143
+ * Useful for finding the closest package scope (subpath: package.json,
144
+ * type f, breakOnSegment: node_modules) or closest potential package root
145
+ * (subpath: node_modules/pkg, type: d) in Node.js resolution.
146
+ */
147
+ hierarchicalLookup(mixedStartPath: string, subpath: string, opts: {
148
+ breakOnSegment: string | null | undefined;
149
+ invalidatedBy: Set<string> | null | undefined;
150
+ subpathType: 'f' | 'd';
151
+ }): {
152
+ absolutePath: string;
153
+ containerRelativePath: string;
154
+ } | null | undefined;
155
+ metadataIterator(opts: MetadataIteratorOptions): Generator<{
156
+ baseName: string;
157
+ canonicalPath: string;
158
+ metadata: FileMetadata;
159
+ }>;
160
+ }
161
+ export {};