diff --git a/apps/desktop/src/lib/stores/extensions.ts b/apps/desktop/src/lib/stores/extensions.ts index db5e245..7b93f0c 100644 --- a/apps/desktop/src/lib/stores/extensions.ts +++ b/apps/desktop/src/lib/stores/extensions.ts @@ -1,6 +1,6 @@ import { getExtensionsFolder } from "@/constants" import { db } from "@kksh/api/commands" -import type { ExtPackageJsonExtra } from "@kksh/api/models" +import type { ExtPackageJson, ExtPackageJsonExtra } from "@kksh/api/models" import * as extAPI from "@kksh/extension" import * as path from "@tauri-apps/api/path" import * as fs from "@tauri-apps/plugin-fs" @@ -21,22 +21,44 @@ function createExtensionsStore(): Writable & { findStoreExtensionByIdentifier: (identifier: string) => ExtPackageJsonExtra | undefined registerNewExtensionByPath: (extPath: string) => Promise uninstallStoreExtensionByIdentifier: (identifier: string) => Promise + uninstallDevExtensionByIdentifier: (identifier: string) => Promise upgradeStoreExtension: (identifier: string, tarballUrl: string) => Promise } { const store = writable([]) + /** + * Load all extensions from the database and disk, all extensions manifest will be stored in the store + * @returns loaded extensions + */ function init() { return extAPI.loadAllExtensionsFromDb().then((exts) => { store.set(exts) }) } + /** + * Get all extensions installed from the store (non-dev extensions) + */ function getExtensionsFromStore(): ExtPackageJsonExtra[] { const extContainerPath = get(appConfig).extensionsInstallDir if (!extContainerPath) return [] return get(extensions).filter((ext) => !extAPI.isExtPathInDev(extContainerPath, ext.extPath)) } + /** + * Get all dev extensions + */ + function getDevExtensions(): ExtPackageJsonExtra[] { + const extContainerPath = get(appConfig).extensionsInstallDir + if (!extContainerPath) return [] + return get(extensions).filter((ext) => extAPI.isExtPathInDev(extContainerPath, ext.extPath)) + } + + /** + * Find an extension by its identifier + * @param identifier extension identifier + * @returns found extension or undefined + */ function findStoreExtensionByIdentifier(identifier: string): ExtPackageJsonExtra | undefined { return get(extensions).find((ext) => ext.kunkun.identifier === identifier) } @@ -106,7 +128,12 @@ function createExtensionsStore(): Writable & { }) } - async function uninstallExtensionByPath(targetPath: string) { + /** + * Uninstall an extension by its path + * @param targetPath absolute path to the extension folder + * @returns uninstalled extension + */ + async function uninstallExtensionByPath(targetPath: string): Promise { const targetExt = get(extensions).find((ext) => ext.extPath === targetPath) if (!targetExt) throw new Error(`Extension ${targetPath} not registered in DB`) return extAPI @@ -115,7 +142,33 @@ function createExtensionsStore(): Writable & { .then(() => targetExt) } - async function uninstallStoreExtensionByIdentifier(identifier: string) { + /** + * Uninstall a dev extension by its path + * Files will not be removed from disk, only unregistered from the DB + * @param targetPath absolute path to the extension folder + * @returns uninstalled extension + */ + async function uninstallDevExtensionByPath(targetPath: string): Promise { + const targetExt = get(extensions).find((ext) => ext.extPath === targetPath) + if (!targetExt) throw new Error(`Extension ${targetPath} not registered in DB`) + // remove from DB + return db + .deleteExtensionByPath(targetPath) + .then(() => store.update((exts) => exts.filter((ext) => ext.extPath !== targetExt.extPath))) + .then(() => targetExt) + } + + async function uninstallDevExtensionByIdentifier( + identifier: string + ): Promise { + const targetExt = getDevExtensions().find((ext) => ext.kunkun.identifier === identifier) + if (!targetExt) throw new Error(`Extension ${identifier} not found`) + return uninstallDevExtensionByPath(targetExt.extPath) + } + + async function uninstallStoreExtensionByIdentifier( + identifier: string + ): Promise { const targetExt = getExtensionsFromStore().find((ext) => ext.kunkun.identifier === identifier) if (!targetExt) throw new Error(`Extension ${identifier} not found`) return uninstallExtensionByPath(targetExt.extPath) @@ -143,6 +196,7 @@ function createExtensionsStore(): Writable & { installFromTarballUrl, installFromNpmPackageName, uninstallStoreExtensionByIdentifier, + uninstallDevExtensionByIdentifier, upgradeStoreExtension } } diff --git a/apps/desktop/src/routes/app/settings/extensions/+page.svelte b/apps/desktop/src/routes/app/settings/extensions/+page.svelte index e69de29..b0a231c 100644 --- a/apps/desktop/src/routes/app/settings/extensions/+page.svelte +++ b/apps/desktop/src/routes/app/settings/extensions/+page.svelte @@ -0,0 +1,73 @@ + + +{#snippet extRow(ext: ExtPackageJsonExtra, type: "Dev Extension" | "Extension")} + + {ext.kunkun.name} + {ext.kunkun.identifier} + {type} + {ext.version} + + + + +{/snippet} +
+

Your Extensions

+ + Your Extensions + + + Name + Identifier + Type + Version + Uninstall + + + + {#each $devStoreExts as ext, i (i)} + {@render extRow(ext, "Dev Extension")} + {/each} + {#each $installedStoreExts as ext, i (i)} + {@render extRow(ext, "Extension")} + {/each} + + + +
diff --git a/packages/db/src/lib.rs b/packages/db/src/lib.rs index 5dc0177..d921d6c 100644 --- a/packages/db/src/lib.rs +++ b/packages/db/src/lib.rs @@ -214,6 +214,7 @@ impl JarvisDB { // } pub fn delete_extension_by_path(&self, path: &str) -> Result<()> { + println!("DB deleting extension by path: {}", path); self.conn .execute("DELETE FROM extensions WHERE path = ?1", params![path])?; Ok(()) diff --git a/packages/extension/src/load.ts b/packages/extension/src/load.ts index 087a69b..76c53e1 100644 --- a/packages/extension/src/load.ts +++ b/packages/extension/src/load.ts @@ -54,10 +54,14 @@ export function loadAllExtensionsFromDisk( }) } +/** + * Load all extensions from the database + * Then load the manifest from the disk + * If a extension is in database but cannot be loaded from disk, it will be skipped + * @returns loaded extensions + */ export async function loadAllExtensionsFromDb(): Promise { - console.log("loadAllExtensionsFromDb start") const allDbExts = await (await db.getAllExtensions()).filter((ext) => ext.path) - console.log("allDbExts", allDbExts) const results: ExtPackageJsonExtra[] = [] for (const ext of allDbExts) { if (!ext.path) continue