core: loader: support profile

This commit is contained in:
undefined committed 2024-06-07 06:08:43 +08:00
1 parent 1c8a6ee9ab
commit 8f0476e7cb
9 files changed
+73 -68

No files matched your search

+2 -1
View File
@@ -1,4 +1,5 @@
移除了 app/listen, app/load/${category} 钩子
移除了 ctx.app (请使用 ctx.root)
移除了 ctx.options (请使用 ctx.root.config)
serializer: 移除 showDisplayName 参数
serializer: 移除 showDisplayName 参数
移除了 loader.addScript, loader.addon 函数
+2 -11
View File
@@ -1,21 +1,11 @@
/* eslint-disable import/no-dynamic-require */
import os from 'os';
import path from 'path';
import cac from 'cac';
import fs from 'fs-extra';
import { getAddons } from '../src/options';
const argv = cac().parse();
const hydroPath = path.resolve(os.homedir(), '.hydro');
fs.ensureDirSync(hydroPath);
const addonPath = path.resolve(hydroPath, 'addon.json');
if (!fs.existsSync(addonPath)) fs.writeFileSync(addonPath, '[]');
let addons = JSON.parse(fs.readFileSync(addonPath).toString());
addons = Array.from(new Set(addons));
if (!argv.args[0] || argv.args[0] === 'cli') {
const hydro = require('../src/loader');
for (const addon of addons) hydro.addon(addon);
(argv.args[0] === 'cli' ? hydro.loadCli : hydro.load)().catch((e) => {
console.error(e);
process.exit(1);
@@ -29,6 +19,7 @@ if (!argv.args[0] || argv.args[0] === 'cli') {
cli.help();
cli.parse();
if (!cli.matchedCommand) {
const addons = getAddons();
for (const i of addons) {
try {
require(`${i}/command.ts`).apply(cli);
+3 -3
View File
@@ -4,9 +4,9 @@ import path from 'path';
import { CAC } from 'cac';
import fs from 'fs-extra';
import { Logger } from '@hydrooj/utils';
import { getAddons, writeAddons } from '../options';
const logger = new Logger('addon');
const addonPath = path.resolve(os.homedir(), '.hydro', 'addon.json');
const addonDir = path.resolve(os.homedir(), '.hydro', 'addons');
export function register(cli: CAC) {
@@ -15,7 +15,7 @@ export function register(cli: CAC) {
console.log('Unknown operation.');
return;
}
let addons = JSON.parse(fs.readFileSync(addonPath).toString());
let addons = getAddons();
if (operation === 'create') {
const dir = `${addonDir}/${name || 'addon'}`;
fs.mkdirSync(dir, { recursive: true });
@@ -48,6 +48,6 @@ export function register(cli: CAC) {
addons = Array.from(new Set(addons));
logger.info('Current Addons: ');
console.log(addons);
fs.writeFileSync(addonPath, JSON.stringify(addons, null, 2));
writeAddons(addons);
});
}
+7 -2
View File
@@ -1,5 +1,6 @@
/* eslint-disable import/no-dynamic-require */
/* eslint-disable no-await-in-loop */
import os from 'os';
import path from 'path';
import cac from 'cac';
import fs from 'fs-extra';
@@ -11,6 +12,7 @@ import {
} from './common';
const argv = cac().parse();
const tmpdir = path.resolve(os.tmpdir(), 'hydro');
const COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
const ARR = /=>.*$/mg;
function parseParameters(fn: Function) {
@@ -92,16 +94,19 @@ async function cli() {
}
export async function load(ctx: Context) {
const pending = global.addons;
const fail = [];
fs.ensureDirSync(tmpdir);
require('../lib/i18n');
require('../utils');
require('../error');
require('../service/bus').apply(ctx);
const pending = global.addons;
const fail = [];
await db.start();
await require('../settings').loadConfig();
await require('../model/system').runConfig();
await require('../service/storage').loadStorageService();
await ctx.root.start();
await ctx.lifecycle.flush();
require('../lib/index');
await Promise.all([
lib(pending, fail, ctx),
+2 -1
View File
@@ -6,6 +6,7 @@ import cac from 'cac';
import fs from 'fs-extra';
import { Context } from '../context';
import { Logger } from '../logger';
import { load } from '../options';
import db from '../service/db';
import {
addon, builtinModel, handler, lib, locale, model,
@@ -22,7 +23,7 @@ export async function apply(ctx: Context) {
require('../utils');
require('../error');
require('../service/bus').apply(ctx);
const config = require('../options')();
const config = load();
if (!process.env.CI && !config) {
logger.info('Starting setup');
await require('./setup').load();
+22 -33
View File
@@ -5,7 +5,6 @@
/* eslint-disable no-eval */
import './init';
import './interface';
import Schema from 'schemastery';
import path from 'path';
import child from 'child_process';
// eslint-disable-next-line import/no-duplicates
@@ -19,6 +18,7 @@ import { Context } from './context';
// eslint-disable-next-line import/no-duplicates
import { sleep, unwrapExports } from './utils';
import { PRIV } from './model/builtin';
import { getAddons } from './options';
const argv = cac().parse();
const logger = new Logger('loader');
@@ -135,45 +135,33 @@ export class Loader {
}
}
export function addon(addonPath: string, prepend = false) {
try {
// Is a npm package
const packagejson = require.resolve(`${addonPath}/package.json`);
// eslint-disable-next-line import/no-dynamic-require
const payload = require(packagejson);
const name = payload.name.startsWith('@hydrooj/') ? payload.name.split('@hydrooj/')[1] : payload.name;
global.Hydro.version[name] = payload.version;
const modulePath = path.dirname(packagejson);
global.addons[prepend ? 'unshift' : 'push'](modulePath);
} catch (e) {
logger.error(`Addon not found: ${addonPath}`);
logger.error(e);
app.injectUI('Notification', 'Addon not found: {0}', { args: [addonPath], type: 'warn' }, PRIV.PRIV_VIEW_SYSTEM_NOTIFICATION);
}
}
/** @deprecated */
export function addScript(name: string, description: string) {
if (global.Hydro.script[name]) throw new Error(`duplicate script ${name} registered.`);
return {
args: <K extends Schema>(validate: K) => ({
action: (run: (args: ReturnType<K>, report: any) => boolean | Promise<boolean>) => {
global.Hydro.script[name] = {
description, validate, run,
};
},
}),
};
}
const loader = new Loader();
app.provide('loader');
app.loader = loader;
loader.app = app;
app.state[Loader.Record] = Object.create(null);
function preload() {
for (const a of [path.resolve(__dirname, '..'), ...getAddons()]) {
try {
// Is a npm package
const packagejson = require.resolve(`${a}/package.json`);
// eslint-disable-next-line import/no-dynamic-require
const payload = require(packagejson);
const name = payload.name.startsWith('@hydrooj/') ? payload.name.split('@hydrooj/')[1] : payload.name;
global.Hydro.version[name] = payload.version;
const modulePath = path.dirname(packagejson);
global.addons.push(modulePath);
} catch (e) {
logger.error(`Addon not found: ${a}`);
logger.error(e);
app.injectUI('Notification', 'Addon not found: {0}', { args: [a], type: 'warn' }, PRIV.PRIV_VIEW_SYSTEM_NOTIFICATION);
}
}
}
export async function load() {
addon(path.resolve(__dirname, '..'), true);
preload();
Error.stackTraceLimit = 50;
try {
const { simpleGit } = require('simple-git') as typeof import('simple-git');
@@ -212,6 +200,7 @@ export async function load() {
export async function loadCli() {
process.env.HYDRO_CLI = 'true';
preload();
await require('./entry/cli').load(app);
setTimeout(() => process.exit(0), 300);
}
+32 -14
View File
@@ -1,28 +1,46 @@
import os from 'os';
import path from 'path';
import { existsSync, readFileSync } from 'fs-extra';
import { findFileSync } from '@hydrooj/utils/lib/utils';
import { Logger } from './logger';
import fs from 'fs-extra';
import { findFileSync, Logger } from '@hydrooj/utils/lib/utils';
const logger = new Logger('options');
export = function load() {
const envFile = path.resolve(os.homedir(), '.hydro', 'env');
if (existsSync(envFile)) {
const content = readFileSync(envFile).toString().replace(/\r/g, '');
for (const line of content.split('\n')) {
if (!line.includes('=')) continue;
process.env[line.split('=')[0]] = line.split('=')[1].trim();
}
function loadEnvFile(file: string) {
const content = fs.readFileSync(file).toString().replace(/\r/g, '');
for (const line of content.split('\n')) {
if (!line.includes('=')) continue;
process.env[line.split('=')[0]] = line.split('=')[1].trim();
}
const f = findFileSync('config.json', false);
}
const profile = process.env.HYDRO_PROFILE;
export const hydroPath = profile ? path.resolve(os.homedir(), '.hydro', 'profiles', profile) : path.resolve(os.homedir(), '.hydro');
if (profile && !fs.existsSync(hydroPath)) {
logger.error('Profile %s not found', profile);
process.exit(1);
} else fs.ensureDirSync(hydroPath);
const addonPath = path.resolve(hydroPath, 'addon.json');
export function load() {
const envFile = path.resolve(hydroPath, 'env');
if (fs.existsSync(envFile)) loadEnvFile(envFile);
const f = profile ? path.resolve(hydroPath, 'config.json') : findFileSync('config.json', false);
if (!f) return null;
let result: any = {};
try {
result = JSON.parse(readFileSync(f, 'utf-8'));
result = JSON.parse(fs.readFileSync(f, 'utf-8'));
} catch (e) {
logger.error('Cannot read config file %o', e);
result = {};
}
return result;
};
}
export function getAddons() {
if (!fs.existsSync(addonPath)) fs.writeFileSync(addonPath, '[]');
return JSON.parse(fs.readFileSync(addonPath).toString());
}
export function writeAddons(addons: string[]) {
fs.writeFileSync(addonPath, JSON.stringify(addons, null, 2));
}
+2 -2
View File
@@ -5,7 +5,7 @@ import {
import mongoUri from 'mongodb-uri';
import { Time } from '@hydrooj/utils';
import { Logger } from '../logger';
import options from '../options';
import { load } from '../options';
import * as bus from './bus';
const logger = new Logger('mongo');
@@ -37,7 +37,7 @@ class MongoService {
}
async start() {
const opts = options() || {};
const opts = load() || {};
let mongourl = MongoService.buildUrl(opts);
const url = mongoUri.parse(mongourl);
if (process.env.CI) {
+1 -1
View File
@@ -127,7 +127,6 @@ export class ConnectionHandler extends ConnectionHandlerOriginal {
}
export async function apply(ctx: Context) {
if (process.env.HYDRO_CLI) return;
ctx.plugin(require('@hydrooj/framework'), {
keys: system.get('session.keys'),
proxy: !!system.get('server.xproxy') || !!system.get('server.xff'),
@@ -137,6 +136,7 @@ export async function apply(ctx: Context) {
xff: system.get('server.xff'),
xhost: system.get('server.xhost'),
});
if (process.env.HYDRO_CLI) return;
ctx.inject(['server'], ({ server, on }) => {
const proxyMiddleware = proxy('/fs', {
target: builtinConfig.file.endPoint,