All files persistLink.js

95.83% Statements 23/24
91.67% Branches 11/12
90.91% Functions 10/11
100% Lines 21/21
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87                        36x         1x 10x   10x 80x         17x   17x   17x                           81x       10x 10x             6x           6x     6x   59x 15x         6x 6x 6x     6x         1x      
import { visit } from 'graphql'
import { ApolloLink } from 'apollo-link'
import traverse from 'traverse'
 
import { extractPersistDirectivePaths } from './transform'
 
/**
 * Given a data result object path, return the equivalent query selection path.
 *
 * @param {Array} path The data result object path. i.e.: ["a", 0, "b"]
 * @return {String} the query selection path. i.e.: "a.b"
 */
const toQueryPath = path => path.filter(key => isNaN(Number(key))).join('.')
 
/**
 * Given a data result object, attach __persist values.
 */
const attachPersists = (paths, object) => {
  const queryPaths = paths.map(toQueryPath)
 
  return traverse(object).map(function () {
    if (
      !this.isRoot &&
      typeof this.node === 'object' &&
      !Array.isArray(this.node)
    ) {
      const path = toQueryPath(this.path)
 
      this.update({
        __persist: Boolean(
          queryPaths.find(queryPath => queryPath.indexOf(path) === 0)
        ),
        ...this.node
      })
    }
  })
}
 
class PersistLink extends ApolloLink {
  /**
   * InStorageCache shouldPersist implementation for a __persist field validation.
   */
  static shouldPersist (op, dataId, data) {
    // console.log(dataId, data)
    return dataId === 'ROOT_QUERY' || (!data || !!data.__persist)
  }
 
  constructor () {
    super()
    this.directive = 'persist'
  }
 
  /**
   * Link query requester.
   */
  request = (operation, forward) => {
    const { query, paths } = extractPersistDirectivePaths(
      operation.query,
      this.directive
    )
 
    // Replace query with one without @persist directives.
    operation.query = query
 
    // Remove requesting __persist fields.
    operation.query = visit(operation.query, {
      Field: ({ name: { value: name } }, key, parent, path, ancestors) => {
        if (name === '__persist') {
          return null
        }
      }
    })
 
    return forward(operation).map(result => {
      Eif (result.data) {
        result.data = attachPersists(paths, result.data)
      }
 
      return result
    })
  }
}
 
const createPersistLink = config => new PersistLink(config)
 
export { PersistLink, createPersistLink }