✌️ Thanks for your contributions ✌️
- 任意のIssueについて、せっかく実装してくださっても、実装方法や設計の認識が揃ってないとマージできない/しないことになりかねないので、初めにそのIssue上で着手することを宣言し、必要に応じて他メンバーと実装方法や設計のすり合わせを行ってください。宣言することは作業が他の人と被るのを防止する効果もあります。
- 設計に迷った時はプロジェクトリーダーの判断を仰いでください。
- 時間や優先度の都合上、提出してくださったPRが長期間放置されることもありますがご理解ください。
- 温度感高めで見てほしいものは責付いてください。
Feature suggestions and bug reports are filed in https://github.com/groundpolis/groundpolis/issues .
- Please search existing issues to avoid duplication. If your issue is already filed, please add your reaction or comment to the existing one.
- If you have multiple independent issues, please submit them separately.
- master branch is tracking the latest release and used for production purposes.
- develop branch is where we work for the next release.
Groundpolis uses the Vue.js plugin Vue I18n. Documentation of Vue I18n is available at http://kazupon.github.io/vue-i18n/introduction.html .
- Documents for contributors are located in
/docs
. - Documents for instance admins are located in
/docs
. - Documents for end users are located in
/src/docs
.
- Test codes are located in
/test
.
- Use English for material, object and texture names.
- Use meter for unit of length.
- Your PR should include all source files (e.g.
.png
,.blend
) of your models (for later editing). - Your PR must include the glTF binary files (
.glb
) of your models. - Add a locale key
room.furnitures.YOUR_ITEM
at/locales/ja-JP.yml
. - Add a furniture definition at
/src/client/app/common/scripts/room/furnitures.json5
.
If you have no experience on 3D modeling, we suggest to use the free 3DCG software Blender. You can find information on glTF 2.0 at glTF 2.0 — Blender Manual.
Just execute yarn
to fix it.
Stands for ActivityPub.
Stands for _GroundPolis Flavored MFM.
Stands for Misskey Flavored Markdown.
Stands for Misskey.
Stands for ServiceWorker.
Convert な(na) to にゃ(nya)
Revert Nyaize
This is to avoid Automatic Semicolon Insertion (ASI) hazard.
Ref:
Bad:
if (foo)
bar;
else
baz;
Good:
if (foo) {
bar;
} else {
baz;
}
As a special case, you can omit the curly brackets if
- the body of the
if
-statement have only one statement and, - the
if
-statement does not haveelse
-clause.
Good:
if (foo) bar;
Make sure that the condition and the body statement are on the same line.
🥰
Bad:
if (foo.length)
Good:
if (foo.length > 0)
This is because the current language support does not work well with export default
.
Ref:
- https://basarat.gitbooks.io/typescript/docs/tips/defaultIsBad.html
- https://gfx.hatenablog.com/entry/2017/11/24/135343
Bad:
export default function(foo: string): string {
Good:
export function something(foo: string): string {
src ... Source code
@types ... Type definitions
prelude ... Independence utils for coding JavaScript without side effects
misc ... Independence utils for Groundpolis without side effects
service ... Common functions with side effects
queue ... Job queues and Jobs
server ... Web Server
client ... Client
mfm ... MFM
test ... Test code
SQLをクエリビルダで組み立てる際、使用するプレースホルダは重複してはならない 例えば
query.andWhere(new Brackets(qb => {
for (const type of ps.fileType) {
qb.orWhere(`:type = ANY(note.attachedFileTypes)`, { type: type });
}
}));
と書くと、ループ中でtype
というプレースホルダが複数回使われてしまいおかしくなる
だから次のようにする必要がある
query.andWhere(new Brackets(qb => {
for (const type of ps.fileType) {
const i = ps.fileType.indexOf(type);
qb.orWhere(`:type${i} = ANY(note.attachedFileTypes)`, { [`type${i}`]: type });
}
}));
const foo = await Foos.findOne({
bar: Not(null)
});
のようなクエリ(bar
がnull
ではない)は期待通りに動作しない。
次のようにします:
const foo = await Foos.findOne({
bar: Not(IsNull())
});
SQLを発行する際、パラメータがnull
になる可能性のある場合はSQL文を出し分けなければならない
例えば
query.where('file.folderId = :folderId', { folderId: ps.folderId });
という処理で、ps.folderId
がnull
だと結果的にfile.folderId = null
のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない
だから次のようにする必要がある
if (ps.folderId) {
query.where('file.folderId = :folderId', { folderId: ps.folderId });
} else {
query.where('file.folderId IS NULL');
}
SQLを発行する際、IN
のパラメータが[]
(空の配列)になる可能性のある場合はSQL文を出し分けなければならない
例えば
const users = await Users.find({
id: In(userIds)
});
という処理で、userIds
が[]
だと結果的にuser.id IN ()
のようなクエリが発行されてしまい、これは正しいSQLではないので期待した結果が得られない
だから次のようにする必要がある
const users = userIds.length > 0 ? await Users.find({
id: In(userIds)
}) : [];
SQLでは配列のインデックスは1始まり。
[a, b, c]
の a
にアクセスしたいなら[0]
ではなく[1]
と書く
nullが含まれる可能性のあるカラムにINするときは、そのままだとおかしくなるのでORなどでnullのハンドリングをしよう。
MongoDBの時とは違い、findOneでレコードを取得する時に対象レコードが存在しない場合 undefined
が返ってくるので注意。
MongoDBはnull
で返してきてたので、その感覚でif (x === null)
とか書くとバグる。代わりにif (x == null)
と書いてください
データベースからレコードを取得するときに、プログラムの流れ的に(ほぼ)絶対undefined
にはならない場合でも、undefined
チェックしないとTypeScriptに怒られます。
でもいちいち複数行を費やして、発生するはずのないundefined
をチェックするのも面倒なので、ensure
というユーティリティ関数を用意しています。
例えば、
const user = await Users.findOne(userId);
// この時点で user の型は User | undefined
if (user == null) {
throw 'missing user';
}
// この時点で user の型は User
という処理をensure
を使うと
const user = await Users.findOne(userId).then(ensure);
// この時点で user の型は User
という風に書けます。
もちろんensure
内部でエラーを握りつぶすようなことはしておらず、万が一undefined
だった場合はPromiseがRejectされ後続の処理は実行されません。
const user = await Users.findOne(userId).then(ensure);
// 万が一 Users.findOne の結果が undefined だったら、ensure でエラーが発生するので
// この行に到達することは無い
// なので、.then(ensure) は
// if (user == null) {
// throw 'missing user';
// }
// の糖衣構文のような扱いです
npx ts-node ./node_modules/typeorm/cli.js migration:generate -n "A name of changes"
Please remove unnecessary codes in the generated scripts.
Adblockers blocks them accidentally...