diff --git a/.umirc.ts b/.umirc.ts index aa7d9c39e..d3399f36d 100644 --- a/.umirc.ts +++ b/.umirc.ts @@ -8,6 +8,13 @@ export default defineConfig({ define: { 'process.env.API_URL': process.env.API_URL, }, + proxy: { + '/api': { + 'target': `http://localhost:${process.env.API_PORT}/`, + 'changeOrigin': true, + 'pathRewrite': { '^/api' : '/api' }, + }, + }, // mfsu: {}, // ssr: {}, // exportStatic: {}, diff --git a/mock/.gitkeep b/mock/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/mock/api.ts b/mock/api.ts deleted file mode 100644 index 6f1e21c83..000000000 --- a/mock/api.ts +++ /dev/null @@ -1,17 +0,0 @@ -import Mock from 'mockjs'; -import * as resources from './resources'; - -export default { - '/api/:resource::action': (req: any, res: any) => { - const action = resources[req.params.resource][req.params.action]; - if (action) { - return action(req, res); - } - }, - '/api/:resource::action/:resourceIndex': (req: any, res: any) => { - const action = resources[req.params.resource][req.params.action]; - if (action) { - return action(req, res); - } - }, -} diff --git a/mock/resources/blocks.ts b/mock/resources/blocks.ts deleted file mode 100644 index 49205f43f..000000000 --- a/mock/resources/blocks.ts +++ /dev/null @@ -1,37 +0,0 @@ -import Mock from 'mockjs'; - -export async function getOptions(req: any, res: any) { - res.json({ - data: { - name: 'grid1', - 'x-component': 'GridBlock', - blocks: [ - { - name: 'form1', - resource: { - resourceName: 'users', - resourceKey: 1, - }, - fields: [ - { - interface: 'string', - type: 'string', - title: `单行文本`, - name: 'username', - required: true, - component: { - type: 'string', - default: 'abcdefg', - 'x-decorator': 'FormItem', - 'x-component': 'Input', - 'x-component-props': { - placeholder: 'please enter', - }, - }, - }, - ], - }, - ], - }, - }); -} diff --git a/mock/resources/examples.ts b/mock/resources/examples.ts deleted file mode 100644 index 83e6d0bd4..000000000 --- a/mock/resources/examples.ts +++ /dev/null @@ -1,8 +0,0 @@ -import Mock from 'mockjs'; - -export async function list(req: any, res: any) { - res.json({ - data: [], - meta: {}, - }); -} \ No newline at end of file diff --git a/mock/resources/index.ts b/mock/resources/index.ts deleted file mode 100644 index 985641bb1..000000000 --- a/mock/resources/index.ts +++ /dev/null @@ -1,7 +0,0 @@ - -import * as blocks from './blocks'; -import * as routes from './routes'; -import * as users from './users'; -import * as examples from './examples'; - -export { blocks, routes, users, examples }; diff --git a/mock/resources/routes.ts b/mock/resources/routes.ts deleted file mode 100644 index 521df3c3b..000000000 --- a/mock/resources/routes.ts +++ /dev/null @@ -1,184 +0,0 @@ -import Mock from 'mockjs'; - -export async function getAccessible(req: any, res: any) { - res.json({ - data: [ - { - type: 'redirect', - from: '/admin', - to: '/admin/welcome', - exact: true, - }, - { - type: 'redirect', - from: '/', - to: '/admin', - exact: true, - }, - { - path: '/admin/:name(.+)?', - component: 'AdminLayout', - title: `后台 - ${Mock.mock('@string')}`, - // providers: ['CurrentUserProvider', 'MenuProvider'], - }, - { - component: 'AuthLayout', - routes: [ - { - name: 'login', - path: '/login', - component: 'PageTemplate', - title: `登录 - ${Mock.mock('@string')}`, - }, - { - name: 'register', - path: '/register', - component: 'PageTemplate', - title: `注册 - ${Mock.mock('@string')}`, - }, - ], - }, - ], - }); -} - -export async function getMenu(req: any, res: any) { - res.json({ - data: [ - { - name: 'welcome', - title: `欢迎 - ${Mock.mock('@string')}`, - children: [ - { - name: 'page2', - title: '页面2', - }, - ], - }, - { - name: 'users', - title: `用户 - ${Mock.mock('@string')}`, - }, - ], - }); -} - -export async function getPage(req: any, res: any) { - const fields = [ - { - interface: 'string', - type: 'string', - title: `单行文本 - ${Mock.mock('@string')}`, - name: 'input', - required: true, - component: { - type: 'string', - default: 'aa', - 'x-decorator': 'FormItem', - 'x-component': 'Input', - 'x-component-props': {}, - }, - }, - { - interface: 'textarea', - type: 'text', - title: `多行文本框 - ${Mock.mock('@string')}`, - name: 'textarea', - required: true, - component: { - type: 'string', - 'x-decorator': 'FormItem', - 'x-component': 'Input.TextArea', - 'x-component-props': {}, - }, - }, - ]; - res.json({ - data: { - title: `page - ${req.query.slug} - ${Mock.mock('@string')}`, - blocks: [ - { - interface: 'form', - type: 'form', - component: { - 'x-component': 'Form', - }, - fields, - }, - { - interface: 'table', - type: 'table', - component: { - 'x-component': 'Table', - }, - fields, - }, - { - interface: 'calendar', - type: 'calendar', - component: { - 'x-component': 'Calendar', - }, - }, - { - interface: 'kanban', - type: 'kanban', - component: { - 'x-component': 'Kanban', - }, - }, - { - interface: 'grid', - type: 'grid', - component: { - 'x-component': 'Grid', - }, - rowProps: { - gutter: 16, - }, - colsProps: [12, 12], - blocks: [ - { - interface: 'markdown', - type: 'markdown', - component: { - 'x-component': 'Markdown', - }, - content: `# Markdown Content 1`, - rowOrder: 1, - columnOrder: 1, - }, - { - interface: 'markdown', - type: 'markdown', - component: { - 'x-component': 'Markdown', - }, - content: `# Markdown Content 2`, - rowOrder: 2, - columnOrder: 2, - }, - { - interface: 'markdown', - type: 'markdown', - component: { - 'x-component': 'Markdown', - }, - content: `# Markdown Content 1`, - rowOrder: 1, - columnOrder: 2, - }, - ], - }, - { - interface: 'markdown', - type: 'markdown', - component: { - 'x-component': 'Markdown', - }, - content: `# Markdown Content`, - }, - ], - }, - }); -} diff --git a/mock/resources/users.ts b/mock/resources/users.ts deleted file mode 100644 index 9847df2a2..000000000 --- a/mock/resources/users.ts +++ /dev/null @@ -1,19 +0,0 @@ -import Mock from 'mockjs'; - -export async function check(req: any, res: any) { - res.json({ - data: { - username: `username - ${Mock.mock('@string')}`, - token: Mock.mock('@string'), - }, - }); -} - -export async function get(req: any, res: any) { - res.json({ - data: { - username: `username - ${Mock.mock('@string')}`, - token: Mock.mock('@string'), - }, - }); -} diff --git a/packages/app/.umirc.ts b/packages/app/.umirc.ts index 3a9e3e09d..8879794d4 100644 --- a/packages/app/.umirc.ts +++ b/packages/app/.umirc.ts @@ -13,6 +13,13 @@ export default defineConfig({ define: { 'process.env.API_URL': process.env.API_URL, }, + proxy: { + '/api': { + 'target': `http://localhost:${process.env.API_PORT}/`, + 'changeOrigin': true, + 'pathRewrite': { '^/api' : '/api' }, + }, + }, routes: [ { path: '/', exact: false, component: '@/pages/index' }, ], diff --git a/packages/app/mock/.gitkeep b/packages/app/mock/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/app/mock/api.ts b/packages/app/mock/api.ts deleted file mode 100644 index be0b42fd4..000000000 --- a/packages/app/mock/api.ts +++ /dev/null @@ -1,11 +0,0 @@ -import Mock from 'mockjs'; -import * as resources from './resources'; - -export default { - '/api/:resource::action': (req: any, res: any) => { - const action = resources[req.params.resource][req.params.action]; - if (action) { - return action(req, res); - } - }, -} diff --git a/packages/app/mock/resources/examples.ts b/packages/app/mock/resources/examples.ts deleted file mode 100644 index 83e6d0bd4..000000000 --- a/packages/app/mock/resources/examples.ts +++ /dev/null @@ -1,8 +0,0 @@ -import Mock from 'mockjs'; - -export async function list(req: any, res: any) { - res.json({ - data: [], - meta: {}, - }); -} \ No newline at end of file diff --git a/packages/app/mock/resources/index.ts b/packages/app/mock/resources/index.ts deleted file mode 100644 index d77e56720..000000000 --- a/packages/app/mock/resources/index.ts +++ /dev/null @@ -1,6 +0,0 @@ - -import * as routes from './routes'; -import * as users from './users'; -import * as examples from './examples'; - -export { routes, users, examples }; diff --git a/packages/app/mock/resources/routes.ts b/packages/app/mock/resources/routes.ts deleted file mode 100644 index 521df3c3b..000000000 --- a/packages/app/mock/resources/routes.ts +++ /dev/null @@ -1,184 +0,0 @@ -import Mock from 'mockjs'; - -export async function getAccessible(req: any, res: any) { - res.json({ - data: [ - { - type: 'redirect', - from: '/admin', - to: '/admin/welcome', - exact: true, - }, - { - type: 'redirect', - from: '/', - to: '/admin', - exact: true, - }, - { - path: '/admin/:name(.+)?', - component: 'AdminLayout', - title: `后台 - ${Mock.mock('@string')}`, - // providers: ['CurrentUserProvider', 'MenuProvider'], - }, - { - component: 'AuthLayout', - routes: [ - { - name: 'login', - path: '/login', - component: 'PageTemplate', - title: `登录 - ${Mock.mock('@string')}`, - }, - { - name: 'register', - path: '/register', - component: 'PageTemplate', - title: `注册 - ${Mock.mock('@string')}`, - }, - ], - }, - ], - }); -} - -export async function getMenu(req: any, res: any) { - res.json({ - data: [ - { - name: 'welcome', - title: `欢迎 - ${Mock.mock('@string')}`, - children: [ - { - name: 'page2', - title: '页面2', - }, - ], - }, - { - name: 'users', - title: `用户 - ${Mock.mock('@string')}`, - }, - ], - }); -} - -export async function getPage(req: any, res: any) { - const fields = [ - { - interface: 'string', - type: 'string', - title: `单行文本 - ${Mock.mock('@string')}`, - name: 'input', - required: true, - component: { - type: 'string', - default: 'aa', - 'x-decorator': 'FormItem', - 'x-component': 'Input', - 'x-component-props': {}, - }, - }, - { - interface: 'textarea', - type: 'text', - title: `多行文本框 - ${Mock.mock('@string')}`, - name: 'textarea', - required: true, - component: { - type: 'string', - 'x-decorator': 'FormItem', - 'x-component': 'Input.TextArea', - 'x-component-props': {}, - }, - }, - ]; - res.json({ - data: { - title: `page - ${req.query.slug} - ${Mock.mock('@string')}`, - blocks: [ - { - interface: 'form', - type: 'form', - component: { - 'x-component': 'Form', - }, - fields, - }, - { - interface: 'table', - type: 'table', - component: { - 'x-component': 'Table', - }, - fields, - }, - { - interface: 'calendar', - type: 'calendar', - component: { - 'x-component': 'Calendar', - }, - }, - { - interface: 'kanban', - type: 'kanban', - component: { - 'x-component': 'Kanban', - }, - }, - { - interface: 'grid', - type: 'grid', - component: { - 'x-component': 'Grid', - }, - rowProps: { - gutter: 16, - }, - colsProps: [12, 12], - blocks: [ - { - interface: 'markdown', - type: 'markdown', - component: { - 'x-component': 'Markdown', - }, - content: `# Markdown Content 1`, - rowOrder: 1, - columnOrder: 1, - }, - { - interface: 'markdown', - type: 'markdown', - component: { - 'x-component': 'Markdown', - }, - content: `# Markdown Content 2`, - rowOrder: 2, - columnOrder: 2, - }, - { - interface: 'markdown', - type: 'markdown', - component: { - 'x-component': 'Markdown', - }, - content: `# Markdown Content 1`, - rowOrder: 1, - columnOrder: 2, - }, - ], - }, - { - interface: 'markdown', - type: 'markdown', - component: { - 'x-component': 'Markdown', - }, - content: `# Markdown Content`, - }, - ], - }, - }); -} diff --git a/packages/app/mock/resources/users.ts b/packages/app/mock/resources/users.ts deleted file mode 100644 index b266cac9e..000000000 --- a/packages/app/mock/resources/users.ts +++ /dev/null @@ -1,10 +0,0 @@ -import Mock from 'mockjs'; - -export async function check(req: any, res: any) { - res.json({ - data: { - username: `username - ${Mock.mock('@string')}`, - token: Mock.mock('@string'), - }, - }); -} diff --git a/packages/app/src/pages/index.tsx b/packages/app/src/pages/index.tsx index 62595b2b8..55fd482bb 100644 --- a/packages/app/src/pages/index.tsx +++ b/packages/app/src/pages/index.tsx @@ -24,6 +24,7 @@ request.use(async (ctx, next) => { if (token) { headers['Authorization'] = `Bearer ${token}`; } + headers['X-Hostname'] = window.location.hostname; await next(); }); diff --git a/packages/plugin-multi-apps/src/server.ts b/packages/plugin-multi-apps/src/server.ts index 6245e9b58..0111aa823 100644 --- a/packages/plugin-multi-apps/src/server.ts +++ b/packages/plugin-multi-apps/src/server.ts @@ -8,7 +8,7 @@ function createApp(opts) { database: { username: process.env.DB_USER, password: process.env.DB_PASSWORD, - database: process.env.DB_DATABASE, + database: name, host: process.env.DB_HOST, port: process.env.DB_PORT as any, dialect: process.env.DB_DIALECT as any, @@ -32,33 +32,20 @@ function createApp(opts) { }, }, // 不能再 bodyParser,会卡死 - bodyParser: false, + // bodyParser: false, // dataWrapping: false, resourcer: { - prefix: `/api/multiapps/${name}`, + prefix: '/api', + // prefix: `/api/multiapps/${name}`, }, }; const app = new Application(options); - app.db.sequelize.beforeDefine((model, options) => { - options.tableName = `multiapps_${name}_${ - options.tableName || options.name.plural - }`; - }); - - app.resource({ - name: 'saas', - actions: { - async getInfo(ctx, next) { - ctx.body = { - m: Object.values(ctx.db.sequelize.models).map( - (m: any) => m.tableName, - ), - }; - await next(); - }, - }, - }); + // app.db.sequelize.beforeDefine((model, options) => { + // options.tableName = `multiapps_${name}_${ + // options.tableName || options.name.plural + // }`; + // }); const plugins = [ '@nocobase/plugin-ui-schema', @@ -86,10 +73,12 @@ function createApp(opts) { function multiApps({ getAppName }) { return async function (ctx: Koa.Context, next) { const appName = getAppName(ctx); + console.log({ appName }); if (!appName) { return next(); } - const App = ctx.db.getModel('applications'); + // @ts-ignore + const App = ctx.app.db.getModel('applications'); const model = await App.findOne({ where: { name: appName }, }); @@ -108,9 +97,11 @@ function multiApps({ getAppName }) { console.log('..........................start........................'); // 完全隔离的做法 const app = apps.get(appName) as Application; + // @ts-ignore + console.log(app.db.options); const bodyParser = async (ctx2, next) => { // @ts-ignore - ctx2.request.body = ctx.request.body || {}; + // ctx2.request.body = ctx.request.body || {}; await next(); }; app.middleware.unshift(bodyParser); @@ -172,15 +163,23 @@ export default { }, ], }); - this.app.use( - multiApps({ - getAppName(ctx) { - return ctx.path.split('/')[3]; - }, - }), - ); + this.app.middleware.unshift(multiApps({ + getAppName(ctx) { + const hostname = ctx.get('X-Hostname'); + if (!hostname) { + return; + } + const keys = hostname.split('.'); + if (keys.length < 4) { + return; + } + console.log('ctx.hostname', ctx.get('X-Hostname')); + return keys.shift(); + }, + })); this.app.db.on('applications.afterCreate', async (model: Model) => { const name = model.get('name'); + await this.app.db.sequelize.query(`CREATE DATABASE "${name}";`); const app = createApp({ name, }); @@ -193,7 +192,7 @@ export default { }, }); await app.emitAsync('db.init'); - await app.destroy(); + // await app.destroy(); this.app['apps'].set(name, app); model.set('status', 'running'); await model.save({ hooks: false });