/* eslint-disable vue/one-component-per-file */ import { lazyValuesKey, mutationEventKey } from "./keys.js"; import type { Component, InjectionKey } from "vue"; import { createApp, defineComponent, h, provide, shallowRef } from "vue"; type InstanceType = V extends { new (...arg: unknown[]): infer X } ? X : never; type VM = InstanceType & { unmount: () => void }; export function withSetup( composable: () => TResult, injections: { [key: InjectionKey]: typeof key extends InjectionKey ? Value : never; } = {}, ) { let result!: TResult; const Comp = defineComponent({ setup() { result = composable(); return () => h("div"); }, }); const Provider = defineComponent({ setup() { provide(lazyValuesKey, new Map()); provide(mutationEventKey, shallowRef()); [ ...Object.entries(injections), ...Object.getOwnPropertySymbols(injections).map( (symbol) => [symbol, injections[symbol]] as const, ), ].forEach(([key, value]) => { provide(key, value); }); return () => h(Comp); }, }); const mounted = mount(Provider); return { result, unmount: mounted.unmount, }; } function mount(Comp: V) { const el = document.createElement("div"); const app = createApp(Comp as Component); const unmount = () => app.unmount(); const comp = app.mount(el) as unknown as VM; comp.unmount = unmount; return comp; }