"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.calculateHash = calculateHash; exports.optimizeImageAsync = optimizeImageAsync; exports.hasUnoptimizedAssetsAsync = hasUnoptimizedAssetsAsync; exports.getAssetFilesAsync = getAssetFilesAsync; exports.readAssetJsonAsync = readAssetJsonAsync; exports.createNewFilename = createNewFilename; function _fsExtra() { const data = _interopRequireDefault(require("fs-extra")); _fsExtra = function () { return data; }; return data; } function _path() { const data = _interopRequireDefault(require("path")); _path = function () { return data; }; return data; } function _crypto() { const data = _interopRequireDefault(require("crypto")); _crypto = function () { return data; }; return data; } function _chalk() { const data = _interopRequireDefault(require("chalk")); _chalk = function () { return data; }; return data; } function _glob() { const data = _interopRequireDefault(require("glob")); _glob = function () { return data; }; return data; } function _imageUtils() { const data = require("@expo/image-utils"); _imageUtils = function () { return data; }; return data; } function _jsonFile() { const data = _interopRequireDefault(require("@expo/json-file")); _jsonFile = function () { return data; }; return data; } function _config() { const data = require("@expo/config"); _config = function () { return data; }; return data; } function _tempy() { const data = _interopRequireDefault(require("tempy")); _tempy = function () { return data; }; return data; } function _Logger() { const data = _interopRequireDefault(require("./Logger")); _Logger = function () { return data; }; return data; } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* * Calculate SHA256 Checksum value of a file based on its contents */ function calculateHash(filePath) { const contents = _fsExtra().default.readFileSync(filePath); return _crypto().default.createHash('sha256').update(contents).digest('hex'); } /* * Compress an inputted jpg or png */ async function optimizeImageAsync(inputPath, quality) { _Logger().default.global.info(`Optimizing ${inputPath}`); const outputPath = _tempy().default.directory(); await (0, _imageUtils().sharpAsync)({ input: inputPath, output: outputPath, quality }); return _path().default.join(outputPath, _path().default.basename(inputPath)); } /* * Returns a boolean indicating whether or not there are assets to optimize */ async function hasUnoptimizedAssetsAsync(projectDir, options) { if (!_fsExtra().default.existsSync(_path().default.join(projectDir, '.expo-shared/assets.json'))) { return true; } const { selectedFiles } = await getAssetFilesAsync(projectDir, options); const { assetInfo } = await readAssetJsonAsync(projectDir); for (const file of selectedFiles) { const hash = calculateHash(file); if (!assetInfo[hash]) { return true; } } return false; } /* * Find all project assets under assetBundlePatterns in app.json excluding node_modules. * If --include of --exclude flags were passed in those results are filtered out. */ async function getAssetFilesAsync(projectDir, options) { const { exp } = await (0, _config().readConfigJsonAsync)(projectDir); const { assetBundlePatterns } = exp; const globOptions = { cwd: projectDir, ignore: ['**/node_modules/**', '**/ios/**', '**/android/**'] }; // All files must be returned even if flags are passed in to properly update assets.json const allFiles = []; const patterns = assetBundlePatterns || ['**/*']; patterns.forEach(pattern => { allFiles.push(..._glob().default.sync(pattern, globOptions)); }); // If --include is passed in, only return files matching that pattern const included = options && options.include ? [..._glob().default.sync(options.include, globOptions)] : allFiles; const toExclude = new Set(); if (options && options.exclude) { _glob().default.sync(options.exclude, globOptions).forEach(file => toExclude.add(file)); } // If --exclude is passed in, filter out files matching that pattern const excluded = included.filter(file => !toExclude.has(file)); const filtered = options && options.exclude ? excluded : included; return { allFiles: filterImages(allFiles, projectDir), selectedFiles: filterImages(filtered, projectDir) }; } /* * Formats an array of files to include the project directory and filters out PNGs and JPGs. */ function filterImages(files, projectDir) { const regex = /\.(png|jpg|jpeg)$/; const withDirectory = files.map(file => `${projectDir}/${file}`.replace('//', '/')); const allImages = withDirectory.filter(file => regex.test(file.toLowerCase())); return allImages; } /* * Read the contents of assets.json under .expo-shared folder. Create the file/directory if they don't exist. */ async function readAssetJsonAsync(projectDir) { const dirPath = _path().default.join(projectDir, '.expo-shared'); if (!_fsExtra().default.existsSync(dirPath)) { _fsExtra().default.mkdirSync(dirPath); } const assetJson = new (_jsonFile().default)(_path().default.join(dirPath, 'assets.json')); if (!_fsExtra().default.existsSync(assetJson.file)) { const message = `Creating ${_chalk().default.italic('.expo-shared/assets.json')} in the project's root directory.\n` + `This file is autogenerated and should not be edited directly.\n` + 'You should commit this to git so that asset state is shared between collaborators.'; _Logger().default.global.info(message); await assetJson.writeAsync({}); } const assetInfo = await assetJson.readAsync(); return { assetJson, assetInfo }; } /* * Add .orig extension to a filename in a path string */ function createNewFilename(imagePath) { const { dir, name, ext } = _path().default.parse(imagePath); return _path().default.join(dir, name + '.orig' + ext); } //# sourceMappingURL=__sourcemaps__/AssetUtils.js.map