workspace: upgrade to cordis@4.0.0-beta.1, fix #975

This commit is contained in:
undefined committed 2025-04-11 21:21:47 +08:00
1 parent 5d5f6c69d7
commit bf51bd30c7
34 files changed
+87 -88

No files matched your search

+1
View File
@@ -159,6 +159,7 @@ Hydro 用户群:1085853538
- core: 移除 setting.yaml
- core: oauth: 改为使用 ctx.oauth.provide() 注册
- framework: 移除 ready 与 dispose 事件 (使用 ctx.effect 代替)
- core: 最低要求 node 22
## Hydro 4.19.0 / UI 4.57.0
+4 -4
View File
@@ -4,12 +4,12 @@
"license": "MIT",
"main": "base.mjs",
"dependencies": {
"@eslint-react/eslint-plugin": "^1.40.1",
"@eslint-react/eslint-plugin": "^1.45.0",
"@eslint/compat": "^1.2.8",
"@eslint/eslintrc": "^3.3.1",
"@stylistic/eslint-plugin": "^4.2.0",
"@typescript-eslint/eslint-plugin": "^8.29.0",
"@typescript-eslint/parser": "^8.29.0",
"@typescript-eslint/eslint-plugin": "^8.29.1",
"@typescript-eslint/parser": "^8.29.1",
"eslint-config-airbnb": "^19.0.4",
"eslint-plugin-de-morgan": "^1.2.1",
"eslint-plugin-github": "^6.0.0",
@@ -24,6 +24,6 @@
"eslint": ">= 9"
},
"optionalDependencies": {
"typescript": "^5.8.2"
"typescript": "^5.8.3"
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
import { Context } from '@cordisjs/core';
import { Context } from 'cordis';
import { ValidationError } from './error';
import type { Handler } from './server';
import { Converter, Type, Validator } from './validator';
+1 -1
View File
@@ -33,7 +33,7 @@ export interface ServerEvents<C> extends KnownHandlerEvents, HandlerEvents<C> {
[k: `handler/error/${string}`]: (thisArg: Handler<C>, e: Error) => VoidReturn
}
declare module '@cordisjs/core' {
declare module 'cordis' {
interface Events<C> extends ServerEvents<C> {
}
}
+2 -2
View File
@@ -4,13 +4,13 @@
"main": "index.ts",
"license": "MIT",
"peerDependencies": {
"@cordisjs/core": "*"
"cordis": "*"
},
"dependencies": {
"@hydrooj/utils": "workspace:^",
"emoji-regex": "^10.4.0",
"fs-extra": "^11.3.0",
"koa": "^2.16.0",
"koa": "^2.16.1",
"koa-body": "^6.0.1",
"koa-compress": "^5.1.1",
"koa-router": "^13.0.1",
+3 -3
View File
@@ -2,7 +2,7 @@ import http from 'http';
import { tmpdir } from 'os';
import { join } from 'path';
import { PassThrough } from 'stream';
import { Context as CordisContext, Service } from '@cordisjs/core';
import { Context as CordisContext, Service } from 'cordis';
import type { Files } from 'formidable';
import fs from 'fs-extra';
import Koa from 'koa';
@@ -625,7 +625,7 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
for (const { name, target } of h.__subscribe || []) sub.ctx.on(name, target.bind(h));
if (layer) {
let lastHeartbeat = Date.now();
sub.ctx.setInterval(() => {
sub.ctx.interval(() => {
if (Date.now() - lastHeartbeat > 80000) {
clean();
conn.terminate();
@@ -841,7 +841,7 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`);
}
}
declare module '@cordisjs/core' {
declare module 'cordis' {
interface Context {
server: WebService<this>;
Route: WebService<this>['Route'];
+1 -1
View File
@@ -7,7 +7,7 @@
"node": ">=16"
},
"dependencies": {
"esbuild": "0.25.0",
"esbuild": "0.25.2",
"source-map-support": "^0.5.21"
},
"devDependencies": {
+5 -5
View File
@@ -42,9 +42,9 @@
"chai": "^5.2.0",
"cross-env": "^7.0.3",
"cross-spawn": "^7.0.6",
"esbuild": "0.25.0",
"eslint": "^9.23.0",
"eslint-import-resolver-typescript": "^4.3.1",
"esbuild": "0.25.2",
"eslint": "^9.24.0",
"eslint-import-resolver-typescript": "^4.3.2",
"eslint-import-resolver-webpack": "^0.13.10",
"fs-extra": "^11.3.0",
"globals": "^16.0.0",
@@ -53,13 +53,13 @@
"mongodb-memory-server": "10.1.4",
"nyc": "^17.1.0",
"ora": "^8.2.0",
"oxlint": "^0.16.4",
"oxlint": "^0.16.5",
"package-json": "^10.0.1",
"semver": "^7.7.1",
"simple-git": "^3.27.0",
"supertest": "^7.1.0",
"supports-hyperlinks": "^3.2.0",
"typescript": "5.8.2",
"typescript": "5.8.3",
"wtfnode": "^0.10.0"
}
}
+1 -1
View File
@@ -15,6 +15,6 @@
"@types/diff": "^7.0.2",
"@types/js-yaml": "^4.0.9",
"@types/lodash": "^4.17.16",
"sass": "^1.86.1"
"sass": "^1.86.3"
}
}
+2 -3
View File
@@ -16,18 +16,17 @@
"@aws-sdk/lib-storage": "3.726.1",
"@aws-sdk/s3-presigned-post": "3.726.1",
"@aws-sdk/s3-request-presigner": "3.726.1",
"@cordisjs/core": "4.0.0-alpha.8",
"@cordisjs/logger": "1.0.0-alpha.5",
"@cordisjs/plugin-timer": "1.0.0-alpha.0",
"@cordisjs/plugin-timer": "1.1.1",
"@graphql-tools/schema": "^10.0.23",
"@hydrooj/common": "workspace:^",
"@hydrooj/framework": "workspace:^",
"@hydrooj/utils": "workspace:^",
"@simplewebauthn/server": "13.1.1",
"@undefined-moe/require-resolve-hook": "^1.1.0",
"@yarnpkg/libzip": "^3.1.1",
"adm-zip": "0.5.16",
"cac": "^6.7.14",
"cordis": "4.0.0-beta.1",
"csv-stringify": "^6.5.2",
"emoji-regex": "^10.4.0",
"emojis-list": "2.1.0",
+3 -13
View File
@@ -1,4 +1,4 @@
import * as cordis from '@cordisjs/core';
import * as cordis from 'cordis';
import LoggerService from '@cordisjs/logger';
import { TimerService } from '@cordisjs/plugin-timer';
import Schema from 'schemastery';
@@ -23,9 +23,9 @@ function provideModule<T extends keyof ModuleInterfaces>(type: T, id: string, mo
return () => delete global.Hydro.module[type][id];
}
export type EffectScope = cordis.EffectScope<Context>;
export type Fiber = cordis.Fiber<Context>;
export { Disposable, Plugin, ScopeStatus } from '@cordisjs/core';
export { Disposable, Plugin, FiberState } from 'cordis';
export interface Context extends cordis.Context {
[Context.events]: EventMap & cordis.Events<Context>;
@@ -74,13 +74,3 @@ export class Context extends cordis.Context {
this.plugin(LoggerService);
}
}
const old = cordis.Registry.prototype.inject;
// cordis.Registry.prototype.using = old;
cordis.Registry.prototype.inject = function wrapper(...args) {
if (typeof args[0] === 'string') {
console.warn('old functionality of ctx.inject is deprecated. please use ctx.injectUI instead.');
return T(inject).call(this, ...args as any) as any;
}
return old.call(this, ...args);
};
+1 -1
View File
@@ -142,7 +142,7 @@ class DomainUserHandler extends ManageHandler {
user: 1,
role: 1,
join: 1,
displayName: this.user.hasPerm(PERM.PERM_VIEW_DISPLAYNAME),
...(this.user.hasPerm(PERM.PERM_VIEW_DISPLAYNAME) ? { displayName: 1 } : {}),
},
},
]).toArray(),
+1 -5
View File
@@ -13,7 +13,7 @@ declare module '../service/bus' {
}
}
class I18nService extends Service {
export class I18nService extends Service {
constructor(ctx: Context) {
super(ctx, 'i18n');
this.translate = this.translate.bind(this);
@@ -55,10 +55,6 @@ class I18nService extends Service {
}
export const name = 'i18n';
export function apply(ctx: Context) {
ctx.provide('i18n', undefined, true);
ctx.i18n = new I18nService(ctx);
}
function collect(lang: string) {
const s = translations[lang];
+1 -3
View File
@@ -1,4 +1,3 @@
import { ZipFS, ZipOpenFS } from '@yarnpkg/libzip';
import AdmZip from 'adm-zip';
import _ from 'lodash';
import { ObjectId as ObjectID } from 'mongodb';
@@ -10,9 +9,8 @@ export { WebSocket, WebSocketServer } from '@hydrooj/framework';
export * from './utils';
export * from './interface';
export * from './typeutils';
export * as LibZip from '@yarnpkg/libzip';
export {
Schema, AdmZip, superagent, _, ObjectID, ZipFS, ZipOpenFS,
Schema, AdmZip, superagent, _, ObjectID,
};
export const definePlugin = <T = never>(args: {
using?: keyof Context[];
+8 -8
View File
@@ -9,11 +9,11 @@ import child from 'child_process';
import './utils';
import cac from 'cac';
import './ui';
import * as I18n from './lib/i18n';
import { I18nService } from './lib/i18n';
import { Logger } from './logger';
import {
Context, Service, ScopeStatus, EffectScope,
Context, Service, FiberState, Fiber,
} from './context';
// eslint-disable-next-line import/no-duplicates
import { sleep, unwrapExports } from './utils';
@@ -45,7 +45,7 @@ if (process.env.NIX_PROFILES) {
}
export class Loader extends Service {
public state: Record<string, EffectScope> = Object.create(null);
public state: Record<string, Fiber> = Object.create(null);
public suspend = false;
public cache: Record<string, string> = Object.create(null);
// public warnings: Record<string, string> = Object.create(null);
@@ -56,8 +56,8 @@ export class Loader extends Service {
super(ctx, 'loader');
ctx.on('app/started', () => {
ctx.setInterval(async () => {
const pending = Object.entries(this.state).filter((v) => v[1].status === ScopeStatus.PENDING);
ctx.interval(async () => {
const pending = Object.entries(this.state).filter((v) => v[1].state === FiberState.PENDING);
if (pending.length) {
logger.warn('Plugins are still pending: %s', pending.map((v) => v[0]).join(', '));
for (const [key, value] of pending) {
@@ -65,7 +65,7 @@ export class Loader extends Service {
console.log(value);
}
}
const loading = Object.entries(this.state).filter((v) => v[1].status === ScopeStatus.LOADING);
const loading = Object.entries(this.state).filter((v) => v[1].state === FiberState.LOADING);
if (loading.length) {
logger.warn('Plugins are still loading: %s', loading.map((v) => v[0]).join(', '));
for (const [key, value] of loading) {
@@ -73,7 +73,7 @@ export class Loader extends Service {
console.log(value);
}
}
const failed = Object.entries(this.state).filter((v) => v[1].status === ScopeStatus.FAILED);
const failed = Object.entries(this.state).filter((v) => v[1].state === FiberState.FAILED);
if (failed.length) {
logger.warn('Plugins failed to load: %s', failed.map((v) => v[0]).join(', '));
for (const [key, value] of failed) {
@@ -143,7 +143,7 @@ export class Loader extends Service {
}
}
app.plugin(I18n);
app.plugin(I18nService);
app.plugin(Loader);
async function preload() {
+2 -2
View File
@@ -1,6 +1,6 @@
/* eslint-disable max-len */
/* eslint-disable no-await-in-loop */
import * as cordis from '@cordisjs/core';
import * as cordis from 'cordis';
import yaml from 'js-yaml';
import { Dictionary } from 'lodash';
import moment from 'moment-timezone';
@@ -356,7 +356,7 @@ SystemSetting(
export const langs: Record<string, LangConfig> = {};
declare module '@cordisjs/core' {
declare module 'cordis' {
interface Context {
setting: SettingService;
}
+1 -1
View File
@@ -1,7 +1,7 @@
// TODO check more
import os from 'os';
import { DisposableList } from '@cordisjs/core';
import { DisposableList } from 'cordis';
import { Context, Service } from '../context';
import * as system from '../model/system';
import db from './db';
+1 -1
View File
@@ -62,7 +62,7 @@ export class MongoService extends Service {
yield () => { this.client.close(); };
this.db = this.client.db(url.database || 'hydro');
await bus.parallel('database/connect', this.db);
yield this.ctx.setInterval(() => this.fixExpireAfter(), Time.hour);
yield this.ctx.interval(() => this.fixExpireAfter(), Time.hour);
}
public collection<K extends keyof Collections>(c: K) {
+1 -1
View File
@@ -209,7 +209,7 @@ export default class HMR extends Service {
const reload = async (plugin: any, runtime?: Plugin.Runtime) => {
if (!runtime) return;
for (const oldFiber of runtime.scopes) {
for (const oldFiber of runtime.fibers) {
// eslint-disable-next-line no-await-in-loop
await oldFiber.parent.plugin(plugin, oldFiber.config);
}
+17 -1
View File
@@ -1,8 +1,11 @@
/* eslint-disable no-await-in-loop */
import cac from 'cac';
import { Logger } from '@hydrooj/utils';
import { Context, Service } from '../context';
import * as system from '../model/system';
const argv = cac().parse();
export type MigrationScript = null | ((ctx: Context) => Promise<boolean | void>);
const logger = new Logger('migration');
@@ -43,6 +46,18 @@ export default class MigrationService extends Service {
await system.set(name, expected);
continue;
}
let upgraded = false;
if (dbVer > expected) {
logger.warn('Current database version for [%s] is %d, expected %d.', channel, dbVer, expected);
logger.warn('You are likely trying to apply a downgrade.');
logger.warn('This version of Hydro is not compatible with newer data version.');
if (!argv.options.ignoreVersion) {
logger.warn('To prevent data corruption, the startup has been aborted.');
logger.warn('If you want to continue, use --ignore-version on startup.');
logger.warn('Do it at your own risk.');
await new Promise(() => { });
}
}
while (dbVer < expected) {
const func = scripts[dbVer];
if (typeof func !== 'function') {
@@ -62,8 +77,9 @@ export default class MigrationService extends Service {
}
dbVer++;
await system.set(name, dbVer);
upgraded = true;
}
logger.success('Database upgraded [%s]: current version %d', channel, dbVer);
if (upgraded) logger.success('Database upgraded [%s]: current version %d', channel, dbVer);
}
}
}
+1 -1
View File
@@ -107,5 +107,5 @@ export async function apply(ctx: Context) {
{ upsert: true },
);
feedback();
return ctx.setInterval(update, 1800 * 1000); // eslint-disable-line
return ctx.interval(update, 1800 * 1000); // eslint-disable-line
}
+1 -1
View File
@@ -425,7 +425,7 @@ export async function apply(ctx: Context, config: ReturnType<typeof FileSetting>
return await next();
});
});
ctx.set('storage', service);
ctx.provide('storage', service);
}
declare module '../context' {
+1 -1
View File
@@ -11,7 +11,7 @@ async function terminate() {
}, 1000);
try {
await bus.parallel('app/exit');
await app.scope.dispose();
await app.fiber.dispose();
} catch (e) {
hasError = true;
}
+1 -1
View File
@@ -6,7 +6,7 @@
"author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0-or-later",
"dependencies": {
"mariadb": "^3.4.0",
"mariadb": "^3.4.1",
"mongodb": "^6.15.0",
"turndown": "^7.2.0",
"xml2js": "^0.6.2"
+1 -1
View File
@@ -55,7 +55,7 @@ export function apply(ctx: Context) {
const registry = createRegistry(ctx);
ctx.on('metrics', (id, metrics) => { instances[id] = metrics; });
let pushError = '';
ctx.setInterval(async () => {
ctx.interval(async () => {
try {
const [gateway, name, pass] = SystemModel.getMany(['prom-client.gateway', 'prom-client.name', 'prom-client.password']);
if (gateway) {
+1 -1
View File
@@ -75,6 +75,6 @@ export function createRegistry(ctx: Context) {
collectDefaultMetrics({ register: registry });
ctx.set('metrics', registry);
ctx.provide('metrics', registry);
return registry;
}
@@ -66,7 +66,7 @@ export default function ScratchpadContainer() {
const store = useStore();
if (!scratchpad) {
scratchpad = new ScratchpadService(store);
ctx.set('scratchpad', scratchpad);
ctx.provide('scratchpad', scratchpad);
}
const [, updateState] = React.useState<any>();
const forceUpdate = React.useCallback(() => updateState({}), []);
+3 -3
View File
@@ -1,9 +1,9 @@
import * as cordis from '@cordisjs/core';
import * as cordis from 'cordis';
import type { EventMap } from './api';
export interface Events<C extends Context = Context> extends cordis.Events<C>, EventMap { }
export type { Disposable, ScopeStatus, Plugin } from '@cordisjs/core';
export type { Disposable, FiberState, Plugin } from 'cordis';
export interface Context {
[Context.events]: Events<this>;
@@ -11,7 +11,7 @@ export interface Context {
}
export class Context extends cordis.Context { }
export type EffectScope = cordis.EffectScope<Context>;
export type Fiber = cordis.Fiber<Context>;
export class Service<C extends Context = Context> extends cordis.Service<C> {
}
+12 -12
View File
@@ -11,8 +11,7 @@
"cli": false
},
"devDependencies": {
"@blueprintjs/core": "^5.17.6",
"@cordisjs/core": "4.0.0-alpha.8",
"@blueprintjs/core": "^5.18.0",
"@fontsource/dm-mono": "^5.2.5",
"@fontsource/fira-code": "^5.2.5",
"@fontsource/inconsolata": "^5.2.5",
@@ -22,8 +21,8 @@
"@fontsource/source-code-pro": "^5.2.5",
"@fontsource/ubuntu-mono": "^5.2.5",
"@hydrooj/utils": "workspace:^",
"@sentry/browser": "^9.10.1",
"@sentry/webpack-plugin": "^3.2.4",
"@sentry/browser": "^9.12.0",
"@sentry/webpack-plugin": "^3.3.1",
"@simplewebauthn/browser": "13.1.0",
"@svgr/webpack": "^8.1.0",
"@types/html-to-text": "^9.0.4",
@@ -36,7 +35,7 @@
"@types/pickadate": "^3.5.35",
"@types/qrcode": "^1.5.5",
"@types/react": "^18.3.20",
"@types/react-dom": "^18.3.5",
"@types/react-dom": "^18.3.6",
"@types/redux-logger": "^3.0.13",
"@types/uuid": "^10.0.0",
"@types/webpack-env": "^1.18.8",
@@ -50,6 +49,7 @@
"clean-webpack-plugin": "^4.0.0",
"clipboard": "^2.0.11",
"copy-webpack-plugin": "^13.0.0",
"cordis": "4.0.0-beta.1",
"core-js": "^3.41.0",
"core-js-compat": "^3.41.0",
"css-loader": "^7.1.2",
@@ -99,7 +99,7 @@
"redux-promise-middleware": "^6.2.0",
"redux-thunk": "^3.1.0",
"rupture": "^0.7.1",
"sass": "^1.86.1",
"sass": "^1.86.3",
"sass-loader": "^16.0.5",
"schemastery": "^3.16.1",
"schemastery-react": "^0.1.2",
@@ -108,15 +108,15 @@
"sticky-kit": "^1.1.3",
"style-loader": "^4.0.0",
"stylus": "^0.64.0",
"stylus-loader": "7.1.2",
"svgtofont": "^6.3.1",
"stylus-loader": "7.1.3",
"svgtofont": "^6.3.2",
"tether": "1.4.7",
"tether-drop": "^1.4.2",
"timeago-react": "^3.0.7",
"timeago.js": "^4.0.2",
"ts-loader": "^9.5.2",
"web-streams-polyfill": "^4.1.0",
"webpack": "^5.98.0",
"webpack": "^5.99.5",
"webpack-bundle-analyzer": "^4.10.2",
"webpack-dev-server": "^5.2.1",
"webpack-manifest-plugin": "^5.0.1",
@@ -124,14 +124,14 @@
},
"dependencies": {
"@hydrooj/common": "workspace:^",
"ansi_up": "^6.0.2",
"ansi_up": "^6.0.5",
"cssfilter": "^0.0.11",
"esbuild": "0.25.0",
"esbuild": "0.25.2",
"fs-extra": "^11.3.0",
"html-to-text": "^9.0.5",
"js-yaml": "^4.1.0",
"jsesc": "^3.1.0",
"katex": "^0.16.21",
"katex": "^0.16.22",
"lodash": "^4.17.21",
"markdown-it": "^14.1.0",
"markdown-it-anchor": "^9.2.0",
+1 -1
View File
@@ -21,7 +21,7 @@ export default new NamedPage('api', async () => {
} as any;
createRoot(document.getElementById('main')!).render(
<GraphiQL
fetcher={(body, opts = {}) => request.post('/api', body, pick(opts, 'headers'))}
fetcher={(body, opts = {}) => request.post(`/d/${UiContext.domain._id}/api`, body, pick(opts, 'headers'))}
defaultQuery={defaultQuery}
variables='{"name": "Hydro"}'
/>,
@@ -43,7 +43,7 @@ const page = new NamedPage('home_messages', () => {
reduxStore = store;
(window as any).store = reduxStore;
ctx.set('messagepad', new MessagePadService(store, WebSocket));
ctx.provide('messagepad', new MessagePadService(store, WebSocket));
const sock = new WebSocket(`${UiContext.ws_prefix}home/messages-conn`);
sock.onmessage = (message) => {
@@ -1,6 +1,5 @@
import { browserSupportsWebAuthn, platformAuthenticatorIsAvailable, startRegistration } from '@simplewebauthn/browser';
import $ from 'jquery';
import { escape } from 'lodash';
import QRCode from 'qrcode';
import { ActionDialog } from 'vj/components/dialog';
import Notification from 'vj/components/notification';
@@ -28,7 +27,7 @@ async function changeMail() {
<input className="textbox" type="text" name="mail" required></input>
</div>
</label>
</div>
</div>,
),
onDispatch(action) {
if (action === 'ok') {
@@ -199,7 +198,7 @@ export default new NamedPage('home_security', () => {
</MenuLink>
</>)}
</ol>
</div>
</div>,
);
const action = await new ActionDialog({ $body, $action: [] }).open();
if (!action || action === 'cancel') return;
+3 -3
View File
@@ -13,9 +13,9 @@
"react-dom": "^18.3.1"
},
"devDependencies": {
"@types/react": "^19.0.12",
"@types/react-dom": "^19.0.4",
"@types/react": "^19.1.0",
"@types/react-dom": "^19.1.2",
"@vitejs/plugin-react-swc": "^3.8.1",
"vite": "^6.2.4"
"vite": "^6.2.6"
}
}
+1 -1
View File
@@ -193,7 +193,7 @@ class VJudgeService extends Service {
if (process.env.NODE_APP_INSTANCE !== '0') return;
if (process.env.HYDRO_CLI) return;
this.accounts = await coll.find().toArray();
this.ctx.setInterval(this.sync.bind(this), Time.week);
this.ctx.interval(this.sync.bind(this), Time.week);
}
addProvider(type: string, provider: BasicProvider, override = false) {