Skip to content
Snippets Groups Projects
helpers.ts 4.38 KiB
Newer Older
  • Learn to ignore specific revisions
  • import { AxiosError } from 'axios'
    import { Dispatch } from 'vuex'
    import { MutationHandler } from 'vuex-typex'
    
    export function nameSpacer (namespace: string) {
      return function (commitType: string) {
    
    robinwilliam.hundt's avatar
    robinwilliam.hundt committed
        return namespace + commitType
      }
    }
    
    
    export function getObjectValueByPath (obj: any, path: string): any {
    
    robinwilliam.hundt's avatar
    robinwilliam.hundt committed
      // credit: http://stackoverflow.com/questions/6491463/accessing-nested-javascript-objects-with-string-key#comment55278413_6491621
      if (!path || path.constructor !== String) return
      path = path.replace(/\[(\w+)\]/g, '.$1') // convert indexes to properties
      path = path.replace(/^\./, '') // strip a leading dot
      const a = path.split('.')
    
      for (let i = 0, n = a.length; i < n; ++i) {
        const k = a[i]
    
    robinwilliam.hundt's avatar
    robinwilliam.hundt committed
        if (obj instanceof Object && k in obj) {
          obj = obj[k]
        } else {
          return
        }
      }
      return obj
    }
    
    interface GetSetPair<P> {
    
        get: () => any,
    
        set: (val: P) => void
    
    /**
     * Use this method to generate a computed property accessing the store for a Vue instance.
     * The get method will return the value at this.$store.state.<path>.
     * The set method will commit the passed value as payload for the specified mutation
     * @param path to the store variable/object being returned
     * @param mutation name of mutation type
     * @param namespace to prepend the mutation type with
     * @returns {*}
     */
    
    export function createComputedGetterSetter<P> (
    
      { path, mutation, namespace }:
    
      {path: string, mutation: string | ((payload?: P) => void), namespace:string}): GetSetPair<P> {
    
          return getObjectValueByPath((this as any).$store.state, path)
    
        set (val: P): void {
    
          if (typeof mutation === 'string') {
            (this as any).$store.commit(`${namespace ? namespace + '/' : ''}${mutation}`, val)
    
          } else {
            mutation(val)
          }
    
    interface StateMapperItem {
        name: string,
        mutation: string,
        path?: string
    }
    
    interface MappedState {
    
        [key: string]: GetSetPair<any>
    
    /**
     * Returns an object of generated computed getter/setter pairs.
     * Can be used to quickly bind a stores state and corresponding setters to a vue component
     * @param namespace optional namespace of mutations
     * @param pathPrefix if set, all items path will be prepended by the path prefix
     * @param items array that contains objects {name, path, mutation}
     */
    
    export function mapStateToComputedGetterSetter (
    
      { namespace = '', pathPrefix = '', items = [] }:
    
      {namespace: string, pathPrefix: string, items: StateMapperItem[]}): MappedState {
    
      return items.reduce((acc: MappedState, curr) => {
    
        // if no path is give, use name
        const itemPath = curr.path || curr.name
        const path = pathPrefix ? `${pathPrefix}.${itemPath}` : itemPath
    
        acc[curr.name] = createComputedGetterSetter({ mutation: curr.mutation, path, namespace })
    
    
    // thanks to rsp
    // https://stackoverflow.com/questions/12303989/cartesian-product-of-multiple-arrays-in-javascript/43053803#43053803
    
    function cartesianHelper (a: Array<any>, b: Array<any>): Array<Array<any>> {
    
      return ([] as Array<any>).concat(...a.map((a: any) => b.map((b: any) => [].concat(a, b))))
    
    }
    export function cartesian (a: Array<any>, b?: Array<any>, ...c: Array<Array<any>>): Array<Array<any>> {
    
      return b ? cartesian(cartesianHelper(a, b), ...c) : a
    }
    
    // flatten an array
    
    export function flatten (list: any[]): any[] {
    
      return list.reduce(
        (a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
      )
    }
    
    
    export function objectifyArray<T, P extends keyof T> (arr: T[], key: P): {[index: string]: T} {
      return arr.reduce((acc: any, curr) => {
    
    interface OnceFunc {
        (): any
        reset: () => void
    }
    
    export function once (fn: Function, context?: object): OnceFunc {
      let result: any
      let wrapped = <OnceFunc> function (this: any) {
    
        if (!result) {
          result = fn.apply(context || this, arguments)
        }
        return result
      }
    
      wrapped.reset = function () { result = undefined }
    
      return wrapped
    
    
    export function syntaxPostProcess (code: string): string {
      const spanPrefix = '<span class="hljs-comment">'
      const spanSuffix = '</span>'
      
      code = code.replace(/(<span class="hljs-comment">)([\s\S]*?)(<\/span>)/gim, (match, p1, p2, p3) => {
        const splitted = p2.split(/\n/)
        for (let i = 0; i < splitted.length; i++) {
          splitted[i] = spanPrefix + splitted[i] + spanSuffix
        }
        
        return splitted.join("\n")
      })
      return code
    }