129 lines
2.8 KiB
JavaScript
129 lines
2.8 KiB
JavaScript
const { STORAGE_KEYS } = require('../../config/constants')
|
|
|
|
const EMPTY_STATE = Object.freeze({
|
|
isLoggedIn: false,
|
|
token: '',
|
|
userInfo: null,
|
|
permissions: []
|
|
})
|
|
|
|
function cloneSessionState(state) {
|
|
return {
|
|
isLoggedIn: Boolean(state.token),
|
|
token: state.token || '',
|
|
userInfo: state.userInfo ? { ...state.userInfo } : null,
|
|
permissions: Array.isArray(state.permissions) ? [...state.permissions] : []
|
|
}
|
|
}
|
|
|
|
function normalizeSession(payload = {}) {
|
|
return cloneSessionState({
|
|
...EMPTY_STATE,
|
|
...payload
|
|
})
|
|
}
|
|
|
|
function createStorageAdapter() {
|
|
return {
|
|
get(key) {
|
|
if (typeof wx === 'undefined' || typeof wx.getStorageSync !== 'function') {
|
|
return undefined
|
|
}
|
|
|
|
try {
|
|
return wx.getStorageSync(key)
|
|
} catch (error) {
|
|
return undefined
|
|
}
|
|
},
|
|
set(key, value) {
|
|
if (typeof wx === 'undefined' || typeof wx.setStorageSync !== 'function') {
|
|
return
|
|
}
|
|
|
|
wx.setStorageSync(key, value)
|
|
},
|
|
remove(key) {
|
|
if (typeof wx === 'undefined' || typeof wx.removeStorageSync !== 'function') {
|
|
return
|
|
}
|
|
|
|
wx.removeStorageSync(key)
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @typedef {Object} SessionPayload
|
|
* @property {string} token
|
|
* @property {Record<string, any>|null} userInfo
|
|
* @property {string[]} permissions
|
|
*/
|
|
|
|
/**
|
|
* @param {{
|
|
* storage?: {get(key: string): any, set(key: string, value: any): void, remove(key: string): void},
|
|
* storageKey?: string
|
|
* }} [options]
|
|
*/
|
|
function createSessionStore(options = {}) {
|
|
const storage = options.storage || createStorageAdapter()
|
|
const storageKey = options.storageKey || STORAGE_KEYS.session
|
|
const listeners = new Set()
|
|
let state = normalizeSession()
|
|
|
|
function emitChange() {
|
|
const snapshot = cloneSessionState(state)
|
|
listeners.forEach(listener => listener(snapshot))
|
|
}
|
|
|
|
return {
|
|
getState() {
|
|
return cloneSessionState(state)
|
|
},
|
|
hydrate() {
|
|
const cachedSession = storage.get(storageKey)
|
|
|
|
if (cachedSession) {
|
|
state = normalizeSession(cachedSession)
|
|
emitChange()
|
|
}
|
|
|
|
return this.getState()
|
|
},
|
|
/**
|
|
* @param {SessionPayload} payload
|
|
*/
|
|
setSession(payload) {
|
|
state = normalizeSession(payload)
|
|
storage.set(storageKey, {
|
|
token: state.token,
|
|
userInfo: state.userInfo,
|
|
permissions: state.permissions
|
|
})
|
|
emitChange()
|
|
return this.getState()
|
|
},
|
|
clearSession() {
|
|
state = normalizeSession()
|
|
storage.remove(storageKey)
|
|
emitChange()
|
|
return this.getState()
|
|
},
|
|
subscribe(listener) {
|
|
listeners.add(listener)
|
|
|
|
return () => {
|
|
listeners.delete(listener)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const sessionStore = createSessionStore()
|
|
|
|
module.exports = {
|
|
createSessionStore,
|
|
sessionStore
|
|
}
|