diff --git a/packages/core/client/src/api-client/APIClient.ts b/packages/core/client/src/api-client/APIClient.ts index 5c6993aa3f..7e33287a08 100644 --- a/packages/core/client/src/api-client/APIClient.ts +++ b/packages/core/client/src/api-client/APIClient.ts @@ -92,7 +92,7 @@ export class APIClient extends APIClientSDK { return response; }, (error) => { - const errs = error?.response?.data?.errors || [{ message: 'Server error' }]; + const errs = this.toErrMessages(error); // Hard code here temporarily // TODO(yangqia): improve error code and message if (errs.find((error: { code?: string }) => error.code === 'ROLE_NOT_FOUND_ERR')) { @@ -103,6 +103,17 @@ export class APIClient extends APIClientSDK { ); } + toErrMessages(error) { + if (typeof error?.response?.data === 'string') { + return [{ message: error?.response?.data }]; + } + return ( + error?.response?.data?.errors || + error?.response?.data?.messages || + error?.response?.error || [{ message: error.message || 'Server error' }] + ); + } + useNotificationMiddleware() { this.axios.interceptors.response.use( (response) => { @@ -143,7 +154,7 @@ export class APIClient extends APIClientSDK { } else if (this.app.error) { this.app.error = null; } - let errs = error?.response?.data?.errors || error?.response?.data?.messages || [{ message: 'Server error' }]; + let errs = this.toErrMessages(error); errs = errs.filter((error) => { const lastTime = errorCache.get(error.message); if (lastTime && new Date().getTime() - lastTime < 500) { diff --git a/packages/core/client/src/application/Application.tsx b/packages/core/client/src/application/Application.tsx index 6b92e390f9..d190ee577a 100644 --- a/packages/core/client/src/application/Application.tsx +++ b/packages/core/client/src/application/Application.tsx @@ -34,17 +34,17 @@ import { compose, normalizeContainer } from './utils'; import { defineGlobalDeps } from './utils/globalDeps'; import { getRequireJs } from './utils/requirejs'; +import { CollectionFieldInterfaceComponentOption } from '../data-source/collection-field-interface/CollectionFieldInterface'; import { CollectionField } from '../data-source/collection-field/CollectionField'; import { DataSourceApplicationProvider } from '../data-source/components/DataSourceApplicationProvider'; import { DataBlockProvider } from '../data-source/data-block/DataBlockProvider'; import { DataSourceManager, type DataSourceManagerOptions } from '../data-source/data-source/DataSourceManager'; -import { CollectionFieldInterfaceComponentOption } from '../data-source/collection-field-interface/CollectionFieldInterface'; +import type { CollectionFieldInterfaceFactory } from '../data-source'; import { OpenModeProvider } from '../modules/popup/OpenModeProvider'; import { AppSchemaComponentProvider } from './AppSchemaComponentProvider'; import type { Plugin } from './Plugin'; import type { RequireJS } from './utils/requirejs'; -import type { CollectionFieldInterfaceFactory } from '../data-source'; declare global { interface Window { @@ -282,10 +282,21 @@ export class Application { }); } loadFailed = true; - const others = error?.response?.data?.error || error?.response?.data?.errors?.[0] || { message: error?.message }; + const toError = (error) => { + if (typeof error?.response?.data === 'string') { + return { message: error?.response?.data }; + } + if (error?.response?.data?.error) { + return error?.response?.data?.error; + } + if (error?.response?.data?.errors?.[0]) { + return error?.response?.data?.errors?.[0]; + } + return { message: error?.message }; + }; this.error = { code: 'LOAD_ERROR', - ...others, + ...toError(error), }; console.error(error, this.error); } diff --git a/packages/core/client/src/nocobase-buildin-plugin/index.tsx b/packages/core/client/src/nocobase-buildin-plugin/index.tsx index e846be160a..a27b741482 100644 --- a/packages/core/client/src/nocobase-buildin-plugin/index.tsx +++ b/packages/core/client/src/nocobase-buildin-plugin/index.tsx @@ -142,7 +142,7 @@ const getProps = (app: Application) => { }; } - if (app.error.code === 'APP_ERROR' || app.error.code === 'LOAD_ERROR') { + if (['ENOENT', 'APP_ERROR', 'LOAD_ERROR'].includes(app.error.code)) { return { status: 'error', title: 'App error', @@ -205,7 +205,11 @@ const getProps = (app: Application) => { return { ...props, ...commands[app.error?.command?.name] }; } - return {}; + return { + status: 'warning', + title: 'App warning', + subTitle: app.error?.message, + }; }; const AppMaintaining: FC<{ app: Application; error: Error }> = observer( diff --git a/packages/core/server/src/plugin-manager/options/resource.ts b/packages/core/server/src/plugin-manager/options/resource.ts index 210512b079..5e758f1be7 100644 --- a/packages/core/server/src/plugin-manager/options/resource.ts +++ b/packages/core/server/src/plugin-manager/options/resource.ts @@ -9,11 +9,10 @@ import { uid } from '@nocobase/utils'; import fs from 'fs'; +import fse from 'fs-extra'; import path from 'path'; import Application from '../../application'; -import { getExposeUrl } from '../clientStaticUtils'; import PluginManager from '../plugin-manager'; -//@ts-ignore export default { name: 'pm', @@ -135,21 +134,19 @@ export default { enabled: true, }, }); - ctx.body = items - .map((item) => { - try { - return { - ...item.toJSON(), - url: `${process.env.APP_SERVER_BASE_URL}${getExposeUrl( - item.packageName, - PLUGIN_CLIENT_ENTRY_FILE, - )}?version=${item.version}`, - }; - } catch { - return false; - } - }) - .filter(Boolean); + const arr = []; + for (const item of items) { + const pkgPath = path.resolve(process.env.NODE_MODULES_PATH, item.packageName); + const r = await fse.exists(pkgPath); + if (r) { + const url = `${process.env.APP_SERVER_BASE_URL}${process.env.PLUGIN_STATICS_PATH}${item.packageName}/${PLUGIN_CLIENT_ENTRY_FILE}?version=${item.version}`; + arr.push({ + ...item.toJSON(), + url, + }); + } + } + ctx.body = arr; await next(); }, async get(ctx, next) {