This commit is contained in:
dream2023 2023-07-13 19:05:50 +08:00
parent bb2a8019d6
commit 985d5c3771
4 changed files with 50 additions and 37 deletions

View File

@ -51,9 +51,8 @@ export interface DefaultState extends KoaDefaultState {
[key: string]: any;
}
export interface AppLoadOptions {
export interface AppLoadOptions extends InstallOptions {
method?: 'install' | 'upgrade' | 'start';
force?: boolean;
reload?: boolean;
}
@ -381,27 +380,14 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
}
async beforeLoad(options: AppLoadOptions) {
console.log('app beforeLoad');
console.log(`app [${this.name}]: beforeLoad`);
// wait all plugins init
await this.pm.waitPluginsInit();
await this.emitAsync('beforeLoad', this, options);
if (options.method === 'install') {
if (options.force) {
console.log('Truncate database and reload app configuration');
await this.db.clean({ drop: true });
await this.db.sync();
} else {
// check if the database is empty, if not, throw an error
if (await this.isInstalled()) {
throw new Error(
'You have already installed the application, please use the `-f` method to reinstall the application.',
);
}
}
} else if (options.method === 'upgrade') {
if (options.method === 'upgrade') {
// TODO: upgrade
}
@ -409,7 +395,7 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
}
async afterLoad(options: AppLoadOptions) {
console.log('app afterLoad');
console.log(`app [${this.name}]: afterLoad`);
await this.emitAsync('afterLoad', this, options);
if (options.method === 'install') {
@ -425,7 +411,7 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
}
}
async loadLifeCycles(options: AppLoadOptions) {
async load(options: AppLoadOptions = {}) {
await this.beforeLoad(options);
await this.emitAsync('load', this, options);
@ -434,13 +420,13 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
await this.afterLoad(options);
}
async reload(options: AppLoadOptions) {
console.log(`Reload the ${this.name} application configuration`);
async reload(options: AppLoadOptions = {}) {
console.log(`app [${this.name}]: reload`);
const oldDb = this._db;
this.init();
await oldDb.close();
await this.loadLifeCycles({ ...options, reload: true });
// await this.load({ ...options, reload: true });
}
getPlugin<P extends Plugin>(name: string | typeof Plugin) {
@ -477,7 +463,7 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
}
await this.emitAsync('beforeStart', this, options);
await this.loadLifeCycles({ ...options, method: 'start' });
await this.load({ ...options, method: 'start' });
if (options?.listen?.port) {
const pmServer = await this.pm.listen();
@ -587,13 +573,28 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
}
async install(options: InstallOptions = {}) {
if (options?.clean || options?.sync?.force) {
console.log('Truncate database and reload app configuration');
await this.db.clean({ drop: true });
await this.reload({ method: 'install' });
} else {
// check if the database is empty, if not, throw an error
if (await this.isInstalled()) {
throw new Error(
'You have already installed the application, please use the `-f` method to reinstall the application.',
);
}
}
console.log(`app [${this.name}]: beforeInstall`);
await this.emitAsync('beforeInstall', this, options);
await this.loadLifeCycles({ ...options, method: 'install', force: !!options?.clean || options?.sync?.force });
await this.load({ ...options, method: 'install' });
await this.pm.doAllPluginsLifecycle('install', { ...options, method: 'install' });
await this.version.update();
console.log(`app [${this.name}]: afterInstall`);
await this.emitAsync('afterInstall', this, options);
}
@ -609,7 +610,7 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
});
await this.version.update();
await this.loadLifeCycles({ ...options, force, method: 'upgrade' });
await this.load({ ...options, force, method: 'upgrade' });
await this.db.migrator.up();
// TODO: 更新所有插件版本号

View File

@ -69,13 +69,16 @@ export class PluginManager {
this.app.use(pluginStatic);
this.initStaticPluginsPromise = this.initStaticPlugins(options.plugins);
this.app.on('beforeInstall', async (app, options) => {
await this.collection.sync();
});
this.app.on('beforeUpgrade', async (app, options) => {
await this.collection.sync();
});
this.app.on('beforeLoad', async (app, options) => {
if (options?.method && ['install', 'upgrade'].includes(options.method)) {
await this.collection.sync();
}
const exists = await this.app.db.collectionExistsInDb('applicationPlugins');
if (!exists) {
this.app.log.warn(`applicationPlugins collection not exists in ${this.app.name}`);
return;
@ -112,8 +115,10 @@ export class PluginManager {
const pluginsWithOptions: [typeof Plugin, any][] = plugins.map((item) => (Array.isArray(item) ? item : [item, {}]));
for await (const [PluginClass, options] of pluginsWithOptions) {
console.log(`static plugin [${PluginClass.name}]: init`);
const pluginInstance = this.setPluginInstance(PluginClass, options);
console.log(`database plugin [${PluginClass.name}]: afterAdd`);
await this.app.emitAsync('beforeAddPlugin', pluginInstance, options);
await pluginInstance.afterAdd();
await this.app.emitAsync('beforeAddPlugin', pluginInstance, options);
@ -125,8 +130,10 @@ export class PluginManager {
for await (const pluginData of pluginList) {
await checkPluginPackage(pluginData);
console.log(`database plugin [${pluginData.name}]: init`);
const pluginInstance = await this.setDatabasePlugin(pluginData);
console.log(`database plugin [${pluginData.name}]: afterAdd`);
await this.app.emitAsync('beforeAddPlugin', pluginInstance, pluginData);
await pluginInstance.afterAdd();
await this.app.emitAsync('beforeAddPlugin', pluginInstance, pluginData);
@ -205,6 +212,7 @@ export class PluginManager {
if (this.plugins.has(name)) {
throw new Error(`plugin name [${name}] already exists`);
}
console.log(`plugin [${name}]: add`);
// 1. emit event: beforeAddPlugin
await this.app.emitAsync('beforeAddPlugin', name, data);
@ -253,6 +261,7 @@ export class PluginManager {
if (this.plugins.has(name)) {
throw new Error(`plugin [${name}] already exists`);
}
console.log(`plugin [${name}]: add`);
// 1. run `beforeAddPlugin` hook
await this.app.emitAsync('beforeAddPlugin', name, data);
@ -304,6 +313,7 @@ export class PluginManager {
}
async enable(name: string) {
console.log(`plugin [${name}]: enable`);
const pluginInstance = this.getPluginInstance(name);
const pluginData = await this.getPluginData(name);
@ -330,7 +340,7 @@ export class PluginManager {
},
});
// 3. run app action: `reload`
// 3. run app: `reload`
await this.app.reload({ reload: true });
// 4. sync database
@ -483,11 +493,13 @@ export class PluginManager {
}
async doAllPluginsLifecycle(lifecycle: string, options?: any) {
console.log('Do all plugins lifecycle: ', lifecycle);
for await (const pluginInstance of this.plugins.values()) {
await pluginInstance[lifecycle](options);
if (lifecycle === 'install') {
await this.app.db.sync();
if (pluginInstance.enabled) {
console.log(`plugin [${pluginInstance.name}]: ${lifecycle}`);
await pluginInstance[lifecycle](options);
if (lifecycle === 'install') {
await this.app.db.sync();
}
}
}
}

View File

@ -25,7 +25,7 @@ export interface PluginOptions {
export type PluginType = typeof Plugin;
export class Plugin implements PluginInterface {
export class Plugin<O = any> implements PluginInterface {
options: PluginOptions;
app: Application;

View File

@ -51,7 +51,7 @@ export class PresetNocoBase extends Plugin {
for await (const plugin of this.customPlugins) {
await this.app.pm.add(plugin, { enabled: false, installed: true, builtIn: false, isOfficial: true });
}
await this.app.reload({ method: options.method });
// await this.app.reload({ method: options.method });
}
async afterAdd() {