文件结构更改

pull/10/head
undefined 4 years ago
parent b3af28dc43
commit 1f1d12ad73

@ -0,0 +1,3 @@
dist
*.d.ts
*.js

@ -1,20 +1,39 @@
name: Build
name: CI
on:
push:
branches:
- master
- push
- pull_request
env:
CI: true
jobs:
build:
name: Build
runs-on: ubuntu-latest
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- name: Check out
uses: actions/checkout@v1
- name: Set up Node
uses: actions/setup-node@v1
with:
node-version: '13.x'
- run: |
yarn
yarn build
- uses: JS-DevTools/npm-publish@v1
node-version: 13.x
- name: Create .npmrc
run: 'echo "//registry.npmjs.org/:_authToken=${{secrets.NPM_TOKEN}}" > .npmrc'
- name: Install
run: yarn
- name: Build
run: yarn build
- name: Lint
run: yarn lint
- name: Unit Test
run: yarn jest --runInBand
- name: Report Coverage
uses: codecov/codecov-action@v1
with:
token: ${{ secrets.NPM_TOKEN }}
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage/lcov.info
name: codecov
- name: Publish
run: node build/publish.js

11
.gitignore vendored

@ -2,8 +2,6 @@ node_modules/
config.yaml
config.json
.build/
*.build
public/
dist/
.cache/
*.cache
@ -11,5 +9,14 @@ __*
ui/misc/.iconfont
ui/static/locale
*.log
*.d.ts
build/*.js
*.js.map
*.hydro
!.gitkeep
tsconfig.tsbuildinfo
yarn.lock
packages/**/*.js
packages/**/*.js.map
packages/**/*.d.ts

@ -1,14 +0,0 @@
node_modules/
ui/
config.yaml
config.json
.cache/
*.cache
__*
*.log
*.hydro
locales
templates
.vscode
.github
examples

@ -1,21 +0,0 @@
{
// 使 IntelliSense
//
// 访: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": [
"<node_internals>/**"
],
"program": "${workspaceFolder}/.build/app.js",
"preLaunchTask": "npm: build",
"outFiles": [
"${workspaceFolder}/dist/**/*.js"
]
}
]
}

13
.vscode/tasks.json vendored

@ -1,13 +0,0 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "build",
"group": "build",
"problemMatcher": [],
"label": "npm: build",
"detail": "node build --development"
}
]
}

