Skip to content

Commit

Permalink
feat: improve storage (#360)
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 authored May 30, 2019
1 parent e68c4eb commit d05fcca
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 35 deletions.
118 changes: 83 additions & 35 deletions lib/core/storage.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import Vue from 'vue'
import Cookies from 'js-cookie'
import getProp from 'dotprop'
import { parse as parseCookie } from 'cookie'

import { isUnset, isSet } from './utilities'
import { parse as parseCookie, serialize as serializeCookie } from 'cookie'
import { isUnset, isSet, decodeValue, encodeValue } from './utilities'

export default class Storage {
constructor (ctx, options) {
Expand All @@ -17,38 +15,43 @@ export default class Storage {
// Universal
// ------------------------------------

setUniversal (key, value, isJson) {
setUniversal (key, value) {
// Unset null, undefined
if (isUnset(value)) {
return this.removeUniversal(key)
}

// Local state
this.setState(key, value)

// Cookies
this.setCookie(key, value)

// Local Storage
this.setLocalStorage(key, value, isJson)
this.setLocalStorage(key, value)

return value
}

getUniversal (key, isJson) {
getUniversal (key) {
// Local state
let value = this.getState(key)

// Cookies
if (isUnset(value)) {
value = this.getCookie(key, isJson)
value = this.getCookie(key)
}

// Local Storage
if (isUnset(value)) {
value = this.getLocalStorage(key, isJson)
value = this.getLocalStorage(key)
}

return value
}

syncUniversal (key, defaultValue, isJson) {
let value = this.getUniversal(key, isJson)
syncUniversal (key, defaultValue) {
let value = this.getUniversal(key)

if (isUnset(value) && isSet(defaultValue)) {
value = defaultValue
Expand All @@ -61,6 +64,12 @@ export default class Storage {
return value
}

removeUniversal (key) {
this.removeState(key)
this.removeLocalStorage(key)
this.removeCookie(key)
}

// ------------------------------------
// Local state (reactive)
// ------------------------------------
Expand Down Expand Up @@ -128,79 +137,118 @@ export default class Storage {
}
}

removeState (key) {
this.setState(key, undefined)
}

// ------------------------------------
// Local storage
// ------------------------------------

setLocalStorage (key, value, isJson) {
setLocalStorage (key, value) {
// Unset null, undefined
if (isUnset(value)) {
return this.removeLocalStorage(key)
}

if (typeof localStorage === 'undefined' || !this.options.localStorage) {
return
}

const _key = this.options.localStorage.prefix + key

if (isUnset(value)) {
localStorage.removeItem(_key)
} else {
localStorage.setItem(_key, isJson ? JSON.stringify(value) : value)
try {
localStorage.setItem(_key, encodeValue(value))
} catch (e) {
if (!this.options.ignoreExceptions) {
throw e
}
}

return value
}

getLocalStorage (key, isJson) {
getLocalStorage (key) {
if (typeof localStorage === 'undefined' || !this.options.localStorage) {
return
}

const _key = this.options.localStorage.prefix + key

const value = localStorage.getItem(_key)
if (value === 'false') {
return false

return decodeValue(value)
}

removeLocalStorage (key) {
if (typeof localStorage === 'undefined' || !this.options.localStorage) {
return
}

return isJson ? JSON.parse(value) : value
const _key = this.options.localStorage.prefix + key
localStorage.removeItem(_key)
}

// ------------------------------------
// Cookies
// ------------------------------------
getCookies () {
const cookieStr = process.client
? document.cookie
: this.ctx.req.headers.cookie

return parseCookie(cookieStr || '') || {}
}

setCookie (key, value, options = {}) {
if (process.server || !this.options.cookie) {
if (!this.options.cookie || (process.server && !this.ctx.res)) {
return
}

const _key = this.options.cookie.prefix + key

const _options = Object.assign({}, this.options.cookie.options, options)
const _value = encodeValue(value)

// Unset null, undefined
if (isUnset(value)) {
Cookies.remove(_key, _options)
} else {
Cookies.set(_key, value, _options)
_options.maxAge = -1
}

const serializedCookie = serializeCookie(_key, _value, _options)

if (process.client) {
// Set in browser
document.cookie = serializedCookie
} else if (process.server && this.ctx.res) {
// Send Set-Cookie header from server side
const prev = this.ctx.res.getHeader('Set-Cookie')
let value = serializedCookie
if (prev) {
value = Array.isArray(prev)
? prev.concat(serializedCookie)
: [prev, serializedCookie]
}
this.ctx.res.setHeader('Set-Cookie', value)
}

return value
}

getCookie (key, isJson) {
getCookie (key) {
if (!this.options.cookie || (process.server && !this.ctx.req)) {
return
}

const _key = this.options.cookie.prefix + key

const cookieStr = process.client
? document.cookie
: this.ctx.req.headers.cookie
const cookies = this.getCookies()

const cookies = parseCookie(cookieStr || '') || {}
const value = cookies[_key]
if (value === 'false') {
return false
}
return isJson ? JSON.parse(value) : value
const value = cookies[_key] ? decodeURIComponent(cookies[_key]) : undefined

return decodeValue(value)
}

removeCookie (key, options) {
this.setCookie(key, undefined, options)
}
}
19 changes: 19 additions & 0 deletions lib/core/utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,22 @@ export function normalizePath (path = '') {

return result
}

export function encodeValue (val) {
if (typeof val === 'string') {
return val
}
return JSON.stringify(val)
}

export function decodeValue (val) {
// Try to parse as json
if (typeof val === 'string') {
try {
return JSON.parse(val)
} catch (_) { }
}

// Return as is
return val
}

0 comments on commit d05fcca

Please sign in to comment.