chamesu
Version:
This package contains all packages of the chat application.
365 lines (275 loc) • 9.47 kB
text/typescript
/*
* Copyright (c) 2022.
* Author Peter Placzek (tada5hi)
* For the full copyright and license information,
* view the LICENSE file that was distributed with this source code.
*/
import Vue from 'vue';
import {CookieSerializeOptions, parse as parseCookie, serialize as serializeCookie} from 'cookie';
import {Context} from "@nuxt/types";
import {decodeValue, encodeValue, isSet, isUnset} from "~/modules/storage/utils";
import {StorageOptionsInterface} from "~/modules/storage/types";
export default class BaseStorage {
public ctx: Context
public options: StorageOptionsInterface;
public state : {[key: string] : any} = {};
// ------------------------------------
constructor (ctx: Context, options: StorageOptionsInterface) {
this.ctx = ctx
this.options = options;
this.initState();
}
// ------------------------------------
getKeyWithNamespace(key: string) : string {
let fullKey: string = '';
if(typeof this.options.namespace !== 'undefined') {
fullKey += this.options.namespace+'_';
}
return fullKey+key;
}
// ------------------------------------
// Universal
// ------------------------------------
set (key: string, value: any) {
// Unset null, undefined
if (isUnset(value)) {
console.log('Unset key:'+key)
return this.remove(key)
}
this.setState(key,value);
this.setCookie(key, value)
this.setLocalStorageItem(key, value);
this.setSessionStorageItem(key, value);
return value
}
get (key: string) {
let value : any = this.getState(key);
// Cookies
if (isUnset(value)) {
value = this.getCookie(key);
}
// Local Storage
if (isUnset(value)) {
value = this.getLocalStorageItem(key);
}
if(isUnset(value)) {
value = this.getSessionStorageItem(key);
}
if (isUnset(value)) {
value = this.getState(key)
}
return value
}
getAll() {
let value : any = {};
let storageValue : any;
storageValue = this.getCookies();
if(storageValue) {
value = {...value, ...storageValue}
}
storageValue = this.getLocalStorageItems();
if(storageValue) {
value = {...value, ...storageValue}
}
storageValue = this.getSessionStorageItems();
if(storageValue) {
value = {...value, ...storageValue}
}
return value;
}
sync (key: string, defaultValue?: any) {
let value = this.get(key)
if (isUnset(value) && isSet(defaultValue)) {
value = defaultValue
}
if (isSet(value)) {
this.set(key, value)
}
return value
}
remove (key: string) {
this.removeState(key);
this.removeSessionStorageItem(key);
this.removeLocalStorageItem(key)
this.removeCookie(key)
}
// ------------------------------------
// State
// ------------------------------------
initState() {
Vue.set(this, 'state', {});
}
setState<T>(key: string, value: T) : T {
Vue.set(this.state, key, value);
return value;
}
getState(key: string) {
return this.state[key];
}
removeState(key: string) {
this.setState(key, undefined);
}
// ------------------------------------
// Browser Storage
// ------------------------------------
getBrowserStorageItems(type: 'sessionStorage' | 'localStorage') {
let storage : any;
switch (type) {
case 'sessionStorage':
storage = sessionStorage;
break;
case 'localStorage':
storage = localStorage;
break;
}
if (typeof storage === 'undefined' || !this.options[type]) {
return;
}
let items : {[key: string] : any} = {},
keys = Object.keys(storage),
i = keys.length;
while ( i-- ) {
let key = keys[i];
if(typeof this.options.namespace !== "undefined") {
if(key.substr(0, this.options.namespace.length) !== this.options.namespace) {
continue;
}
key = key.replace(this.options.namespace+'_', '');
}
items[key] = decodeValue(storage.getItem(keys[i]));
}
return items;
}
// ------------------------------------
// Local storage
// ------------------------------------
setLocalStorageItem (key: string, value: any) {
// Unset null, undefined
if (isUnset(value)) {
return this.removeLocalStorageItem(key)
}
if (typeof localStorage === 'undefined' || !this.options.localStorage) {
return
}
const _key = this.getKeyWithNamespace(key);
try {
localStorage.setItem(_key, encodeValue(value))
} catch (e) {
if (!this.options.ignoreExceptions) {
throw e
}
}
return value
}
getLocalStorageItem (key: string) : any {
if (typeof localStorage === 'undefined' || !this.options.localStorage) {
return
}
const _key = this.getKeyWithNamespace(key);
const value = localStorage.getItem(_key)
return decodeValue(value)
}
getLocalStorageItems() : any {
return this.getBrowserStorageItems('localStorage');
}
removeLocalStorageItem (key: string) {
if (typeof localStorage === 'undefined' || !this.options.localStorage) {
return
}
const _key = this.getKeyWithNamespace(key);
localStorage.removeItem(_key)
}
// ------------------------------------
// Session storage
// ------------------------------------
setSessionStorageItem (key: string, value: any) {
// Unset null, undefined
if (isUnset(value)) {
return this.removeSessionStorageItem(key)
}
if (typeof sessionStorage === 'undefined' || !this.options.sessionStorage) {
return
}
const _key = this.getKeyWithNamespace(key);
try {
sessionStorage.setItem(_key, encodeValue(value))
} catch (e) {
throw e;
}
return value
}
getSessionStorageItem (key: string) {
if (typeof sessionStorage === 'undefined' || !this.options.sessionStorage) {
return
}
const _key = this.getKeyWithNamespace(key);
const value = sessionStorage.getItem(_key)
return decodeValue(value)
}
getSessionStorageItems() : any {
return this.getBrowserStorageItems('sessionStorage');
}
removeSessionStorageItem (key: string) {
if (typeof sessionStorage === 'undefined' || !this.options.sessionStorage) {
return
}
const _key = this.getKeyWithNamespace(key);
sessionStorage.removeItem(_key)
}
// ------------------------------------
// Cookies
// ------------------------------------
getCookies () {
const cookieStr = process.client
? document.cookie
: this.ctx.req.headers.cookie
let items : {[key: string] : any} = decodeValue(parseCookie(cookieStr || '') || {});
for(let key in items) {
items[key] = decodeValue(decodeURIComponent(items[key]));
}
return items;
}
setCookie (key: string, value: any) {
if (!this.options.cookie || (process.server && !this.ctx.res)) {
return
}
const _key = this.getKeyWithNamespace(key);
const _options = <CookieSerializeOptions> Object.assign({}, this.options.cookie);
const _value = encodeValue(value)
// Unset null, undefined
if (isUnset(value)) {
_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
let cookies = this.ctx.res.getHeader('Set-Cookie') || [];
if(typeof cookies === 'number' || typeof cookies === 'string') {
if(typeof cookies === 'number') {
cookies = cookies.toString();
}
cookies = [cookies];
}
cookies.unshift(serializedCookie);
this.ctx.res.setHeader('Set-Cookie', cookies.filter((v, i, arr) => arr.findIndex(val => val.startsWith(v.substr(0, v.indexOf('=')))) === i));
}
return value
}
getCookie (key: string) {
if (!this.options.cookie || (process.server && !this.ctx.req)) {
return
}
const _key = this.getKeyWithNamespace(key);
const cookies = this.getCookies()
return cookies[_key] ?? undefined;
}
removeCookie (key: string) {
this.setCookie(key, undefined)
}
}
export function createStorage(ctx: Context, options: StorageOptionsInterface) {
return new BaseStorage(ctx, options);
}