UNPKG

@expo/metro-config

Version:

A Metro config for running React Native projects with the Metro bundler

115 lines 4.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FileStore = void 0; const FileStore_1 = __importDefault(require("@expo/metro/metro-cache/stores/FileStore")); const node_fs_1 = __importDefault(require("node:fs")); const node_path_1 = __importDefault(require("node:path")); const serializer_1 = require("./binary-file-store/serializer"); const file_store_1 = require("./file-store"); const { pid } = process; const debug = require('debug')('expo:metro:cache'); /** Pre-create shard directories all at once as a preflight task */ function ensureShardDirs(root) { const tasks = []; for (let i = 0; i < 256; i++) { const shard = ('0' + i.toString(16)).slice(-2); tasks.push(node_fs_1.default.promises.mkdir(node_path_1.default.join(root, shard), { recursive: true })); } return Promise.all(tasks).then(() => undefined); } async function renameWithRetry(from, to) { try { await node_fs_1.default.promises.rename(from, to); } catch (err) { if (err?.code !== 'EPERM' && err?.code !== 'EBUSY') throw err; await new Promise((resolve) => setTimeout(resolve, 50)); await node_fs_1.default.promises.rename(from, to); } } const getTmpName = (name) => `.tmp${pid}_${name}`; class BinaryFileStore extends FileStore_1.default { #root; #prepare; constructor(options) { super(options); this.#root = node_path_1.default.resolve(options.root); } prepare() { if (!this.#prepare) { this.#prepare = ensureShardDirs(this.#root); } return this.#prepare; } async get(key) { const filePath = this.#getFileDir(key) + node_path_1.default.sep + this.#getFileName(key); let data; try { data = await node_fs_1.default.promises.readFile(filePath); } catch (err) { if (err.code === 'ENOENT') { return null; } throw err; } try { return (0, serializer_1.decode)(data); } catch (err) { node_fs_1.default.promises.unlink(filePath).catch(() => { }); return null; } } async set(key, value) { // Prevent caching of CSS files that have the skipCache flag set. if (value?.output?.[0]?.data?.css?.skipCache) { debug('Skipping caching for CSS file:', value.path); return; } const buffer = (0, serializer_1.encode)(value); await this.prepare(); const fileDir = this.#getFileDir(key); const fileName = this.#getFileName(key); const targetTemp = fileDir + node_path_1.default.sep + getTmpName(fileName); const targetPath = fileDir + node_path_1.default.sep + fileName; let renamed = false; try { await node_fs_1.default.promises.writeFile(targetTemp, buffer); await renameWithRetry(targetTemp, targetPath); renamed = true; } catch (err) { // The cache root can disappear underneath us if a parallel process clears the cache root if (err?.code !== 'ENOENT') throw err; this.#prepare = undefined; await this.prepare(); await node_fs_1.default.promises.writeFile(targetTemp, buffer); await renameWithRetry(targetTemp, targetPath); renamed = true; } finally { if (!renamed) await node_fs_1.default.promises.unlink(targetTemp).catch(() => { }); } } clear() { this.#prepare = undefined; if (!(0, file_store_1.tryRenameAndDeleteAsync)(this.#root)) { super.clear(); } } #getFileDir(key) { return this.#root + node_path_1.default.sep + key.subarray(0, 1).toString('hex'); } #getFileName(key) { return key.subarray(1).toString('hex') + '.mp'; } } exports.FileStore = BinaryFileStore; //# sourceMappingURL=binary-file-store.js.map