Skip to content

Commit c66dc70

Browse files
committed
move feature
1 parent f7d45e9 commit c66dc70

File tree

1 file changed

+130
-0
lines changed

1 file changed

+130
-0
lines changed

app/stores/app.js

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,140 @@ export const useAppStore = defineStore("app", () => {
6767
console.log(`[AppStore] Imported ${importedCount} stores`)
6868
}
6969

70+
const loadedExtensions = ref(new Map())
71+
const extensionAPI = ref(null)
72+
73+
function setExtensionAPI(api) {
74+
extensionAPI.value = api
75+
}
76+
77+
function getExtension(path) {
78+
return loadedExtensions.value.get(path)
79+
}
80+
81+
async function loadExtension(path, codeTransformer = null) {
82+
try {
83+
if (loadedExtensions.value.has(path)) {
84+
console.warn(`[AppStore] Extension already loaded from this path: ${path}`)
85+
throw new Error('This extension file is already loaded')
86+
}
87+
88+
if (!extensionAPI.value) {
89+
throw new Error("Extension API not initialized")
90+
}
91+
92+
let finalURL = path
93+
94+
if (codeTransformer && path.startsWith('blob:')) {
95+
const response = await fetch(path)
96+
const code = await response.text()
97+
const transformedCode = codeTransformer(code)
98+
99+
const newBlob = new Blob([transformedCode], { type: 'application/javascript' })
100+
finalURL = URL.createObjectURL(newBlob)
101+
}
102+
103+
const extensionModule = await import(finalURL)
104+
105+
if (finalURL !== path && finalURL.startsWith('blob:')) {
106+
URL.revokeObjectURL(finalURL)
107+
}
108+
109+
const extensionName = extensionModule.metadata?.name
110+
if (extensionName) {
111+
const alreadyLoaded = Array.from(loadedExtensions.value.values()).find(
112+
ext => ext.metadata?.name === extensionName
113+
)
114+
if (alreadyLoaded) {
115+
console.warn(`[AppStore] Extension "${extensionName}" is already loaded`)
116+
throw new Error(`Extension "${extensionName}" is already loaded.`)
117+
}
118+
}
119+
120+
if (typeof extensionModule.install === 'function') {
121+
await extensionModule.install(extensionAPI.value, path)
122+
123+
const extensionData = {
124+
module: extensionModule,
125+
path,
126+
loadedAt: new Date().toISOString(),
127+
metadata: extensionModule.metadata || {},
128+
enabled: true,
129+
}
130+
loadedExtensions.value.set(path, extensionData)
131+
132+
console.log(`[AppStore] Extension loaded successfully: ${path}`)
133+
134+
return extensionModule
135+
} else {
136+
throw new Error('Extension must export an install function')
137+
}
138+
} catch (error) {
139+
console.error(`[AppStore] Failed to load extension from ${path}:`, error)
140+
throw error
141+
}
142+
}
143+
144+
function getLoadedExtensions() {
145+
return Array.from(loadedExtensions.value.values())
146+
}
147+
148+
function unloadExtension(path) {
149+
const extensionData = getExtension(path)
150+
if (!extensionData) return false
151+
152+
if (extensionData.module && typeof extensionData.module.uninstall === 'function') {
153+
try {
154+
extensionData.module.uninstall(extensionAPI.value, path)
155+
console.log(`[AppStore] Extension uninstall called: ${path}`)
156+
} catch (error) {
157+
console.error(`[AppStore] Error calling uninstall for ${path}:`, error)
158+
}
159+
}
160+
161+
if (extensionAPI.value && typeof extensionAPI.value.unregisterToolsByExtension === 'function') {
162+
extensionAPI.value.unregisterToolsByExtension(path)
163+
}
164+
165+
loadedExtensions.value.delete(path)
166+
console.log(`[AppStore] Extension unloaded: ${path}`)
167+
return true
168+
}
169+
170+
function toggleExtension(path) {
171+
const extensionData = getExtension(path)
172+
if (!extensionData) return false
173+
174+
extensionData.enabled = !extensionData.enabled
175+
console.log(`[AppStore] Extension ${extensionData.enabled ? 'enabled' : 'disabled'}: ${path}`)
176+
return extensionData.enabled
177+
}
178+
179+
function setExtensionEnabled(path, enabled) {
180+
const extensionData = getExtension(path)
181+
if (!extensionData) return false
182+
183+
extensionData.enabled = enabled
184+
console.log(`[AppStore] Extension ${enabled ? 'enabled' : 'disabled'}: ${path}`)
185+
return true
186+
}
187+
188+
function getExtensionEnabled(path) {
189+
return getExtension(path)?.enabled ?? false
190+
}
191+
70192
return {
71193
stores,
72194
registerStore,
73195
exportStores,
74196
importStores,
197+
loadedExtensions,
198+
setExtensionAPI,
199+
loadExtension,
200+
getLoadedExtensions,
201+
unloadExtension,
202+
toggleExtension,
203+
setExtensionEnabled,
204+
getExtensionEnabled,
75205
}
76206
})

0 commit comments

Comments
 (0)