From 30e95b4511e5d6c7b73d4647673eb601b0e44a09 Mon Sep 17 00:00:00 2001 From: undefined Date: Wed, 2 Oct 2024 08:33:52 +0800 Subject: [PATCH] upgrade to typescript@5.6 and cordis@3.18 --- framework/eslint-config/package.json | 6 +++--- framework/framework/package.json | 2 +- framework/framework/server.ts | 13 ++++++++----- framework/register/package.json | 2 +- install/install.sh | 5 +++-- install/install.ts | 5 ++++- package.json | 11 +++++------ packages/geoip/index.ts | 3 +-- packages/geoip/package.json | 2 +- packages/hydrooj/package.json | 12 ++++++------ packages/hydrooj/src/handler/user.ts | 2 +- packages/hydrooj/src/interface.ts | 1 + packages/hydrooj/src/model/setting.ts | 2 +- packages/hydrooj/src/service/server.ts | 1 + packages/hydrooj/src/service/watcher.ts | 5 +++-- packages/prom-client/metrics.ts | 3 +-- packages/ui-default/components/scratchpad/index.tsx | 3 +-- packages/ui-default/package.json | 8 ++++---- packages/ui-default/pages/home_messages.page.tsx | 3 +-- packages/ui-default/pages/problem_detail.page.tsx | 4 ++-- packages/utils/lib/utils.ts | 3 ++- packages/utils/package.json | 2 +- 22 files changed, 52 insertions(+), 46 deletions(-) diff --git a/framework/eslint-config/package.json b/framework/eslint-config/package.json index 633eae9f7..d755e8f85 100644 --- a/framework/eslint-config/package.json +++ b/framework/eslint-config/package.json @@ -5,13 +5,13 @@ "main": "react.yaml", "dependencies": { "@stylistic/eslint-plugin": "^2.8.0", - "@typescript-eslint/eslint-plugin": "^8.7.0", - "@typescript-eslint/parser": "^8.7.0", + "@typescript-eslint/eslint-plugin": "^8.8.0", + "@typescript-eslint/parser": "^8.8.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-github": "^5.0.2", "eslint-plugin-import": "2.30.0", "eslint-plugin-jsx-a11y": "^6.10.0", - "eslint-plugin-react": "^7.36.1", + "eslint-plugin-react": "^7.37.1", "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-simple-import-sort": "^12.1.1" }, diff --git a/framework/framework/package.json b/framework/framework/package.json index 28026e3d4..f2e64ad86 100644 --- a/framework/framework/package.json +++ b/framework/framework/package.json @@ -16,7 +16,7 @@ "koa-router": "^13.0.1", "lodash": "^4.17.21", "moment-timezone": "^0.5.45", - "path-to-regexp": "^8.1.0", + "path-to-regexp": "^8.2.0", "sanitize-filename": "^1.6.3", "saslprep": "^1.0.3", "shorty.js": "^1.0.1", diff --git a/framework/framework/server.ts b/framework/framework/server.ts index 9b20a6b1a..cc0828a89 100644 --- a/framework/framework/server.ts +++ b/framework/framework/server.ts @@ -23,6 +23,8 @@ import serializer from './serializer'; export { WebSocket, WebSocketServer } from 'ws'; +const kHandler = Symbol.for('hydro.handler'); + // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent export function encodeRFC5987ValueChars(str: string) { return ( @@ -109,6 +111,7 @@ export interface UserModel { export interface HandlerCommon { } export class HandlerCommon { + static [kHandler] = true; session: Record; args: Record; request: HydroRequest; @@ -316,6 +319,7 @@ interface WebServiceConfig { cors?: string; upload?: string; port: number; + host?: string; xff?: string; xhost?: string; } @@ -446,7 +450,7 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`); wsServer.close(); }); await new Promise((r) => { - httpServer.listen(this.config.port, () => { + httpServer.listen(this.config.port, this.config.host || '127.0.0.1', () => { logger.success('Server listening at: %d', this.config.port); r(true); }); @@ -596,7 +600,7 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`); private register(type: 'route' | 'conn', routeName: string, path: string, HandlerClass: any, ...permPrivChecker) { const name = HandlerClass.name; - if (!isClass(HandlerClass)) throw new Error('Invalid registration.'); + if (!HandlerClass?.[kHandler] || !isClass(HandlerClass)) throw new Error('Invalid registration.'); if (this.registrationCount[name] && this.registry[name] !== HandlerClass) { logger.warn('Route with name %s already exists.', name); } @@ -625,10 +629,9 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`); ) { if (this.registry[name]) callback(this.registry[name]); // @ts-ignore - this.ctx.on(`handler/register/${name}`, callback); + const dispose = this.ctx.on(`handler/register/${name}`, callback); this[Context.current]?.on('dispose', () => { - // @ts-ignore - this.ctx.off(`handler/register/${name}`, callback); + dispose(); }); } diff --git a/framework/register/package.json b/framework/register/package.json index 8a7f9dacb..712949235 100644 --- a/framework/register/package.json +++ b/framework/register/package.json @@ -7,7 +7,7 @@ "node": ">=16" }, "dependencies": { - "esbuild": "0.23.0", + "esbuild": "0.24.0", "source-map-support": "^0.5.21" }, "devDependencies": { diff --git a/install/install.sh b/install/install.sh index 947ce03d1..b77cffa83 100644 --- a/install/install.sh +++ b/install/install.sh @@ -8,7 +8,7 @@ if [ $EUID != 0 ]; then exit $? fi set -e -echo "Executing Hydro install script v3.0.0" +echo "Executing Hydro install script v3.0.1" echo "Hydro includes system telemetry, which helps developers figure out the most commonly used operating system and platform. To disable this feature, checkout our sourcecode." @@ -22,6 +22,7 @@ echo "// File created by Hydro install script\n" >/tmp/install.js cat >/tmp/install.b64 << EOF123 %PLACEHOLDER% EOF123 -cat /tmp/install.b64 | base64 -d >>/tmp/install.js +cat /tmp/install.b64 | base64 -d >>/tmp/install.js +rm /tmp/install.b64 node /tmp/install.js "$@" set +e diff --git a/install/install.ts b/install/install.ts index f8df6392a..d92691794 100644 --- a/install/install.ts +++ b/install/install.ts @@ -483,7 +483,10 @@ ${nixConfBase}`); `pm2 start mongod --name mongodb -e /dev/null -- --auth --bind_ip 0.0.0.0 --wiredTigerCacheSizeGB=${wtsize}`, () => sleep(1000), async () => { - if (noCaddy) return; + if (noCaddy) { + exec('hydrooj cli system set server.host 0.0.0.0'); + return; + } if (!await isPortFree(80)) log.warn('port.80'); if (migration === 'hustoj') { exec('systemctl stop nginx || true'); diff --git a/package.json b/package.json index 6444f5ee4..00c2b9e49 100644 --- a/package.json +++ b/package.json @@ -35,16 +35,16 @@ "devDependencies": { "@simplewebauthn/types": "9.0.1", "@types/autocannon": "^7.12.5", - "@types/chai": "^4.3.20", + "@types/chai": "^5.0.0", "@types/cross-spawn": "^6.0.6", - "@types/node": "20.12.12", + "@types/node": "22.7.4", "@types/semver": "^7.5.8", "autocannon": "^7.15.0", "cac": "^6.7.14", "chai": "^5.1.1", "cross-env": "^7.0.3", "cross-spawn": "^7.0.3", - "esbuild": "0.23.0", + "esbuild": "0.24.0", "eslint": "^8.57.1", "eslint-import-resolver-typescript": "^3.6.3", "eslint-import-resolver-webpack": "^0.13.9", @@ -58,11 +58,10 @@ "semver": "^7.6.3", "simple-git": "^3.27.0", "supertest": "^7.0.0", - "typescript": "5.3.3", + "typescript": "5.6.2", "wtfnode": "^0.9.3" }, "resolutions": { - "@cordisjs/logger": "0.3.2", - "reggol": "1.6.3" + "monaco-editor": "0.50.0" } } diff --git a/packages/geoip/index.ts b/packages/geoip/index.ts index f3a8b6678..b2e4a00ed 100644 --- a/packages/geoip/index.ts +++ b/packages/geoip/index.ts @@ -36,6 +36,5 @@ export default class GeoIPService extends Service { } export async function apply(ctx: Context) { - ctx.provide('geoip'); - ctx.geoip = new GeoIPService(ctx); + ctx.set('geoip', new GeoIPService(ctx)); } diff --git a/packages/geoip/package.json b/packages/geoip/package.json index ba95ce937..ded9e2236 100644 --- a/packages/geoip/package.json +++ b/packages/geoip/package.json @@ -6,7 +6,7 @@ "author": "undefined ", "license": "AGPL-3.0-or-later", "dependencies": { - "maxmind": "^4.3.21" + "maxmind": "^4.3.22" }, "preferUnplugged": true } diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index afaec738e..2eac321b3 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -12,10 +12,10 @@ }, "preferUnplugged": true, "dependencies": { - "@aws-sdk/client-s3": "3.658.1", - "@aws-sdk/lib-storage": "3.658.1", - "@aws-sdk/s3-presigned-post": "3.658.1", - "@aws-sdk/s3-request-presigner": "3.658.1", + "@aws-sdk/client-s3": "3.662.0", + "@aws-sdk/lib-storage": "3.662.0", + "@aws-sdk/s3-presigned-post": "3.662.0", + "@aws-sdk/s3-request-presigner": "3.662.0", "@graphql-tools/schema": "^10.0.6", "@hydrooj/framework": "workspace:^", "@hydrooj/utils": "workspace:^", @@ -24,7 +24,7 @@ "@yarnpkg/libzip": "^3.1.0", "adm-zip": "0.5.14", "cac": "^6.7.14", - "cordis": "3.16.0", + "cordis": "3.18.1", "detect-browser": "^5.3.0", "emoji-regex": "^10.4.0", "emojis-list": "2.1.0", @@ -66,7 +66,7 @@ "@types/saslprep": "^1.0.3", "@types/semver": "^7.5.8", "@types/superagent": "^8.1.9", - "chokidar": "^3.6.0", + "chokidar": "^4.0.1", "moment": "^2.30.1" } } diff --git a/packages/hydrooj/src/handler/user.ts b/packages/hydrooj/src/handler/user.ts index 91ea0676f..5866fd224 100644 --- a/packages/hydrooj/src/handler/user.ts +++ b/packages/hydrooj/src/handler/user.ts @@ -506,7 +506,7 @@ export async function apply(ctx: Context) { ctx.Route('user_lostpass', '/lostpass', UserLostPassHandler); ctx.Route('user_lostpass_with_code', '/lostpass/:code', UserLostPassWithCodeHandler); ctx.Route('user_delete', '/user/delete', UserDeleteHandler, PRIV.PRIV_USER_PROFILE); - ctx.Route('user_detail', '/user/:uid(-?\\d+)', UserDetailHandler); + ctx.Route('user_detail', '/user/:uid', UserDetailHandler); if (system.get('server.contestmode')) { ctx.Route('contest_mode', '/contestmode', ContestModeHandler, PRIV.PRIV_EDIT_SYSTEM); } diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index eec84a52d..60c04d3a5 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -28,6 +28,7 @@ export interface SystemKeys { 'server.url': string, 'server.xff': string, 'server.xhost': string, + 'server.host': string, 'server.port': number, 'server.language': string, 'limit.problem_files_max': number, diff --git a/packages/hydrooj/src/model/setting.ts b/packages/hydrooj/src/model/setting.ts index b4a0e43ec..2d66fde0f 100644 --- a/packages/hydrooj/src/model/setting.ts +++ b/packages/hydrooj/src/model/setting.ts @@ -246,6 +246,7 @@ SystemSetting( Setting('setting_server', 'server.upload', '256m', 'text', 'server.upload', 'Max upload file size'), Setting('setting_server', 'server.cdn', '/', 'text', 'server.cdn', 'CDN Prefix'), Setting('setting_server', 'server.ws', '/', 'text', 'server.ws', 'WebSocket Prefix'), + Setting('setting_server', 'server.host', '127.0.0.1', 'text', 'server.host', 'Listen host'), Setting('setting_server', 'server.port', 8888, 'number', 'server.port', 'Server Port'), Setting('setting_server', 'server.xff', null, 'text', 'server.xff', 'IP Header'), Setting('setting_server', 'server.xhost', null, 'text', 'server.xhost', 'Hostname Header'), @@ -312,7 +313,6 @@ export class SettingService extends Service { SystemSetting = T(SystemSetting); constructor(ctx: Context) { super(ctx, 'setting', true); - ctx.mixin('setting', ['PreferenceSetting', 'AccountSetting', 'DomainSetting', 'DomainUserSetting', 'SystemSetting']); } get(key: string) { diff --git a/packages/hydrooj/src/service/server.ts b/packages/hydrooj/src/service/server.ts index 13c7d7397..48de0520c 100644 --- a/packages/hydrooj/src/service/server.ts +++ b/packages/hydrooj/src/service/server.ts @@ -138,6 +138,7 @@ export async function apply(ctx: Context) { cors: system.get('server.cors') || '', upload: system.get('server.upload') || '256m', port: argv.options.port || system.get('server.port'), + host: argv.options.host || system.get('server.host'), xff: system.get('server.xff'), xhost: system.get('server.xhost'), }); diff --git a/packages/hydrooj/src/service/watcher.ts b/packages/hydrooj/src/service/watcher.ts index 63c601a8b..8de73ed8d 100644 --- a/packages/hydrooj/src/service/watcher.ts +++ b/packages/hydrooj/src/service/watcher.ts @@ -49,8 +49,9 @@ export default class Watcher extends Service { if (process.env.WATCH_ROOT) roots.push(process.env.WATCH_ROOT); this.watcher = watch(roots, { ...this.config, - ignored: ['node_modules', '.git', 'logs', '.cache', '.yarn'] - .map((i) => `**/${i}/**`).concat('**/tsconfig.tsbuildinfo'), + ignored: (file) => [ + 'node_modules', '.git', 'logs', '.cache', '.yarn', 'tsconfig.tsbuildinfo', + ].some((rule) => file.startsWith(`${rule}/`) || file.endsWith(`/${rule}`) || file.includes(`/${rule}/`)), }); logger.info(`Start watching changes in ${this.root}`); diff --git a/packages/prom-client/metrics.ts b/packages/prom-client/metrics.ts index f523adbcc..417c7afd6 100644 --- a/packages/prom-client/metrics.ts +++ b/packages/prom-client/metrics.ts @@ -75,7 +75,6 @@ export function createRegistry(ctx: Context) { collectDefaultMetrics({ register: registry }); - ctx.provide('metrics'); - ctx.metrics = registry; + ctx.set('metrics', registry); return registry; } diff --git a/packages/ui-default/components/scratchpad/index.tsx b/packages/ui-default/components/scratchpad/index.tsx index e20e18095..2f215f931 100644 --- a/packages/ui-default/components/scratchpad/index.tsx +++ b/packages/ui-default/components/scratchpad/index.tsx @@ -62,8 +62,7 @@ declare module '../../context' { export default function ScratchpadContainer() { const store = useStore(); - ctx.provide('scratchpad'); - ctx.scratchpad ||= new ScratchpadService(store); + ctx.set('scratchpad', new ScratchpadService(store)); const [, updateState] = React.useState(); const forceUpdate = React.useCallback(() => updateState({}), []); React.useEffect(() => { diff --git a/packages/ui-default/package.json b/packages/ui-default/package.json index 94a312327..73dc72033 100644 --- a/packages/ui-default/package.json +++ b/packages/ui-default/package.json @@ -15,7 +15,7 @@ }, "devDependencies": { "@blueprintjs/core": "^5.13.0", - "@cordisjs/core": "3.17.3", + "@cordisjs/core": "3.18.1", "@fontsource/dm-mono": "^5.1.0", "@fontsource/fira-code": "^5.1.0", "@fontsource/inconsolata": "^5.1.0", @@ -37,7 +37,7 @@ "@types/nunjucks": "^3.2.6", "@types/pickadate": "^3.5.35", "@types/qrcode": "^1.5.5", - "@types/react": "^18.3.9", + "@types/react": "^18.3.10", "@types/react-dom": "^18.3.0", "@types/redux-logger": "^3.0.13", "@types/uuid": "^10.0.0", @@ -46,7 +46,7 @@ "ajv": "^8.17.1", "allotment": "^1.20.2", "autoprefixer": "^10.4.20", - "browser-update": "^3.3.53", + "browser-update": "^3.3.54", "chalk": "^5.3.0", "classnames": "^2.5.1", "clean-webpack-plugin": "^4.0.0", @@ -124,7 +124,7 @@ "dependencies": { "ansi_up": "^6.0.2", "cssfilter": "^0.0.11", - "esbuild": "0.23.0", + "esbuild": "0.24.0", "fs-extra": "^11.2.0", "js-yaml": "^4.1.0", "jsesc": "^3.0.2", diff --git a/packages/ui-default/pages/home_messages.page.tsx b/packages/ui-default/pages/home_messages.page.tsx index e18a612db..01cd67959 100644 --- a/packages/ui-default/pages/home_messages.page.tsx +++ b/packages/ui-default/pages/home_messages.page.tsx @@ -43,8 +43,7 @@ const page = new NamedPage('home_messages', () => { reduxStore = store; (window as any).store = reduxStore; - ctx.provide('messagepad'); - ctx.messagepad = new MessagePadService(store, WebSocket); + ctx.set('messagepad', new MessagePadService(store, WebSocket)); const sock = new WebSocket(`${UiContext.ws_prefix}home/messages-conn`); sock.onmessage = (message) => { diff --git a/packages/ui-default/pages/problem_detail.page.tsx b/packages/ui-default/pages/problem_detail.page.tsx index b7ada19bd..2d87319b5 100644 --- a/packages/ui-default/pages/problem_detail.page.tsx +++ b/packages/ui-default/pages/problem_detail.page.tsx @@ -115,8 +115,8 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor } async function scratchpadFadeIn() { - // @ts-ignore await $('#scratchpad') + // @ts-ignore .transition( { opacity: 1 }, { duration: 200, easing: 'easeOutCubic' }, @@ -125,8 +125,8 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor } async function scratchpadFadeOut() { - // @ts-ignore await $('#scratchpad') + // @ts-ignore .transition( { opacity: 0 }, { duration: 200, easing: 'easeOutCubic' }, diff --git a/packages/utils/lib/utils.ts b/packages/utils/lib/utils.ts index eec732c7a..01ff2759f 100644 --- a/packages/utils/lib/utils.ts +++ b/packages/utils/lib/utils.ts @@ -69,7 +69,8 @@ String.prototype.format = function formatStr(...args) { export function isClass(obj: any, strict = false): obj is new (...args: any) => any { if (typeof obj !== 'function') return false; if (obj.prototype === undefined) return false; - if (obj.prototype.constructor !== obj) return false; + // FIXME cordis proxies the object and make this assertion fail + // if (obj.prototype.constructor !== obj) return false; if (Object.getOwnPropertyNames(obj.prototype).length >= 2) return true; const str = obj.toString(); if (str.slice(0, 5) === 'class') return true; diff --git a/packages/utils/package.json b/packages/utils/package.json index fbebd382d..5600f56b5 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -14,7 +14,7 @@ "js-yaml": "^4.1.0", "moment-timezone": "^0.5.45", "mongodb": "^5.9.2", - "reggol": "^1.6.3", + "reggol": "^1.7.0", "search-query-parser": "^1.6.0", "systeminformation": "^5.23.5" },