mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
core: 优化钩子逻辑
This commit is contained in:
1 parent
03dc8903e2
commit
f2f0212947
27 files changed
+205
-124
No files matched your search
@@ -29,6 +29,7 @@ module.exports = {
|
|||||||
'max-len': ['warn', 150],
|
'max-len': ['warn', 150],
|
||||||
'no-bitwise': 'off',
|
'no-bitwise': 'off',
|
||||||
'no-console': 'off',
|
'no-console': 'off',
|
||||||
|
'no-continue': 'off',
|
||||||
'no-dupe-class-members': 'off',
|
'no-dupe-class-members': 'off',
|
||||||
'no-extend-native': 'off',
|
'no-extend-native': 'off',
|
||||||
'no-inner-declarations': 'off',
|
'no-inner-declarations': 'off',
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ SETTINGS_PRIVACY.allowRegisteredUsers
|
|||||||
model.setting.ui.name
|
model.setting.ui.name
|
||||||
pdoc.secretConfig?
|
pdoc.secretConfig?
|
||||||
message.markAsRead
|
message.markAsRead
|
||||||
基于document的model难以lint,建议拆分
|
基于document的model难以lint,建议拆分
|
||||||
|
检查多余的索引
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "2.13.0",
|
"version": "2.13.1",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "dist/loader.js",
|
"main": "dist/loader.js",
|
||||||
"typings": "dist/loader.d.ts",
|
"typings": "dist/loader.d.ts",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
lib, service, model,
|
lib, service, model,
|
||||||
builtinLib, builtinModel,
|
builtinLib, builtinModel,
|
||||||
} from './common';
|
} from './common';
|
||||||
|
import * as bus from '../service/bus';
|
||||||
|
|
||||||
const COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
|
const COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
|
||||||
const ARR = /=>.*$/mg;
|
const ARR = /=>.*$/mg;
|
||||||
@@ -51,13 +52,8 @@ export async function load() {
|
|||||||
require('../utils');
|
require('../utils');
|
||||||
require('../error');
|
require('../error');
|
||||||
require('../options');
|
require('../options');
|
||||||
const bus = require('../service/bus');
|
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
const h = () => {
|
bus.once('database/connect', resolve);
|
||||||
bus.unsubscribe(['system_database_connected'], h);
|
|
||||||
resolve();
|
|
||||||
};
|
|
||||||
bus.subscribe(['system_database_connected'], h);
|
|
||||||
require('../service/db');
|
require('../service/db');
|
||||||
});
|
});
|
||||||
for (const i of builtinLib) require(`../lib/${i}`);
|
for (const i of builtinLib) require(`../lib/${i}`);
|
||||||
@@ -66,6 +62,6 @@ export async function load() {
|
|||||||
await service(pending, fail);
|
await service(pending, fail);
|
||||||
for (const i of builtinModel) require(`../model/${i}`);
|
for (const i of builtinModel) require(`../model/${i}`);
|
||||||
await model(pending, fail);
|
await model(pending, fail);
|
||||||
for (const postInit of global.Hydro.postInit) await postInit();
|
await bus.parallel('app/started');
|
||||||
await cli();
|
await cli();
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ import pslist from 'ps-list';
|
|||||||
import { argv } from 'yargs';
|
import { argv } from 'yargs';
|
||||||
import { builtinModel } from './common';
|
import { builtinModel } from './common';
|
||||||
import { Entry } from '../loader';
|
import { Entry } from '../loader';
|
||||||
|
import * as bus from '../service/bus';
|
||||||
|
|
||||||
const tmpdir = path.resolve(os.tmpdir(), 'hydro');
|
const tmpdir = path.resolve(os.tmpdir(), 'hydro');
|
||||||
const lockfile = path.resolve(tmpdir, 'lock.json');
|
const lockfile = path.resolve(tmpdir, 'lock.json');
|
||||||
@@ -31,9 +32,6 @@ export async function load(call: Entry) {
|
|||||||
ppid: process.ppid,
|
ppid: process.ppid,
|
||||||
};
|
};
|
||||||
await fs.writeFile(lockfile, JSON.stringify(context));
|
await fs.writeFile(lockfile, JSON.stringify(context));
|
||||||
global.onDestory.push(() => {
|
|
||||||
fs.removeSync(lockfile);
|
|
||||||
});
|
|
||||||
require('../lib/i18n');
|
require('../lib/i18n');
|
||||||
require('../utils');
|
require('../utils');
|
||||||
require('../error');
|
require('../error');
|
||||||
@@ -45,14 +43,15 @@ export async function load(call: Entry) {
|
|||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const bus = require('../service/bus');
|
bus.once('app/exit', () => {
|
||||||
|
fs.removeSync(lockfile);
|
||||||
|
});
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
const h = () => {
|
const h = () => {
|
||||||
console.log('Database connected');
|
console.log('Database connected');
|
||||||
bus.unsubscribe(['system_database_connected'], h);
|
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
bus.subscribe(['system_database_connected'], h);
|
bus.once('database/connect', h);
|
||||||
require('../service/db');
|
require('../service/db');
|
||||||
});
|
});
|
||||||
require('../service/monitor');
|
require('../service/monitor');
|
||||||
@@ -63,11 +62,6 @@ export async function load(call: Entry) {
|
|||||||
const ins = require('../script/upgrade0_1');
|
const ins = require('../script/upgrade0_1');
|
||||||
await ins.run({ username: 'Root', password: 'rootroot' });
|
await ins.run({ username: 'Root', password: 'rootroot' });
|
||||||
}
|
}
|
||||||
for (const postInit of global.Hydro.postInit) {
|
bus.serial('app/started');
|
||||||
await postInit().catch((e) => {
|
|
||||||
console.error('Error running postInit:', postInit.toString());
|
|
||||||
console.error(e);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return await modelSystem.get('server.worker');
|
return await modelSystem.get('server.worker');
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,7 @@ import {
|
|||||||
locale, template, lib, service, model, handler, script, setting, uistatic,
|
locale, template, lib, service, model, handler, script, setting, uistatic,
|
||||||
builtinLib, builtinScript, builtinHandler, builtinModel,
|
builtinLib, builtinScript, builtinHandler, builtinModel,
|
||||||
} from './common';
|
} from './common';
|
||||||
|
import * as bus from '../service/bus';
|
||||||
|
|
||||||
export async function load() {
|
export async function load() {
|
||||||
const pending = global.addons;
|
const pending = global.addons;
|
||||||
@@ -18,14 +19,12 @@ export async function load() {
|
|||||||
template(pending, fail),
|
template(pending, fail),
|
||||||
uistatic(pending, fail),
|
uistatic(pending, fail),
|
||||||
]);
|
]);
|
||||||
const bus = require('../service/bus');
|
|
||||||
await new Promise((resolve) => {
|
await new Promise((resolve) => {
|
||||||
const h = () => {
|
const h = () => {
|
||||||
console.log('Database connected');
|
console.log('Database connected');
|
||||||
bus.unsubscribe(['system_database_connected'], h);
|
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
bus.subscribe(['system_database_connected'], h);
|
bus.once('database/connect', h);
|
||||||
require('../service/db');
|
require('../service/db');
|
||||||
});
|
});
|
||||||
for (const i of builtinLib) require(`../lib/${i}`);
|
for (const i of builtinLib) require(`../lib/${i}`);
|
||||||
@@ -48,7 +47,7 @@ export async function load() {
|
|||||||
await notfound.apply();
|
await notfound.apply();
|
||||||
for (const i of builtinScript) require(`../script/${i}`);
|
for (const i of builtinScript) require(`../script/${i}`);
|
||||||
await script(pending, fail, active);
|
await script(pending, fail, active);
|
||||||
for (const postInit of global.Hydro.postInit) await postInit();
|
await bus.serial('app/started');
|
||||||
await server.start();
|
await server.start();
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
process.send({ event: 'stat', count: global.Hydro.stat.reqCount });
|
process.send({ event: 'stat', count: global.Hydro.stat.reqCount });
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ class ContestProblemSubmitHandler extends ContestProblemHandler {
|
|||||||
record.get(domainId, rid),
|
record.get(domainId, rid),
|
||||||
contest.updateStatus(domainId, this.tdoc.docId, this.user._id, rid, this.pdoc.docId),
|
contest.updateStatus(domainId, this.tdoc.docId, this.user._id, rid, this.pdoc.docId),
|
||||||
]);
|
]);
|
||||||
bus.publish('record_change', rdoc);
|
bus.boardcast('record/change', rdoc);
|
||||||
if (!this.canShowRecord(this.tdoc)) {
|
if (!this.canShowRecord(this.tdoc)) {
|
||||||
this.response.body = { tid };
|
this.response.body = { tid };
|
||||||
this.response.redirect = this.url('contest_detail', { tid });
|
this.response.redirect = this.url('contest_detail', { tid });
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import { PERM, PRIV, CONSTANT } from '../model/builtin';
|
|||||||
import {
|
import {
|
||||||
isContent, isPassword, isEmail, isTitle,
|
isContent, isPassword, isEmail, isTitle,
|
||||||
} from '../lib/validator';
|
} from '../lib/validator';
|
||||||
|
import { Mdoc } from '../interface';
|
||||||
|
|
||||||
const { geoip, useragent } = global.Hydro.lib;
|
const { geoip, useragent } = global.Hydro.lib;
|
||||||
|
|
||||||
@@ -358,18 +359,19 @@ class HomeMessagesHandler extends Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class HomeMessagesConnectionHandler extends ConnectionHandler {
|
class HomeMessagesConnectionHandler extends ConnectionHandler {
|
||||||
id: string;
|
dispose: bus.Disposable;
|
||||||
|
|
||||||
async prepare() {
|
async prepare() {
|
||||||
bus.subscribe([`user_message-${this.user._id}`], this.onMessageReceived.bind(this));
|
this.dispose = bus.on('user/message', this.onMessageReceived.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
async onMessageReceived(e: any) {
|
async onMessageReceived(uid: number, e: any) {
|
||||||
this.send(e.value);
|
if (uid !== this.user._id) return;
|
||||||
|
this.send(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
async cleanup() {
|
async cleanup() {
|
||||||
bus.unsubscribe([`user_message-${this.user._id}`], this.id);
|
if (this.dispose) this.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ class HomeworkDetailProblemSubmitHandler extends HomeworkDetailProblemHandler {
|
|||||||
contest.updateStatus(domainId, tid, this.user._id,
|
contest.updateStatus(domainId, tid, this.user._id,
|
||||||
rid, pid, false, 0, document.TYPE_HOMEWORK),
|
rid, pid, false, 0, document.TYPE_HOMEWORK),
|
||||||
]);
|
]);
|
||||||
bus.publish('record_change', rdoc);
|
bus.boardcast('record/change', rdoc);
|
||||||
this.response.body = { tid, rid };
|
this.response.body = { tid, rid };
|
||||||
if (this.canShowRecord(this.tdoc)) this.response.redirect = this.url('record_detail', { rid });
|
if (this.canShowRecord(this.tdoc)) this.response.redirect = this.url('record_detail', { rid });
|
||||||
else this.response.redirect = this.url('homework_detail', { tid });
|
else this.response.redirect = this.url('homework_detail', { tid });
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ export async function next(body: JudgeResultBody) {
|
|||||||
if (body.memory) $set.memory = body.memory;
|
if (body.memory) $set.memory = body.memory;
|
||||||
if (body.progress) $set.progress = body.progress;
|
if (body.progress) $set.progress = body.progress;
|
||||||
rdoc = await record.update(body.domainId, body.rid, $set, $push);
|
rdoc = await record.update(body.domainId, body.rid, $set, $push);
|
||||||
bus.publish('record_change', { rdoc, $set, $push });
|
bus.boardcast('record/change', rdoc, $set, $push);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function end(body: JudgeResultBody) {
|
export async function end(body: JudgeResultBody) {
|
||||||
@@ -87,7 +87,7 @@ export async function end(body: JudgeResultBody) {
|
|||||||
$set.judger = body.judger;
|
$set.judger = body.judger;
|
||||||
rdoc = await record.update(body.domainId, body.rid, $set, $push, $unset);
|
rdoc = await record.update(body.domainId, body.rid, $set, $push, $unset);
|
||||||
await _postJudge(rdoc);
|
await _postJudge(rdoc);
|
||||||
bus.publish('record_change', { rdoc }); // trigger a full update
|
bus.boardcast('record/change', rdoc); // trigger a full update
|
||||||
}
|
}
|
||||||
|
|
||||||
class JudgeHandler extends Handler {
|
class JudgeHandler extends Handler {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { isSafeInteger, flatten } from 'lodash';
|
import { isSafeInteger, flatten } from 'lodash';
|
||||||
import yaml from 'js-yaml';
|
import yaml from 'js-yaml';
|
||||||
import { ObjectID } from 'mongodb';
|
import { FilterQuery, ObjectID } from 'mongodb';
|
||||||
import {
|
import {
|
||||||
NoProblemError, ProblemDataNotFoundError, BadRequestError,
|
NoProblemError, ProblemDataNotFoundError, BadRequestError,
|
||||||
SolutionNotFoundError, ProblemNotFoundError, ValidationError,
|
SolutionNotFoundError, ProblemNotFoundError, ValidationError,
|
||||||
@@ -61,16 +61,14 @@ class ProblemMainHandler extends ProblemHandler {
|
|||||||
@param('q', Types.String, true)
|
@param('q', Types.String, true)
|
||||||
async get(domainId: string, page = 1, q = '') {
|
async get(domainId: string, page = 1, q = '') {
|
||||||
this.response.template = 'problem_main.html';
|
this.response.template = 'problem_main.html';
|
||||||
const query: any = {};
|
const query: FilterQuery<Pdoc> = {};
|
||||||
let psdict = {};
|
let psdict = {};
|
||||||
const path: PathComponent[] = [
|
const path: PathComponent[] = [
|
||||||
['Hydro', 'homepage'],
|
['Hydro', 'homepage'],
|
||||||
['problem_main', null],
|
['problem_main', null],
|
||||||
];
|
];
|
||||||
if (q) {
|
if (q) {
|
||||||
q = q.toLowerCase();
|
query.$text = { $search: q };
|
||||||
const $regex = new RegExp(`\\A\\Q${q}\\E`, 'gmi');
|
|
||||||
query.title = { $regex };
|
|
||||||
path.push([q, null, null, true]);
|
path.push([q, null, null, true]);
|
||||||
}
|
}
|
||||||
if (!this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)) query.hidden = false;
|
if (!this.user.hasPerm(PERM.PERM_VIEW_PROBLEM_HIDDEN)) query.hidden = false;
|
||||||
@@ -252,7 +250,7 @@ class ProblemSubmitHandler extends ProblemDetailHandler {
|
|||||||
record.get(domainId, rid),
|
record.get(domainId, rid),
|
||||||
domain.incUserInDomain(domainId, this.user._id, 'nSubmit'),
|
domain.incUserInDomain(domainId, this.user._id, 'nSubmit'),
|
||||||
]);
|
]);
|
||||||
bus.publish('record_change', { rdoc });
|
bus.boardcast('record/change', rdoc);
|
||||||
this.response.body = { rid };
|
this.response.body = { rid };
|
||||||
this.response.redirect = this.url('record_detail', { rid });
|
this.response.redirect = this.url('record_detail', { rid });
|
||||||
}
|
}
|
||||||
@@ -275,7 +273,7 @@ class ProblemPretestHandler extends ProblemDetailHandler {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
const rdoc = await record.get(domainId, rid);
|
const rdoc = await record.get(domainId, rid);
|
||||||
bus.publish('record_change', { rdoc });
|
bus.boardcast('record/change', rdoc);
|
||||||
this.response.body = { rid };
|
this.response.body = { rid };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -285,7 +283,7 @@ class ProblemPretestConnectionHandler extends ConnectionHandler {
|
|||||||
|
|
||||||
domainId: string;
|
domainId: string;
|
||||||
|
|
||||||
id: string;
|
dispose: bus.Disposable;
|
||||||
|
|
||||||
@param('pid', Types.String)
|
@param('pid', Types.String)
|
||||||
async prepare(domainId: string, pid: string) {
|
async prepare(domainId: string, pid: string) {
|
||||||
@@ -294,11 +292,10 @@ class ProblemPretestConnectionHandler extends ConnectionHandler {
|
|||||||
if (!pdoc) throw new ProblemNotFoundError(domainId, pid);
|
if (!pdoc) throw new ProblemNotFoundError(domainId, pid);
|
||||||
this.pid = pdoc.docId.toString();
|
this.pid = pdoc.docId.toString();
|
||||||
this.domainId = domainId;
|
this.domainId = domainId;
|
||||||
this.id = bus.subscribe(['record_change'], this.onRecordChange.bind(this));
|
this.dispose = bus.on('record/change', this.onRecordChange.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
async onRecordChange(data) {
|
async onRecordChange(rdoc: Rdoc) {
|
||||||
const rdoc: Rdoc = data.value.rdoc;
|
|
||||||
if (
|
if (
|
||||||
rdoc.uid !== this.user._id
|
rdoc.uid !== this.user._id
|
||||||
|| rdoc.pid.toString() !== this.pid
|
|| rdoc.pid.toString() !== this.pid
|
||||||
@@ -316,7 +313,7 @@ class ProblemPretestConnectionHandler extends ConnectionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async cleanup() {
|
async cleanup() {
|
||||||
bus.unsubscribe(['record_change'], this.id);
|
if (this.dispose) this.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,8 @@ class RecordRejudgeHandler extends Handler {
|
|||||||
const RecordConnectionHandler = contest.ContestHandlerMixin(ConnectionHandler);
|
const RecordConnectionHandler = contest.ContestHandlerMixin(ConnectionHandler);
|
||||||
|
|
||||||
class RecordMainConnectionHandler extends RecordConnectionHandler {
|
class RecordMainConnectionHandler extends RecordConnectionHandler {
|
||||||
|
dispose: bus.Disposable;
|
||||||
|
|
||||||
@param('tid', Types.ObjectID, true)
|
@param('tid', Types.ObjectID, true)
|
||||||
async prepare(domainId: string, tid: ObjectID) {
|
async prepare(domainId: string, tid: ObjectID) {
|
||||||
this.domainId = domainId;
|
this.domainId = domainId;
|
||||||
@@ -113,7 +115,7 @@ class RecordMainConnectionHandler extends RecordConnectionHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.id = bus.subscribe(['record_change'], this.onRecordChange.bind(this));
|
this.dispose = bus.on('record/change', this.onRecordChange.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
async message(msg) {
|
async message(msg) {
|
||||||
@@ -123,17 +125,16 @@ class RecordMainConnectionHandler extends RecordConnectionHandler {
|
|||||||
this.domainId, { _id: { $in: rids } },
|
this.domainId, { _id: { $in: rids } },
|
||||||
).toArray();
|
).toArray();
|
||||||
for (const rdoc of rdocs) {
|
for (const rdoc of rdocs) {
|
||||||
this.onRecordChange({ value: { rdoc } });
|
this.onRecordChange(rdoc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async cleanup() {
|
async cleanup() {
|
||||||
bus.unsubscribe(['record_change'], this.id);
|
if (this.dispose) this.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
async onRecordChange(data) {
|
async onRecordChange(rdoc: Rdoc) {
|
||||||
const rdoc: Rdoc = data.value.rdoc;
|
|
||||||
if (rdoc.contest && rdoc.contest.tid.toString() !== this.tid) return;
|
if (rdoc.contest && rdoc.contest.tid.toString() !== this.tid) return;
|
||||||
// eslint-disable-next-line prefer-const
|
// eslint-disable-next-line prefer-const
|
||||||
let [udoc, pdoc] = await Promise.all([
|
let [udoc, pdoc] = await Promise.all([
|
||||||
@@ -146,6 +147,8 @@ class RecordMainConnectionHandler extends RecordConnectionHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class RecordDetailConnectionHandler extends contest.ContestHandlerMixin(ConnectionHandler) {
|
class RecordDetailConnectionHandler extends contest.ContestHandlerMixin(ConnectionHandler) {
|
||||||
|
dispose: bus.Disposable;
|
||||||
|
|
||||||
@param('rid', Types.ObjectID)
|
@param('rid', Types.ObjectID)
|
||||||
async prepare(domainId: string, rid: ObjectID) {
|
async prepare(domainId: string, rid: ObjectID) {
|
||||||
const rdoc = await record.get(domainId, rid);
|
const rdoc = await record.get(domainId, rid);
|
||||||
@@ -157,13 +160,11 @@ class RecordDetailConnectionHandler extends contest.ContestHandlerMixin(Connecti
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.rid = rid.toString();
|
this.rid = rid.toString();
|
||||||
this.id = bus.subscribe(['record_change'], this.onRecordChange.bind(this));
|
this.dispose = bus.on('record/change', this.onRecordChange.bind(this));
|
||||||
this.onRecordChange({ value: { rdoc } });
|
this.onRecordChange(rdoc);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onRecordChange(data) {
|
async onRecordChange(rdoc: Rdoc, $set?: any, $push?: any) {
|
||||||
const rdoc: Rdoc = data.value.rdoc;
|
|
||||||
const { $set, $push } = data.value;
|
|
||||||
if (rdoc._id.toString() !== this.rid) return;
|
if (rdoc._id.toString() !== this.rid) return;
|
||||||
if ($set) this.send({ $set, $push });
|
if ($set) this.send({ $set, $push });
|
||||||
else {
|
else {
|
||||||
@@ -175,7 +176,7 @@ class RecordDetailConnectionHandler extends contest.ContestHandlerMixin(Connecti
|
|||||||
}
|
}
|
||||||
|
|
||||||
async cleanup() {
|
async cleanup() {
|
||||||
bus.unsubscribe(['record_change'], this.id);
|
if (this.dispose) this.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -455,9 +455,7 @@ declare global {
|
|||||||
ui: UI,
|
ui: UI,
|
||||||
error: typeof import('./error'),
|
error: typeof import('./error'),
|
||||||
locales: Dict<Dict<string>>,
|
locales: Dict<Dict<string>>,
|
||||||
postInit: Array<() => Promise<any>>,
|
|
||||||
},
|
},
|
||||||
onDestory: Array<() => void | Promise<void>>,
|
|
||||||
addons: string[],
|
addons: string[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,9 +36,7 @@ if (!global.Hydro) {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
error: {},
|
error: {},
|
||||||
locales: {},
|
locales: {},
|
||||||
postInit: [],
|
|
||||||
};
|
};
|
||||||
global.onDestory = [];
|
|
||||||
global.addons = [];
|
global.addons = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,9 +45,12 @@ if (argv.debug) {
|
|||||||
console.log(argv);
|
console.log(argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/first
|
||||||
|
import * as bus from './service/bus';
|
||||||
|
|
||||||
async function terminate() {
|
async function terminate() {
|
||||||
try {
|
try {
|
||||||
for (const task of global.onDestory) await task();
|
await bus.parallel('app/exit');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
@@ -127,7 +128,7 @@ async function messageHandler(worker: cluster.Worker, msg: any) {
|
|||||||
cluster.workers[i].send(msg);
|
cluster.workers[i].send(msg);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
global.Hydro.service.bus.publish(msg.eventName, msg.payload, false);
|
global.Hydro.service.bus.emit(msg.eventName, ...msg.payload);
|
||||||
}
|
}
|
||||||
} else if (msg.event === 'stat') {
|
} else if (msg.event === 'stat') {
|
||||||
global.Hydro.stat.reqCount += msg.count;
|
global.Hydro.stat.reqCount += msg.count;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Collection } from 'mongodb';
|
import { Collection } from 'mongodb';
|
||||||
import * as db from '../service/db';
|
import * as db from '../service/db';
|
||||||
|
import * as bus from '../service/bus';
|
||||||
import { Bdoc } from '../interface';
|
import { Bdoc } from '../interface';
|
||||||
|
|
||||||
const coll: Collection<Bdoc> = db.collection('blacklist');
|
const coll: Collection<Bdoc> = db.collection('blacklist');
|
||||||
@@ -36,5 +37,5 @@ function ensureIndexes() {
|
|||||||
return coll.createIndex('expireAt', { expireAfterSeconds: 0 });
|
return coll.createIndex('expireAt', { expireAfterSeconds: 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
global.Hydro.postInit.push(ensureIndexes);
|
bus.once('app/started', ensureIndexes);
|
||||||
global.Hydro.model.blacklist = { add, get, del };
|
global.Hydro.model.blacklist = { add, get, del };
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
import assert from 'assert';
|
import assert from 'assert';
|
||||||
import { ObjectID } from 'mongodb';
|
import { ObjectID } from 'mongodb';
|
||||||
import * as db from '../service/db';
|
import * as db from '../service/db';
|
||||||
|
import * as bus from '../service/bus';
|
||||||
|
|
||||||
type DocID = ObjectID | string | number;
|
type DocID = ObjectID | string | number;
|
||||||
|
|
||||||
const coll = db.collection('document');
|
export const coll = db.collection('document');
|
||||||
const collStatus = db.collection('document.status');
|
export const collStatus = db.collection('document.status');
|
||||||
|
|
||||||
export const TYPE_PROBLEM = 10;
|
export const TYPE_PROBLEM = 10;
|
||||||
export const TYPE_PROBLEM_SOLUTION = 11;
|
export const TYPE_PROBLEM_SOLUTION = 11;
|
||||||
@@ -51,6 +52,7 @@ export async function add(
|
|||||||
doc.parentType = parentType;
|
doc.parentType = parentType;
|
||||||
doc.parentId = parentId;
|
doc.parentId = parentId;
|
||||||
}
|
}
|
||||||
|
await bus.serial('document/add', doc);
|
||||||
const res = await coll.insertOne(doc);
|
const res = await coll.insertOne(doc);
|
||||||
return docId || res.insertedId;
|
return docId || res.insertedId;
|
||||||
}
|
}
|
||||||
@@ -337,6 +339,7 @@ async function ensureIndexes() {
|
|||||||
await ic({ domainId: 1, docType: 1, docId: 1 }, u);
|
await ic({ domainId: 1, docType: 1, docId: 1 }, u);
|
||||||
await ic({ domainId: 1, docType: 1, owner: 1, docId: -1 });
|
await ic({ domainId: 1, docType: 1, owner: 1, docId: -1 });
|
||||||
// For problem
|
// For problem
|
||||||
|
await ic({ domainId: 1, docType: 1, title: 'text' }, s);
|
||||||
await ic({ domainId: 1, docType: 1, category: 1, docId: 1 }, s);
|
await ic({ domainId: 1, docType: 1, category: 1, docId: 1 }, s);
|
||||||
await ic({ domainId: 1, docType: 1, hidden: 1, category: 1, docId: 1 }, s);
|
await ic({ domainId: 1, docType: 1, hidden: 1, category: 1, docId: 1 }, s);
|
||||||
await ic({ domainId: 1, docType: 1, tag: 1, docId: 1 }, s);
|
await ic({ domainId: 1, docType: 1, tag: 1, docId: 1 }, s);
|
||||||
@@ -364,8 +367,11 @@ async function ensureIndexes() {
|
|||||||
await is({ domainId: 1, docType: 1, uid: 1, enroll: 1, docId: 1 }, s);
|
await is({ domainId: 1, docType: 1, uid: 1, enroll: 1, docId: 1 }, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
global.Hydro.postInit.push(ensureIndexes);
|
bus.once('app/started', ensureIndexes);
|
||||||
global.Hydro.model.document = {
|
global.Hydro.model.document = {
|
||||||
|
coll,
|
||||||
|
collStatus,
|
||||||
|
|
||||||
add,
|
add,
|
||||||
addToSet,
|
addToSet,
|
||||||
cappedIncStatus,
|
cappedIncStatus,
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ import { ObjectID, Collection } from 'mongodb';
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { Dictionary } from 'lodash';
|
import { Dictionary } from 'lodash';
|
||||||
import { ForbiddenError, NotFoundError } from '../error';
|
import { ForbiddenError, NotFoundError } from '../error';
|
||||||
|
import { Ufdoc } from '../interface';
|
||||||
import * as db from '../service/db';
|
import * as db from '../service/db';
|
||||||
|
import * as bus from '../service/bus';
|
||||||
import gridfs from '../service/gridfs';
|
import gridfs from '../service/gridfs';
|
||||||
import hash from '../lib/hash.hydro';
|
import hash from '../lib/hash.hydro';
|
||||||
import { Ufdoc } from '../interface';
|
|
||||||
|
|
||||||
const coll: Collection<Ufdoc> = db.collection('file');
|
const coll: Collection<Ufdoc> = db.collection('file');
|
||||||
const collFile = db.collection('fs.files');
|
const collFile = db.collection('fs.files');
|
||||||
@@ -121,7 +122,7 @@ function ensureIndexes() {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
global.Hydro.postInit.push(ensureIndexes);
|
bus.once('app/started', ensureIndexes);
|
||||||
global.Hydro.model.file = {
|
global.Hydro.model.file = {
|
||||||
add, get, del, getMeta, getWithSecret, getMulti, getMetaDict, url,
|
add, get, del, getMeta, getWithSecret, getMulti, getMetaDict, url,
|
||||||
};
|
};
|
||||||
@@ -22,7 +22,7 @@ export async function send(
|
|||||||
if (from !== to) {
|
if (from !== to) {
|
||||||
// ENHANCE domainId?
|
// ENHANCE domainId?
|
||||||
const udoc = await user.getById('system', to);
|
const udoc = await user.getById('system', to);
|
||||||
bus.publish(`user_message-${to}`, { mdoc, udoc });
|
bus.boardcast('user/message', to, mdoc, udoc);
|
||||||
}
|
}
|
||||||
return mdoc;
|
return mdoc;
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@ function ensureIndexes() {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
global.Hydro.postInit.push(ensureIndexes);
|
bus.once('app/started', ensureIndexes);
|
||||||
global.Hydro.model.message = {
|
global.Hydro.model.message = {
|
||||||
FLAG_UNREAD,
|
FLAG_UNREAD,
|
||||||
FLAG_ALERT,
|
FLAG_ALERT,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { OpcountExceededError } from '../error';
|
import { OpcountExceededError } from '../error';
|
||||||
|
import * as bus from '../service/bus';
|
||||||
import * as db from '../service/db';
|
import * as db from '../service/db';
|
||||||
|
|
||||||
const coll = db.collection('opcount');
|
const coll = db.collection('opcount');
|
||||||
@@ -23,5 +24,5 @@ function ensureIndexes() {
|
|||||||
return coll.createIndex('expireAt', { expireAfterSeconds: 0 });
|
return coll.createIndex('expireAt', { expireAfterSeconds: 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
global.Hydro.postInit.push(ensureIndexes);
|
bus.once('app/started', ensureIndexes);
|
||||||
global.Hydro.model.opcount = { inc };
|
global.Hydro.model.opcount = { inc };
|
||||||
@@ -3,6 +3,7 @@ import moment from 'moment-timezone';
|
|||||||
import { Dictionary } from 'lodash';
|
import { Dictionary } from 'lodash';
|
||||||
import * as builtin from './builtin';
|
import * as builtin from './builtin';
|
||||||
import { Setting as _Setting } from '../interface';
|
import { Setting as _Setting } from '../interface';
|
||||||
|
import * as bus from '../service/bus';
|
||||||
|
|
||||||
type SettingDict = Dictionary<_Setting>;
|
type SettingDict = Dictionary<_Setting>;
|
||||||
|
|
||||||
@@ -139,18 +140,16 @@ SystemSetting(
|
|||||||
Setting('setting_storage', 'user', null, 1, 'number', 'User Counter', null, FLAG_DISABLED | FLAG_HIDDEN),
|
Setting('setting_storage', 'user', null, 1, 'number', 'User Counter', null, FLAG_DISABLED | FLAG_HIDDEN),
|
||||||
);
|
);
|
||||||
|
|
||||||
global.Hydro.postInit.push(
|
bus.once('app/started', async () => {
|
||||||
async () => {
|
for (const setting of SYSTEM_SETTINGS) {
|
||||||
for (const setting of SYSTEM_SETTINGS) {
|
if (setting.value) {
|
||||||
if (setting.value) {
|
const current = await global.Hydro.model.system.get(setting.key);
|
||||||
const current = await global.Hydro.model.system.get(setting.key);
|
if (current === null || current === '') {
|
||||||
if (current === null || current === '') {
|
await global.Hydro.model.system.set(setting.key, setting.value);
|
||||||
await global.Hydro.model.system.set(setting.key, setting.value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
);
|
});
|
||||||
|
|
||||||
global.Hydro.model.setting = {
|
global.Hydro.model.setting = {
|
||||||
langRange,
|
langRange,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { Collection } from 'mongodb';
|
import { Collection } from 'mongodb';
|
||||||
import { TokenDoc } from '../interface';
|
import { TokenDoc } from '../interface';
|
||||||
import * as db from '../service/db';
|
import * as db from '../service/db';
|
||||||
|
import * as bus from '../service/bus';
|
||||||
|
|
||||||
export const coll: Collection<TokenDoc> = db.collection('token');
|
export const coll: Collection<TokenDoc> = db.collection('token');
|
||||||
|
|
||||||
@@ -87,7 +88,7 @@ export function delByUid(uid: number) {
|
|||||||
return coll.deleteMany({ uid });
|
return coll.deleteMany({ uid });
|
||||||
}
|
}
|
||||||
|
|
||||||
global.Hydro.postInit.push(ensureIndexes);
|
bus.once('app/started', ensureIndexes);
|
||||||
global.Hydro.model.token = {
|
global.Hydro.model.token = {
|
||||||
coll,
|
coll,
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ import * as setting from './setting';
|
|||||||
import * as domain from './domain';
|
import * as domain from './domain';
|
||||||
import { BUILTIN_USERS, PRIV } from './builtin';
|
import { BUILTIN_USERS, PRIV } from './builtin';
|
||||||
import { UserNotFoundError, UserAlreadyExistError, LoginError } from '../error';
|
import { UserNotFoundError, UserAlreadyExistError, LoginError } from '../error';
|
||||||
|
import { User as _User, Udoc, Udict } from '../interface';
|
||||||
import pwhash from '../lib/hash.hydro';
|
import pwhash from '../lib/hash.hydro';
|
||||||
import * as db from '../service/db';
|
import * as db from '../service/db';
|
||||||
import { User as _User, Udoc, Udict } from '../interface';
|
import * as bus from '../service/bus';
|
||||||
|
|
||||||
const coll: Collection<Udoc> = db.collection('user');
|
const coll: Collection<Udoc> = db.collection('user');
|
||||||
|
|
||||||
@@ -248,7 +249,7 @@ function ensureIndexes() {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
global.Hydro.postInit.push(ensureIndexes);
|
bus.once('app/started', ensureIndexes);
|
||||||
global.Hydro.model.user = {
|
global.Hydro.model.user = {
|
||||||
User,
|
User,
|
||||||
create,
|
create,
|
||||||
|
|||||||
@@ -1,41 +1,122 @@
|
|||||||
|
/* eslint-disable no-await-in-loop */
|
||||||
import cluster from 'cluster';
|
import cluster from 'cluster';
|
||||||
|
import { Db } from 'mongodb';
|
||||||
|
import { Mdoc, Rdoc, User } from '../interface';
|
||||||
|
|
||||||
const bus = {};
|
const _hooks: Record<keyof any, Array<(...args: any[]) => any>> = {};
|
||||||
|
const _disposables = [];
|
||||||
|
|
||||||
export function subscribe(events: string[], handler: any) {
|
function isBailed(value: any) {
|
||||||
const id = String.random(16);
|
return value !== null && value !== false && value !== undefined;
|
||||||
for (const event of events) {
|
|
||||||
if (!bus[event]) bus[event] = {};
|
|
||||||
bus[event][id] = handler;
|
|
||||||
}
|
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function unsubscribe(events: string[], id: string) {
|
export type Disposable = () => void
|
||||||
for (const event of events) {
|
|
||||||
if (!bus[event]) bus[event] = {};
|
interface EventMap {
|
||||||
delete bus[event][id];
|
'app/started': () => void
|
||||||
}
|
'app/exit': () => Promise<void> | void
|
||||||
|
'dispose': () => void
|
||||||
|
|
||||||
|
'database/connect': (db: Db) => void
|
||||||
|
|
||||||
|
'user/message': (uid: number, mdoc: Mdoc, udoc: User) => void
|
||||||
|
|
||||||
|
'document/add': (doc: any) => string | void
|
||||||
|
|
||||||
|
'record/change': (rdoc: Rdoc, $set?: any, $push?: any) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
export function publish(event: string, payload: any, isMaster = true) {
|
function getHooks<K extends keyof EventMap>(name: K) {
|
||||||
|
const hooks = _hooks[name] || (_hooks[name] = []);
|
||||||
|
if (hooks.length >= 128) {
|
||||||
|
console.warn(
|
||||||
|
'max listener count (128) for event "%s" exceeded, which may be caused by a memory leak',
|
||||||
|
name,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return hooks;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function removeListener<K extends keyof EventMap>(name: K, listener: EventMap[K]) {
|
||||||
|
const index = (_hooks[name] || []).findIndex((callback) => callback === listener);
|
||||||
|
if (index >= 0) {
|
||||||
|
_hooks[name].splice(index, 1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addListener<K extends keyof EventMap>(name: K, listener: EventMap[K]) {
|
||||||
|
getHooks(name).push(listener);
|
||||||
|
const dispose = () => removeListener(name, listener);
|
||||||
|
_disposables.push(name === 'dispose' ? listener as Disposable : dispose);
|
||||||
|
return dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function prependListener<K extends keyof EventMap>(name: K, listener: EventMap[K]) {
|
||||||
|
getHooks(name).unshift(listener);
|
||||||
|
const dispose = () => removeListener(name, listener);
|
||||||
|
_disposables.push(name === 'dispose' ? listener as Disposable : dispose);
|
||||||
|
return dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function once<K extends keyof EventMap>(name: K, listener: EventMap[K]) {
|
||||||
|
// @ts-ignore
|
||||||
|
const dispose = addListener(name, (...args: Parameters<EventMap[K]>) => {
|
||||||
|
dispose();
|
||||||
|
// @ts-ignore
|
||||||
|
return listener.apply(this, args);
|
||||||
|
});
|
||||||
|
return dispose;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function on<K extends keyof EventMap>(name: K, listener: EventMap[K]) {
|
||||||
|
return addListener(name, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function off<K extends keyof EventMap>(name: K, listener: EventMap[K]) {
|
||||||
|
return removeListener(name, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function parallel<K extends keyof EventMap>(name: K, ...args: Parameters<EventMap[K]>): Promise<void> {
|
||||||
|
const tasks: Promise<any>[] = [];
|
||||||
|
for (const callback of _hooks[name] || []) {
|
||||||
|
tasks.push(callback.apply(this, args));
|
||||||
|
}
|
||||||
|
await Promise.all(tasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function emit<K extends keyof EventMap>(name: K, ...args: Parameters<EventMap[K]>) {
|
||||||
|
return parallel(name, ...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function serial<K extends keyof EventMap>(name: K, ...args: Parameters<EventMap[K]>): Promise<ReturnType<EventMap[K]>> {
|
||||||
|
for (const callback of _hooks[name] || []) {
|
||||||
|
const result = await callback.apply(this, args);
|
||||||
|
if (isBailed(result)) return result;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function bail<K extends keyof EventMap>(name: K, ...args: Parameters<EventMap[K]>): ReturnType<EventMap[K]> {
|
||||||
|
for (const callback of _hooks[name] || []) {
|
||||||
|
const result = callback.apply(this, args);
|
||||||
|
if (isBailed(result)) return result;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function boardcast<K extends keyof EventMap>(event: K, ...payload: Parameters<EventMap[K]>) {
|
||||||
// Process forked by pm2 would also have process.send
|
// Process forked by pm2 would also have process.send
|
||||||
if (isMaster && process.send && !cluster.isMaster) {
|
if (process.send && !cluster.isMaster) {
|
||||||
process.send({
|
process.send({
|
||||||
event: 'bus',
|
event: 'bus',
|
||||||
eventName: event,
|
eventName: event,
|
||||||
payload,
|
payload,
|
||||||
});
|
});
|
||||||
} else {
|
} else parallel(event, ...payload);
|
||||||
if (!bus[event]) bus[event] = {};
|
|
||||||
const funcs = Object.keys(bus[event]);
|
|
||||||
Promise.all(funcs.map((func) => bus[event][func]({
|
|
||||||
event,
|
|
||||||
value: payload,
|
|
||||||
})));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
global.Hydro.service.bus = {
|
global.Hydro.service.bus = {
|
||||||
subscribe, unsubscribe, publish,
|
addListener, bail, boardcast, emit, on, off, once, parallel, prependListener, removeListener, serial,
|
||||||
};
|
};
|
||||||
@@ -21,7 +21,7 @@ mongodb.MongoClient.connect(mongourl, { useNewUrlParser: true, useUnifiedTopolog
|
|||||||
.then((Client1) => {
|
.then((Client1) => {
|
||||||
db2 = Client1.db(opts.name);
|
db2 = Client1.db(opts.name);
|
||||||
global.Hydro.service.db.db2 = db2;
|
global.Hydro.service.db.db2 = db2;
|
||||||
bus.publish('system_database_connected', null);
|
bus.parallel('database/connect', db);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import cluster from 'cluster';
|
import cluster from 'cluster';
|
||||||
import * as db from './db';
|
import * as db from './db';
|
||||||
|
import * as bus from './bus';
|
||||||
import * as sysinfo from '../lib/sysinfo';
|
import * as sysinfo from '../lib/sysinfo';
|
||||||
|
|
||||||
const coll = db.collection('status');
|
const coll = db.collection('status');
|
||||||
@@ -24,17 +25,15 @@ export function updateJudger(args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cluster.isMaster) {
|
if (cluster.isMaster) {
|
||||||
global.Hydro.postInit.push(
|
bus.on('app/started', async () => {
|
||||||
async () => {
|
const info = await sysinfo.get();
|
||||||
const info = await sysinfo.get();
|
await coll.updateOne(
|
||||||
await coll.updateOne(
|
{ mid: info.mid, type: 'server' },
|
||||||
{ mid: info.mid, type: 'server' },
|
{ $set: { ...info, updateAt: new Date(), type: 'server' } },
|
||||||
{ $set: { ...info, updateAt: new Date(), type: 'server' } },
|
{ upsert: true },
|
||||||
{ upsert: true },
|
);
|
||||||
);
|
setInterval(update, 60 * 1000);
|
||||||
setInterval(update, 60 * 1000);
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
global.Hydro.service.monitor = { update, updateJudger };
|
global.Hydro.service.monitor = { update, updateJudger };
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hydrooj/login-with-qq",
|
"name": "@hydrooj/login-with-qq",
|
||||||
"version": "0.0.3",
|
"version": "0.0.4",
|
||||||
"main": "package.json",
|
"main": "package.json",
|
||||||
"repository": "git@github.com:hydro-dev/Hydro.git",
|
"repository": "git@github.com:hydro-dev/Hydro.git",
|
||||||
"author": "undefined <masnn0@outlook.com>",
|
"author": "undefined <masnn0@outlook.com>",
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
"build": "tsc"
|
"build": "tsc"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"hydrooj": "^2.12.1||^2.13.0"
|
"hydrooj": "^2.13.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ws": "^7.3.1"
|
"ws": "^7.3.1"
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { } from 'hydrooj';
|
import { } from 'hydrooj';
|
||||||
|
import * as bus from 'hydrooj/dist/service/bus';
|
||||||
import WebSocket from 'ws';
|
import WebSocket from 'ws';
|
||||||
|
|
||||||
export async function postInit() {
|
export async function postInit() {
|
||||||
@@ -32,4 +33,4 @@ export async function postInit() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
global.Hydro.postInit.push(postInit);
|
bus.subscribe(['app/started'], postInit);
|
||||||
Reference in new issue
Block a user