"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