const _ = require('lodash') const Promise = require('bluebird') const { fs } = require('./util/fs') const appData = require('./util/app_data') const FileUtil = require('./util/file') const logger = require('./logger') const fileUtil = new FileUtil({ path: appData.path('cache'), }) const convertProjectsToArray = function (obj) { // if our project structure is not // an array then its legacy and we // need to convert it if (!_.isArray(obj.PROJECTS)) { obj.PROJECTS = _.chain(obj.PROJECTS).values().map('PATH').compact().value() return obj } } const renameSessionToken = function (obj) { let st if (obj.USER && (st = obj.USER.session_token)) { delete obj.USER.session_token obj.USER.sessionToken = st return obj } } module.exports = { path: fileUtil.path, defaults () { return { USER: {}, PROJECTS: [], } }, _applyRewriteRules (obj = {}) { return _.reduce([convertProjectsToArray, renameSessionToken], (memo, fn) => { let ret ret = fn(memo) if (ret) { return ret } return memo } , _.cloneDeep(obj)) }, read () { return fileUtil.get().then((contents) => { return _.defaults(contents, this.defaults()) }) }, write (obj = {}) { logger.info('writing to .cy cache', { cache: obj }) return fileUtil.set(obj).return(obj) }, _getProjects (tx) { return tx.get('PROJECTS', []) }, _removeProjects (tx, projects, paths) { // normalize paths in array projects = _.without(projects, ...[].concat(paths)) return tx.set({ PROJECTS: projects }) }, getProjectRoots () { return fileUtil.transaction((tx) => { return this._getProjects(tx).then((projects) => { const pathsToRemove = Promise.reduce(projects, (memo, path) => { return fs.statAsync(path) .catch(() => { return memo.push(path) }).return(memo) } , []) return pathsToRemove.then((removedPaths) => { return this._removeProjects(tx, projects, removedPaths) }).then(() => { return this._getProjects(tx) }) }) }) }, removeProject (path) { return fileUtil.transaction((tx) => { return this._getProjects(tx).then((projects) => { return this._removeProjects(tx, projects, path) }) }) }, insertProject (path) { return fileUtil.transaction((tx) => { return this._getProjects(tx).then((projects) => { // projects are sorted by most recently used, so add a project to // the start or move it to the start if it already exists const existingIndex = _.findIndex(projects, (project) => { return project === path }) if (existingIndex > -1) { projects.splice(existingIndex, 1) } projects.unshift(path) return tx.set('PROJECTS', projects) }) }) }, getUser () { logger.info('getting user') return fileUtil.get('USER', {}) }, setUser (user) { logger.info('setting user', { user }) return fileUtil.set({ USER: user }) }, removeUser () { return fileUtil.set({ USER: {} }) }, remove () { return fileUtil.remove() }, // for testing purposes __get: fileUtil.get.bind(fileUtil), __removeSync () { fileUtil._cache = {} return fs.removeSync(this.path) }, }