import { App, inject, InjectionKey, getCurrentInstance } from "vue" /** * Vue Plugin Base * * - [Vue 3 Docs](https://vuejs.org/guide) * - [Plugins](https://vuejs.org/guide/reusability/plugins.html) * - [Writing a Plugin](https://vuejs.org/guide/reusability/plugins.html#writing-a-plugin) */ export class Plugin { /** * Called automatically by `app.use(Plugin)`. * * ***Should not be called manually by the user*** * * @internal * @param app - Application that uses the plugin */ install(app: App, ...args: any[]): void { return } } /** * Injects or Provides the provided value * - Works in Vue Components and in pure TypeScript code */ function CreateInjector(name: InjectionKey, instance: T): T { return getCurrentInstance() ? inject(name) || instance : instance } /** * Types for {@link createUseHook} */ interface UseHook { /** * Injection Key for the given instance * * [Docs](https://vuejs.org/api/composition-api-dependency-injection.html) */ key: InjectionKey /** * Function for getting the instance in components or scripts * * ***Usage:*** * ```ts * const { useHook } = createUseHook("NAME", INSTANCE) * const instance = useHook() * ``` */ useHook: () => T /** * Function for providing the instance to the app * - Needs to run before `useHook` to provide the instance to the app * * ```ts * const { provide } = createUseHook("NAME", INSTANCE) * * export class ExamplePlugin extends Plugin { * public readonly install = provide * } * ``` */ provide: (app: App) => void } /** * Useful Utility for creating a UseHook for a Vue Plugin * * ***Usage:*** * ```ts * import { createUseHook, Plugin } from "vvic-utils/types" * const { useHook, provide } = createUseHook("NAME", INSTANCE) * * export class ExamplePlugin extends Plugin { * public readonly install = provide * } * * export default ExamplePlugin() * ``` */ export function createUseHook(name: string, instance: T): UseHook { const key = Symbol(name) as InjectionKey const provide = (app: App) => { try { app.provide(key, instance) } catch (error) { return } } const useHook = () => CreateInjector(key, instance) return { key, useHook, provide } } /** * Small Utility for creating an install function with multiple provide functions from Use Hooks * * ***Usage:*** * ```ts * import { createUseHook, createInstall, Plugin } from "vvic-utils/types" * const hook1 = createUseHook("1", INSTANCE_1) * const hook2 = createUseHook("2", INSTANCE_2) * * export class ExamplePlugin extends Plugin { * public readonly install = createInstall( * hook1.provide, * hook2.provide * ) * } * * export default ExamplePlugin() * ``` */ export function createInstall(...fn: ((app: App) => void)[]) { return (app: App) => { fn.forEach((f) => f(app)) } }