Last active
August 17, 2023 13:56
-
-
Save ttkoma/6fdfaf0f0bc61d432ab98f746f97463a to your computer and use it in GitHub Desktop.
nuxt-auth + pinia instead vuex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Context, Plugin } from "@nuxt/types"; | |
import Vue from "vue"; | |
import { defineStore, PiniaPluginContext } from "pinia"; | |
import { ref, set } from "@nuxtjs/composition-api"; | |
export const useAuthStore = defineStore({ | |
id: "auth", | |
state: () => ({ | |
busy: false, | |
user: null as null | false | Record<string, unknown>, | |
loggedIn: false, | |
strategy: undefined, | |
redirect: undefined as undefined | string, | |
}), | |
}); | |
type UseAuthStoreReturn = ReturnType<typeof useAuthStore>; | |
interface IMutationPayload { | |
key: string; | |
value: any; | |
} | |
interface IAuthVuexStore<S> { | |
readonly state: { [p: string]: S }; | |
registerModule(namespace: string, module: any, options: { preserveState?: boolean }): void; | |
commit(mutationName: string, payload: IMutationPayload): void; | |
watch<T>( | |
getter: (state: S, getters: any) => T, | |
cb: (value: T, oldValue: T) => void, | |
options?: any | |
): void; | |
} | |
class NuxtStorePlugin<S> implements IAuthVuexStore<S> { | |
private _ctx: Context; | |
private _namespace = "auth"; // equals with auth.vuex.namespace in nuxt.config | |
private authStore?: UseAuthStoreReturn; | |
private _watcherVM = new Vue(); | |
constructor(ctx: Context) { | |
this._ctx = ctx; | |
} | |
// Fake vuex state contain module 'auth' | |
public get state() { | |
const this$1 = this; | |
return { | |
// 2. implement full state getter | |
get [this$1._namespace](): S { | |
// TODO: return undefined | |
return (this$1.authStore?.$state ?? {}) as S; | |
}, | |
}; | |
} | |
// Fake vuex registerModule | |
public registerModule(name: string, module: any, _options?: any) { | |
this._namespace = name; | |
// 1. Create Auth Store | |
const initState = module.state(); | |
this._ctx.$pinia.use((params: PiniaPluginContext) => { | |
const { store } = params; | |
if (store.$id === "auth") { | |
Object.keys(initState).forEach((prop) => { | |
if (!(prop in store.$state)) { | |
const refValue = ref(initState[prop]); | |
set(store.$state, prop, refValue); | |
set(store, prop, refValue); | |
} | |
}); | |
} | |
}); | |
this.authStore = useAuthStore(this._ctx.$pinia); | |
this.authStore.$state = initState; | |
} | |
// Fake vuex commit | |
public commit(mutationName: string, payload: IMutationPayload) { | |
if (mutationName === `${this._namespace}/SET` && this.authStore) { | |
// 3. implement state property setter | |
this.authStore.$patch({ | |
[payload.key]: payload.value, | |
}); | |
} | |
} | |
// Fake vuex watch | |
public watch<T>( | |
getter: (state: any, getters: any) => T, | |
cb: (value: T, oldValue: T) => void, | |
options: any | |
): void { | |
const this$1 = this; | |
this._watcherVM.$watch( | |
// 4. PINIA getters direct access as state properties | |
() => getter(this$1.state, this$1.state), | |
cb, | |
options | |
); | |
} | |
} | |
// NUXT PLUGIN for inject $store | |
const piniaAuthPlugin: Plugin = (context: Context) => { | |
// @ts-ignore | |
context.store = new NuxtStorePlugin(context); | |
}; | |
export default piniaAuthPlugin; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment