@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,22 @@
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 { AbstractWatcher } from './AbstractWatcher';
8
+ import type { WatcherOptions } from './common';
9
+ /**
10
+ * Watches `dir`.
11
+ */
12
+ export default class WatchmanWatcher extends AbstractWatcher {
13
+ #private;
14
+ readonly subscriptionName: string;
15
+ constructor(dir: string, opts: WatcherOptions);
16
+ startWatching(): Promise<void>;
17
+ /**
18
+ * Closes the watcher.
19
+ */
20
+ stopWatching(): Promise<void>;
21
+ getPauseReason(): string | undefined | null;
22
+ }
@@ -0,0 +1,263 @@
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 __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
9
+ if (k2 === undefined) k2 = k;
10
+ var desc = Object.getOwnPropertyDescriptor(m, k);
11
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
12
+ desc = { enumerable: true, get: function() { return m[k]; } };
13
+ }
14
+ Object.defineProperty(o, k2, desc);
15
+ }) : (function(o, m, k, k2) {
16
+ if (k2 === undefined) k2 = k;
17
+ o[k2] = m[k];
18
+ }));
19
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
20
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
21
+ }) : function(o, v) {
22
+ o["default"] = v;
23
+ });
24
+ var __importStar = (this && this.__importStar) || (function () {
25
+ var ownKeys = function(o) {
26
+ ownKeys = Object.getOwnPropertyNames || function (o) {
27
+ var ar = [];
28
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
+ return ar;
30
+ };
31
+ return ownKeys(o);
32
+ };
33
+ return function (mod) {
34
+ if (mod && mod.__esModule) return mod;
35
+ var result = {};
36
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
+ __setModuleDefault(result, mod);
38
+ return result;
39
+ };
40
+ })();
41
+ var __importDefault = (this && this.__importDefault) || function (mod) {
42
+ return (mod && mod.__esModule) ? mod : { "default": mod };
43
+ };
44
+ Object.defineProperty(exports, "__esModule", { value: true });
45
+ const assert_1 = __importDefault(require("assert"));
46
+ const crypto_1 = require("crypto");
47
+ const fb_watchman_1 = __importDefault(require("fb-watchman"));
48
+ const invariant_1 = __importDefault(require("invariant"));
49
+ const AbstractWatcher_1 = require("./AbstractWatcher");
50
+ const RecrawlWarning_1 = __importDefault(require("./RecrawlWarning"));
51
+ const common = __importStar(require("./common"));
52
+ const normalizePathSeparatorsToSystem_1 = __importDefault(require("../lib/normalizePathSeparatorsToSystem"));
53
+ const debug = require('debug')('Metro:WatchmanWatcher');
54
+ const DELETE_EVENT = common.DELETE_EVENT;
55
+ const TOUCH_EVENT = common.TOUCH_EVENT;
56
+ const SUB_PREFIX = 'metro-file-map';
57
+ /**
58
+ * Watches `dir`.
59
+ */
60
+ class WatchmanWatcher extends AbstractWatcher_1.AbstractWatcher {
61
+ #client;
62
+ subscriptionName;
63
+ #watchProjectInfo;
64
+ #watchmanDeferStates;
65
+ #deferringStates = null;
66
+ constructor(dir, opts) {
67
+ const { watchmanDeferStates, ...baseOpts } = opts;
68
+ super(dir, baseOpts);
69
+ this.#watchmanDeferStates = watchmanDeferStates;
70
+ // Use a unique subscription name per process per watched directory
71
+ const watchKey = (0, crypto_1.createHash)('md5').update(this.root).digest('hex');
72
+ const readablePath = this.root
73
+ .replace(/[/\\]/g, '-') // \ and / to -
74
+ .replace(/[^\-\w]/g, ''); // Remove non-word/hyphen
75
+ this.subscriptionName = `${SUB_PREFIX}-${process.pid}-${readablePath}-${watchKey}`;
76
+ }
77
+ async startWatching() {
78
+ await new Promise((resolve, reject) => this.#init(resolve, reject));
79
+ }
80
+ /**
81
+ * Run the watchman `watch` command on the root and subscribe to changes.
82
+ */
83
+ #init(onReady, onError) {
84
+ if (this.#client) {
85
+ this.#client.removeAllListeners();
86
+ }
87
+ const self = this;
88
+ this.#client = new fb_watchman_1.default.Client();
89
+ this.#client.on('error', (error) => {
90
+ this.emitError(error);
91
+ });
92
+ this.#client.on('subscription', (changeEvent) => this.#handleChangeEvent(changeEvent));
93
+ this.#client.on('end', () => {
94
+ console.warn('[metro-file-map] Warning: Lost connection to Watchman, reconnecting..');
95
+ self.#init(() => { }, (error) => self.emitError(error));
96
+ });
97
+ this.#watchProjectInfo = null;
98
+ function getWatchRoot() {
99
+ return self.#watchProjectInfo ? self.#watchProjectInfo.root : self.root;
100
+ }
101
+ function onWatchProject(error, resp) {
102
+ if (error) {
103
+ onError(error);
104
+ return;
105
+ }
106
+ debug('Received watch-project response: %s', resp.relative_path);
107
+ handleWarning(resp);
108
+ // NB: Watchman outputs posix-separated paths even on Windows, convert
109
+ // them to system-native separators.
110
+ self.#watchProjectInfo = {
111
+ relativePath: resp.relative_path ? (0, normalizePathSeparatorsToSystem_1.default)(resp.relative_path) : '',
112
+ root: (0, normalizePathSeparatorsToSystem_1.default)(resp.watch),
113
+ };
114
+ self.#client.command(['clock', getWatchRoot()], onClock);
115
+ }
116
+ function onClock(error, resp) {
117
+ if (error) {
118
+ onError(error);
119
+ return;
120
+ }
121
+ debug('Received clock response: %s', resp.clock);
122
+ const watchProjectInfo = self.#watchProjectInfo;
123
+ (0, invariant_1.default)(watchProjectInfo != null, 'watch-project response should have been set before clock response');
124
+ handleWarning(resp);
125
+ const options = {
126
+ fields: ['name', 'exists', 'new', 'type', 'size', 'mtime_ms'],
127
+ since: resp.clock,
128
+ defer: self.#watchmanDeferStates,
129
+ relative_root: watchProjectInfo.relativePath,
130
+ };
131
+ // Make sure we honor the dot option if even we're not using globs.
132
+ if (self.globs.length === 0 && !self.dot) {
133
+ options.expression = [
134
+ 'match',
135
+ '**',
136
+ 'wholename',
137
+ {
138
+ includedotfiles: false,
139
+ },
140
+ ];
141
+ }
142
+ self.#client.command(['subscribe', getWatchRoot(), self.subscriptionName, options], onSubscribe);
143
+ }
144
+ const onSubscribe = (error, resp) => {
145
+ if (error) {
146
+ onError(error);
147
+ return;
148
+ }
149
+ debug('Received subscribe response: %s', resp.subscribe);
150
+ handleWarning(resp);
151
+ if (resp['asserted-states'] != null) {
152
+ this.#deferringStates = new Set(resp['asserted-states']);
153
+ }
154
+ onReady();
155
+ };
156
+ self.#client.command(['watch-project', getWatchRoot()], onWatchProject);
157
+ }
158
+ /**
159
+ * Handles a change event coming from the subscription.
160
+ */
161
+ #handleChangeEvent(resp) {
162
+ debug('Received subscription response: %s (fresh: %s, files: %s, enter: %s, leave: %s, clock: %s)', resp.subscription, resp.is_fresh_instance, resp.files?.length, resp['state-enter'], resp['state-leave'], resp.clock);
163
+ assert_1.default.equal(resp.subscription, this.subscriptionName, 'Invalid subscription event.');
164
+ if (Array.isArray(resp.files)) {
165
+ resp.files.forEach((change) => this.#handleFileChange(change, resp.clock));
166
+ }
167
+ const { 'state-enter': stateEnter, 'state-leave': stateLeave } = resp;
168
+ if (stateEnter != null && (this.#watchmanDeferStates ?? []).includes(stateEnter)) {
169
+ this.#deferringStates?.add(stateEnter);
170
+ debug('Watchman reports "%s" just started. Filesystem notifications are paused.', stateEnter);
171
+ }
172
+ if (stateLeave != null && (this.#watchmanDeferStates ?? []).includes(stateLeave)) {
173
+ this.#deferringStates?.delete(stateLeave);
174
+ debug('Watchman reports "%s" ended. Filesystem notifications resumed.', stateLeave);
175
+ }
176
+ }
177
+ /**
178
+ * Handles a single change event record.
179
+ */
180
+ #handleFileChange(changeDescriptor, rawClock) {
181
+ const self = this;
182
+ const watchProjectInfo = self.#watchProjectInfo;
183
+ (0, invariant_1.default)(watchProjectInfo != null, 'watch-project response should have been set before receiving subscription events');
184
+ const { name: relativePosixPath, new: isNew = false, exists = false, type, mtime_ms, size, } = changeDescriptor;
185
+ // Watchman emits posix-separated paths on Windows, which is inconsistent
186
+ // with other watchers. Normalize to system-native separators.
187
+ const relativePath = (0, normalizePathSeparatorsToSystem_1.default)(relativePosixPath);
188
+ debug('Handling change to: %s (new: %s, exists: %s, type: %s)', relativePath, isNew, exists, type);
189
+ // Ignore files of an unrecognized type
190
+ if (type != null && !(type === 'f' || type === 'd' || type === 'l')) {
191
+ return;
192
+ }
193
+ if (this.doIgnore(relativePath) ||
194
+ !common.includedByGlob(type, this.globs, this.dot, relativePath)) {
195
+ return;
196
+ }
197
+ const clock = typeof rawClock === 'string' && this.#watchProjectInfo != null
198
+ ? [this.#watchProjectInfo.root, rawClock]
199
+ : undefined;
200
+ if (!exists) {
201
+ self.emitFileEvent({ event: DELETE_EVENT, clock, relativePath });
202
+ }
203
+ else {
204
+ (0, invariant_1.default)(type != null && mtime_ms != null && size != null, 'Watchman file change event for "%s" missing some requested metadata. ' +
205
+ 'Got type: %s, mtime_ms: %s, size: %s', relativePath, type, mtime_ms, size);
206
+ if (
207
+ // Change event on dirs are mostly useless.
208
+ !(type === 'd' && !isNew)) {
209
+ const mtime = Number(mtime_ms);
210
+ self.emitFileEvent({
211
+ event: TOUCH_EVENT,
212
+ clock,
213
+ relativePath,
214
+ metadata: {
215
+ modifiedTime: mtime !== 0 ? mtime : null,
216
+ size,
217
+ type,
218
+ },
219
+ });
220
+ }
221
+ }
222
+ }
223
+ /**
224
+ * Closes the watcher.
225
+ */
226
+ async stopWatching() {
227
+ await super.stopWatching();
228
+ if (this.#client) {
229
+ this.#client.removeAllListeners();
230
+ this.#client.end();
231
+ }
232
+ this.#deferringStates = null;
233
+ }
234
+ getPauseReason() {
235
+ if (this.#deferringStates == null || this.#deferringStates.size === 0) {
236
+ return null;
237
+ }
238
+ const states = [...this.#deferringStates];
239
+ if (states.length === 1) {
240
+ return `The watch is in the '${states[0]}' state.`;
241
+ }
242
+ return `The watch is in the ${states
243
+ .slice(0, -1)
244
+ .map((s) => `'${s}'`)
245
+ .join(', ')} and '${states[states.length - 1]}' states.`;
246
+ }
247
+ }
248
+ exports.default = WatchmanWatcher;
249
+ /**
250
+ * Handles a warning in the watchman resp object.
251
+ */
252
+ function handleWarning(resp) {
253
+ if ('warning' in resp) {
254
+ if (RecrawlWarning_1.default.isRecrawlWarningDupe(resp.warning)) {
255
+ return true;
256
+ }
257
+ console.warn(resp.warning);
258
+ return true;
259
+ }
260
+ else {
261
+ return false;
262
+ }
263
+ }
@@ -0,0 +1,39 @@
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
+ * Originally vendored from
8
+ * https://github.com/amasad/sane/blob/64ff3a870c42e84f744086884bf55a4f9c22d376/src/common.js
9
+ */
10
+ import type { Stats } from 'fs';
11
+ import type { ChangeEventMetadata } from '../types';
12
+ export declare const DELETE_EVENT = "delete";
13
+ export declare const TOUCH_EVENT = "touch";
14
+ export declare const RECRAWL_EVENT = "recrawl";
15
+ export declare const ALL_EVENT = "all";
16
+ export interface WatcherOptions {
17
+ readonly globs: readonly string[];
18
+ readonly dot: boolean;
19
+ readonly ignored: RegExp | null | undefined;
20
+ readonly watchmanDeferStates: readonly string[];
21
+ readonly watchman?: unknown;
22
+ readonly watchmanPath?: string;
23
+ }
24
+ /**
25
+ * Checks a file relative path against the globs array.
26
+ */
27
+ export declare function includedByGlob(type: 'f' | 'l' | 'd' | null | undefined, globs: readonly string[], dot: boolean, relativePath: string): boolean;
28
+ /**
29
+ * Whether the given filePath matches the given RegExp, after converting
30
+ * (on Windows only) system separators to posix separators.
31
+ *
32
+ * Conversion to posix is for backwards compatibility with the previous
33
+ * anymatch matcher, which normlises all inputs[1]. This may not be consistent
34
+ * with other parts of metro-file-map.
35
+ *
36
+ * [1]: https://github.com/micromatch/anymatch/blob/3.1.1/index.js#L50
37
+ */
38
+ export declare const posixPathMatchesPattern: (pattern: RegExp, filePath: string) => boolean;
39
+ export declare function typeFromStat(stat: Stats): ChangeEventMetadata['type'] | null;
@@ -0,0 +1,60 @@
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
+ * Originally vendored from
9
+ * https://github.com/amasad/sane/blob/64ff3a870c42e84f744086884bf55a4f9c22d376/src/common.js
10
+ */
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.posixPathMatchesPattern = exports.ALL_EVENT = exports.RECRAWL_EVENT = exports.TOUCH_EVENT = exports.DELETE_EVENT = void 0;
16
+ exports.includedByGlob = includedByGlob;
17
+ exports.typeFromStat = typeFromStat;
18
+ const micromatch_1 = __importDefault(require("micromatch"));
19
+ const path_1 = __importDefault(require("path"));
20
+ exports.DELETE_EVENT = 'delete';
21
+ exports.TOUCH_EVENT = 'touch';
22
+ exports.RECRAWL_EVENT = 'recrawl';
23
+ exports.ALL_EVENT = 'all';
24
+ /**
25
+ * Checks a file relative path against the globs array.
26
+ */
27
+ function includedByGlob(type, globs, dot, relativePath) {
28
+ // For non-regular files or if there are no glob matchers, just respect the
29
+ // `dot` option to filter dotfiles if dot === false.
30
+ if (globs.length === 0 || type !== 'f') {
31
+ return dot || micromatch_1.default.some(relativePath, '**/*');
32
+ }
33
+ return micromatch_1.default.some(relativePath, globs, { dot });
34
+ }
35
+ /**
36
+ * Whether the given filePath matches the given RegExp, after converting
37
+ * (on Windows only) system separators to posix separators.
38
+ *
39
+ * Conversion to posix is for backwards compatibility with the previous
40
+ * anymatch matcher, which normlises all inputs[1]. This may not be consistent
41
+ * with other parts of metro-file-map.
42
+ *
43
+ * [1]: https://github.com/micromatch/anymatch/blob/3.1.1/index.js#L50
44
+ */
45
+ exports.posixPathMatchesPattern = path_1.default.sep === '/'
46
+ ? (pattern, filePath) => pattern.test(filePath)
47
+ : (pattern, filePath) => pattern.test(filePath.replaceAll(path_1.default.sep, '/'));
48
+ function typeFromStat(stat) {
49
+ // Note: These tests are not mutually exclusive - a symlink passes isFile
50
+ if (stat.isSymbolicLink()) {
51
+ return 'l';
52
+ }
53
+ if (stat.isDirectory()) {
54
+ return 'd';
55
+ }
56
+ if (stat.isFile()) {
57
+ return 'f'; // "Regular" file
58
+ }
59
+ return null;
60
+ }
@@ -0,0 +1,24 @@
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 { WorkerMessage, WorkerMetadata, WorkerSetupArgs } from './types';
8
+ /**
9
+ * Exposed for use outside a jest-worker context, ie when processing in-band.
10
+ */
11
+ export declare class Worker {
12
+ #private;
13
+ constructor({ plugins }: WorkerSetupArgs);
14
+ processFile(data: WorkerMessage): Promise<WorkerMetadata>;
15
+ }
16
+ /**
17
+ * Called automatically by jest-worker before the first call to `worker` when
18
+ * this module is used as worker thread or child process.
19
+ */
20
+ export declare function setup(args: WorkerSetupArgs): void;
21
+ /**
22
+ * Called by jest-worker with each workload
23
+ */
24
+ export declare function processFile(data: WorkerMessage): Promise<WorkerMetadata>;
@@ -0,0 +1,80 @@
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.Worker = void 0;
13
+ exports.setup = setup;
14
+ exports.processFile = processFile;
15
+ const crypto_1 = require("crypto");
16
+ const fs_1 = __importDefault(require("fs"));
17
+ function sha1hex(content) {
18
+ return (0, crypto_1.createHash)('sha1').update(content).digest('hex');
19
+ }
20
+ /**
21
+ * Exposed for use outside a jest-worker context, ie when processing in-band.
22
+ */
23
+ class Worker {
24
+ #plugins;
25
+ constructor({ plugins = [] }) {
26
+ this.#plugins = plugins.map(({ modulePath, setupArgs }) => {
27
+ const mod = require(modulePath);
28
+ const PluginWorker = mod.__esModule === true && 'default' in mod ? mod.default : mod;
29
+ return new PluginWorker(setupArgs);
30
+ });
31
+ }
32
+ async processFile(data) {
33
+ let contentPromise;
34
+ let sha1Promise;
35
+ const { computeSha1, filePath, pluginsToRun } = data;
36
+ const getContent = () => {
37
+ if (contentPromise == null) {
38
+ contentPromise = fs_1.default.promises.readFile(filePath);
39
+ }
40
+ return contentPromise;
41
+ };
42
+ const workerUtils = { getContent };
43
+ const pluginDataPromise = Promise.all(pluginsToRun.map((pluginIdx) => this.#plugins[pluginIdx].processFile(data, workerUtils)));
44
+ // If a SHA-1 is requested on update, compute it.
45
+ if (computeSha1) {
46
+ sha1Promise = getContent().then(sha1hex);
47
+ }
48
+ return contentPromise != null && data.maybeReturnContent
49
+ ? {
50
+ content: await contentPromise,
51
+ pluginData: await pluginDataPromise,
52
+ sha1: await sha1Promise,
53
+ }
54
+ : {
55
+ pluginData: await pluginDataPromise,
56
+ sha1: await sha1Promise,
57
+ };
58
+ }
59
+ }
60
+ exports.Worker = Worker;
61
+ let singletonWorker;
62
+ /**
63
+ * Called automatically by jest-worker before the first call to `worker` when
64
+ * this module is used as worker thread or child process.
65
+ */
66
+ function setup(args) {
67
+ if (singletonWorker) {
68
+ throw new Error('metro-file-map: setup() should only be called once');
69
+ }
70
+ singletonWorker = new Worker(args);
71
+ }
72
+ /**
73
+ * Called by jest-worker with each workload
74
+ */
75
+ async function processFile(data) {
76
+ if (!singletonWorker) {
77
+ throw new Error('metro-file-map: setup() must be called before processFile()');
78
+ }
79
+ return singletonWorker.processFile(data);
80
+ }
@@ -0,0 +1,8 @@
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
+ declare const extensions: ReadonlySet<string>;
8
+ export default extensions;
@@ -0,0 +1,57 @@
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
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ // This list is compiled after the MDN list of the most common MIME types (see
10
+ // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/
11
+ // Complete_list_of_MIME_types).
12
+ //
13
+ // Only MIME types starting with "image/", "video/", "audio/" and "font/" are
14
+ // reflected in the list. Adding "application/" is too risky since some text
15
+ // file formats (like ".js" and ".json") have an "application/" MIME type.
16
+ //
17
+ // Feel free to add any extensions that cannot be a Haste module.
18
+ const extensions = new Set([
19
+ // JSONs are never haste modules, except for "package.json", which is handled.
20
+ '.json',
21
+ // Image extensions.
22
+ '.bmp',
23
+ '.gif',
24
+ '.ico',
25
+ '.jpeg',
26
+ '.jpg',
27
+ '.png',
28
+ '.svg',
29
+ '.tiff',
30
+ '.tif',
31
+ '.webp',
32
+ // Video extensions.
33
+ '.avi',
34
+ '.mp4',
35
+ '.mpeg',
36
+ '.mpg',
37
+ '.ogv',
38
+ '.webm',
39
+ '.3gp',
40
+ '.3g2',
41
+ // Audio extensions.
42
+ '.aac',
43
+ '.midi',
44
+ '.mid',
45
+ '.mp3',
46
+ '.oga',
47
+ '.wav',
48
+ '.3gp',
49
+ '.3g2',
50
+ // Font extensions.
51
+ '.eot',
52
+ '.otf',
53
+ '.ttf',
54
+ '.woff',
55
+ '.woff2',
56
+ ]);
57
+ exports.default = extensions;
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@expo/metro-file-map",
3
+ "version": "55.0.0-0",
4
+ "description": "A metro-file-map fork for Expo used with the Metro bundler",
5
+ "main": "build/index.js",
6
+ "types": "build/index.d.ts",
7
+ "scripts": {
8
+ "build": "expo-module tsc",
9
+ "clean": "expo-module clean",
10
+ "lint": "expo-module lint",
11
+ "prepublishOnly": "pnpm run clean && pnpm run build",
12
+ "test": "expo-module test",
13
+ "typecheck": "expo-module typecheck",
14
+ "watch": "expo-module tsc --watch --preserveWatchOutput"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "https://github.com/expo/expo.git",
19
+ "directory": "packages/@expo/metro-file-map"
20
+ },
21
+ "keywords": [
22
+ "expo",
23
+ "metro"
24
+ ],
25
+ "license": "MIT",
26
+ "bugs": {
27
+ "url": "https://github.com/expo/expo/issues"
28
+ },
29
+ "homepage": "https://github.com/expo/expo/tree/main/packages/@expo/metro-file-map#readme",
30
+ "files": [
31
+ "build"
32
+ ],
33
+ "dependencies": {
34
+ "debug": "^4.3.4",
35
+ "fb-watchman": "^2.0.2",
36
+ "invariant": "^2.2.4",
37
+ "jest-worker": "^29.7.0",
38
+ "micromatch": "^4.0.4",
39
+ "walker": "^1.0.8"
40
+ },
41
+ "devDependencies": {
42
+ "@expo/metro": "56.0.0-rc.2",
43
+ "@types/debug": "^4.1.7",
44
+ "@types/fb-watchman": "^2.0.6",
45
+ "@types/invariant": "^2.2.37",
46
+ "@types/micromatch": "^4.0.10",
47
+ "@types/node": "^22.14.0",
48
+ "expo-module-scripts": "workspace:*",
49
+ "memfs": "^3.6.0"
50
+ },
51
+ "publishConfig": {
52
+ "access": "public"
53
+ }
54
+ }