mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 05:46:00 +00:00
Fix multiple apps (#316)
* chore: multiple apps * fix: multiple apps with application options * fix: multiple apps AppSelector type * chore: multiple apps with plugin config * chore: rename multiple-apps to multiple-apps-manager * chore: application association * chore: plugin multi-app manager
This commit is contained in:
parent
ea0dd6e31a
commit
b1086ee728
@ -3,7 +3,7 @@ import http, { IncomingMessage } from 'http';
|
||||
import EventEmitter from 'events';
|
||||
import { applyMixins, AsyncEmitter } from '@nocobase/utils';
|
||||
|
||||
type AppSelector = (ctx) => Application | string;
|
||||
type AppSelector = (req: IncomingMessage) => Application | string | undefined | null;
|
||||
|
||||
export class AppManager extends EventEmitter {
|
||||
public applications: Map<string, Application> = new Map<string, Application>();
|
||||
@ -63,7 +63,7 @@ export class AppManager extends EventEmitter {
|
||||
|
||||
callback() {
|
||||
return async (req, res) => {
|
||||
let handleApp = this.appSelector(req);
|
||||
let handleApp = this.appSelector(req) || this.app;
|
||||
|
||||
if (typeof handleApp === 'string') {
|
||||
handleApp = (await this.getApplication(handleApp)) || this.app;
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@nocobase/plugin-multiple-apps",
|
||||
"name": "@nocobase/plugin-multi-app-manager",
|
||||
"version": "0.6.2-alpha.12",
|
||||
"main": "lib/index.js",
|
||||
"license": "MIT",
|
@ -1,7 +1,6 @@
|
||||
import { Plugin } from '@nocobase/server';
|
||||
import { ApplicationModel } from '../models/application';
|
||||
import { Plugin, PluginManager } from '@nocobase/server';
|
||||
import { mockServer } from '@nocobase/test';
|
||||
import { PluginMultipleApps } from '../server';
|
||||
import { PluginMultiAppManager } from '../server';
|
||||
|
||||
describe('test with start', () => {
|
||||
it('should load subApp on create', async () => {
|
||||
@ -24,11 +23,12 @@ describe('test with start', () => {
|
||||
|
||||
const mockGetPluginByName = jest.fn();
|
||||
mockGetPluginByName.mockReturnValue(TestPlugin);
|
||||
ApplicationModel.getPluginByName = mockGetPluginByName;
|
||||
PluginManager.resolvePlugin = mockGetPluginByName;
|
||||
|
||||
const app = mockServer();
|
||||
await app.cleanDb();
|
||||
app.plugin(PluginMultipleApps);
|
||||
|
||||
app.plugin(PluginMultiAppManager);
|
||||
|
||||
await app.loadAndInstall();
|
||||
await app.start();
|
||||
@ -38,11 +38,9 @@ describe('test with start', () => {
|
||||
await db.getRepository('applications').create({
|
||||
values: {
|
||||
name: 'sub1',
|
||||
plugins: [
|
||||
{
|
||||
name: 'test-package',
|
||||
},
|
||||
],
|
||||
options: {
|
||||
plugins: ['test-package'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -55,7 +53,7 @@ describe('test with start', () => {
|
||||
it('should install into difference database', async () => {
|
||||
const app = mockServer();
|
||||
await app.cleanDb();
|
||||
app.plugin(PluginMultipleApps);
|
||||
app.plugin(PluginMultiAppManager);
|
||||
|
||||
await app.loadAndInstall();
|
||||
await app.start();
|
||||
@ -65,11 +63,9 @@ describe('test with start', () => {
|
||||
await db.getRepository('applications').create({
|
||||
values: {
|
||||
name: 'sub1',
|
||||
plugins: [
|
||||
{
|
||||
name: '@nocobase/plugin-ui-schema-storage',
|
||||
},
|
||||
],
|
||||
options: {
|
||||
plugins: ['@nocobase/plugin-ui-schema-storage'],
|
||||
},
|
||||
},
|
||||
});
|
||||
await app.destroy();
|
||||
@ -84,7 +80,7 @@ describe('test with start', () => {
|
||||
|
||||
let app = mockServer();
|
||||
await app.cleanDb();
|
||||
app.plugin(PluginMultipleApps);
|
||||
app.plugin(PluginMultiAppManager);
|
||||
|
||||
await app.loadAndInstall();
|
||||
await app.start();
|
||||
@ -93,16 +89,14 @@ describe('test with start', () => {
|
||||
|
||||
const mockGetPluginByName = jest.fn();
|
||||
mockGetPluginByName.mockReturnValue(TestPlugin);
|
||||
ApplicationModel.getPluginByName = mockGetPluginByName;
|
||||
PluginManager.resolvePlugin = mockGetPluginByName;
|
||||
|
||||
await db.getRepository('applications').create({
|
||||
values: {
|
||||
name: 'sub1',
|
||||
plugins: [
|
||||
{
|
||||
name: 'test-package',
|
||||
},
|
||||
],
|
||||
options: {
|
||||
plugins: ['test-package'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -114,7 +108,7 @@ describe('test with start', () => {
|
||||
database: app.db,
|
||||
});
|
||||
|
||||
newApp.plugin(PluginMultipleApps);
|
||||
newApp.plugin(PluginMultiAppManager);
|
||||
await newApp.db.reconnect();
|
||||
|
||||
await newApp.load();
|
@ -1,6 +1,6 @@
|
||||
import { mockServer, MockServer } from '@nocobase/test';
|
||||
import { Database } from '@nocobase/database';
|
||||
import { PluginMultipleApps } from '../server';
|
||||
import { PluginMultiAppManager } from '../server';
|
||||
|
||||
describe('multiple apps create', () => {
|
||||
let app: MockServer;
|
||||
@ -10,7 +10,7 @@ describe('multiple apps create', () => {
|
||||
app = mockServer({});
|
||||
db = app.db;
|
||||
await app.cleanDb();
|
||||
app.plugin(PluginMultipleApps);
|
||||
app.plugin(PluginMultiAppManager);
|
||||
|
||||
await app.loadAndInstall();
|
||||
});
|
||||
@ -51,29 +51,30 @@ describe('multiple apps create', () => {
|
||||
await db.getRepository('applications').create({
|
||||
values: {
|
||||
name: 'miniApp',
|
||||
plugins: [
|
||||
{
|
||||
name: '@nocobase/plugin-ui-schema-storage',
|
||||
},
|
||||
],
|
||||
options: {
|
||||
plugins: [['@nocobase/plugin-ui-schema-storage', { test: 'B' }]],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const miniApp = app.appManager.applications.get('miniApp');
|
||||
expect(miniApp).toBeDefined();
|
||||
|
||||
expect(miniApp.pm.get('@nocobase/plugin-ui-schema-storage')).toBeDefined();
|
||||
const plugin = miniApp.pm.get('@nocobase/plugin-ui-schema-storage');
|
||||
|
||||
expect(plugin).toBeDefined();
|
||||
expect(plugin.options).toEqual({
|
||||
test: 'B',
|
||||
});
|
||||
});
|
||||
|
||||
it('should lazy load applications', async () => {
|
||||
await db.getRepository('applications').create({
|
||||
values: {
|
||||
name: 'miniApp',
|
||||
plugins: [
|
||||
{
|
||||
name: '@nocobase/plugin-ui-schema-storage',
|
||||
},
|
||||
],
|
||||
options: {
|
||||
plugins: ['@nocobase/plugin-ui-schema-storage'],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
@ -4,21 +4,26 @@ export default defineCollection({
|
||||
name: 'applications',
|
||||
model: 'ApplicationModel',
|
||||
autoGenId: false,
|
||||
title: '{{t("Applications")}}',
|
||||
sortable: 'sort',
|
||||
createdBy: true,
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
type: 'uid',
|
||||
name: 'name',
|
||||
primaryKey: true,
|
||||
prefix: 'a',
|
||||
interface: 'input',
|
||||
uiSchema: {
|
||||
type: 'string',
|
||||
title: '{{t("Application name")}}',
|
||||
'x-component': 'Input',
|
||||
'x-read-pretty': true,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'json',
|
||||
name: 'options',
|
||||
},
|
||||
{
|
||||
type: 'hasMany',
|
||||
name: 'plugins',
|
||||
target: 'applicationPlugins',
|
||||
foreignKey: 'applicationName',
|
||||
},
|
||||
],
|
||||
});
|
1
packages/plugins/multi-app-manager/src/index.ts
Normal file
1
packages/plugins/multi-app-manager/src/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export { PluginMultiAppManager as default } from './server';
|
@ -8,10 +8,6 @@ interface registerAppOptions extends TransactionAble {
|
||||
}
|
||||
|
||||
export class ApplicationModel extends Model {
|
||||
static getPluginByName(pluginName: string) {
|
||||
return require(pluginName).default;
|
||||
}
|
||||
|
||||
static getDatabaseConfig(app: Application): IDatabaseOptions {
|
||||
return lodash.cloneDeep(
|
||||
lodash.isPlainObject(app.options.database)
|
||||
@ -23,15 +19,12 @@ export class ApplicationModel extends Model {
|
||||
async registerToMainApp(mainApp: Application, options: registerAppOptions) {
|
||||
const { transaction } = options;
|
||||
const appName = this.get('name') as string;
|
||||
const app = mainApp.appManager.createApplication(appName, ApplicationModel.initOptions(appName, mainApp));
|
||||
const appOptions = (this.get('options') as any) || {};
|
||||
|
||||
// @ts-ignore
|
||||
const plugins = await this.getPlugins({ transaction });
|
||||
|
||||
for (const pluginInstance of plugins) {
|
||||
const plugin = ApplicationModel.getPluginByName(pluginInstance.get('name') as string);
|
||||
app.plugin(plugin);
|
||||
}
|
||||
const app = mainApp.appManager.createApplication(appName, {
|
||||
...ApplicationModel.initOptions(appName, mainApp),
|
||||
...appOptions,
|
||||
});
|
||||
|
||||
app.on('beforeInstall', async function createDatabase() {
|
||||
const { host, port, username, password, database, dialect } = ApplicationModel.getDatabaseConfig(app);
|
@ -3,7 +3,7 @@ import { resolve } from 'path';
|
||||
import { ApplicationModel } from './models/application';
|
||||
import { AppManager } from '@nocobase/server';
|
||||
|
||||
export class PluginMultipleApps extends Plugin {
|
||||
export class PluginMultiAppManager extends Plugin {
|
||||
getName(): string {
|
||||
return this.getPackageName(__dirname);
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
import { defineCollection } from '@nocobase/database';
|
||||
|
||||
export default defineCollection({
|
||||
name: 'applicationPlugins',
|
||||
timestamps: false,
|
||||
fields: [
|
||||
{
|
||||
type: 'string',
|
||||
name: 'name',
|
||||
},
|
||||
{
|
||||
type: 'belongsTo',
|
||||
name: 'application',
|
||||
foreignKey: 'applicationName',
|
||||
},
|
||||
],
|
||||
});
|
@ -14,7 +14,7 @@ Promise.all(packageDirs.map((d) => getDirectories(d)))
|
||||
.then((res) => res.flat())
|
||||
.then((res) =>
|
||||
res.forEach((d) => {
|
||||
exec(`cd ${d} && npm unpublish -f && npm publish`, (error, stdout, stderr) => {
|
||||
exec(`cd ${d} && npm unpublish -f; npm publish`, (error, stdout, stderr) => {
|
||||
if (error) {
|
||||
console.log(`error: ${error.message}`);
|
||||
return;
|
||||
|
Loading…
Reference in New Issue
Block a user