diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index 14e6fb55a..c100e3131 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "3.1.10", + "version": "3.1.11", "bin": "bin/hydrooj.js", "main": "src/loader", "module": "src/loader", @@ -12,6 +12,7 @@ }, "preferUnplugged": true, "dependencies": { + "@graphql-tools/schema": "^8.3.1", "@hydrooj/utils": "workspace:*", "adm-zip": "0.5.5", "ansi_up": "^5.0.1", diff --git a/packages/hydrooj/src/handler/api.ts b/packages/hydrooj/src/handler/api.ts index 2a0f66767..506228f0e 100644 --- a/packages/hydrooj/src/handler/api.ts +++ b/packages/hydrooj/src/handler/api.ts @@ -1,4 +1,5 @@ -import graphql from 'graphql'; +import { makeExecutableSchema } from '@graphql-tools/schema'; +import { graphql, GraphQLSchema } from 'graphql'; import { resolvers, typeDefs } from 'graphql-scalars'; import * as bus from '../service/bus'; import { Handler, Route } from '../service/server'; @@ -6,7 +7,9 @@ import { Handler, Route } from '../service/server'; const types: Record> = {}; const unions: Record = {}; const descriptions: Record> = {}; -const handlers: Record> = {}; +const handlers: Record> = { + Query: {}, +}; let root: Record = {}; export function registerValue(typeName: string, key: string, value: string, description?: string): void; @@ -51,30 +54,32 @@ function setDescription(desc: string) { return JSON.stringify(desc); } -function buildSchemaStr() { - let res = `${Object.keys(unions).map((i) => `union ${i} = ${unions[i]}`)}\n${typeDefs.join('\n')}\n`; - for (const key in types) { - if (descriptions[key]?._description) res += `${setDescription(descriptions[key]._description)}\n`; - res += `type ${key}{\n`; - for (const k in types[key]) { - if (descriptions[key]?.[k]) res += ` ${setDescription(descriptions[key][k])}\n`; - res += ` ${k}: ${types[key][k]}\n`; - } - res += '}\n'; - } - return res; -} - -let schemaStr = buildSchemaStr(); -let schema = graphql.buildSchema(schemaStr); -root = { ...handlers.Query, ...resolvers }; +let schema: GraphQLSchema; +let schemaStr = ''; +root = handlers.Query; export function rebuild() { try { - const str = buildSchemaStr(); - schema = graphql.buildSchema(str); - schemaStr = str; - root = { ...handlers.Query, ...resolvers }; + const defs = [ + ...Object.keys(unions).map((i) => `union ${i} = ${unions[i]}`), + ...typeDefs, + ...Object.keys(types).map((key) => { + let def = ''; + if (descriptions[key]?._description) def += `${setDescription(descriptions[key]._description)}\n`; + def += `type ${key}{\n`; + for (const k in types[key]) { + if (descriptions[key]?.[k]) def += ` ${setDescription(descriptions[key][k])}\n`; + def += ` ${k}: ${types[key][k]}\n`; + } + def += '}\n'; + return def; + }), + ]; + schema = makeExecutableSchema({ + typeDefs: defs, + resolvers, + }); + schemaStr = defs.join('\n'); } catch (e) { console.error(e); } @@ -85,6 +90,11 @@ bus.on('app/started', () => { }); class ApiHandler extends Handler { + async query(q: string, variables: any) { + // FIXME validation for fields like ObjectID doesn't work. + return graphql(schema, q, root, this, variables); + } + async get() { const q = decodeURIComponent(this.ctx.request.querystring); if (q === 'schema') { @@ -92,15 +102,10 @@ class ApiHandler extends Handler { this.response.body = { schema: schemaStr }; } else if (q) { this.response.type = 'application/json'; - this.response.body = await graphql.graphql(schema, q, root, this); + this.response.body = await this.query(q, {}); } else this.response.template = 'api.html'; } - async query(q: string, variables: any) { - // FIXME validation for fields like ObjectID doesn't work. - return graphql.graphql(schema, q, root, this, variables); - } - async post() { this.response.type = 'application/json'; this.response.body = await this.query(this.args.query, this.args.variables); diff --git a/packages/hydrooj/src/handler/judge.ts b/packages/hydrooj/src/handler/judge.ts index 7a5359a25..930a29f4c 100644 --- a/packages/hydrooj/src/handler/judge.ts +++ b/packages/hydrooj/src/handler/judge.ts @@ -167,7 +167,7 @@ class JudgeConnectionHandler extends ConnectionHandler { } async message(msg) { - if (msg.key !== 'ping') logger[['status', 'next'].includes(msg.key) ? 'debug' : 'info']('%o', msg); + if (msg.key !== 'ping' && msg.key !== 'prio') logger[['status', 'next'].includes(msg.key) ? 'debug' : 'info']('%o', msg); if (msg.key === 'next') await next(msg); else if (msg.key === 'end') { await end({ judger: this.user._id, ...msg }).catch((e) => logger.error(e)); diff --git a/packages/hydrooj/src/handler/problem.ts b/packages/hydrooj/src/handler/problem.ts index f83230003..b61d11e34 100644 --- a/packages/hydrooj/src/handler/problem.ts +++ b/packages/hydrooj/src/handler/problem.ts @@ -76,7 +76,7 @@ registerResolver( ); registerResolver( 'Problem', 'manage', 'ProblemManage', - async (arg, ctx) => { + (arg, ctx) => { if (!ctx.user.own(ctx.pdoc, PERM.PERM_EDIT_PROBLEM_SELF)) ctx.checkPerm(PERM.PERM_EDIT_PROBLEM); return {}; },