const fs = require('node:fs') const vm = require('node:vm') const { randomUUID } = require('node:crypto') const vue = require('vue') function memoryStorage() { const storage = Object.create(null) Object.defineProperties(storage, { getItem: { value: key => storage[key] ?? null }, setItem: { value: (key, value) => { storage[key] = value } }, removeItem: { value: key => { delete storage[key] } }, }) return storage } function createDraftHarness({ auth = vue.reactive({ user: { id: 'user-1' }, activeTenant: '1', profile: { id: 'profile-1' } }), storage = memoryStorage() } = {}) { const scope = vue.effectScope(), toasts = [], calls = [] const context = vm.createContext({ ...vue, crypto: { randomUUID }, sessionStorage: storage, defineStore: (_, setup) => setup, useAuthStore: () => auth, useRuntimeConfig: () => ({ public: { apiBase: 'https://api.example.test' } }), useToast: () => ({ add: toast => toasts.push(toast) }), useNuxtApp: () => ({ $api: async (url, options) => { calls.push({ url, options }) } }), }) const storeSource = fs.readFileSync(`${__dirname}/../../stores/temp.js`, 'utf8').replace(/^import .*$/mg, '').replace('export const', 'const') const store = scope.run(() => vm.runInContext(`${storeSource}\nuseTempStore()`, context)) context.useTempStore = () => store const composable = fs.readFileSync(`${__dirname}/../../composables/useChatDraft.js`, 'utf8').replace('export function', 'function') vm.runInContext(composable, context) return { auth, storage, store, calls, toasts, useChatDraft: (key, options) => scope.run(() => context.useChatDraft(key, options)), close: () => scope.stop(), } } module.exports = { createDraftHarness, memoryStorage }