{"version":3,"file":"index.mjs","sources":["../src/utils/io.js","../src/utils/cache.js","../src/utils/compatCache.js","../src/utils/parallel.js","../src/utils/beforeUpload.js"],"sourcesContent":["import fs from 'fs'\n/**\n * read files in string\n * @param {string} location\n */\nexport const read = (location) => fs.readFileSync(location, 'utf-8')\n/**\n * write file\n * @param {string} location\n * @param {string|buffer} content\n */\nexport const write = (location, content) => fs.writeFileSync(location, content)\n","import path from 'path'\nimport fse from 'fs-extra'\nimport md5 from 'md5'\nimport { write, read as readFile } from './io'\n// tricky part\n// everything refer to this object\nconst trivialCache = {}\nconst OPTION_KEY = 'passToCdn'\nconst LAST_OPTION_KEY = 'lastPassToCdn'\nconst LOCATION_KEY = 'location'\nconst CACHE_KEY = 'cache'\n\n/**\n * save things to trivialCache\n * @param {string} key\n * @param {*} value\n */\nconst save = (key, value) => {\n  trivialCache[key] = value\n  return trivialCache\n}\n\n/**\n * get value from trivialCache\n * @param {string} key\n */\nconst read = (key) => trivialCache[key]\n\nconst updateCache = (key, cdnUrl) => {\n  const cache = read(CACHE_KEY)\n  cache[key] = cdnUrl\n  return cache\n}\n/**\n * get hash for file\n * @param {string} fileContent\n * @returns {string}\n */\nconst getHash = md5\n\n/**\n * update cache file\n * @param {string|object} input\n * @returns {void}\n */\nconst updateCacheFile = (input = {}) => {\n  const inputObj = typeof input === 'string' ? JSON.parse(input) : input\n  const cache = read(CACHE_KEY)\n  const location = read(LOCATION_KEY)\n  const toSave = Object.assign(cache, inputObj)\n  write(location, JSON.stringify(toSave))\n}\n\n/**\n * whether has a record\n * if the option (passToCdn) has changed\n * consider as there is no valid record\n * @param {string} hash\n * @param {string} locationHash\n * @returns {boolean}\n */\nconst shouldUseCache = (hash, locationHash) => {\n  const oldOption = read(LAST_OPTION_KEY)\n  const newOption = read(OPTION_KEY)\n  const cache = read(CACHE_KEY)\n  const key = Object.keys(cache).find(findContent(hash))\n  const sameOption = JSON.stringify(oldOption) === JSON.stringify(newOption)\n  const useCache =\n    sameOption && !!key && cache[key] && typeof cache[key] === 'string'\n  const contentSameButLocChanged = useCache && key.indexOf(locationHash) !== 0\n  // try to delete old entry with location when it is new content\n  if (!useCache) {\n    tryDeleteOldEntry(hash, 'content')\n    tryDeleteOldEntry(locationHash, 'location')\n  } else if (contentSameButLocChanged) {\n    updateCache(locationHash + hash, cache[key])\n    tryDeleteOldEntry(hash, 'content')\n  }\n  return useCache\n}\n\n/**\n * find key from cache based on location hash\n * @param {string} locationHash\n * @return {(key: string) => *}\n */\nconst findLocation = (locationHash) => (k) => k.indexOf(locationHash) === 0\n/**\n * find key from cache based on content hash\n * @param {string} hash\n * @return {(key: string) => *}\n */\nconst findContent = (hash) => (k) => k.slice(0 - hash.length) === hash\n\n/**\n * delete entry in cache\n * avoid giant cache\n * @param {string} hash\n * @param {string=} mode\n * @returns {void}\n */\nconst tryDeleteOldEntry = (hash, mode) => {\n  const cache = read(CACHE_KEY)\n  const keys = Object.keys(cache)\n  let key\n  switch (mode) {\n    case 'location':\n      key = keys.find(findLocation(hash))\n      break\n    case 'content':\n    default:\n      key = keys.find(findContent(hash))\n  }\n  if (key) {\n    delete cache[key]\n  }\n}\n\n/**\n * save to cache\n * @param {string} key\n * @param {*} value\n * @returns {object}\n */\nconst saveToCache = (key, value) => {\n  const cache = read(CACHE_KEY)\n  cache[key] = value\n  return cache\n}\n\n/**\n * read from cache\n * @param {string} key\n * @returns {*}\n */\nconst readFromCache = (key) => {\n  const cache = read(CACHE_KEY)\n  return cache[key]\n}\n\n/**\n * save configs and initiate triviaCache\n * @param {object=} option\n * @param {object=} option.passToCdn\n * @param {string=} option.cacheLocation\n * @returns {void}\n */\nconst init = (option = {}) => {\n  const {\n    passToCdn = {},\n    cacheLocation = path.resolve(__dirname, '../cache.json'),\n  } = option\n  const location = path.join(\n    cacheLocation.replace(/cache\\.json$/, ''),\n    '/cache.json'\n  )\n  save(LOCATION_KEY, location)\n  fse.ensureFileSync(location)\n  const cacheRaw = readFile(location).trim() || '{}'\n  const cacheObj = JSON.parse(cacheRaw)\n  save(CACHE_KEY, cacheObj)\n  save(OPTION_KEY, passToCdn)\n  const lastPassToCdn = cacheObj[OPTION_KEY]\n  save(LAST_OPTION_KEY, lastPassToCdn)\n  saveToCache(OPTION_KEY, passToCdn)\n}\n\nexport const Cache = {\n  update: updateCache,\n  end: updateCacheFile,\n  shouldUpload: (hash, locationHash) => !shouldUseCache(hash, locationHash),\n  getUrl: readFromCache,\n  getHash,\n  init,\n}\n","import path from 'path'\nimport { Cache } from './cache'\nimport { read } from './io'\n\n/**\n * @typedef {(files: string[], option: object=) => Promise<object>} upload\n */\n\n/**\n * @typedef {object} Cdn\n * @property {upload} upload\n */\n\n/**\n * compatible API for cdn when enable cache\n * @param {Cdn} cdn\n * @param {object=} option\n * @param {object=} option.passToCdn passToCdn needs to be saved\n * @param {string=} option.cacheLocation where to put cache file\n * @returns {Cdn}\n */\nexport const compatCache = (cdn, option = {}) => {\n  // init to save option\n  Cache.init(option)\n  const upload = async (files) => {\n    const { toUpload, pairFromCache, localHashMap } = files.reduce(\n      (last, file) => {\n        const fileContent = read(file)\n        // using relative location so cache could be shared among developers\n        const relativeLocation = path.relative(__dirname, file)\n        const locationHash = Cache.getHash(relativeLocation)\n        const hash = Cache.getHash(fileContent)\n        if (Cache.shouldUpload(hash, locationHash)) {\n          return Object.assign(last, {\n            toUpload: last.toUpload.concat(file),\n            localHashMap: Object.assign(last.localHashMap, {\n              [file]: locationHash + hash,\n            }),\n          })\n        }\n        return Object.assign(last, {\n          pairFromCache: Object.assign(last.pairFromCache, {\n            [file]: Cache.getUrl(locationHash + hash),\n          }),\n        })\n      },\n      {\n        localHashMap: {},\n        toUpload: [],\n        pairFromCache: {},\n      }\n    )\n    const res = toUpload.length\n      ? await cdn.upload(toUpload)\n      : await Promise.resolve({})\n    // new pair to cache\n    const newPair = Object.entries(res).reduce((_, [localPath, cdnUrl]) => {\n      const hash = localHashMap[localPath]\n      return Cache.update(hash, cdnUrl)\n    }, {})\n    // update cache\n    Cache.end(newPair)\n    return Object.assign(res, pairFromCache)\n  }\n  return {\n    upload,\n  }\n}\n","const LIMIT = 10\n\n/**\n * slice array based on given limit\n * @param {number} limit\n * @returns {(files: string[]) => string[]}\n */\nconst slice = (limit) => (files) =>\n  files.reduce((last, item, index) => {\n    const i = Math.floor(index / limit)\n    if (!last[i]) last[i] = []\n    last[i].push(item)\n    return last\n  }, [])\n\n/**\n * @typedef {(files: string[], option: object=) => Promise<object>} upload\n */\n\n/**\n * @typedef {object} Cdn\n * @property {upload} upload\n */\n\n/**\n * @param {Cdn} cdn\n * @param {object=} option\n * @param {number=} option.sliceLimit slice limit\n * @returns {Cdn}\n */\nexport const parallel = (cdn, option = {}) => {\n  const { sliceLimit = LIMIT } = option\n  const sliceFn = slice(sliceLimit)\n  const parallelCdn = {\n    upload: async (files) => {\n      const res = await Promise.all(\n        sliceFn(files).map((chunk) => cdn.upload(chunk))\n      )\n      return res.reduce((last, chunkRes) => {\n        return Object.assign(last, chunkRes)\n      }, {})\n    },\n  }\n  return parallelCdn\n}\n","import { read, write } from './io'\nexport const beforeUpload = (cdn, processFn) => {\n  return {\n    async upload(files) {\n      if (typeof processFn === 'function') {\n        await Promise.all(\n          files.map(async (file) => {\n            const oldContent = read(file)\n            // allow async operation on file content\n            const newContent = await Promise.resolve(\n              processFn(oldContent, file)\n            )\n            if (oldContent !== newContent) write(file, newContent)\n          })\n        )\n      }\n      return cdn.upload(files)\n    },\n  }\n}\n"],"names":["read","location","fs","readFileSync","write","content","writeFileSync","trivialCache","save","key","value","updateCache","cdnUrl","cache","findContent","hash","k","slice","length","tryDeleteOldEntry","mode","locationHash","keys","Object","find","indexOf","Cache","update","end","input","inputObj","JSON","parse","toSave","assign","stringify","shouldUpload","oldOption","newOption","useCache","contentSameButLocChanged","shouldUseCache","getUrl","getHash","md5","init","option","passToCdn","cacheLocation","path","resolve","__dirname","join","replace","fse","ensureFileSync","cacheRaw","readFile","trim","cacheObj","compatCache","cdn","upload","files","reduce","last","file","fileContent","relativeLocation","relative","toUpload","concat","localHashMap","pairFromCache","Promise","res","newPair","entries","_","parallel","limit","sliceLimit","sliceFn","item","index","i","Math","floor","push","all","map","chunk","chunkRes","beforeUpload","processFn","oldContent","newContent"],"mappings":"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"}