Skip to content

Instantly share code, notes, and snippets.

@ttkoma
Last active August 17, 2023 13:56
Show Gist options
  • Save ttkoma/6fdfaf0f0bc61d432ab98f746f97463a to your computer and use it in GitHub Desktop.
Save ttkoma/6fdfaf0f0bc61d432ab98f746f97463a to your computer and use it in GitHub Desktop.
nuxt-auth + pinia instead vuex
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