hydro 套件開發隨筆記 – 1
參考自https://hydro.js.org/
該文檔未更新之內容則從https://github.com/hydro-dev/Hydro
如果不知道怎麼寫可以參考別人寫的像上面的官方的套件
Service
範例取自自己的套件hydrooj-turnstile
最基礎的
export default class TurnstileService extends Service {
static Config = Schema.object({
key: Schema.string().description('Turnstile key').required(),
secret: Schema.string().description('Turnstile Secret').role('secret').required(),
});
constructor(ctx: Context, config: ReturnType<typeof TurnstileService.Config>) {
super(ctx, 'hydrooj-turnstile');
}
}
這可以在配置管理(即/manage/config)中新增可以填數值的欄位
大概像這樣
ctx.on
// (放在constructor裡)
ctx.on('handler/after/UserRegister', async (thisArg) => {
/* some function */
});
在handler/after/UserRegister發生會叫他
IDE可以判別有什麼是可以呼叫的
(包括但不限於api/update problem/add)
ctx.Route
ctx.Route('hitokoto', '/hitokoto', hitokotoHandler);
製造一個/hitokoto的路徑,由hitokotoHandler處理hitokoto會是那個頁面的data-page(參考注入HTML element)
Handler
class hitokotoHandler extends Handler {
async get() {
}
async post() {
}
}
get會在用戶提出請求時被調用(你可以給用戶渲染HTML)post會在提交時被調用(你可以查看他給你什麼並渲染HTML)
get
async get() {
this.response.body = ['hello', 'world'];
}
這個就不會渲染HTML 而是直接回傳資料給用戶
this.response.body = this.request.body ||{
packages: packages,
lockedPackages: lockedPackages,
success: null,
result: null
};
this.response.template = 'manage_addons.html';
this.renderHTML(this.response.template, {title: 'manage_addons'});
這個就會渲染HTML 並且用manage_addons.html這個template去渲染manage_addons.html會收到this.response.body內的內容
詳細可參考template 渲染
post
async post() {
}
他會收到用戶給的資訊 在this.request.body裡
{
package_name : "something"
}
之類的
可以this.request.body['package_name']
怎麼讓用戶回傳可以參考template 渲染
UserFacingError
import
import { UserFacingError } from 'hydrooj';
throw new UserFacingError('Turnstile token is missing');

注入HTML element
在你的套件建立frontend/<不能有除_以外的特殊符號>.page.tsx(放在frontend底下)
import { addPage, NamedPage } from '@hydrooj/ui-default';
addPage(new NamedPage(['hitokoto'], () => {
console.log('我會在data-page為hitokoto的地方執行');
}));
查詢該頁 data-page
打開該網頁
右鍵 選檢查
你就會看到data-page標籤了
template 渲染
{% extends "layout/basic.html" %}
{% block content %}
<div>
<a>這樣外面就會套用"layout/basic.html"(如下)</a>
<a>可以參考原版的模板去extends(記得注意他是把block插到哪裡 要取相同的block名稱)</a>
</div>
{% endblock %}

可以調用剛剛講的傳入的東西
<input type="text" name="package_name" value="{{ package }}" hidden >
這樣他的value就會是body["package"]
{% for package in packages %}
<div>
</div>
{% endfor %}
會遍歷body["packages"]
{% if package not in lockedPackages %}
<a></a>
{% endif %}
同理
<script>
const message = {{ result | dump | safe }};
alert('✓ success: ' + message);
</script>
會傳入{{ result }}
提交表單
<form method="post" class="activate-package-form">
<div class="activate-package-item">
<a>{{ package }}</a>
<input type="text" name="package_name" value="{{ package }}" hidden >
{% if package not in lockedPackages %}
{% endif %}
<button type="submit" name="action" value="update" class="btn btn--secondary">{{ _('update') }}</button>
</div>
</form>
按下按鈕 會傳入
{
package_name: "<{{ package }}>的值",
action: "delete", //或"update"
}
參考
hydro-github
hydrooj-doc
和我的自製套件
hydrooj-addons-manager
hydrooj-hitokoto-google-sheet
hydrooj-turnstile