diff --git a/packages/api/src/index.ts b/packages/api/src/index.ts
index 58e06fe30..75aecc112 100644
--- a/packages/api/src/index.ts
+++ b/packages/api/src/index.ts
@@ -35,9 +35,9 @@ const api = new Server({
});
const plugins = [
- '@nocobase/plugin-collections',
'@nocobase/plugin-ui-router',
'@nocobase/plugin-ui-schema',
+ '@nocobase/plugin-collections',
'@nocobase/plugin-users',
'@nocobase/plugin-action-logs',
'@nocobase/plugin-file-manager',
diff --git a/packages/app/package.json b/packages/app/package.json
index 529e8ce4d..f44da2545 100644
--- a/packages/app/package.json
+++ b/packages/app/package.json
@@ -36,7 +36,7 @@
"@nocobase/plugin-ui-router": "^0.4.0-alpha.7",
"@nocobase/plugin-ui-schema": "^0.4.0-alpha.7",
"@nocobase/plugin-users": "^0.4.0-alpha.7",
- "@nocobase/plugin-saas": "^0.4.0-alpha.7",
+ "@nocobase/plugin-multi-apps": "^0.4.0-alpha.7",
"@nocobase/server": "^0.4.0-alpha.7",
"@umijs/preset-react": "1.x",
"koa-mount": "^4.0.0",
diff --git a/packages/app/src/apis/index.ts b/packages/app/src/apis/index.ts
index bdb3a2c2f..5aede5b64 100644
--- a/packages/app/src/apis/index.ts
+++ b/packages/app/src/apis/index.ts
@@ -41,9 +41,9 @@ const api = new Server({
});
const plugins = [
- '@nocobase/plugin-saas',
- '@nocobase/plugin-ui-schema',
+ '@nocobase/plugin-multi-apps',
'@nocobase/plugin-ui-router',
+ '@nocobase/plugin-ui-schema',
'@nocobase/plugin-collections',
'@nocobase/plugin-users',
'@nocobase/plugin-action-logs',
diff --git a/packages/app/src/pages/index.tsx b/packages/app/src/pages/index.tsx
index be4e3c722..62595b2b8 100644
--- a/packages/app/src/pages/index.tsx
+++ b/packages/app/src/pages/index.tsx
@@ -8,8 +8,9 @@ import {
AdminLayout,
AuthLayout,
RouteSchemaRenderer,
+ ConfigProvider,
+ ClientSDK,
} from '@nocobase/client';
-import { UseRequestProvider } from 'ahooks';
import { extend } from 'umi-request';
const request = extend({
@@ -26,6 +27,8 @@ request.use(async (ctx, next) => {
await next();
});
+const client = new ClientSDK({ request });
+
const RouteSwitch = createRouteSwitch({
components: {
AdminLayout,
@@ -52,12 +55,8 @@ const App = () => {
export default function IndexPage() {
return (
- request(service),
- }}
- >
+
-
+
);
}
diff --git a/packages/collections/src/database.ts b/packages/collections/src/database.ts
index 5aae72e00..64acf66de 100644
--- a/packages/collections/src/database.ts
+++ b/packages/collections/src/database.ts
@@ -133,7 +133,15 @@ export class Database extends EventEmitter {
}
async sync(options?: SyncOptions) {
- return this.sequelize.sync(options);
+ const isMySQL = this.sequelize.getDialect() === 'mysql';
+ if (isMySQL) {
+ await this.sequelize.query('SET FOREIGN_KEY_CHECKS = 0', null);
+ }
+ const result = await this.sequelize.sync(options);
+ if (isMySQL) {
+ await this.sequelize.query('SET FOREIGN_KEY_CHECKS = 1', null);
+ }
+ return result;
}
async close() {
diff --git a/packages/database/src/database.ts b/packages/database/src/database.ts
index eee4f26d9..d9ad5782a 100644
--- a/packages/database/src/database.ts
+++ b/packages/database/src/database.ts
@@ -465,6 +465,33 @@ type HookType =
return this.sequelize.close();
}
+ /**
+ * 添加 hook
+ *
+ * @param hookType
+ * @param fn
+ */
+ public addHook(hookType: HookType | string, fn: Function) {
+ const hooks = this.hooks[hookType] || [];
+ hooks.push(fn);
+ this.hooks[hookType] = hooks;
+ }
+
+ /**
+ * 运行 hook
+ *
+ * @param hookType
+ * @param args
+ */
+ public async runHooks(hookType: HookType | string, ...args) {
+ const hooks = this.hooks[hookType] || [];
+ for (const hook of hooks) {
+ if (typeof hook === 'function') {
+ await hook(...args);
+ }
+ }
+ }
+
public getFieldByPath(fieldPath: string) {
const [tableName, fieldName] = fieldPath.split('.');
return this.getTable(tableName).getField(fieldName);
diff --git a/packages/database/src/model.ts b/packages/database/src/model.ts
index 0caffbe97..0d734adcf 100644
--- a/packages/database/src/model.ts
+++ b/packages/database/src/model.ts
@@ -534,8 +534,6 @@ export abstract class Model extends SequelizeModel {
...options,
transaction,
});
- // @ts-ignore
- // await this.sequelize.runHooks('afterUpdateAssociations', this, options);
if (!options.transaction) {
await transaction.commit();
diff --git a/packages/database/src/table.ts b/packages/database/src/table.ts
index c2d3e007d..47d54c59c 100644
--- a/packages/database/src/table.ts
+++ b/packages/database/src/table.ts
@@ -139,6 +139,7 @@ export class Table {
constructor(options: TableOptions, context: TabelContext) {
const { database } = context;
+ database.runHooks('beforeTableInit', options);
database.emit('beforeTableInit', options);
const {
model,
@@ -158,6 +159,7 @@ export class Table {
this.setFields(fields);
this.initSortable();
database.emit('afterTableInit', this);
+ database.runHooks('afterTableInit', this);
}
public initSortable() {
@@ -313,6 +315,7 @@ export class Table {
* @param reinitialize
*/
public addField(options: FieldOptions, reinitialize: Reinitialize = true) {
+ this.database.runHooks('beforeAddField', options, this);
this.database.emit('beforeAddField', options, this);
const { name, index } = options;
const field = buildField(options, {
@@ -350,6 +353,7 @@ export class Table {
}
this.modelInit(reinitialize);
this.database.emit('afterAddField', field, this);
+ this.database.runHooks('afterAddField', field, this);
return field;
}
diff --git a/packages/plugin-collections/src/server.ts b/packages/plugin-collections/src/server.ts
index b9a53eed8..5ff485d1b 100644
--- a/packages/plugin-collections/src/server.ts
+++ b/packages/plugin-collections/src/server.ts
@@ -5,31 +5,40 @@ import * as models from './models';
import { createOrUpdate, findAll } from './actions';
import { create } from './actions/fields';
+registerModels(models);
+
export default {
name: 'collections',
async load(this: Plugin) {
const database = this.app.db;
- registerModels(models);
-
database.import({
directory: path.resolve(__dirname, 'collections'),
});
this.app.on('beforeStart', async () => {
- await database.getModel('collections').load();
+ await database.getModel('collections').load({
+ skipExisting: true,
+ });
});
this.app.on('db.init', async () => {
- const userTable = database.getTable('users');
- const config = userTable.getOptions();
+ const tableNames = ['users', 'applications'];
const Collection = database.getModel('collections');
- const collection = await Collection.create(config);
- await collection.updateAssociations({
- generalFields: config.fields.filter((field) => field.state !== 0),
- systemFields: config.fields.filter((field) => field.state === 0),
- });
- await collection.migrate();
+ for (const tableName of tableNames) {
+ const table = database.getTable(tableName);
+ console.log(tableName, table);
+ if (!table) {
+ continue;
+ }
+ const config = table.getOptions();
+ const collection = await Collection.create(config);
+ await collection.updateAssociations({
+ generalFields: config.fields.filter((field) => field.state !== 0),
+ systemFields: config.fields.filter((field) => field.state === 0),
+ });
+ // await collection.migrate();
+ }
});
const [Collection, Field] = database.getModels(['collections', 'fields']);
diff --git a/packages/plugin-saas/.gitignore b/packages/plugin-multi-apps/.gitignore
similarity index 100%
rename from packages/plugin-saas/.gitignore
rename to packages/plugin-multi-apps/.gitignore
diff --git a/packages/plugin-saas/.npmignore b/packages/plugin-multi-apps/.npmignore
similarity index 100%
rename from packages/plugin-saas/.npmignore
rename to packages/plugin-multi-apps/.npmignore
diff --git a/packages/plugin-saas/package.json b/packages/plugin-multi-apps/package.json
similarity index 89%
rename from packages/plugin-saas/package.json
rename to packages/plugin-multi-apps/package.json
index ac9f3792d..e47d03ede 100644
--- a/packages/plugin-saas/package.json
+++ b/packages/plugin-multi-apps/package.json
@@ -1,5 +1,5 @@
{
- "name": "@nocobase/plugin-saas",
+ "name": "@nocobase/plugin-multi-apps",
"version": "0.4.0-alpha.7",
"main": "lib/index.js",
"license": "MIT",
diff --git a/packages/plugin-saas/src/index.ts b/packages/plugin-multi-apps/src/index.ts
similarity index 100%
rename from packages/plugin-saas/src/index.ts
rename to packages/plugin-multi-apps/src/index.ts
diff --git a/packages/plugin-saas/src/server.ts b/packages/plugin-multi-apps/src/server.ts
similarity index 82%
rename from packages/plugin-saas/src/server.ts
rename to packages/plugin-multi-apps/src/server.ts
index 8a77572a7..5ae7a5d4f 100644
--- a/packages/plugin-saas/src/server.ts
+++ b/packages/plugin-multi-apps/src/server.ts
@@ -31,6 +31,7 @@ function createApp(opts) {
},
},
},
+ // 不能再 bodyParser,会卡死
bodyParser: false,
// dataWrapping: false,
resourcer: {
@@ -40,9 +41,8 @@ function createApp(opts) {
const app = new Application(options);
app.db.sequelize.beforeDefine((model, options) => {
- options.tableName = `saas_${name}_${
- options.tableName || options.name.plural
- }`;
+ options.tableName = `saas_${name}_${options.tableName || options.name.plural
+ }`;
});
app.resource({
@@ -126,9 +126,19 @@ export default {
this.app['apps'] = new Map();
this.app.collection({
name: 'applications',
+ title: '应用',
fields: [
- { type: 'string', name: 'name', unique: true },
- { type: 'belongsTo', name: 'user' },
+ {
+ type: 'string',
+ name: 'name',
+ interface: 'string',
+ unique: true,
+ uiSchema: {
+ type: 'string',
+ title: '名称',
+ 'x-component': 'Input',
+ },
+ },
],
});
this.app.use(
@@ -138,6 +148,23 @@ export default {
},
}),
);
+ this.app.db.on('applications.afterCreate', async (model) => {
+ const name = model.get('name');
+ const app = createApp({
+ name,
+ });
+ (async () => {
+ await app.load();
+ await app.db.sync({
+ force: true,
+ alter: {
+ drop: true,
+ },
+ });
+ await app.emitAsync('db.init');
+ await app.destroy();
+ })()
+ });
this.app
.command('app:create')
.argument('')