feat(server): improve application (#177)
* feat: getRepository * getRepository return type * export action * refactor(plugin-acl): plugin * refactor(plugin-action-logs): plugin class * refactor(plugin-china-region): plugin class * refactor: plugin class * fix: cli start command * feat: pass install-command options into app.install * fix: cli args Co-authored-by: chenos <chenlinxh@gmail.com>
This commit is contained in:
		
							parent
							
								
									de25f56a79
								
							
						
					
					
						commit
						8e4336cbe1
					
				@ -82,17 +82,13 @@ export default class PluginACL extends Plugin {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async load() {
 | 
					  async beforeLoad() {
 | 
				
			||||||
    this.app.db.registerModels({
 | 
					 | 
				
			||||||
      RoleResourceActionModel,
 | 
					 | 
				
			||||||
      RoleResourceModel,
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const acl = createACL();
 | 
					    const acl = createACL();
 | 
				
			||||||
    this.acl = acl;
 | 
					    this.acl = acl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await this.app.db.import({
 | 
					    this.app.db.registerModels({
 | 
				
			||||||
      directory: path.resolve(__dirname, 'collections'),
 | 
					      RoleResourceActionModel,
 | 
				
			||||||
 | 
					      RoleResourceModel,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.registerAssociationFieldsActions();
 | 
					    this.registerAssociationFieldsActions();
 | 
				
			||||||
@ -100,8 +96,6 @@ export default class PluginACL extends Plugin {
 | 
				
			|||||||
    this.app.resourcer.define(availableActionResource);
 | 
					    this.app.resourcer.define(availableActionResource);
 | 
				
			||||||
    this.app.resourcer.define(roleCollectionsResource);
 | 
					    this.app.resourcer.define(roleCollectionsResource);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.app.resourcer.use(this.acl.middleware());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this.app.db.on('roles.afterSave', async (model, options) => {
 | 
					    this.app.db.on('roles.afterSave', async (model, options) => {
 | 
				
			||||||
      const { transaction } = options;
 | 
					      const { transaction } = options;
 | 
				
			||||||
      const roleName = model.get('name');
 | 
					      const roleName = model.get('name');
 | 
				
			||||||
@ -187,4 +181,12 @@ export default class PluginACL extends Plugin {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async load() {
 | 
				
			||||||
 | 
					    await this.app.db.import({
 | 
				
			||||||
 | 
					      directory: path.resolve(__dirname, 'collections'),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    this.app.resourcer.use(this.acl.middleware());
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,16 +1,17 @@
 | 
				
			|||||||
import path from 'path';
 | 
					import path from 'path';
 | 
				
			||||||
import { Plugin } from '@nocobase/server';
 | 
					 | 
				
			||||||
import { afterCreate, afterUpdate, afterDestroy } from './hooks';
 | 
					import { afterCreate, afterUpdate, afterDestroy } from './hooks';
 | 
				
			||||||
 | 
					import { Plugin } from '@nocobase/server';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class PluginActionLogs extends Plugin {
 | 
				
			||||||
 | 
					  async beforeLoad() {
 | 
				
			||||||
 | 
					    this.db.on('afterCreate', afterCreate);
 | 
				
			||||||
 | 
					    this.db.on('afterUpdate', afterUpdate);
 | 
				
			||||||
 | 
					    this.db.on('afterDestroy', afterDestroy);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class extends Plugin {
 | 
					 | 
				
			||||||
  name: 'action-logs';
 | 
					 | 
				
			||||||
  async load() {
 | 
					  async load() {
 | 
				
			||||||
    const database = this.app.db;
 | 
					    await this.db.import({
 | 
				
			||||||
    await database.import({
 | 
					 | 
				
			||||||
      directory: path.resolve(__dirname, 'collections'),
 | 
					      directory: path.resolve(__dirname, 'collections'),
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
    database.on('afterCreate', afterCreate);
 | 
					 | 
				
			||||||
    database.on('afterUpdate', afterUpdate);
 | 
					 | 
				
			||||||
    database.on('afterDestroy', afterDestroy);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -51,18 +51,17 @@ async function importData(model) {
 | 
				
			|||||||
  console.log(`${count} rows of region data imported in ${(Date.now() - timer) / 1000}s`);
 | 
					  console.log(`${count} rows of region data imported in ${(Date.now() - timer) / 1000}s`);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default class PluginChinaRegion extends Plugin {
 | 
				
			||||||
  name: 'china-region',
 | 
					  async beforeLoad() {
 | 
				
			||||||
  async load(this: Plugin) {
 | 
					    this.app.on('installing', async () => {
 | 
				
			||||||
    const db = this.app.db;
 | 
					      const ChinaRegion = this.db.getCollection('china_regions').model;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    await db.import({
 | 
					 | 
				
			||||||
      directory: path.resolve(__dirname, 'collections'),
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this.app.on('db.init', async () => {
 | 
					 | 
				
			||||||
      const ChinaRegion = db.getCollection('china_regions').model;
 | 
					 | 
				
			||||||
      await importData(ChinaRegion);
 | 
					      await importData(ChinaRegion);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  },
 | 
					  }
 | 
				
			||||||
};
 | 
					
 | 
				
			||||||
 | 
					  async load() {
 | 
				
			||||||
 | 
					    await this.db.import({
 | 
				
			||||||
 | 
					      directory: path.resolve(__dirname, 'collections'),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -10,16 +10,12 @@ import { afterCreateForReverseField } from './hooks/afterCreateForReverseField';
 | 
				
			|||||||
export * from './repositories/collection-repository';
 | 
					export * from './repositories/collection-repository';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class CollectionManagerPlugin extends Plugin {
 | 
					export default class CollectionManagerPlugin extends Plugin {
 | 
				
			||||||
  async load() {
 | 
					  async beforeLoad() {
 | 
				
			||||||
    this.app.db.registerModels({
 | 
					    this.app.db.registerModels({
 | 
				
			||||||
      CollectionModel,
 | 
					      CollectionModel,
 | 
				
			||||||
      FieldModel,
 | 
					      FieldModel,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await this.app.db.import({
 | 
					 | 
				
			||||||
      directory: path.resolve(__dirname, './collections'),
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // 要在 beforeInitOptions 之前处理
 | 
					    // 要在 beforeInitOptions 之前处理
 | 
				
			||||||
    this.app.db.on('fields.beforeCreate', beforeCreateForReverseField(this.app.db));
 | 
					    this.app.db.on('fields.beforeCreate', beforeCreateForReverseField(this.app.db));
 | 
				
			||||||
    this.app.db.on('fields.beforeCreate', beforeCreateForChildrenCollection(this.app.db));
 | 
					    this.app.db.on('fields.beforeCreate', beforeCreateForChildrenCollection(this.app.db));
 | 
				
			||||||
@ -47,4 +43,10 @@ export default class CollectionManagerPlugin extends Plugin {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async load() {
 | 
				
			||||||
 | 
					    await this.app.db.import({
 | 
				
			||||||
 | 
					      directory: path.resolve(__dirname, './collections'),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,44 +1,41 @@
 | 
				
			|||||||
import path from 'path';
 | 
					import path from 'path';
 | 
				
			||||||
import Database from '@nocobase/database';
 | 
					import { Plugin } from '@nocobase/server';
 | 
				
			||||||
import Resourcer from '@nocobase/resourcer';
 | 
					 | 
				
			||||||
import { PluginOptions } from '@nocobase/server';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { action as uploadAction, middleware as uploadMiddleware } from './actions/upload';
 | 
					import { action as uploadAction, middleware as uploadMiddleware } from './actions/upload';
 | 
				
			||||||
import { getStorageConfig } from './storages';
 | 
					import { getStorageConfig } from './storages';
 | 
				
			||||||
import { STORAGE_TYPE_LOCAL } from './constants';
 | 
					import { STORAGE_TYPE_LOCAL } from './constants';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default class PluginFileManager extends Plugin {
 | 
				
			||||||
  name: 'file-manager',
 | 
					  storageType() {
 | 
				
			||||||
  async load() {
 | 
					    return process.env.DEFAULT_STORAGE_TYPE;
 | 
				
			||||||
    const database: Database = this.app.db;
 | 
					  }
 | 
				
			||||||
    const resourcer: Resourcer = this.app.resourcer;
 | 
					  async beforeLoad() {
 | 
				
			||||||
 | 
					    this.app.on('installing', async () => {
 | 
				
			||||||
    await database.import({
 | 
					      const defaultStorageConfig = getStorageConfig(this.storageType());
 | 
				
			||||||
      directory: path.resolve(__dirname, 'collections'),
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    // 暂时中间件只能通过 use 加进来
 | 
					 | 
				
			||||||
    resourcer.use(uploadMiddleware);
 | 
					 | 
				
			||||||
    resourcer.registerActionHandler('upload', uploadAction);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const { DEFAULT_STORAGE_TYPE } = process.env;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (process.env.NOCOBASE_ENV !== 'production') {
 | 
					 | 
				
			||||||
      await getStorageConfig(STORAGE_TYPE_LOCAL).middleware(this.app);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this.app.on('db.init', async () => {
 | 
					 | 
				
			||||||
      const defaultStorageConfig = getStorageConfig(DEFAULT_STORAGE_TYPE);
 | 
					 | 
				
			||||||
      if (defaultStorageConfig) {
 | 
					      if (defaultStorageConfig) {
 | 
				
			||||||
        const Storage = database.getCollection('storages');
 | 
					        const Storage = this.db.getCollection('storages');
 | 
				
			||||||
        await Storage.repository.create({
 | 
					        await Storage.repository.create({
 | 
				
			||||||
          values: {
 | 
					          values: {
 | 
				
			||||||
            ...defaultStorageConfig.defaults(),
 | 
					            ...defaultStorageConfig.defaults(),
 | 
				
			||||||
            type: DEFAULT_STORAGE_TYPE,
 | 
					            type: this.storageType(),
 | 
				
			||||||
            default: true,
 | 
					            default: true,
 | 
				
			||||||
          },
 | 
					          },
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  },
 | 
					  }
 | 
				
			||||||
} as PluginOptions;
 | 
					
 | 
				
			||||||
 | 
					  async load() {
 | 
				
			||||||
 | 
					    await this.db.import({
 | 
				
			||||||
 | 
					      directory: path.resolve(__dirname, 'collections'),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // 暂时中间件只能通过 use 加进来
 | 
				
			||||||
 | 
					    this.app.resourcer.use(uploadMiddleware);
 | 
				
			||||||
 | 
					    this.app.resourcer.registerActionHandler('upload', uploadAction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (process.env.NOCOBASE_ENV !== 'production') {
 | 
				
			||||||
 | 
					      await getStorageConfig(STORAGE_TYPE_LOCAL).middleware(this.app);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +1,10 @@
 | 
				
			|||||||
import path from 'path';
 | 
					import path from 'path';
 | 
				
			||||||
import { PluginOptions } from '@nocobase/server';
 | 
					import { Plugin } from '@nocobase/server';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default class PluginNotifications extends Plugin {
 | 
				
			||||||
  name: 'notifications',
 | 
					 | 
				
			||||||
  async load() {
 | 
					  async load() {
 | 
				
			||||||
    await this.app.db.import({
 | 
					    await this.app.db.import({
 | 
				
			||||||
      directory: path.resolve(__dirname, 'collections'),
 | 
					      directory: path.resolve(__dirname, 'collections'),
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
} as PluginOptions
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,19 +1,10 @@
 | 
				
			|||||||
import path from 'path';
 | 
					import path from 'path';
 | 
				
			||||||
import { PluginOptions } from '@nocobase/server';
 | 
					import { Plugin, PluginOptions } from '@nocobase/server';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default class PluginSystemSettings extends Plugin {
 | 
				
			||||||
  name: 'system-settings',
 | 
					  async beforeLoad() {
 | 
				
			||||||
  async load() {
 | 
					    this.app.on('installing', async () => {
 | 
				
			||||||
    const database = this.app.db;
 | 
					      await this.db.getRepository('system_settings').create({
 | 
				
			||||||
 | 
					 | 
				
			||||||
    await database.import({
 | 
					 | 
				
			||||||
      directory: path.resolve(__dirname, 'collections'),
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const SystemSetting = database.getCollection('system_settings');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this.app.on('db.init', async () => {
 | 
					 | 
				
			||||||
      await SystemSetting.repository.create({
 | 
					 | 
				
			||||||
        values: {
 | 
					        values: {
 | 
				
			||||||
          title: 'NocoBase',
 | 
					          title: 'NocoBase',
 | 
				
			||||||
          logo: {
 | 
					          logo: {
 | 
				
			||||||
@ -26,5 +17,11 @@ export default {
 | 
				
			|||||||
        },
 | 
					        },
 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  },
 | 
					  }
 | 
				
			||||||
} as PluginOptions;
 | 
					
 | 
				
			||||||
 | 
					  async load() {
 | 
				
			||||||
 | 
					    await this.app.db.import({
 | 
				
			||||||
 | 
					      directory: path.resolve(__dirname, 'collections'),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
import { mockServer, MockServer } from '@nocobase/test';
 | 
					import { mockServer, MockServer } from '@nocobase/test';
 | 
				
			||||||
import { Collection, Database } from '@nocobase/database';
 | 
					import { Collection, Database } from '@nocobase/database';
 | 
				
			||||||
import PluginUiSchema, { UiSchemaRepository } from '@nocobase/plugin-ui-schema';
 | 
					import PluginUiSchema, { UiSchemaRepository } from '..';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('ui schema model', () => {
 | 
					describe('ui schema model', () => {
 | 
				
			||||||
  let app: MockServer;
 | 
					  let app: MockServer;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
import { ISchema } from '@formily/json-schema';
 | 
					import { ISchema } from '@formily/json-schema';
 | 
				
			||||||
import { mockServer, MockServer } from '@nocobase/test';
 | 
					import { mockServer, MockServer } from '@nocobase/test';
 | 
				
			||||||
import { Collection, Database } from '@nocobase/database';
 | 
					import { Collection, Database } from '@nocobase/database';
 | 
				
			||||||
import PluginUiSchema, { UiSchemaRepository } from '@nocobase/plugin-ui-schema';
 | 
					import PluginUiSchema, { UiSchemaRepository } from '..';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('ui-schema', () => {
 | 
					describe('ui-schema', () => {
 | 
				
			||||||
  let app: MockServer;
 | 
					  let app: MockServer;
 | 
				
			||||||
 | 
				
			|||||||
@ -11,17 +11,13 @@ export default class PluginUiSchema extends Plugin {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async load() {
 | 
					  async beforeLoad() {
 | 
				
			||||||
    const db = this.app.db;
 | 
					    const db = this.app.db;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.app.db.registerModels({ MagicAttributeModel });
 | 
					    this.app.db.registerModels({ MagicAttributeModel });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.registerRepository();
 | 
					    this.registerRepository();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await db.import({
 | 
					 | 
				
			||||||
      directory: path.resolve(__dirname, 'collections'),
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    db.on('ui_schemas.beforeCreate', (model) => {
 | 
					    db.on('ui_schemas.beforeCreate', (model) => {
 | 
				
			||||||
      model.set('uid', model.get('x-uid'));
 | 
					      model.set('uid', model.get('x-uid'));
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
@ -44,23 +40,15 @@ export default class PluginUiSchema extends Plugin {
 | 
				
			|||||||
      });
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await db.getCollection('ui_schemas').sync({
 | 
					 | 
				
			||||||
      force: false,
 | 
					 | 
				
			||||||
      alter: {
 | 
					 | 
				
			||||||
        drop: false,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    await db.getCollection('ui_schema_tree_path').sync({
 | 
					 | 
				
			||||||
      force: false,
 | 
					 | 
				
			||||||
      alter: {
 | 
					 | 
				
			||||||
        drop: false,
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this.app.resourcer.define({
 | 
					    this.app.resourcer.define({
 | 
				
			||||||
      name: 'ui_schemas',
 | 
					      name: 'ui_schemas',
 | 
				
			||||||
      actions: uiSchemaActions,
 | 
					      actions: uiSchemaActions,
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  async load() {
 | 
				
			||||||
 | 
					    await this.db.import({
 | 
				
			||||||
 | 
					      directory: path.resolve(__dirname, 'collections'),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ describe('role', () => {
 | 
				
			|||||||
    await api.cleanDb();
 | 
					    await api.cleanDb();
 | 
				
			||||||
    api.plugin(require('../server').default);
 | 
					    api.plugin(require('../server').default);
 | 
				
			||||||
    api.plugin(PluginACL);
 | 
					    api.plugin(PluginACL);
 | 
				
			||||||
    await api.loadAndSync();
 | 
					    await api.loadAndInstall();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    db = api.db;
 | 
					    db = api.db;
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
 | 
				
			|||||||
@ -2,16 +2,12 @@ import path from 'path';
 | 
				
			|||||||
import * as actions from './actions/users';
 | 
					import * as actions from './actions/users';
 | 
				
			||||||
import * as middlewares from './middlewares';
 | 
					import * as middlewares from './middlewares';
 | 
				
			||||||
import { Collection } from '@nocobase/database';
 | 
					import { Collection } from '@nocobase/database';
 | 
				
			||||||
import { PluginOptions } from '@nocobase/server';
 | 
					import { Plugin, PluginOptions } from '@nocobase/server';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default class PluginUsers extends Plugin {
 | 
				
			||||||
  name: 'users',
 | 
					  async beforeLoad() {
 | 
				
			||||||
  async load() {
 | 
					    this.app.on('installing', async () => {
 | 
				
			||||||
    const database = this.app.db;
 | 
					      const User = this.db.getCollection('users');
 | 
				
			||||||
    const resourcer = this.app.resourcer;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    this.app.on('db.init', async () => {
 | 
					 | 
				
			||||||
      const User = database.getCollection('users');
 | 
					 | 
				
			||||||
      await User.model.create({
 | 
					      await User.model.create({
 | 
				
			||||||
        nickname: 'Super Admin',
 | 
					        nickname: 'Super Admin',
 | 
				
			||||||
        email: process.env.ADMIN_EMAIL || 'admin@nocobase.com',
 | 
					        email: process.env.ADMIN_EMAIL || 'admin@nocobase.com',
 | 
				
			||||||
@ -19,7 +15,7 @@ export default {
 | 
				
			|||||||
      });
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    database.on('users.afterCreateWithAssociations', async (model, options) => {
 | 
					    this.db.on('users.afterCreateWithAssociations', async (model, options) => {
 | 
				
			||||||
      const { transaction } = options;
 | 
					      const { transaction } = options;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      const defaultRole = await this.app.db.getRepository('roles').findOne({
 | 
					      const defaultRole = await this.app.db.getRepository('roles').findOne({
 | 
				
			||||||
@ -34,7 +30,7 @@ export default {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    database.on('afterDefineCollection', (collection: Collection) => {
 | 
					    this.db.on('afterDefineCollection', (collection: Collection) => {
 | 
				
			||||||
      let { createdBy, updatedBy } = collection.options;
 | 
					      let { createdBy, updatedBy } = collection.options;
 | 
				
			||||||
      if (createdBy === true) {
 | 
					      if (createdBy === true) {
 | 
				
			||||||
        collection.setField('createdById', {
 | 
					        collection.setField('createdById', {
 | 
				
			||||||
@ -65,14 +61,16 @@ export default {
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await database.import({
 | 
					 | 
				
			||||||
      directory: path.resolve(__dirname, 'collections'),
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (const [key, action] of Object.entries(actions)) {
 | 
					    for (const [key, action] of Object.entries(actions)) {
 | 
				
			||||||
      resourcer.registerActionHandler(`users:${key}`, action);
 | 
					      this.app.resourcer.registerActionHandler(`users:${key}`, action);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    resourcer.use(middlewares.parseToken({}));
 | 
					    this.app.resourcer.use(middlewares.parseToken({}));
 | 
				
			||||||
  },
 | 
					  }
 | 
				
			||||||
} as PluginOptions;
 | 
					
 | 
				
			||||||
 | 
					  async load() {
 | 
				
			||||||
 | 
					    await this.db.import({
 | 
				
			||||||
 | 
					      directory: path.resolve(__dirname, 'collections'),
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@ import { Application } from '../application';
 | 
				
			|||||||
import { Plugin } from '../plugin';
 | 
					import { Plugin } from '../plugin';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MyPlugin extends Plugin {
 | 
					class MyPlugin extends Plugin {
 | 
				
			||||||
  load() {}
 | 
					  async load() {}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
describe('application', () => {
 | 
					describe('application', () => {
 | 
				
			||||||
 | 
				
			|||||||
@ -65,10 +65,12 @@ interface ListenOptions {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface StartOptions {
 | 
					interface StartOptions {
 | 
				
			||||||
 | 
					  cliArgs?: any[];
 | 
				
			||||||
  listen?: ListenOptions;
 | 
					  listen?: ListenOptions;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface InstallOptions {
 | 
					interface InstallOptions {
 | 
				
			||||||
 | 
					  cliArgs?: any[];
 | 
				
			||||||
  clean?: CleanOptions | boolean;
 | 
					  clean?: CleanOptions | boolean;
 | 
				
			||||||
  sync?: SyncOptions;
 | 
					  sync?: SyncOptions;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -174,8 +176,8 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
 | 
				
			|||||||
    await this.emitAsync('afterStart', this, options);
 | 
					    await this.emitAsync('afterStart', this, options);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async stop() {
 | 
					  async stop(options?: any) {
 | 
				
			||||||
    await this.emitAsync('beforeStop', this);
 | 
					    await this.emitAsync('beforeStop', this, options);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // close database connection
 | 
					    // close database connection
 | 
				
			||||||
    await this.db.close();
 | 
					    await this.db.close();
 | 
				
			||||||
@ -188,7 +190,6 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
 | 
				
			|||||||
            if (err) {
 | 
					            if (err) {
 | 
				
			||||||
              return reject(err);
 | 
					              return reject(err);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					 | 
				
			||||||
            this.listenServer = null;
 | 
					            this.listenServer = null;
 | 
				
			||||||
            resolve(true);
 | 
					            resolve(true);
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
@ -197,13 +198,13 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
 | 
				
			|||||||
      await closeServer();
 | 
					      await closeServer();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await this.emitAsync('afterStop', this);
 | 
					    await this.emitAsync('afterStop', this, options);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async destroy() {
 | 
					  async destroy(options?: any) {
 | 
				
			||||||
    await this.emitAsync('beforeDestroy', this);
 | 
					    await this.emitAsync('beforeDestroy', this, options);
 | 
				
			||||||
    await this.stop();
 | 
					    await this.stop(options);
 | 
				
			||||||
    await this.emitAsync('afterDestroy', this);
 | 
					    await this.emitAsync('afterDestroy', this, options);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  async install(options?: InstallOptions) {
 | 
					  async install(options?: InstallOptions) {
 | 
				
			||||||
@ -211,7 +212,9 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
 | 
				
			|||||||
      await this.db.clean(isBoolean(options.clean) ? { drop: options.clean } : options.clean);
 | 
					      await this.db.clean(isBoolean(options.clean) ? { drop: options.clean } : options.clean);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    await this.db.sync(options?.sync);
 | 
					    await this.db.sync(options?.sync);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await this.emitAsync('beforeInstall', this, options);
 | 
					    await this.emitAsync('beforeInstall', this, options);
 | 
				
			||||||
 | 
					    await this.emitAsync('installing', this, options);
 | 
				
			||||||
    await this.emitAsync('afterInstall', this, options);
 | 
					    await this.emitAsync('afterInstall', this, options);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +1,13 @@
 | 
				
			|||||||
import { DefaultContext, DefaultState } from 'koa';
 | 
					 | 
				
			||||||
import bodyParser from 'koa-bodyparser';
 | 
					 | 
				
			||||||
import cors from '@koa/cors';
 | 
					import cors from '@koa/cors';
 | 
				
			||||||
import Database from '@nocobase/database';
 | 
					import Database from '@nocobase/database';
 | 
				
			||||||
import Resourcer from '@nocobase/resourcer';
 | 
					import Resourcer from '@nocobase/resourcer';
 | 
				
			||||||
import { Command } from 'commander';
 | 
					import { Command } from 'commander';
 | 
				
			||||||
 | 
					import i18next from 'i18next';
 | 
				
			||||||
 | 
					import { DefaultContext, DefaultState } from 'koa';
 | 
				
			||||||
 | 
					import bodyParser from 'koa-bodyparser';
 | 
				
			||||||
import Application, { ApplicationOptions } from './application';
 | 
					import Application, { ApplicationOptions } from './application';
 | 
				
			||||||
import { dataWrapping } from './middlewares/data-wrapping';
 | 
					import { dataWrapping } from './middlewares/data-wrapping';
 | 
				
			||||||
import { table2resource } from './middlewares/table2resource';
 | 
					import { table2resource } from './middlewares/table2resource';
 | 
				
			||||||
import i18next from 'i18next';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export function createDatabase(options: ApplicationOptions) {
 | 
					export function createDatabase(options: ApplicationOptions) {
 | 
				
			||||||
  if (options.database instanceof Database) {
 | 
					  if (options.database instanceof Database) {
 | 
				
			||||||
@ -37,12 +37,11 @@ export function createCli(app: Application, options: ApplicationOptions) {
 | 
				
			|||||||
  cli
 | 
					  cli
 | 
				
			||||||
    .command('db:sync')
 | 
					    .command('db:sync')
 | 
				
			||||||
    .option('-f, --force')
 | 
					    .option('-f, --force')
 | 
				
			||||||
    .action(async (...args) => {
 | 
					    .action(async (...cliArgs) => {
 | 
				
			||||||
 | 
					      const [opts] = cliArgs;
 | 
				
			||||||
      console.log('db sync...');
 | 
					      console.log('db sync...');
 | 
				
			||||||
      const cli = args.pop();
 | 
					 | 
				
			||||||
      const force = cli.opts()?.force;
 | 
					 | 
				
			||||||
      await app.db.sync(
 | 
					      await app.db.sync(
 | 
				
			||||||
        force
 | 
					        opts.force
 | 
				
			||||||
          ? {
 | 
					          ? {
 | 
				
			||||||
              force: true,
 | 
					              force: true,
 | 
				
			||||||
              alter: {
 | 
					              alter: {
 | 
				
			||||||
@ -51,44 +50,44 @@ export function createCli(app: Application, options: ApplicationOptions) {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
          : {},
 | 
					          : {},
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
      await app.destroy();
 | 
					      await app.stop({
 | 
				
			||||||
 | 
					        cliArgs,
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  cli
 | 
					  cli
 | 
				
			||||||
    .command('init')
 | 
					    .command('install')
 | 
				
			||||||
    .option('-f, --force')
 | 
					    .option('-f, --force')
 | 
				
			||||||
    .action(async (opts, ...args) => {
 | 
					    .action(async (...cliArgs) => {
 | 
				
			||||||
      if (!opts?.force) {
 | 
					      const [opts] = cliArgs;
 | 
				
			||||||
        const tables = await app.db.sequelize.getQueryInterface().showAllTables();
 | 
					      await app.install({
 | 
				
			||||||
        if (tables.includes('collections')) {
 | 
					        cliArgs,
 | 
				
			||||||
          console.log('NocoBase is already installed. To reinstall, please execute:');
 | 
					        sync: {
 | 
				
			||||||
          console.log();
 | 
					          force: opts.force,
 | 
				
			||||||
          let command = 'yarn nocobase init --force';
 | 
					        },
 | 
				
			||||||
          for (const [key, value] of Object.entries(opts || {})) {
 | 
					      });
 | 
				
			||||||
            command += value === true ? ` --${key}` : ` --${key}=${value}`;
 | 
					      await app.stop({
 | 
				
			||||||
          }
 | 
					        cliArgs,
 | 
				
			||||||
          console.log(command);
 | 
					 | 
				
			||||||
          console.log();
 | 
					 | 
				
			||||||
          return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
      await app.db.sync({
 | 
					 | 
				
			||||||
        force: true,
 | 
					 | 
				
			||||||
      });
 | 
					      });
 | 
				
			||||||
      await app.emitAsync('db.init', opts, ...args);
 | 
					 | 
				
			||||||
      await app.destroy();
 | 
					 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  cli
 | 
					  cli
 | 
				
			||||||
    .command('start')
 | 
					    .command('start')
 | 
				
			||||||
    .option('-p, --port [port]')
 | 
					    .option('-p, --port [port]')
 | 
				
			||||||
    .action(async (...args) => {
 | 
					    .action(async (...cliArgs) => {
 | 
				
			||||||
      const cli = args.pop();
 | 
					      const [opts] = cliArgs;
 | 
				
			||||||
      const opts = cli.opts();
 | 
					      const port = opts.port || 3000;
 | 
				
			||||||
      await app.emitAsync('beforeStart');
 | 
					
 | 
				
			||||||
      await app.start(opts.port || 3000);
 | 
					      await app.start({
 | 
				
			||||||
      console.log(`http://localhost:${opts.port || 3000}/`);
 | 
					        cliArgs,
 | 
				
			||||||
 | 
					        listen: {
 | 
				
			||||||
 | 
					          port,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      console.log(`http://localhost:${port}/`);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return cli;
 | 
					  return cli;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,6 @@
 | 
				
			|||||||
import { Database } from '@nocobase/database';
 | 
					import { Database } from '@nocobase/database';
 | 
				
			||||||
import { Application } from './application';
 | 
					import { Application } from './application';
 | 
				
			||||||
 | 
					import path from 'path';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export interface PluginInterface {
 | 
					export interface PluginInterface {
 | 
				
			||||||
  beforeLoad?: () => void;
 | 
					  beforeLoad?: () => void;
 | 
				
			||||||
@ -41,5 +42,16 @@ export abstract class Plugin<O = any> implements PluginInterface {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  beforeLoad() {}
 | 
					  beforeLoad() {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  abstract load();
 | 
					  async load() {
 | 
				
			||||||
 | 
					    const collectionPath = this.collectionPath();
 | 
				
			||||||
 | 
					    if (collectionPath) {
 | 
				
			||||||
 | 
					      await this.db.import({
 | 
				
			||||||
 | 
					        directory: collectionPath,
 | 
				
			||||||
 | 
					      });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  collectionPath() {
 | 
				
			||||||
 | 
					    return null;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user