import { inject , reactive , UnwrapNestedRefs } from '@kirei/element' ; import type { InjectionKey , App } from '@kirei/element' ; export const INJECTION_KEY = Symbol ( 'kirei::store' ) ; param provide export type Plugin = ( provide : < T > ( key : string , value : T ) => void ) => void ; param context returns export type Setup < T extends object > = ( context : Context ) => T ; /**
 * Store context, used to allow users apply custom plugins.
 */ export interface Context { param store returns vue use < T extends object > ( store ) : UnwrapNestedRefs < T > ; } /**
 * Store instance
 */ interface Store < T extends object > { /**
     * Store name, used when composing the store and to display informational messages.
     */ name : string ; /**
     * Setup function for this store, just like the composition api's setup function.
     */ setup : Setup < T > ; } /**
 * Root store options, only used to add plugins for now.
 */ interface StoreOptions { /**
     * Store plugins as functions to inject non-reactive obejcts into reactive states.
     */ plugins : Plugin [ ] ; } /**
 * Root store, used to mount to an app instance.
 */ interface KireiStore { param app install ( app ) : void ; param store returns vue store < T extends object > ( store ) : UnwrapNestedRefs < T > ; } param options returns export function createStore ( options ? ) { const stores = new Map < string , unknown > ( ) ; const setupContext = Object . create ( null ) ; const rootStore = Object . create ( null ) ; function store < T extends object > ( { name , setup } ) { const store = stores . get ( name ) ; if ( store ) { return store as UnwrapNestedRefs < any > ; } const instance = reactive ( setup ( setupContext ) ) ; return stores . set ( name , instance ) , instance ; } function install ( app ) { app . provide ( INJECTION_KEY , rootStore ) ; } rootStore . install = install ; rootStore . store = store ; setupContext . use = rootStore . store ; if ( Array . isArray ( options ?. plugins ) ) { function pluginProvider ( key , value ) { if ( ! ( key in setupContext ) ) { setupContext [ key ] = value ; } else if ( __DEV__ ) { console . warn ( `Store plugin ${ key } already defined!` ) ; } } options . plugins . forEach ( plugin => plugin ( pluginProvider ) ) ; } return rootStore ; } param name param setup returns export function defineStore < T extends object > ( name , setup ) { return { name , setup } ; } param store returns vue export function useStore < T extends object > ( store ) { const rootStore = inject ( INJECTION_KEY ) ; if ( ! rootStore ) { throw new TypeError ( 'No store provided' ) ; } return rootStore . store ( store ) ; }