From df5d75d1f81a1f495e90d843ca2621b3ffd8f0be Mon Sep 17 00:00:00 2001 From: Louis <133622055+louis-jan@users.noreply.github.com> Date: Wed, 25 Oct 2023 01:06:37 +0700 Subject: [PATCH] fix: plugin & model catalog import cache are not cleared properly (#437) * fix: plugin catalog cache is not wiped properly * fix: import cache issue --- plugins/data-plugin/@types/global.d.ts | 1 + plugins/data-plugin/index.ts | 20 ++++++ plugins/data-plugin/package.json | 8 ++- plugins/data-plugin/tsconfig.json | 2 +- plugins/data-plugin/webpack.config.js | 3 + plugins/model-management-plugin/index.ts | 67 ++++++++++++++----- web/app/_components/Preferences.tsx | 9 ++- web/hooks/useGetSystemResources.ts | 4 ++ web/next.config.js | 9 +-- web/package.json | 2 +- .../Settings/CorePlugins/PluginsCatalog.tsx | 12 ++-- 11 files changed, 97 insertions(+), 40 deletions(-) diff --git a/plugins/data-plugin/@types/global.d.ts b/plugins/data-plugin/@types/global.d.ts index 87105f099..d9ac97172 100644 --- a/plugins/data-plugin/@types/global.d.ts +++ b/plugins/data-plugin/@types/global.d.ts @@ -1,2 +1,3 @@ declare const PLUGIN_NAME: string; declare const MODULE_PATH: string; +declare const PLUGIN_CATALOG: string; diff --git a/plugins/data-plugin/index.ts b/plugins/data-plugin/index.ts index f9716291a..0ff0fcd68 100644 --- a/plugins/data-plugin/index.ts +++ b/plugins/data-plugin/index.ts @@ -216,6 +216,9 @@ export function init({ register }: { register: RegisterExtensionPoint }) { register(DataService.GetBotById, getBotById.name, getBotById); register(DataService.DeleteBot, deleteBot.name, deleteBot); register(DataService.UpdateBot, updateBot.name, updateBot); + + // for plugin manifest + register(DataService.GetPluginManifest, getPluginManifest.name, getPluginManifest) } function getConversations(): Promise { @@ -323,3 +326,20 @@ function getBotById(botId: string): Promise { return Promise.reject(err); }); } + +/** + * Retrieves the plugin manifest by importing the remote model catalog and clearing the cache to get the latest version. + * A timestamp is added to the URL to prevent caching. + * @returns A Promise that resolves with the plugin manifest. + */ +function getPluginManifest(): Promise { + // Clear cache to get the latest model catalog + delete require.cache[ + require.resolve(/* webpackIgnore: true */ PLUGIN_CATALOG) + ]; + // Import the remote model catalog + // Add a timestamp to the URL to prevent caching + return import( + /* webpackIgnore: true */ PLUGIN_CATALOG + `?t=${Date.now()}` + ).then((module) => module.default); +} diff --git a/plugins/data-plugin/package.json b/plugins/data-plugin/package.json index f856313d1..a7ee25939 100644 --- a/plugins/data-plugin/package.json +++ b/plugins/data-plugin/package.json @@ -40,8 +40,12 @@ "node_modules" ], "dependencies": { - "@janhq/core": "^0.1.6", + "@janhq/core": "^0.1.7", "pouchdb-find": "^8.0.1", "pouchdb-node": "^8.0.1" - } + }, + "bundleDependencies": [ + "pouchdb-node", + "pouchdb-find" + ] } diff --git a/plugins/data-plugin/tsconfig.json b/plugins/data-plugin/tsconfig.json index 3b321034a..3a82721e6 100644 --- a/plugins/data-plugin/tsconfig.json +++ b/plugins/data-plugin/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "target": "es2016", - "module": "ES6", + "module": "esnext", "moduleResolution": "node", "outDir": "./dist", "esModuleInterop": true, diff --git a/plugins/data-plugin/webpack.config.js b/plugins/data-plugin/webpack.config.js index b88dd14d3..affb5950a 100644 --- a/plugins/data-plugin/webpack.config.js +++ b/plugins/data-plugin/webpack.config.js @@ -19,6 +19,9 @@ module.exports = { new webpack.DefinePlugin({ PLUGIN_NAME: JSON.stringify(packageJson.name), MODULE_PATH: JSON.stringify(`${packageJson.name}/${packageJson.module}`), + PLUGIN_CATALOG: JSON.stringify( + "https://cdn.jsdelivr.net/npm/@janhq/plugin-catalog@latest/dist/index.js" + ), }), ], output: { diff --git a/plugins/model-management-plugin/index.ts b/plugins/model-management-plugin/index.ts index 1d6e037f4..f20814fd3 100644 --- a/plugins/model-management-plugin/index.ts +++ b/plugins/model-management-plugin/index.ts @@ -8,19 +8,24 @@ import { } from "@janhq/core"; import { parseToModel } from "./helper"; -const downloadModel = (product) => downloadFile(product.downloadUrl, product.fileName); +const downloadModel = (product) => + downloadFile(product.downloadUrl, product.fileName); const deleteModel = (path) => deleteFile(path); -async function getConfiguredModels() { - // Clear cache to get the latest model catalog - delete require.cache[MODEL_CATALOG_URL]; - - // Import the remote model catalog - const module = require(MODEL_CATALOG_URL); - return module.default.map((e) => { - return parseToModel(e); - }); +/** + * Retrieves a list of configured models from the model catalog URL. + * @returns A Promise that resolves to an array of configured models. + */ +async function getConfiguredModels(): Promise { + // Add a timestamp to the URL to prevent caching + return import( + /* webpackIgnore: true */ MODEL_CATALOG_URL + `?t=${Date.now()}` + ).then((module) => + module.default.map((e) => { + return parseToModel(e); + }) + ); } /** @@ -44,7 +49,11 @@ function storeModel(model: any) { * @param model Product */ function updateFinishedDownloadAt(_id: string): Promise { - return store.updateMany("models", { _id }, { time: Date.now(), finishDownloadAt: 1 }); + return store.updateMany( + "models", + { _id }, + { time: Date.now(), finishDownloadAt: 1 } + ); } /** @@ -84,14 +93,38 @@ function onStart() { export function init({ register }: { register: RegisterExtensionPoint }) { register(PluginService.OnStart, PLUGIN_NAME, onStart); - register(ModelManagementService.DownloadModel, downloadModel.name, downloadModel); + register( + ModelManagementService.DownloadModel, + downloadModel.name, + downloadModel + ); register(ModelManagementService.DeleteModel, deleteModel.name, deleteModel); - register(ModelManagementService.GetConfiguredModels, getConfiguredModels.name, getConfiguredModels); + register( + ModelManagementService.GetConfiguredModels, + getConfiguredModels.name, + getConfiguredModels + ); register(ModelManagementService.StoreModel, storeModel.name, storeModel); - register(ModelManagementService.UpdateFinishedDownloadAt, updateFinishedDownloadAt.name, updateFinishedDownloadAt); + register( + ModelManagementService.UpdateFinishedDownloadAt, + updateFinishedDownloadAt.name, + updateFinishedDownloadAt + ); - register(ModelManagementService.DeleteDownloadModel, deleteDownloadModel.name, deleteDownloadModel); - register(ModelManagementService.GetModelById, getModelById.name, getModelById); - register(ModelManagementService.GetFinishedDownloadModels, getFinishedDownloadModels.name, getFinishedDownloadModels); + register( + ModelManagementService.DeleteDownloadModel, + deleteDownloadModel.name, + deleteDownloadModel + ); + register( + ModelManagementService.GetModelById, + getModelById.name, + getModelById + ); + register( + ModelManagementService.GetFinishedDownloadModels, + getFinishedDownloadModels.name, + getFinishedDownloadModels + ); } diff --git a/web/app/_components/Preferences.tsx b/web/app/_components/Preferences.tsx index a9b2c1548..7870cbf2d 100644 --- a/web/app/_components/Preferences.tsx +++ b/web/app/_components/Preferences.tsx @@ -12,9 +12,10 @@ import { import { MagnifyingGlassIcon } from '@heroicons/react/20/solid' import classNames from 'classnames' -import { PluginService, preferences } from '@janhq/core' +import { DataService, PluginService, preferences } from '@janhq/core' import { execute } from '../../../electron/core/plugin-manager/execution/extension-manager' import LoadingIndicator from './LoadingIndicator' +import { executeSerial } from '@services/pluginService' export const Preferences = () => { const [search, setSearch] = useState('') @@ -30,12 +31,10 @@ export const Preferences = () => { /** * Loads the plugin catalog module from a CDN and sets it as the plugin catalog state. - * The `webpackIgnore` comment is used to prevent Webpack from bundling the module. */ useEffect(() => { - // @ts-ignore - import(/* webpackIgnore: true */ PLUGIN_CATALOGS).then((module) => { - setPluginCatalog(module.default) + executeSerial(DataService.GetPluginManifest).then((data) => { + setPluginCatalog(data) }) }, []) diff --git a/web/hooks/useGetSystemResources.ts b/web/hooks/useGetSystemResources.ts index 1062d1d6a..0e77882a5 100644 --- a/web/hooks/useGetSystemResources.ts +++ b/web/hooks/useGetSystemResources.ts @@ -1,5 +1,6 @@ import { useEffect, useState } from 'react' import { executeSerial } from '../../electron/core/plugin-manager/execution/extension-manager' +import { extensionPoints } from '../../electron/core/plugin-manager/execution' import { SystemMonitoringService } from '@janhq/core' import { useSetAtom } from 'jotai' import { totalRamAtom } from '@helpers/atoms/SystemBar.atom' @@ -9,6 +10,9 @@ export default function useGetSystemResources() { const setTotalRam = useSetAtom(totalRamAtom) const getSystemResources = async () => { + if (!extensionPoints.get(SystemMonitoringService.GetResourcesInfo)) { + return + } const resourceInfor = await executeSerial( SystemMonitoringService.GetResourcesInfo ) diff --git a/web/next.config.js b/web/next.config.js index d72a1ee86..dde766300 100644 --- a/web/next.config.js +++ b/web/next.config.js @@ -21,14 +21,7 @@ const nextConfig = { // do some stuff here config.optimization.minimize = false config.optimization.minimizer = [] - config.plugins = [ - ...config.plugins, - new webpack.DefinePlugin({ - PLUGIN_CATALOGS: JSON.stringify( - 'https://cdn.jsdelivr.net/npm/@janhq/plugin-catalog@latest/dist/index.js' - ), - }), - ] + config.plugins = [...config.plugins, new webpack.DefinePlugin({})] return config }, } diff --git a/web/package.json b/web/package.json index 8b33f67e7..2925b1156 100644 --- a/web/package.json +++ b/web/package.json @@ -14,7 +14,7 @@ "dependencies": { "@headlessui/react": "^1.7.15", "@heroicons/react": "^2.0.18", - "@janhq/core": "^0.1.6", + "@janhq/core": "^0.1.7", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-toggle": "^1.0.3", diff --git a/web/screens/Settings/CorePlugins/PluginsCatalog.tsx b/web/screens/Settings/CorePlugins/PluginsCatalog.tsx index 13e46fe62..74dd2d827 100644 --- a/web/screens/Settings/CorePlugins/PluginsCatalog.tsx +++ b/web/screens/Settings/CorePlugins/PluginsCatalog.tsx @@ -9,6 +9,8 @@ import { plugins, extensionPoints, } from '@/../../electron/core/plugin-manager/execution/index' +import { executeSerial } from '@services/pluginService' +import { DataService } from '@janhq/core' const PluginCatalog = () => { // const [search, setSearch] = useState('') @@ -20,12 +22,10 @@ const PluginCatalog = () => { /** * Loads the plugin catalog module from a CDN and sets it as the plugin catalog state. - * The `webpackIgnore` comment is used to prevent Webpack from bundling the module. */ useEffect(() => { - // @ts-ignore - import(/* webpackIgnore: true */ PLUGIN_CATALOGS).then((module) => { - setPluginCatalog(module.default) + executeSerial(DataService.GetPluginManifest).then((data) => { + setPluginCatalog(data) }) }, []) @@ -127,7 +127,7 @@ const PluginCatalog = () => { return (
- {pluginCatalog.map((item, i) => { + {pluginCatalog?.map((item, i) => { const isActivePlugin = activePlugins.some((x) => x.name === item.name) const updateVersionPlugins = Number( activePlugins @@ -163,7 +163,7 @@ const PluginCatalog = () => { )}
{ if (e === true) { downloadTarball(item.name)