UNPKG

payload

Version:

Node, React and MongoDB Headless CMS and Application Framework

228 lines (227 loc) • 29.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "generateFileData", { enumerable: true, get: function() { return generateFileData; } }); const _filetype = require("file-type"); const _fs = /*#__PURE__*/ _interop_require_default(require("fs")); const _mkdirp = /*#__PURE__*/ _interop_require_default(require("mkdirp")); const _path = /*#__PURE__*/ _interop_require_default(require("path")); const _sanitizefilename = /*#__PURE__*/ _interop_require_default(require("sanitize-filename")); const _sharp = /*#__PURE__*/ _interop_require_default(require("sharp")); const _errors = require("../errors"); const _canResizeImage = /*#__PURE__*/ _interop_require_default(require("./canResizeImage")); const _cropImage = /*#__PURE__*/ _interop_require_default(require("./cropImage")); const _getFileByPath = /*#__PURE__*/ _interop_require_default(require("./getFileByPath")); const _getExternalFile = require("./getExternalFile"); const _getImageSize = /*#__PURE__*/ _interop_require_default(require("./getImageSize")); const _getSafeFilename = /*#__PURE__*/ _interop_require_default(require("./getSafeFilename")); const _imageResizer = /*#__PURE__*/ _interop_require_default(require("./imageResizer")); const _isImage = /*#__PURE__*/ _interop_require_default(require("./isImage")); function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const generateFileData = async ({ collection: { config: collectionConfig }, config, data, overwriteExistingFiles, req, throwOnMissingFile })=>{ if (!collectionConfig.upload) { return { data, files: [] }; } let file = req.files?.file || undefined; const { uploadEdits } = req.query || {}; const { disableLocalStorage, formatOptions, imageSizes, resizeOptions, staticDir, trimOptions } = collectionConfig.upload; let staticPath = staticDir; if (staticDir.indexOf('/') !== 0) { staticPath = _path.default.resolve(config.paths.configDir, staticDir); } if (!file && uploadEdits && data) { const { filename, url } = data; try { if (url && url.startsWith('/') && !disableLocalStorage) { const filePath = `${staticPath}/${filename}`; const response = await (0, _getFileByPath.default)(filePath); file = response; overwriteExistingFiles = true; } else if (filename && url) { file = await (0, _getExternalFile.getExternalFile)({ req, data: data }); overwriteExistingFiles = true; } } catch (err) { throw new _errors.FileUploadError(req.t); } } if (!file) { if (throwOnMissingFile) throw new _errors.MissingFile(req.t); return { data, files: [] }; } if (!disableLocalStorage) { _mkdirp.default.sync(staticPath); } let newData = data; const filesToSave = []; const fileData = {}; const fileIsAnimated = file.mimetype === 'image/gif' || file.mimetype === 'image/webp'; const cropData = typeof uploadEdits === 'object' && 'crop' in uploadEdits ? uploadEdits.crop : undefined; try { const fileSupportsResize = (0, _canResizeImage.default)(file.mimetype); let fsSafeName; let sharpFile; let dimensions; let fileBuffer; let ext; let mime; const fileHasAdjustments = fileSupportsResize && Boolean(resizeOptions || formatOptions || trimOptions || file.tempFilePath); const sharpOptions = {}; if (fileIsAnimated) sharpOptions.animated = true; if (fileHasAdjustments) { if (file.tempFilePath) { sharpFile = (0, _sharp.default)(file.tempFilePath, sharpOptions).rotate() // pass rotate() to auto-rotate based on EXIF data. https://github.com/payloadcms/payload/pull/3081 ; } else { sharpFile = (0, _sharp.default)(file.data, sharpOptions).rotate() // pass rotate() to auto-rotate based on EXIF data. https://github.com/payloadcms/payload/pull/3081 ; } if (resizeOptions) { sharpFile = sharpFile.resize(resizeOptions); } if (formatOptions) { sharpFile = sharpFile.toFormat(formatOptions.format, formatOptions.options); } if (trimOptions) { sharpFile = sharpFile.trim(trimOptions); } } if ((0, _isImage.default)(file.mimetype)) { dimensions = await (0, _getImageSize.default)(file); fileData.width = dimensions.width; fileData.height = dimensions.height; } if (sharpFile) { const metadata = await sharpFile.metadata(); fileBuffer = await sharpFile.toBuffer({ resolveWithObject: true }); ({ ext, mime } = await (0, _filetype.fromBuffer)(fileBuffer.data) // This is getting an incorrect gif height back. ); fileData.width = fileBuffer.info.width; fileData.height = fileBuffer.info.height; fileData.filesize = fileBuffer.info.size; // Animated GIFs + WebP aggregate the height from every frame, so we need to use divide by number of pages if (metadata.pages) { fileData.height = fileBuffer.info.height / metadata.pages; fileData.filesize = fileBuffer.data.length; } } else { mime = file.mimetype; fileData.filesize = file.size; if (file.name.includes('.')) { ext = file.name.split('.').pop(); } else { ext = ''; } } // Adust SVG mime type. fromBuffer modifies it. if (mime === 'application/xml' && ext === 'svg') mime = 'image/svg+xml'; fileData.mimeType = mime; const baseFilename = (0, _sanitizefilename.default)(file.name.substring(0, file.name.lastIndexOf('.')) || file.name); fsSafeName = `${baseFilename}${ext ? `.${ext}` : ''}`; if (!overwriteExistingFiles) { fsSafeName = await (0, _getSafeFilename.default)({ collectionSlug: collectionConfig.slug, desiredFilename: fsSafeName, req, staticPath }); } fileData.filename = fsSafeName; let fileForResize = file; if (cropData) { const { data: croppedImage, info } = await (0, _cropImage.default)({ cropData, dimensions, file }); filesToSave.push({ buffer: croppedImage, path: `${staticPath}/${fsSafeName}` }); fileForResize = { ...file, data: croppedImage, size: info.size }; fileData.width = info.width; fileData.height = info.height; fileData.filesize = info.size; if (file.tempFilePath) { await _fs.default.promises.writeFile(file.tempFilePath, croppedImage) // write fileBuffer to the temp path ; } else { req.files.file = fileForResize; } } else { filesToSave.push({ buffer: fileBuffer?.data || file.data, path: `${staticPath}/${fsSafeName}` }); // If using temp files and the image is being resized, write the file to the temp path if (fileBuffer?.data || file.data.length > 0) { if (file.tempFilePath) { await _fs.default.promises.writeFile(file.tempFilePath, fileBuffer?.data || file.data) // write fileBuffer to the temp path ; } else { // Assign the _possibly modified_ file to the request object req.files.file = { ...file, data: fileBuffer?.data || file.data, size: fileBuffer?.info.size }; } } } if (Array.isArray(imageSizes) && fileSupportsResize) { req.payloadUploadSizes = {}; const { sizeData, sizesToSave } = await (0, _imageResizer.default)({ config: collectionConfig, dimensions: !cropData ? dimensions : { ...dimensions, height: fileData.height, width: fileData.width }, file: fileForResize, mimeType: fileData.mimeType, req, savedFilename: fsSafeName || file.name, staticPath }); fileData.sizes = sizeData; filesToSave.push(...sizesToSave); } } catch (err) { console.error(err); throw new _errors.FileUploadError(req.t); } newData = { ...newData, ...fileData }; return { data: newData, files: filesToSave }; }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy91cGxvYWRzL2dlbmVyYXRlRmlsZURhdGEudHMiXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBVcGxvYWRlZEZpbGUgfSBmcm9tICdleHByZXNzLWZpbGV1cGxvYWQnXG5pbXBvcnQgdHlwZSB7IE91dHB1dEluZm8sIFNoYXJwLCBTaGFycE9wdGlvbnMgfSBmcm9tICdzaGFycCdcblxuaW1wb3J0IHsgZnJvbUJ1ZmZlciB9IGZyb20gJ2ZpbGUtdHlwZSdcbmltcG9ydCBmcyBmcm9tICdmcydcbmltcG9ydCBta2RpcnAgZnJvbSAnbWtkaXJwJ1xuaW1wb3J0IHBhdGggZnJvbSAncGF0aCdcbmltcG9ydCBzYW5pdGl6ZSBmcm9tICdzYW5pdGl6ZS1maWxlbmFtZSdcbmltcG9ydCBzaGFycCBmcm9tICdzaGFycCdcblxuaW1wb3J0IHR5cGUgeyBDb2xsZWN0aW9uIH0gZnJvbSAnLi4vY29sbGVjdGlvbnMvY29uZmlnL3R5cGVzJ1xuaW1wb3J0IHR5cGUgeyBTYW5pdGl6ZWRDb25maWcgfSBmcm9tICcuLi9jb25maWcvdHlwZXMnXG5pbXBvcnQgdHlwZSB7IFBheWxvYWRSZXF1ZXN0IH0gZnJvbSAnLi4vZXhwcmVzcy90eXBlcydcbmltcG9ydCB0eXBlIHsgRmlsZURhdGEsIEZpbGVUb1NhdmUsIFByb2JlZEltYWdlU2l6ZSB9IGZyb20gJy4vdHlwZXMnXG5cbmltcG9ydCB7IEZpbGVVcGxvYWRFcnJvciwgTWlzc2luZ0ZpbGUgfSBmcm9tICcuLi9lcnJvcnMnXG5pbXBvcnQgY2FuUmVzaXplSW1hZ2UgZnJvbSAnLi9jYW5SZXNpemVJbWFnZSdcbmltcG9ydCBjcm9wSW1hZ2UgZnJvbSAnLi9jcm9wSW1hZ2UnXG5pbXBvcnQgZ2V0RmlsZUJ5UGF0aCBmcm9tICcuL2dldEZpbGVCeVBhdGgnXG5pbXBvcnQgeyBnZXRFeHRlcm5hbEZpbGUgfSBmcm9tICcuL2dldEV4dGVybmFsRmlsZSdcbmltcG9ydCBnZXRJbWFnZVNpemUgZnJvbSAnLi9nZXRJbWFnZVNpemUnXG5pbXBvcnQgZ2V0U2FmZUZpbGVOYW1lIGZyb20gJy4vZ2V0U2FmZUZpbGVuYW1lJ1xuaW1wb3J0IHJlc2l6ZUFuZFRyYW5zZm9ybUltYWdlU2l6ZXMgZnJvbSAnLi9pbWFnZVJlc2l6ZXInXG5pbXBvcnQgaXNJbWFnZSBmcm9tICcuL2lzSW1hZ2UnXG5cbnR5cGUgQXJnczxUPiA9IHtcbiAgY29sbGVjdGlvbjogQ29sbGVjdGlvblxuICBjb25maWc6IFNhbml0aXplZENvbmZpZ1xuICBkYXRhOiBUXG4gIG92ZXJ3cml0ZUV4aXN0aW5nRmlsZXM/OiBib29sZWFuXG4gIHJlcTogUGF5bG9hZFJlcXVlc3RcbiAgdGhyb3dPbk1pc3NpbmdGaWxlPzogYm9vbGVhblxufVxuXG50eXBlIFJlc3VsdDxUPiA9IFByb21pc2U8e1xuICBkYXRhOiBUXG4gIGZpbGVzOiBGaWxlVG9TYXZlW11cbn0+XG5cbmV4cG9ydCBjb25zdCBnZW5lcmF0ZUZpbGVEYXRhID0gYXN5bmMgPFQ+KHtcbiAgY29sbGVjdGlvbjogeyBjb25maWc6IGNvbGxlY3Rpb25Db25maWcgfSxcbiAgY29uZmlnLFxuICBkYXRhLFxuICBvdmVyd3JpdGVFeGlzdGluZ0ZpbGVzLFxuICByZXEsXG4gIHRocm93T25NaXNzaW5nRmlsZSxcbn06IEFyZ3M8VD4pOiBSZXN1bHQ8VD4gPT4ge1xuICBpZiAoIWNvbGxlY3Rpb25Db25maWcudXBsb2FkKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGEsXG4gICAgICBmaWxlczogW10sXG4gICAgfVxuICB9XG5cbiAgbGV0IGZpbGUgPSByZXEuZmlsZXM/LmZpbGUgfHwgdW5kZWZpbmVkXG4gIGNvbnN0IHsgdXBsb2FkRWRpdHMgfSA9IHJlcS5xdWVyeSB8fCB7fVxuXG4gIGNvbnN0IHsgZGlzYWJsZUxvY2FsU3RvcmFnZSwgZm9ybWF0T3B0aW9ucywgaW1hZ2VTaXplcywgcmVzaXplT3B0aW9ucywgc3RhdGljRGlyLCB0cmltT3B0aW9ucyB9ID1cbiAgICBjb2xsZWN0aW9uQ29uZmlnLnVwbG9hZFxuXG4gIGxldCBzdGF0aWNQYXRoID0gc3RhdGljRGlyXG4gIGlmIChzdGF0aWNEaXIuaW5kZXhPZignLycpICE9PSAwKSB7XG4gICAgc3RhdGljUGF0aCA9IHBhdGgucmVzb2x2ZShjb25maWcucGF0aHMuY29uZmlnRGlyLCBzdGF0aWNEaXIpXG4gIH1cblxuICBpZiAoIWZpbGUgJiYgdXBsb2FkRWRpdHMgJiYgZGF0YSkge1xuICAgIGNvbnN0IHsgZmlsZW5hbWUsIHVybCB9ID0gZGF0YSBhcyBGaWxlRGF0YVxuXG4gICAgdHJ5IHtcbiAgICAgIGlmICh1cmwgJiYgdXJsLnN0YXJ0c1dpdGgoJy8nKSAmJiAhZGlzYWJsZUxvY2FsU3RvcmFnZSkge1xuICAgICAgICBjb25zdCBmaWxlUGF0aCA9IGAke3N0YXRpY1BhdGh9LyR7ZmlsZW5hbWV9YFxuICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGdldEZpbGVCeVBhdGgoZmlsZVBhdGgpXG4gICAgICAgIGZpbGUgPSByZXNwb25zZSBhcyBVcGxvYWRlZEZpbGVcbiAgICAgICAgb3ZlcndyaXRlRXhpc3RpbmdGaWxlcyA9IHRydWVcbiAgICAgIH0gZWxzZSBpZiAoZmlsZW5hbWUgJiYgdXJsKSB7XG4gICAgICAgIGZpbGUgPSAoYXdhaXQgZ2V0RXh0ZXJuYWxGaWxlKHsgcmVxLCBkYXRhOiBkYXRhIGFzIEZpbGVEYXRhIH0pKSBhcyBVcGxvYWRlZEZpbGVcbiAgICAgICAgb3ZlcndyaXRlRXhpc3RpbmdGaWxlcyA9IHRydWVcbiAgICAgIH1cbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRocm93IG5ldyBGaWxlVXBsb2FkRXJyb3IocmVxLnQpXG4gICAgfVxuICB9XG5cbiAgaWYgKCFmaWxlKSB7XG4gICAgaWYgKHRocm93T25NaXNzaW5nRmlsZSkgdGhyb3cgbmV3IE1pc3NpbmdGaWxlKHJlcS50KVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGRhdGEsXG4gICAgICBmaWxlczogW10sXG4gICAgfVxuICB9XG5cbiAgaWYgKCFkaXNhYmxlTG9jYWxTdG9yYWdlKSB7XG4gICAgbWtkaXJwLnN5bmMoc3RhdGljUGF0aClcbiAgfVxuXG4gIGxldCBuZXdEYXRhID0gZGF0YVxuICBjb25zdCBmaWxlc1RvU2F2ZTogRmlsZVRvU2F2ZVtdID0gW11cbiAgY29uc3QgZmlsZURhdGE6IFBhcnRpYWw8RmlsZURhdGE+ID0ge31cbiAgY29uc3QgZmlsZUlzQW5pbWF0ZWQgPSBmaWxlLm1pbWV0eXBlID09PSAnaW1hZ2UvZ2lmJyB8fCBmaWxlLm1pbWV0eXBlID09PSAnaW1hZ2Uvd2VicCdcbiAgY29uc3QgY3JvcERhdGEgPVxuICAgIHR5cGVvZiB1cGxvYWRFZGl0cyA9PT0gJ29iamVjdCcgJiYgJ2Nyb3AnIGluIHVwbG9hZEVkaXRzID8gdXBsb2FkRWRpdHMuY3JvcCA6IHVuZGVmaW5lZFxuXG4gIHRyeSB7XG4gICAgY29uc3QgZmlsZVN1cHBvcnRzUmVzaXplID0gY2FuUmVzaXplSW1hZ2UoZmlsZS5taW1ldHlwZSlcbiAgICBsZXQgZnNTYWZlTmFtZTogc3RyaW5nXG4gICAgbGV0IHNoYXJwRmlsZTogU2hhcnAgfCB1bmRlZmluZWRcbiAgICBsZXQgZGltZW5zaW9uczogUHJvYmVkSW1hZ2VTaXplIHwgdW5kZWZpbmVkXG4gICAgbGV0IGZpbGVCdWZmZXI6IHsgZGF0YTogQnVmZmVyOyBpbmZvOiBPdXRwdXRJbmZvIH1cbiAgICBsZXQgZXh0XG4gICAgbGV0IG1pbWU6IHN0cmluZ1xuICAgIGNvbnN0IGZpbGVIYXNBZGp1c3RtZW50cyA9XG4gICAgICBmaWxlU3VwcG9ydHNSZXNpemUgJiZcbiAgICAgIEJvb2xlYW4ocmVzaXplT3B0aW9ucyB8fCBmb3JtYXRPcHRpb25zIHx8IHRyaW1PcHRpb25zIHx8IGZpbGUudGVtcEZpbGVQYXRoKVxuXG4gICAgY29uc3Qgc2hhcnBPcHRpb25zOiBTaGFycE9wdGlvbnMgPSB7fVxuXG4gICAgaWYgKGZpbGVJc0FuaW1hdGVkKSBzaGFycE9wdGlvbnMuYW5pbWF0ZWQgPSB0cnVlXG5cbiAgICBpZiAoZmlsZUhhc0FkanVzdG1lbnRzKSB7XG4gICAgICBpZiAoZmlsZS50ZW1wRmlsZVBhdGgpIHtcbiAgICAgICAgc2hhcnBGaWxlID0gc2hhcnAoZmlsZS50ZW1wRmlsZVBhdGgsIHNoYXJwT3B0aW9ucykucm90YXRlKCkgLy8gcGFzcyByb3RhdGUoKSB0byBhdXRvLXJvdGF0ZSBiYXNlZCBvbiBFWElGIGRhdGEuIGh0dHBzOi8vZ2l0aHViLmNvbS9wYXlsb2FkY21zL3BheWxvYWQvcHVsbC8zMDgxXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzaGFycEZpbGUgPSBzaGFycChmaWxlLmRhdGEsIHNoYXJwT3B0aW9ucykucm90YXRlKCkgLy8gcGFzcyByb3RhdGUoKSB0byBhdXRvLXJvdGF0ZSBiYXNlZCBvbiBFWElGIGRhdGEuIGh0dHBzOi8vZ2l0aHViLmNvbS9wYXlsb2FkY21zL3BheWxvYWQvcHVsbC8zMDgxXG4gICAgICB9XG5cbiAgICAgIGlmIChyZXNpemVPcHRpb25zKSB7XG4gICAgICAgIHNoYXJwRmlsZSA9IHNoYXJwRmlsZS5yZXNpemUocmVzaXplT3B0aW9ucylcbiAgICAgIH1cbiAgICAgIGlmIChmb3JtYXRPcHRpb25zKSB7XG4gICAgICAgIHNoYXJwRmlsZSA9IHNoYXJwRmlsZS50b0Zvcm1hdChmb3JtYXRPcHRpb25zLmZvcm1hdCwgZm9ybWF0T3B0aW9ucy5vcHRpb25zKVxuICAgICAgfVxuICAgICAgaWYgKHRyaW1PcHRpb25zKSB7XG4gICAgICAgIHNoYXJwRmlsZSA9IHNoYXJwRmlsZS50cmltKHRyaW1PcHRpb25zKVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChpc0ltYWdlKGZpbGUubWltZXR5cGUpKSB7XG4gICAgICBkaW1lbnNpb25zID0gYXdhaXQgZ2V0SW1hZ2VTaXplKGZpbGUpXG4gICAgICBmaWxlRGF0YS53aWR0aCA9IGRpbWVuc2lvbnMud2lkdGhcbiAgICAgIGZpbGVEYXRhLmhlaWdodCA9IGRpbWVuc2lvbnMuaGVpZ2h0XG4gICAgfVxuXG4gICAgaWYgKHNoYXJwRmlsZSkge1xuICAgICAgY29uc3QgbWV0YWRhdGEgPSBhd2FpdCBzaGFycEZpbGUubWV0YWRhdGEoKVxuICAgICAgZmlsZUJ1ZmZlciA9IGF3YWl0IHNoYXJwRmlsZS50b0J1ZmZlcih7IHJlc29sdmVXaXRoT2JqZWN0OiB0cnVlIH0pXG4gICAgICA7KHsgZXh0LCBtaW1lIH0gPSBhd2FpdCBmcm9tQnVmZmVyKGZpbGVCdWZmZXIuZGF0YSkpIC8vIFRoaXMgaXMgZ2V0dGluZyBhbiBpbmNvcnJlY3QgZ2lmIGhlaWdodCBiYWNrLlxuICAgICAgZmlsZURhdGEud2lkdGggPSBmaWxlQnVmZmVyLmluZm8ud2lkdGhcbiAgICAgIGZpbGVEYXRhLmhlaWdodCA9IGZpbGVCdWZmZXIuaW5mby5oZWlnaHRcbiAgICAgIGZpbGVEYXRhLmZpbGVzaXplID0gZmlsZUJ1ZmZlci5pbmZvLnNpemVcblxuICAgICAgLy8gQW5pbWF0ZWQgR0lGcyArIFdlYlAgYWdncmVnYXRlIHRoZSBoZWlnaHQgZnJvbSBldmVyeSBmcmFtZSwgc28gd2UgbmVlZCB0byB1c2UgZGl2aWRlIGJ5IG51bWJlciBvZiBwYWdlc1xuICAgICAgaWYgKG1ldGFkYXRhLnBhZ2VzKSB7XG4gICAgICAgIGZpbGVEYXRhLmhlaWdodCA9IGZpbGVCdWZmZXIuaW5mby5oZWlnaHQgLyBtZXRhZGF0YS5wYWdlc1xuICAgICAgICBmaWxlRGF0YS5maWxlc2l6ZSA9IGZpbGVCdWZmZXIuZGF0YS5sZW5ndGhcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgbWltZSA9IGZpbGUubWltZXR5cGVcbiAgICAgIGZpbGVEYXRhLmZpbGVzaXplID0gZmlsZS5zaXplXG5cbiAgICAgIGlmIChmaWxlLm5hbWUuaW5jbHVkZXMoJy4nKSkge1xuICAgICAgICBleHQgPSBmaWxlLm5hbWUuc3BsaXQoJy4nKS5wb3AoKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZXh0ID0gJydcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBZHVzdCBTVkcgbWltZSB0eXBlLiBmcm9tQnVmZmVyIG1vZGlmaWVzIGl0LlxuICAgIGlmIChtaW1lID09PSAnYXBwbGljYXRpb24veG1sJyAmJiBleHQgPT09ICdzdmcnKSBtaW1lID0gJ2ltYWdlL3N2Zyt4bWwnXG4gICAgZmlsZURhdGEubWltZVR5cGUgPSBtaW1lXG5cbiAgICBjb25zdCBiYXNlRmlsZW5hbWUgPSBzYW5pdGl6ZShmaWxlLm5hbWUuc3Vic3RyaW5nKDAsIGZpbGUubmFtZS5sYXN0SW5kZXhPZignLicpKSB8fCBmaWxlLm5hbWUpXG4gICAgZnNTYWZlTmFtZSA9IGAke2Jhc2VGaWxlbmFtZX0ke2V4dCA/IGAuJHtleHR9YCA6ICcnfWBcblxuICAgIGlmICghb3ZlcndyaXRlRXhpc3RpbmdGaWxlcykge1xuICAgICAgZnNTYWZlTmFtZSA9IGF3YWl0IGdldFNhZmVGaWxlTmFtZSh7XG4gICAgICAgIGNvbGxlY3Rpb25TbHVnOiBjb2xsZWN0aW9uQ29uZmlnLnNsdWcsXG4gICAgICAgIGRlc2lyZWRGaWxlbmFtZTogZnNTYWZlTmFtZSxcbiAgICAgICAgcmVxLFxuICAgICAgICBzdGF0aWNQYXRoLFxuICAgICAgfSlcbiAgICB9XG5cbiAgICBmaWxlRGF0YS5maWxlbmFtZSA9IGZzU2FmZU5hbWVcbiAgICBsZXQgZmlsZUZvclJlc2l6ZSA9IGZpbGVcblxuICAgIGlmIChjcm9wRGF0YSkge1xuICAgICAgY29uc3QgeyBkYXRhOiBjcm9wcGVkSW1hZ2UsIGluZm8gfSA9IGF3YWl0IGNyb3BJbWFnZSh7IGNyb3BEYXRhLCBkaW1lbnNpb25zLCBmaWxlIH0pXG5cbiAgICAgIGZpbGVzVG9TYXZlLnB1c2goe1xuICAgICAgICBidWZmZXI6IGNyb3BwZWRJbWFnZSxcbiAgICAgICAgcGF0aDogYCR7c3RhdGljUGF0aH0vJHtmc1NhZmVOYW1lfWAsXG4gICAgICB9KVxuXG4gICAgICBmaWxlRm9yUmVzaXplID0ge1xuICAgICAgICAuLi5maWxlLFxuICAgICAgICBkYXRhOiBjcm9wcGVkSW1hZ2UsXG4gICAgICAgIHNpemU6IGluZm8uc2l6ZSxcbiAgICAgIH1cbiAgICAgIGZpbGVEYXRhLndpZHRoID0gaW5mby53aWR0aFxuICAgICAgZmlsZURhdGEuaGVpZ2h0ID0gaW5mby5oZWlnaHRcbiAgICAgIGZpbGVEYXRhLmZpbGVzaXplID0gaW5mby5zaXplXG5cbiAgICAgIGlmIChmaWxlLnRlbXBGaWxlUGF0aCkge1xuICAgICAgICBhd2FpdCBmcy5wcm9taXNlcy53cml0ZUZpbGUoZmlsZS50ZW1wRmlsZVBhdGgsIGNyb3BwZWRJbWFnZSkgLy8gd3JpdGUgZmlsZUJ1ZmZlciB0byB0aGUgdGVtcCBwYXRoXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXEuZmlsZXMuZmlsZSA9IGZpbGVGb3JSZXNpemVcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZmlsZXNUb1NhdmUucHVzaCh7XG4gICAgICAgIGJ1ZmZlcjogZmlsZUJ1ZmZlcj8uZGF0YSB8fCBmaWxlLmRhdGEsXG4gICAgICAgIHBhdGg6IGAke3N0YXRpY1BhdGh9LyR7ZnNTYWZlTmFtZX1gLFxuICAgICAgfSlcblxuICAgICAgLy8gSWYgdXNpbmcgdGVtcCBmaWxlcyBhbmQgdGhlIGltYWdlIGlzIGJlaW5nIHJlc2l6ZWQsIHdyaXRlIHRoZSBmaWxlIHRvIHRoZSB0ZW1wIHBhdGhcbiAgICAgIGlmIChmaWxlQnVmZmVyPy5kYXRhIHx8IGZpbGUuZGF0YS5sZW5ndGggPiAwKSB7XG4gICAgICAgIGlmIChmaWxlLnRlbXBGaWxlUGF0aCkge1xuICAgICAgICAgIGF3YWl0IGZzLnByb21pc2VzLndyaXRlRmlsZShmaWxlLnRlbXBGaWxlUGF0aCwgZmlsZUJ1ZmZlcj8uZGF0YSB8fCBmaWxlLmRhdGEpIC8vIHdyaXRlIGZpbGVCdWZmZXIgdG8gdGhlIHRlbXAgcGF0aFxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIEFzc2lnbiB0aGUgX3Bvc3NpYmx5IG1vZGlmaWVkXyBmaWxlIHRvIHRoZSByZXF1ZXN0IG9iamVjdFxuICAgICAgICAgIHJlcS5maWxlcy5maWxlID0ge1xuICAgICAgICAgICAgLi4uZmlsZSxcbiAgICAgICAgICAgIGRhdGE6IGZpbGVCdWZmZXI/LmRhdGEgfHwgZmlsZS5kYXRhLFxuICAgICAgICAgICAgc2l6ZTogZmlsZUJ1ZmZlcj8uaW5mby5zaXplLFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChBcnJheS5pc0FycmF5KGltYWdlU2l6ZXMpICYmIGZpbGVTdXBwb3J0c1Jlc2l6ZSkge1xuICAgICAgcmVxLnBheWxvYWRVcGxvYWRTaXplcyA9IHt9XG4gICAgICBjb25zdCB7IHNpemVEYXRhLCBzaXplc1RvU2F2ZSB9ID0gYXdhaXQgcmVzaXplQW5kVHJhbnNmb3JtSW1hZ2VTaXplcyh7XG4gICAgICAgIGNvbmZpZzogY29sbGVjdGlvbkNvbmZpZyxcbiAgICAgICAgZGltZW5zaW9uczogIWNyb3BEYXRhXG4gICAgICAgICAgPyBkaW1lbnNpb25zXG4gICAgICAgICAgOiB7XG4gICAgICAgICAgICAgIC4uLmRpbWVuc2lvbnMsXG4gICAgICAgICAgICAgIGhlaWdodDogZmlsZURhdGEuaGVpZ2h0LFxuICAgICAgICAgICAgICB3aWR0aDogZmlsZURhdGEud2lkdGgsXG4gICAgICAgICAgICB9LFxuICAgICAgICBmaWxlOiBmaWxlRm9yUmVzaXplLFxuICAgICAgICBtaW1lVHlwZTogZmlsZURhdGEubWltZVR5cGUsXG4gICAgICAgIHJlcSxcbiAgICAgICAgc2F2ZWRGaWxlbmFtZTogZnNTYWZlTmFtZSB8fCBmaWxlLm5hbWUsXG4gICAgICAgIHN0YXRpY1BhdGgsXG4gICAgICB9KVxuXG4gICAgICBmaWxlRGF0YS5zaXplcyA9IHNpemVEYXRhXG4gICAgICBmaWxlc1RvU2F2ZS5wdXNoKC4uLnNpemVzVG9TYXZlKVxuICAgIH1cbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgY29uc29sZS5lcnJvcihlcnIpXG4gICAgdGhyb3cgbmV3IEZpbGVVcGxvYWRFcnJvcihyZXEudClcbiAgfVxuXG4gIG5ld0RhdGEgPSB7XG4gICAgLi4ubmV3RGF0YSxcbiAgICAuLi5maWxlRGF0YSxcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZGF0YTogbmV3RGF0YSxcbiAgICBmaWxlczogZmlsZXNUb1NhdmUsXG4gIH1cbn1cbiJdLCJuYW1lcyI6WyJnZW5lcmF0ZUZpbGVEYXRhIiwiY29sbGVjdGlvbiIsImNvbmZpZyIsImNvbGxlY3Rpb25Db25maWciLCJkYXRhIiwib3ZlcndyaXRlRXhpc3RpbmdGaWxlcyIsInJlcSIsInRocm93T25NaXNzaW5nRmlsZSIsInVwbG9hZCIsImZpbGVzIiwiZmlsZSIsInVuZGVmaW5lZCIsInVwbG9hZEVkaXRzIiwicXVlcnkiLCJkaXNhYmxlTG9jYWxTdG9yYWdlIiwiZm9ybWF0T3B0aW9ucyIsImltYWdlU2l6ZXMiLCJyZXNpemVPcHRpb25zIiwic3RhdGljRGlyIiwidHJpbU9wdGlvbnMiLCJzdGF0aWNQYXRoIiwiaW5kZXhPZiIsInBhdGgiLCJyZXNvbHZlIiwicGF0aHMiLCJjb25maWdEaXIiLCJmaWxlbmFtZSIsInVybCIsInN0YXJ0c1dpdGgiLCJmaWxlUGF0aCIsInJlc3BvbnNlIiwiZ2V0RmlsZUJ5UGF0aCIsImdldEV4dGVybmFsRmlsZSIsImVyciIsIkZpbGVVcGxvYWRFcnJvciIsInQiLCJNaXNzaW5nRmlsZSIsIm1rZGlycCIsInN5bmMiLCJuZXdEYXRhIiwiZmlsZXNUb1NhdmUiLCJmaWxlRGF0YSIsImZpbGVJc0FuaW1hdGVkIiwibWltZXR5cGUiLCJjcm9wRGF0YSIsImNyb3AiLCJmaWxlU3VwcG9ydHNSZXNpemUiLCJjYW5SZXNpemVJbWFnZSIsImZzU2FmZU5hbWUiLCJzaGFycEZpbGUiLCJkaW1lbnNpb25zIiwiZmlsZUJ1ZmZlciIsImV4dCIsIm1pbWUiLCJmaWxlSGFzQWRqdXN0bWVudHMiLCJCb29sZWFuIiwidGVtcEZpbGVQYXRoIiwic2hhcnBPcHRpb25zIiwiYW5pbWF0ZWQiLCJzaGFycCIsInJvdGF0ZSIsInJlc2l6ZSIsInRvRm9ybWF0IiwiZm9ybWF0Iiwib3B0aW9ucyIsInRyaW0iLCJpc0ltYWdlIiwiZ2V0SW1hZ2VTaXplIiwid2lkdGgiLCJoZWlnaHQiLCJtZXRhZGF0YSIsInRvQnVmZmVyIiwicmVzb2x2ZVdpdGhPYmplY3QiLCJmcm9tQnVmZmVyIiwiaW5mbyIsImZpbGVzaXplIiwic2l6ZSIsInBhZ2VzIiwibGVuZ3RoIiwibmFtZSIsImluY2x1ZGVzIiwic3BsaXQiLCJwb3AiLCJtaW1lVHlwZSIsImJhc2VGaWxlbmFtZSIsInNhbml0aXplIiwic3Vic3RyaW5nIiwibGFzdEluZGV4T2YiLCJnZXRTYWZlRmlsZU5hbWUiLCJjb2xsZWN0aW9uU2x1ZyIsInNsdWciLCJkZXNpcmVkRmlsZW5hbWUiLCJmaWxlRm9yUmVzaXplIiwiY3JvcHBlZEltYWdlIiwiY3JvcEltYWdlIiwicHVzaCIsImJ1ZmZlciIsImZzIiwicHJvbWlzZXMiLCJ3cml0ZUZpbGUiLCJBcnJheSIsImlzQXJyYXkiLCJwYXlsb2FkVXBsb2FkU2l6ZXMiLCJzaXplRGF0YSIsInNpemVzVG9TYXZlIiwicmVzaXplQW5kVHJhbnNmb3JtSW1hZ2VTaXplcyIsInNhdmVkRmlsZW5hbWUiLCJzaXplcyIsImNvbnNvbGUiLCJlcnJvciJdLCJtYXBwaW5ncyI6Ijs7OzsrQkF1Q2FBOzs7ZUFBQUE7OzswQkFwQ2M7MkRBQ1o7K0RBQ0k7NkRBQ0Y7eUVBQ0k7OERBQ0g7d0JBTzJCO3VFQUNsQjtrRUFDTDtzRUFDSTtpQ0FDTTtxRUFDUDt3RUFDRztxRUFDYTtnRUFDckI7Ozs7OztBQWdCYixNQUFNQSxtQkFBbUIsT0FBVSxFQUN4Q0MsWUFBWSxFQUFFQyxRQUFRQyxnQkFBZ0IsRUFBRSxFQUN4Q0QsTUFBTSxFQUNORSxJQUFJLEVBQ0pDLHNCQUFzQixFQUN0QkMsR0FBRyxFQUNIQyxrQkFBa0IsRUFDVjtJQUNSLElBQUksQ0FBQ0osaUJBQWlCSyxNQUFNLEVBQUU7UUFDNUIsT0FBTztZQUNMSjtZQUNBSyxPQUFPLEVBQUU7UUFDWDtJQUNGO0lBRUEsSUFB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