mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 09:46:28 +08:00
core: use cordis to manage app lifecycle
This commit is contained in:
1 parent
d7ec26b772
commit
5b7067d77d
19 files changed
+307
-375
No files matched your search
@@ -1,3 +1,5 @@
|
||||
/* eslint-disable import/no-dynamic-require */
|
||||
/* eslint-disable consistent-return */
|
||||
/* eslint-disable simple-import-sort/imports */
|
||||
/* eslint-disable no-await-in-loop */
|
||||
/* eslint-disable no-eval */
|
||||
@@ -5,15 +7,18 @@ import './init';
|
||||
import './interface';
|
||||
import Schema from 'schemastery';
|
||||
import path from 'path';
|
||||
// eslint-disable-next-line import/no-duplicates
|
||||
import './utils';
|
||||
import cac from 'cac';
|
||||
import { Logger } from './logger';
|
||||
import './ui';
|
||||
|
||||
import { Logger } from './logger';
|
||||
import { ApiMixin, Context } from './context';
|
||||
// eslint-disable-next-line import/no-duplicates
|
||||
import { unwrapExports } from './utils';
|
||||
// This is the main entry. So let's re-export some modules.
|
||||
export * from './interface';
|
||||
export { Schema, Logger };
|
||||
export { requestConfig } from './settings';
|
||||
|
||||
const argv = cac().parse();
|
||||
const logger = new Logger('loader');
|
||||
@@ -22,6 +27,66 @@ logger.debug('%o', argv);
|
||||
process.on('unhandledRejection', logger.error);
|
||||
process.on('uncaughtException', logger.error);
|
||||
|
||||
export function resolveConfig(plugin: any, config: any) {
|
||||
if (config === false) return;
|
||||
if (config === true) config = undefined;
|
||||
config ??= {};
|
||||
const schema = plugin['Config'] || plugin['schema'];
|
||||
if (schema && plugin['schema'] !== false) config = schema(config);
|
||||
return config;
|
||||
}
|
||||
Context.service('loader');
|
||||
|
||||
export class Loader {
|
||||
static readonly kUpdate = Symbol.for('koishi.loader.update');
|
||||
static readonly kRecord = Symbol.for('koishi.loader.record');
|
||||
|
||||
public app: Context;
|
||||
public config: Context.Config;
|
||||
public suspend = false;
|
||||
public cache: Record<string, string> = Object.create(null);
|
||||
|
||||
unloadPlugin(ctx: Context, key: string) {
|
||||
const fork = ctx.state[Loader.kRecord][key];
|
||||
if (fork) {
|
||||
fork.dispose();
|
||||
delete ctx.state[Loader.kRecord][key];
|
||||
logger.info('unload plugin %c', key);
|
||||
}
|
||||
}
|
||||
|
||||
async reloadPlugin(parent: Context, key: string, config: any, asName = '') {
|
||||
let fork = parent.state[Loader.kRecord]?.[key];
|
||||
if (fork) {
|
||||
logger.info('reload plugin %c', key);
|
||||
fork[Loader.kUpdate] = true;
|
||||
fork.update(config);
|
||||
} else {
|
||||
logger.info('apply plugin %c', key);
|
||||
const plugin = await this.resolvePlugin(key);
|
||||
if (!plugin) return;
|
||||
resolveConfig(plugin, config);
|
||||
if (asName) plugin.name = asName;
|
||||
// fork = parent.plugin(plugin, this.interpolate(config));
|
||||
fork = parent.plugin(plugin, config);
|
||||
if (!fork) return;
|
||||
parent.state[Loader.kRecord] ||= Object.create(null);
|
||||
parent.state[Loader.kRecord][key] = fork;
|
||||
}
|
||||
return fork;
|
||||
}
|
||||
|
||||
async resolvePlugin(name: string) {
|
||||
try {
|
||||
this.cache[name] ||= require.resolve(name);
|
||||
} catch (err) {
|
||||
logger.error(err.message);
|
||||
return;
|
||||
}
|
||||
return unwrapExports(require(this.cache[name]));
|
||||
}
|
||||
}
|
||||
|
||||
export function addon(addonPath: string, prepend = false) {
|
||||
try {
|
||||
// Is a npm package
|
||||
@@ -52,15 +117,22 @@ export function addScript(name: string, description: string) {
|
||||
};
|
||||
}
|
||||
|
||||
Context.service('loader');
|
||||
app.api = new ApiMixin(app);
|
||||
const loader = new Loader();
|
||||
app.loader = loader;
|
||||
loader.app = app;
|
||||
app.state[Loader.kRecord] = Object.create(null);
|
||||
|
||||
export async function load() {
|
||||
addon(path.resolve(__dirname, '..'), true);
|
||||
Error.stackTraceLimit = 50;
|
||||
require('./entry/worker').load();
|
||||
await require('./entry/worker').apply(app);
|
||||
global.gc?.();
|
||||
}
|
||||
|
||||
export async function loadCli() {
|
||||
process.env.HYDRO_CLI = 'true';
|
||||
await require('./entry/cli').load();
|
||||
await require('./entry/cli').load(app);
|
||||
setTimeout(() => process.exit(0), 300);
|
||||
}
|
||||
Reference in new issue
Block a user