@ -3,7 +3,6 @@
Hydro是一个高效的信息学在线测评系统。特点易于部署轻量功能强大且易于扩展。
[中文文档](https://hydro.js.org/)
[Hydro UI 传送门](https://github.com/hydro-dev/ui-default)
如果您认为本项目有价值,欢迎 star 。
相关文档若说明的不够详细,请提交 Pull Request 或联系开发组说明。

@ -1,56 +0,0 @@
#!/usr/bin/env node
const os = require('os');
const path = require('path');
const cluster = require('cluster');
const fs = require('fs-extra');
const { argv } = require('yargs');
const hydro = require('../dist/loader');
if (!cluster.isMaster) {
// Forked by hydro
hydro.load().catch((e) => {
console.error(e);
process.exit(1);
});
} else {
fs.ensureDirSync(path.resolve(os.homedir(), '.hydro'));
const addonPath = path.resolve(os.homedir(), '.hydro', 'addon.json');
if (!fs.existsSync(addonPath)) fs.writeFileSync(addonPath, '[]');
let addons = JSON.parse(fs.readFileSync(addonPath).toString());
try {
const ui = argv.ui || '@hydrooj/ui-default';
require.resolve(ui);
addons.push(ui);
} catch (e) {
console.error('Please also install @hydrooj/ui-default');
}
if (argv._[0] && argv._[0] !== 'cli') {
const operation = argv._[0];
const arg1 = argv._[1];
const arg2 = argv._[2];
if (operation === 'addon') {
if (arg1 === 'add') addons.push(arg2);
else if (arg1 === 'remove') {
for (let i = 0; i < addons.length; i++) {
if (addons[i] === arg2) {
addons.splice(i, 1);
break;
}
}
}
addons = Array.from(new Set(addons));
console.log('Current Addons: ', addons);
fs.writeFileSync(addonPath, JSON.stringify(addons, null, 2));
}
} else {
addons = Array.from(new Set(addons));
for (const addon of addons) hydro.addon(addon);
(argv._[0] === 'cli' ? hydro.loadCli : hydro.load)().catch((e) => {
console.error(e);
process.exit(1);
});
}
}

@ -0,0 +1,25 @@
/* eslint-disable import/no-extraneous-dependencies */
import spawn from 'cross-spawn';
const args = ['jest', '--coverage'];
const [, , argv2, argv3] = process.argv;
if (argv2 && !argv2.startsWith('-')) {
args.push(argv2);
if (argv3 && !argv3.startsWith('-')) {
args.push('--collectCoverageFrom');
if (argv3.endsWith('.ts')) {
args.push(`**/${argv3}`);
} else {
args.push(`**/${argv3}/**/*.ts`);
}
args.push(...process.argv.slice(4));
} else {
args.push(...process.argv.slice(3));
}
} else {
args.push('packages/.+\\.spec\\.ts', ...process.argv.slice(2));
}
spawn('npx', args, { stdio: 'inherit' });

@ -0,0 +1,54 @@
/* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable consistent-return */
/* eslint-disable no-await-in-loop */
/* eslint-disable import/no-dynamic-require */
import { gt } from 'semver';
import latest from 'latest-version';
import ora from 'ora';
import {
PackageJson, getWorkspaces, spawnAsync,
} from './utils';
const {
CI, GITHUB_EVENT_NAME, GITHUB_REF,
} = process.env;
if (CI && (GITHUB_REF !== 'refs/heads/master' || GITHUB_EVENT_NAME !== 'push')) {
console.log('publish skipped.');
process.exit(0);
}
(async () => {
let folders = await getWorkspaces();
if (process.argv[2]) {
folders = folders.filter((path) => path.startsWith(process.argv[2]));
}
const spinner = ora();
const bumpMap: Record<string, string> = {};
let progress = 0;
spinner.start(`Loading workspaces (0/${folders.length})`);
await Promise.all(folders.map(async (name) => {
let meta: PackageJson;
try {
meta = require(`../${name}/package`);
if (!meta.private) {
const version = await latest(meta.name);
if (gt(meta.version, version)) {
bumpMap[name] = meta.version;
}
}
} catch { /* pass */ }
spinner.text = `Loading workspaces (${++progress}/${folders.length})`;
}));
spinner.succeed();
if (Object.keys(bumpMap).length) {
for (const name in bumpMap) {
console.log(`publishing ${name}@${bumpMap[name]} ...`);
await spawnAsync(`yarn publish ${name} --new-version ${bumpMap[name]} --access public`);
}
}
console.log('Release created successfully.');
})();

@ -0,0 +1,42 @@
import path from 'path';
import globby from 'globby';
import spawn from 'cross-spawn';
export const cwd = path.resolve(__dirname, '..');
export function getWorkspaces() {
return globby(require('../package').workspaces, {
cwd,
deep: 0,
onlyDirectories: true,
expandDirectories: false,
});
}
export type DependencyType = 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies'
export interface PackageJson extends Partial<Record<DependencyType, Record<string, string>>> {
name?: string
private?: boolean
version?: string
}
export function spawnSync(command: string, silent?: boolean) {
if (!silent) console.log(`$ ${command}`);
const args = command.split(/\s+/);
const result = spawn.sync(args[0], [...args.slice(1), '--color'], { cwd, encoding: 'utf8' });
if (result.status) {
throw new Error(result.stderr);
} else {
if (!silent) console.log(result.stdout);
return result.stdout.trim();
}
}
export function spawnAsync(command: string) {
const args = command.split(/\s+/);
const child = spawn(args[0], args.slice(1), { stdio: 'inherit' });
return new Promise((resolve, reject) => {
child.on('close', resolve);
});
}

@ -0,0 +1,22 @@
module.exports = {
globals: {
'ts-jest': {
diagnostics: {
warnOnly: true,
},
},
},
preset: 'ts-jest',
testEnvironment: 'node',
moduleFileExtensions: ['ts', 'js', 'json'],
moduleNameMapper: {
'[\\w-]+': '<rootDir>/packages/$0/src',
},
coverageProvider: 'v8',
coverageReporters: ['text', 'lcov'],
coveragePathIgnorePatterns: [
'node_modules/',
'tests/',
'dist/',
],
};

@ -1,81 +1,35 @@
{
"name": "hydrooj",
"version": "2.12.1",
"main": "dist/loader.js",
"bin": "bin/hydrooj.js",
"repository": "https://github.com/hydro-dev/Hydro.git",
"author": "masnn",
"license": "GPL-3.0-only",
"engines": {
"node": ">=10.10"
},
"dependencies": {
"adm-zip": "^0.4.16",
"ansi_up": "^4.0.4",
"cookies": "^0.8.0",
"detect-browser": "^5.1.1",
"fs-extra": "^9.0.1",
"html-to-text": "^5.1.1",
"js-yaml": "^3.13.1",
"koa": "^2.13.0",
"koa-body": "^4.2.0",
"koa-morgan": "^1.0.1",
"koa-router": "^8.0.8",
"koa-static-cache": "^5.1.3",
"lodash": "^4.17.19",
"lru-cache": "^6.0.0",
"markdown-it": "^11.0.0",
"markdown-it-anchor": "^5.3.0",
"markdown-it-footnote": "^3.0.2",
"markdown-it-imsize": "^2.0.1",
"markdown-it-mark": "^3.0.0",
"markdown-it-table-of-contents": "^0.4.4",
"moment-timezone": "^0.5.31",
"mongodb": "^3.5.9",
"nodemailer": "^6.4.10",
"nunjucks": "^3.2.2",
"prismjs": "^1.20.0",
"proxy-agent": "^3.1.1",
"ps-list": "^7.2.0",
"serialize-javascript": "^4.0.0",
"sockjs": "^0.3.20",
"superagent": "^5.2.2",
"systeminformation": "^4.26.10",
"yargs": "^15.4.1"
},
"devDependencies": {
"@types/adm-zip": "^0.4.33",
"@types/fs-extra": "^9.0.1",
"@types/html-to-text": "^5.1.1",
"@types/js-yaml": "^3.12.5",
"@types/katex": "^0.11.0",
"@types/koa": "^2.11.3",
"@types/koa-morgan": "^1.0.4",
"@types/koa-router": "^7.4.1",
"@types/koa-static-cache": "^5.1.0",
"@types/lodash": "^4.14.158",
"@types/lru-cache": "^5.1.0",
"@types/markdown-it": "^10.0.1",
"@types/mongodb": "^3.5.25",
"@types/node": "^14.0.24",
"@types/nodemailer": "^6.4.0",
"@types/nunjucks": "^3.1.3",
"@types/prismjs": "^1.16.1",
"@types/serialize-javascript": "^4.0.0",
"@types/sockjs": "^0.3.32",
"@types/superagent": "^4.1.8",
"@types/yargs": "^15.0.5",
"@typescript-eslint/eslint-plugin": "^3.7.0",
"@typescript-eslint/parser": "^3.7.0",
"eslint": "^7.5.0",
"eslint-config-airbnb-base": "^14.2.0",
"eslint-import-resolver-typescript": "^2.0.0",
"eslint-plugin-import": "^2.20.2",
"typescript": "^3.9.7"
},
"scripts": {
"build": "tsc",
"build:watch": "tsc --watch",
"lint": "eslint bin hydro tool --ext ts,js --fix"
}
"name": "hydro-workspace",
"private": true,
"workspaces": [
"packages/*"
],
"scripts": {
"build": "tsc -b",
"build:watch": "tsc -b --watch",
"lint": "eslint packages/**/*.ts --fix",
"pub": "node build/publish",
"jest": "node build/jest",
"start": "node_modules/.bin/hydrooj"
},
"version": "1.0.0",
"license": "AGPL-3.0-only",
"devDependencies": {
"@types/cross-spawn": "^6.0.2",
"@types/node": "^14.0.27",
"@typescript-eslint/eslint-plugin": "^3.8.0",
"@typescript-eslint/parser": "^3.8.0",
"cross-spawn": "^7.0.3",
"eslint": "^7.6.0",
"eslint-config-airbnb-base": "^14.2.0",
"eslint-import-resolver-typescript": "^2.2.0",
"eslint-plugin-import": "^2.22.0",
"globby": "^11.0.1",
"jest": "^26.2.2",
"latest-version": "^5.1.0",
"ora": "^4.0.5",
"semver": "^7.3.2",
"ts-jest": "^26.1.4",
"typescript": "^3.9.7"
}
}

@ -0,0 +1 @@
这是Hydro的核心文件。

@ -4,5 +4,4 @@ discussion前端权限节点显示异常?
SETTINGS_PRIVACY.allowRegisteredUsers
model.setting.ui.name
pdoc.secretConfig?
move to @hydrooj/core?
message.markAsRead

@ -0,0 +1,73 @@
{
"name": "hydrooj",
"version": "2.12.1",
"main": "dist/loader.js",
"bin": "bin/hydrooj.js",
"repository": "https://github.com/hydro-dev/Hydro.git",
"author": "masnn",
"license": "GPL-3.0-only",
"engines": {
"node": ">=10.10"
},
"dependencies": {
"adm-zip": "^0.4.16",
"ansi_up": "^4.0.4",
"cookies": "^0.8.0",
"detect-browser": "^5.1.1",
"fs-extra": "^9.0.1",
"html-to-text": "^5.1.1",
"js-yaml": "^3.13.1",
"koa": "^2.13.0",
"koa-body": "^4.2.0",
"koa-morgan": "^1.0.1",
"koa-router": "^8.0.8",
"koa-static-cache": "^5.1.3",
"lodash": "^4.17.19",
"lru-cache": "^6.0.0",
"markdown-it": "^11.0.0",
"markdown-it-anchor": "^5.3.0",
"markdown-it-footnote": "^3.0.2",
"markdown-it-imsize": "^2.0.1",
"markdown-it-mark": "^3.0.0",
"markdown-it-table-of-contents": "^0.4.4",
"moment-timezone": "^0.5.31",
"mongodb": "^3.5.9",
"mongodb-watcher": "^1.3.0",
"nodemailer": "^6.4.10",
"nunjucks": "^3.2.2",
"prismjs": "^1.20.0",
"proxy-agent": "^3.1.1",
"ps-list": "^7.2.0",
"serialize-javascript": "^4.0.0",
"sockjs": "^0.3.20",
"superagent": "^5.2.2",
"systeminformation": "^4.26.10",
"yargs": "^15.4.1"
},
"devDependencies": {
"@types/adm-zip": "^0.4.33",
"@types/fs-extra": "^9.0.1",
"@types/html-to-text": "^5.1.1",
"@types/js-yaml": "^3.12.5",
"@types/katex": "^0.11.0",
"@types/koa": "^2.11.3",
"@types/koa-morgan": "^1.0.4",
"@types/koa-router": "^7.4.1",
"@types/koa-static-cache": "^5.1.0",
"@types/lodash": "^4.14.158",
"@types/lru-cache": "^5.1.0",
"@types/markdown-it": "^10.0.1",
"@types/mongodb": "^3.5.25",
"@types/nodemailer": "^6.4.0",
"@types/nunjucks": "^3.1.3",
"@types/prismjs": "^1.16.1",
"@types/serialize-javascript": "^4.0.0",
"@types/sockjs": "^0.3.32",
"@types/superagent": "^4.1.8",
"@types/yargs": "^15.0.5"
},
"scripts": {
"build": "tsc",
"build:watch": "tsc --watch"
}
}

@ -1,4 +1,5 @@
import mongodb from 'mongodb';
import MongoWatcher from 'mongodb-watcher';
import * as bus from './bus';
import options from '../options';
@ -15,6 +16,12 @@ mongodb.MongoClient.connect(mongourl, { useNewUrlParser: true, useUnifiedTopolog
.then((Client) => {
db = Client.db(opts.name);
global.Hydro.service.db.db = db;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const watcher = new MongoWatcher(db, {
longCursorThreshold: 100,
largeInsertThreshold: 1024 * 30,
largeFetchThreshold: 1024 * 30,
});
bus.publish('system_database_connected', null);
});

@ -278,6 +278,7 @@ export class Handler {
gravatar: misc.gravatar(this.user.gravatar || '', 128),
perm: this.user.perm.toString(),
};
if (!global.Hydro.lib.template) return JSON.stringify(context);
const res = await global.Hydro.lib.template.render(name, {
handler: this,
UserContext,

@ -80,7 +80,7 @@ namespace Proxy {
}
declare module 'superagent' {
interface Request {
interface SuperAgentRequest {
proxy(url: string): this;
}
}

@ -0,0 +1,10 @@
{
"extends": "../../tsconfig.base",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src",
},
"include": [
"src",
]
}

@ -0,0 +1,59 @@
import 'hydrooj';
import superagent from 'superagent';
async function get() {
const { system, token } = global.Hydro.model;
const [appid, [state]] = await Promise.all([
system.get('login-with-github.id'),
token.add(token.TYPE_OAUTH, 600, { redirect: this.request.referer }),
]);
this.response.redirect = `https://github.com/login/oauth/authorize?client_id=${appid}&state=${state}`;
}
async function callback({ state, code }) {
const { system, token } = global.Hydro.model;
const { UserFacingError } = global.Hydro.error;
const [[appid, secret, proxy, url], s] = await Promise.all([
system.getMany([
'login-with-github.id',
'login-with-github.secret',
'login-with-github.proxy',
'server.url',
]),
token.get(state, token.TYPE_OAUTH),
]);
const res = await superagent.post('https://github.com/login/oauth/access_token')
.proxy(proxy)
.send({
client_id: appid,
client_secret: secret,
code,
redirect_uri: `${url}oauth/github/callback`,
state,
})
.set('accept', 'application/json');
if (res.body.error) {
throw new UserFacingError(
res.body.error, res.body.error_description, res.body.error_uri,
);
}
const t = res.body.access_token;
const userInfo = await superagent.get('https://api.github.com/user')
.proxy(proxy)
.set('User-Agent', 'Hydro-OAuth')
.set('Authorization', `token ${t}`);
const ret = {
email: userInfo.body.email,
bio: userInfo.body.bio,
uname: [userInfo.body.name, userInfo.body.login],
};
this.response.redirect = s.redirect;
await token.del(s._id, token.TYPE_OAUTH);
return ret;
}
global.Hydro.lib.oauth_github = {
text: 'Login with Github',
callback,
get,
};

@ -0,0 +1,22 @@
{
"name": "@hydrooj/login-with-github",
"version": "0.0.2",
"main": "package.json",
"repository": "git@github.com:hydro-dev/Hydro.git",
"author": "undefined <masnn0@outlook.com>",
"license": "MIT",
"scripts": {
"lint": "eslint lib.ts --fix",
"build": "tsc"
},
"devDependencies": {
"@types/superagent": "^4.1.8",
"hydrooj": "2.12.1"
},
"peerDependencies": {
"hydrooj": "^2.12.1"
},
"dependencies": {
"superagent": "^5.3.1"
}
}

@ -0,0 +1,15 @@
id:
type: text
category: system
desc: Github OAuth AppID
name: id
secret:
type: text
category: system
desc: Github OAuth Secret
name: secret
proxy:
type: text
category: system
desc: Github OAuth Proxy
name: proxy

@ -0,0 +1,11 @@
{
"extends": "../../tsconfig.base",
"compilerOptions": {
"outDir": ".",
"rootDir": ".",
},
"include": [
"*.ts"
],
"exclude": []
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save