From 2344a41816b9d495be5a7b473583e78924141431 Mon Sep 17 00:00:00 2001 From: undefined Date: Mon, 8 Mar 2021 14:07:26 +0800 Subject: [PATCH] core: add projection for discussion --- packages/hydrooj/package.json | 2 +- packages/hydrooj/src/interface.ts | 51 +++++++++--------- packages/hydrooj/src/model/discussion.ts | 68 +++++++++++++++++++++--- packages/hydrooj/src/model/document.ts | 18 +++---- packages/hydrooj/src/model/problem.ts | 6 +-- 5 files changed, 99 insertions(+), 46 deletions(-) diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index ae785ef57..e36564406 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "2.20.10", + "version": "2.20.11", "bin": "bin/hydrooj.js", "main": "dist/loader.js", "typings": "dist/loader.d.ts", diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 4ad17f90f..0d6755f41 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -162,13 +162,19 @@ export interface SampleContentNode { export type ContentNode = PlainContentNode | TextContentNode | SampleContentNode; export type Content = string | ContentNode[] | Record; +export interface Document { + _id: ObjectID, + docId: any, + docType: number, + domainId: string, + owner: number, +} + declare module './model/problem' { interface Pdoc { - domainId: string, - docType: 10, + docType: document['TYPE_PROBLEM'], docId: number, pid: string, - owner: number, title: string, content: Content, nSubmit: number, @@ -202,14 +208,6 @@ export interface StatusDoc { uid: number, } -export interface Document { - _id: ObjectID, - docId: any, - docType: number, - domainId: string, - owner: number, -} - export interface ProblemStatusDoc extends StatusDoc { docId: number, docType: 10, @@ -339,20 +337,23 @@ export interface HistoryDoc { } // Discussion -export interface Ddoc extends Document { - docType: document['TYPE_DISCUSSION'], - docId: ObjectID, - parentType: number, - parentId: ObjectID | number | string, - title: string, - content: string, - ip: string, - pin: boolean, - highlight: boolean, - updateAt: Date, - nReply: number, - views: number, - history: HistoryDoc[], +export { Ddoc } from './model/discussion'; +declare module './model/discussion' { + interface Ddoc { + docType: document['TYPE_DISCUSSION'], + docId: ObjectID, + parentType: number, + parentId: ObjectID | number | string, + title: string, + content: string, + ip: string, + pin: boolean, + highlight: boolean, + updateAt: Date, + nReply: number, + views: number, + history: HistoryDoc[], + } } // Discussion reply diff --git a/packages/hydrooj/src/model/discussion.ts b/packages/hydrooj/src/model/discussion.ts index 23b6813e0..f4aefb06c 100644 --- a/packages/hydrooj/src/model/discussion.ts +++ b/packages/hydrooj/src/model/discussion.ts @@ -4,9 +4,57 @@ import * as contest from './contest'; import * as training from './training'; import * as document from './document'; import { DocumentNotFoundError } from '../error'; -import { Ddoc, Drdoc, Drrdoc } from '../interface'; +import { Drdoc, Drrdoc, Document } from '../interface'; +import { buildProjection } from '../utils'; import * as bus from '../service/bus'; +export interface Ddoc extends Document { } +export namespace Ddoc { + export type Field = keyof Ddoc; + export const fields: Field[] = []; + type Getter = () => Partial; + const getters: Getter[] = []; + export function extend(getter: Getter) { + getters.push(getter); + fields.push(...Object.keys(getter()) as any); + } + + extend(() => ({ + _id: new ObjectID(), + domainId: 'system', + docType: document.TYPE_DISCUSSION, + docId: new ObjectID(), + owner: 1, + title: '*', + content: '', + parentId: new ObjectID(), + ip: '1.1.1.1', + pin: false, + highlight: false, + updateAt: new Date(), + nReply: 0, + views: 0, + history: [], + })); + + export function create() { + const result = {} as Ddoc; + for (const getter of getters) { + Object.assign(result, getter()); + } + return result; + } +} + +export const PROJECTION_LIST: Ddoc.Field[] = [ + '_id', 'domainId', 'docType', 'docId', 'highlight', + 'nReply', 'views', 'pin', 'updateAt', 'owner', + 'parentId', 'parentType', +]; +export const PROJECTION_PUBLIC: Ddoc.Field[] = [ + ...PROJECTION_LIST, 'content', 'history', +]; + export const typeDisplay = { [document.TYPE_PROBLEM]: 'problem', [document.TYPE_CONTEST]: 'contest', @@ -35,8 +83,9 @@ export function add( ); } -export function get(domainId: string, did: ObjectID): Promise { - return document.get(domainId, document.TYPE_DISCUSSION, did); +// FIXME typings doesn't work +export function get(domainId: string, did: ObjectID, projection: T[] = PROJECTION_PUBLIC as any): Promise> { + return document.get(domainId, document.TYPE_DISCUSSION, did, projection); } export function edit( @@ -48,23 +97,24 @@ export function edit( }); } -export function del(domainId: string, did: ObjectID) { +export function del(domainId: string, did: ObjectID): Promise { return Promise.all([ document.deleteOne(domainId, document.TYPE_DISCUSSION, did), document.deleteMulti(domainId, document.TYPE_DISCUSSION_REPLY, { parentType: document.TYPE_DISCUSSION, parentId: did, }), document.deleteMultiStatus(domainId, document.TYPE_DISCUSSION, { docId: did }), - ]); + ]) as any; } export function count(domainId: string, query: FilterQuery) { return document.count(domainId, document.TYPE_DISCUSSION, query); } -export function getMulti(domainId: string, query: FilterQuery = {}) { +export function getMulti(domainId: string, query: FilterQuery = {}, projection = PROJECTION_LIST) { return document.getMulti(domainId, document.TYPE_DISCUSSION, query) - .sort({ pin: -1, updateAt: -1 }); + .sort({ pin: -1, updateAt: -1 }) + .project(buildProjection(projection)); } export async function addReply( @@ -234,6 +284,10 @@ bus.on('problem/delete', async (domainId, docId) => { global.Hydro.model.discussion = { typeDisplay, + Ddoc, + PROJECTION_LIST, + PROJECTION_PUBLIC, + add, get, edit, diff --git a/packages/hydrooj/src/model/document.ts b/packages/hydrooj/src/model/document.ts index 9a8828af9..5d8e8a7ca 100644 --- a/packages/hydrooj/src/model/document.ts +++ b/packages/hydrooj/src/model/document.ts @@ -17,15 +17,15 @@ type DocID = ObjectID | string | number; export const coll = db.collection('document'); export const collStatus = db.collection('document.status'); -export const TYPE_PROBLEM = 10; -export const TYPE_PROBLEM_SOLUTION = 11; -export const TYPE_PROBLEM_LIST = 12; -export const TYPE_DISCUSSION_NODE = 20; -export const TYPE_DISCUSSION = 21; -export const TYPE_DISCUSSION_REPLY = 22; -export const TYPE_CONTEST = 30; -export const TYPE_TRAINING = 40; -export const TYPE_HOMEWORK = 60; +export const TYPE_PROBLEM: 10 = 10; +export const TYPE_PROBLEM_SOLUTION: 11 = 11; +export const TYPE_PROBLEM_LIST: 12 = 12; +export const TYPE_DISCUSSION_NODE: 20 = 20; +export const TYPE_DISCUSSION: 21 = 21; +export const TYPE_DISCUSSION_REPLY: 22 = 22; +export const TYPE_CONTEST: 30 = 30; +export const TYPE_TRAINING: 40 = 40; +export const TYPE_HOMEWORK: 60 = 60; export interface DocType { [TYPE_PROBLEM]: Pdoc, diff --git a/packages/hydrooj/src/model/problem.ts b/packages/hydrooj/src/model/problem.ts index 21ca8ada9..eaebac635 100644 --- a/packages/hydrooj/src/model/problem.ts +++ b/packages/hydrooj/src/model/problem.ts @@ -5,16 +5,14 @@ import { STATUS } from './builtin'; import * as document from './document'; import * as domain from './domain'; import { buildProjection } from '../utils'; -import { ProblemStatusDoc, Pdict } from '../interface'; +import type { ProblemStatusDoc, Pdict, Document } from '../interface'; import { Content } from '../loader'; import { ArrayKeys, NumberKeys, Projection } from '../typeutils'; import { ProblemNotFoundError } from '../error'; import storage from '../service/storage'; import * as bus from '../service/bus'; -export interface Pdoc { - _id: ObjectID -} +export interface Pdoc extends Document { } export namespace Pdoc { export type Field = keyof Pdoc; export const fields: Field[] = [];