diff --git a/packages/core/server/src/__tests__/gateway.test.ts b/packages/core/server/src/__tests__/gateway.test.ts index e5bf38d05..c5846d382 100644 --- a/packages/core/server/src/__tests__/gateway.test.ts +++ b/packages/core/server/src/__tests__/gateway.test.ts @@ -156,8 +156,12 @@ describe('gateway', () => { return JSON.parse(messages[messages.length - 1]); }; - beforeEach(async () => { + const clearMessages = () => { messages = []; + }; + + beforeEach(async () => { + clearMessages(); port = await startServerWithRandomPort(gateway.startHttpServer.bind(gateway)); }); @@ -173,6 +177,55 @@ describe('gateway', () => { await waitSecond(); }); + describe('plugin manager api', () => { + let app; + + beforeEach(async () => { + await connectClient(port); + + app = new Application({ + database: { + dialect: 'sqlite', + storage: ':memory:', + }, + plugins: ['nocobase'], + }); + + await waitSecond(); + + await app.runAsCLI(['install'], { from: 'user' }); + await app.runAsCLI(['start'], { from: 'user' }); + await waitSecond(); + + clearMessages(); + }); + + it('should silently handle the exception when the plugin does not exist', async () => { + await app.runAsCLI(['pm', 'add', 'not-exists-plugin'], { from: 'user' }); + await waitSecond(); + }); + + it('should display a notification-type error message when plugin installation fails', async () => { + const pluginClass = app.pm.get('mobile-client'); + pluginClass.install = async () => { + throw new Error('install error'); + }; + + await app.runAsCLI(['pm', 'enable', 'mobile-client'], { from: 'user' }); + await waitSecond(); + + const runningMessage = messages + .map((m) => { + return JSON.parse(m); + }) + .find((m) => { + return m.payload.code == 'APP_RUNNING'; + }); + + expect(runningMessage.payload.refresh).not.toBeTruthy(); + }); + }); + it('should receive app error message', async () => { await connectClient(port); diff --git a/packages/core/server/src/app-supervisor.ts b/packages/core/server/src/app-supervisor.ts index 832f06914..aa63763e3 100644 --- a/packages/core/server/src/app-supervisor.ts +++ b/packages/core/server/src/app-supervisor.ts @@ -260,12 +260,14 @@ export class AppSupervisor extends EventEmitter implements AsyncEmitter { }); app.on('__started', async (_app, options) => { - const { maintainingStatus } = options; + const { maintainingStatus, options: startOptions } = options; + if ( maintainingStatus && ['install', 'upgrade', 'pm.add', 'pm.update', 'pm.enable', 'pm.disable', 'pm.remove'].includes( maintainingStatus.command.name, - ) + ) && + !startOptions.recover ) { this.setAppStatus(app.name, 'running', { refresh: true, diff --git a/packages/core/server/src/application.ts b/packages/core/server/src/application.ts index 692767e36..42dfa962a 100644 --- a/packages/core/server/src/application.ts +++ b/packages/core/server/src/application.ts @@ -88,6 +88,7 @@ interface StartOptions { cliArgs?: any[]; dbSync?: boolean; checkInstall?: boolean; + recover?: boolean; } type MaintainingStatus = 'command_begin' | 'command_end' | 'command_running' | 'command_error'; @@ -471,14 +472,15 @@ export class Application exten this.setMaintainingMessage('emit afterStart'); await this.emitAsync('afterStart', this, options); - await this.emitStartedEvent(); + await this.emitStartedEvent(options); this.stopped = false; } - async emitStartedEvent() { + async emitStartedEvent(options: StartOptions = {}) { await this.emitAsync('__started', this, { maintainingStatus: lodash.cloneDeep(this._maintainingCommandStatus), + options, }); } @@ -486,11 +488,11 @@ export class Application exten return this._started; } - async tryReloadOrRestart() { + async tryReloadOrRestart(options: StartOptions = {}) { if (this._started) { - await this.restart(); + await this.restart(options); } else { - await this.reload(); + await this.reload(options); } } diff --git a/packages/core/server/src/plugin-manager/plugin-manager.ts b/packages/core/server/src/plugin-manager/plugin-manager.ts index 4db965264..f9e7df26a 100644 --- a/packages/core/server/src/plugin-manager/plugin-manager.ts +++ b/packages/core/server/src/plugin-manager/plugin-manager.ts @@ -415,7 +415,9 @@ export class PluginManager { installed: false, }, }); - await this.app.tryReloadOrRestart(); + await this.app.tryReloadOrRestart({ + recover: true, + }); throw error; } } @@ -467,7 +469,9 @@ export class PluginManager { enabled: true, }, }); - await this.app.tryReloadOrRestart(); + await this.app.tryReloadOrRestart({ + recover: true, + }); throw error; } }