mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-06-17 21:04:51 +02:00
Compare commits
11 Commits
master
...
refine-piz
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2402754dcc | ||
|
|
2493592bd0 | ||
|
|
eec4ab841a | ||
|
|
d0b8ffe629 | ||
|
|
cef7575b76 | ||
|
|
9842eb2eeb | ||
|
|
05078e9c14 | ||
|
|
db5c6fa3c2 | ||
|
|
8a4e2659ed | ||
|
|
d19c094a9b | ||
|
|
a7f7ff33e7 |
2
.claude/.gitignore
vendored
2
.claude/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
/settings.local.json
|
||||
/.credentials.json
|
||||
@@ -1,76 +0,0 @@
|
||||
# Third-Party Licenses (`.claude/`)
|
||||
|
||||
`.claude/` é
ä¸ãĢåãčžŧãžããĻãããĩãŧãããŧããŖįąæĨãŗãŗããŧããŗããŽãŠã¤ãģãŗãšãģåēå
¸æ
å ąããžã¨ãããMisskey æŦäŊ㯠AGPL-3.0-only ã ããæŦããŖãŦã¯ããĒå
ãĢ㯠MIT ãŠã¤ãģãŗãšãŽããĄã¤ãĢãåĢãžããĻãããåããĄã¤ãĢåé ãĢã `SPDX-License-Identifier` ã¨åēå
¸ãŗãĄãŗããäŊĩč¨ããĻããã
|
||||
|
||||
æįĩæ´æ°: 2026-05-11
|
||||
|
||||
---
|
||||
|
||||
## 1. everything-claude-code (ECC)
|
||||
|
||||
- 䏿ĩãĒãã¸ããĒ: <https://github.com/affaan-m/everything-claude-code>
|
||||
- åãčžŧãã ããŧã¸ã§ãŗ: v2.0.0-rc.1
|
||||
- ãŠã¤ãģãŗãš: **MIT**
|
||||
- Copyright: Copyright (c) 2026 Affaan Mustafa
|
||||
|
||||
### åãčžŧãã ããĄã¤ãĢ
|
||||
|
||||
| `.claude/` å
ãŽããš | 䏿ĩããš | 䏿ĩ frontmatter `origin` | Misskey ã§ãŽæšå¤ |
|
||||
|---|---|---|---|
|
||||
| `skills/context-budget/SKILL.md` | `skills/context-budget/SKILL.md` | ECC | description ãæĨæŦčĒåãMisskey åēæãĄãĸãčŋŊč¨ |
|
||||
| `commands/harness-audit.md` | `commands/harness-audit.md` | ECC | scripts äžåãŽčĒåæĄįšããClaude ã `pnpm`/`git`/`grep` ã§æåæĄįšããįãĢæ¸ãæããMisskey åēæãŽčŠäžĄčģ¸ (SPDX / endpoint-list / migration / locales) ãįĩãŋčžŧãŋ |
|
||||
| `commands/quality-gate.md` | `commands/quality-gate.md` | ECC | č¨čĒčĒåå¤åŽãæé¤ã Misskey åēåŽ pipeline (`pnpm` + tsgo + ESLint + Vitest) ãĢãPrettier/Biome ãã§ãŧãēãåé¤ |
|
||||
|
||||
### MIT License (full text)
|
||||
|
||||
```
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Affaan Mustafa
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
```
|
||||
|
||||
### 䏿ĩ LICENSE ããĄã¤ãĢ
|
||||
|
||||
<https://github.com/affaan-m/everything-claude-code/blob/main/LICENSE>
|
||||
|
||||
---
|
||||
|
||||
## 2. AGPL ãŗãŧãããŧãšã¨ãŽäēææ§
|
||||
|
||||
Misskey æŦäŊ㯠**AGPL-3.0-only** ã§é
å¸ãããĻãããã`.claude/` é
ä¸ãŽ MIT ãŠã¤ãģãŗãšããĄã¤ãĢã¯ããŽãžãž MIT ã¨ããĻæŽããĻããã
|
||||
|
||||
- MIT 㯠permissive ãŠã¤ãģãŗãšã§ãAGPL ãåĢã copyleft ãŠã¤ãģãŗãšãŽããã¸ã§ã¯ããĢ **åãčžŧãŋãģåé
å¸ã訹ããã**
|
||||
- MIT ãčĻæąããæĄäģļ (copyright notice + license text ãŽäŋæ) ãæŦããĄã¤ãĢ + åããĄã¤ãĢåé ㎠SPDX/åēå
¸ãŗãĄãŗãã§æēãããĻãã
|
||||
- Misskey å
¨äŊãŽé
å¸įŠã¨ããĻ㯠AGPL-3.0-only ã§æąããããã`.claude/` é
ä¸ãŽ MIT ããĄã¤ãĢã¯ååĨãĢ MIT ã¨ããĻčåĨå¯čŊ
|
||||
|
||||
`.ts` / `.js` / `.vue` / `.scss` ㎠SPDX įžŠåå ([AGENTS.md §1](../AGENTS.md#1-spdx-ããããŧåŋ
é )) 㯠Misskey æŦäŊãŗãŧãåãã§ã`.claude/` é
ä¸ãŽ `.md` / `.sh` ãĢã¯éŠį¨ãããĒãã
|
||||
|
||||
---
|
||||
|
||||
## 3. æ°čĻčŋŊå æãŽæé
|
||||
|
||||
`.claude/` ãĢæ°ããĢãĩãŧãããŧããŖįąæĨãŽããĄã¤ãĢãåãčžŧãéã¯:
|
||||
|
||||
1. ãŠã¤ãģãŗãšãįĸēčĒ (äēææ§: MIT / Apache-2.0 / BSD 㯠OKãGPL/AGPL ã¯čĻį¸čĢ)
|
||||
2. åããĄã¤ãĢåé ãĢ SPDX ããã + åēå
¸ãŗãĄãŗããčŋŊå
|
||||
3. æŦããĄã¤ãĢ Â§1 ãŽããŧããĢãĢ 1 čĄčŋŊč¨
|
||||
4. åŋ
čĻãĒãæ°ãããģã¯ãˇã§ãŗã§ãŠã¤ãģãŗãšå
¨æãåæĸą
|
||||
5. AGENTS.md ãããŽåį
§ãįĸēčĒ (įžįļ㎠[AGENTS.md §ããŧãĢåēæãŽčŖåŠããĄã¤ãĢ](../AGENTS.md) ã§ `THIRD_PARTY_LICENSES.md` ãæĄå
æ¸ãCLAUDE.md 㯠`@AGENTS.md` įĩįąã§čĒãŋčžŧããŽã§ååĨãŽčŋŊč¨ã¯ä¸čĻ)
|
||||
@@ -1,23 +0,0 @@
|
||||
# `.claude/agents/` â ããã¸ã§ã¯ãåēæãŽãĩãã¨ãŧã¸ã§ãŗã
|
||||
|
||||
Misskey ãŽįšåŽé åãĢįšåãããŦããĨãŧ / čĒŋæģã¨ãŧã¸ã§ãŗãã `.claude/agents/<name>.md` åŊĸåŧã§é
įŊŽããã
|
||||
|
||||
frontmatter (`name` + `description` + `tools`) ã¯ãClaude ã **čĒåã§ã¨ãŧã¸ã§ãŗããåŧãŗåēãã夿ãã** å¯ä¸ãŽæããããĢãĒãã`description` ãĢã¯į¨éãå
ˇäŊįãã¤įļ˛įž
įãĢæ¸ãã㨠(åčŠ + å¯žčąĄ + ããĒãŦãŧæĄäģļ)ã
|
||||
|
||||
## åŽčŖ
æ¸ãĩãã¨ãŧã¸ã§ãŗã
|
||||
|
||||
| ã¨ãŧã¸ã§ãŗãå | åŊšå˛ | åĒå
åēĻ |
|
||||
|---|---|---|
|
||||
| [misskey-api-reviewer](misskey-api-reviewer.md) | NestJS DI + meta/paramDef + UUID éč¤ + endpoint-list.ts įģé˛ + ApiError throw + misskey-js åįæ + e2e + CHANGELOG ããã§ã㯠| éĢ (įģ鞿ŧãã§ 404 / autogen CI čŊãĄé ģįē) |
|
||||
| [vue-component-reviewer](vue-component-reviewer.md) | Mk\* åŊå / `<script lang="ts" setup>` / type-only defineProps / SCSS module / CSS 夿° / i18n.ts 㨠i18n.tsx ãŽäŊŋãåã / os.\* įĩįą / a11y / `*.stories.impl.ts` äŊĩč¨ããã§ã㯠| ä¸ (CI į´æã¯ SPDX / locales ᎍééåãŽãŋãäģã¯åŽåŽŗãåēãĻããæ¤åēããããąãŧãšãå¤ã API ãģãŠãŽåŗæģæ§ã¯ãĒã) |
|
||||
|
||||
č¨č¨æšé: `tools` ãᎍ鿍ŠéãĒã (Edit/Write ãæ¸ĄããĒã) ãĢįĩããPR baseline (`git merge-base origin/develop HEAD`) ã¨ãŽåˇŽåããčĒåįãĢãŦããĨãŧå¯žčąĄãæŊåēããã
|
||||
|
||||
## æ°čĻã¨ãŧã¸ã§ãŗããčŋŊå ããå ´å
|
||||
|
||||
- `.claude/agents/<name>.md` ãĢ YAML frontmatter (`name` / `description` / `tools`) ã¨æŦæ Markdown ãæ¸ãã
|
||||
- `description` ã¯åŧãŗåēã夿ãĢäŊŋããããããå¯žčąĄããĄã¤ãŗãģä¸ģčĻãã§ãã¯é
įŽãģããĒãŦãŧæĄäģļã **å
ˇäŊįãĢ** åæããã
|
||||
- ãŦããĨãŧå°éãĒã `tools: Read, Grep, Glob, Bash` ãĢįĩã (Edit/Write ãæ¸ĄããĒã)ã**`Bash` ã¯äģģæãŽãˇã§ãĢãŗããŗããåŽčĄã§ããåŧˇåãĒæ¨Šéã§ããįšãĢæŗ¨æ**: ãŦããĨãŧį¨éã§ã¯ `git diff` / `git ls-files` / `grep` / `sed` į㎠**čĒãŋåãįŗģãŗããŗããĢéåŽããĻäŊŋã** ãã¨ãæ¸ãčžŧãŋãģåé¤ãģãããã¯ãŧã¯éäŋĄãäŧ´ãæäŊã¯æŦæä¸ãŽäžį¤ēãģæį¤ēãĢåĢããĒãã㨠(ã¨ãŧã¸ã§ãŗãæŦæããŦãŧããŦãŧãĢãĢãĒã)ã
|
||||
- ä¸ģčĻåį
§ããĄã¤ãĢã¸ãŽãĒãŗã¯ã¯ããĒãã¸ããĒãĢãŧããããŽį¸å¯žããš (äž: `../../packages/backend/...`) ã§č˛ŧããįĩļ寞ããšã¯ contributor ãŽããŧã ããŖãŦã¯ããĒäžåãĢãĒããŽã§äŊŋããĒãã
|
||||
- åˇŽåæŊåē㯠`git merge-base origin/develop HEAD` ã baseline ãĢãã (PR / ããŠãŗãå
¨äŊãčĻããã)ã`git diff HEAD` åäŊ㯠**æĒãŗãããåˇŽåããåããããŗãããæ¸ãŽ PR ã§ã¯įŠēãĢãĒãŖãĻčǤå¤åŽãã** ãŽã§äŊŋããĒãã
|
||||
- åŽæãããã㎠README ãŽčĄ¨ãĢã 1 čĄčŋŊå ããã
|
||||
@@ -1,167 +0,0 @@
|
||||
---
|
||||
name: misskey-api-reviewer
|
||||
description: Misskey ㎠API ã¨ãŗããã¤ãŗã (packages/backend/src/server/api/endpoints/) ãŽčŋŊå ãģ夿´ãå°éãŦããĨãŧãããSPDX / meta / paramDef / UUID éč¤ / endpoint-list.ts įģé˛ / ApiError throw / misskey-js åįæ / e2e / CHANGELOG ãæŠæĸ°įãĢãã§ãã¯ãããã¯ã¨ãŗã API ãčŋŊå ãģ夿´ãã PR ãŦããĨãŧã§åŧãŗåēãã
|
||||
tools: Read, Grep, Glob, Bash
|
||||
---
|
||||
|
||||
# Misskey API ã¨ãŗããã¤ãŗããŦããĨãĸãŧ
|
||||
|
||||
Misskey ããã¯ã¨ãŗã (`packages/backend`) ㎠REST API ã¨ãŗããã¤ãŗãčŋŊå ãģ夿´ PR ãæŠæĸ°įãĢãŦããĨãŧããå°éã¨ãŧã¸ã§ãŗããčĻį´ãŽæ šæ 㯠[.claude/skills/add-api-endpoint/SKILL.md](../skills/add-api-endpoint/SKILL.md)ã
|
||||
|
||||
## åŊšå˛
|
||||
|
||||
`packages/backend/src/server/api/endpoints/` é
ä¸ãŽ `.ts` 夿´ãå¯žčąĄãĢãčĻį´é¸čąãģįģ鞿ŧããģåčĒåįææŧããģããšãä¸čļŗãæŊåēãããč¯ãįšãĢã¯č§Ļãããæšåãåŋ
čĻãĒįŽæãŽãŋå ąåããã
|
||||
|
||||
## ãŦããĨãŧå¯žčąĄãŽįšåŽ
|
||||
|
||||
åŧãŗåēãå
ããæį¤ēįãĢããĄã¤ãĢãæ¸ĄãããããããåĒå
ãããæ¸ĄãããĒããŖãå ´å㯠**PR / ããŠãŗãå
¨äŊãŽåˇŽå** ãååžãã (æĒãŗãããåˇŽåãŽãŋã§ã¯ãĒããã¨ãĢæŗ¨æ)ã
|
||||
|
||||
```bash
|
||||
BASE=$(git merge-base origin/develop HEAD)
|
||||
{ git diff --name-only "$BASE"...HEAD; git diff --name-only HEAD; git ls-files --others --exclude-standard; } \
|
||||
| sort -u \
|
||||
| grep -E '^packages/backend/src/server/api/endpoints/.*\.ts$'
|
||||
```
|
||||
|
||||
`origin/develop` ãįĄãį°åĸã§ã¯ `develop` ãžã㯠`master` ãĢããŠãŧãĢããã¯ããã
|
||||
|
||||
å ããĻäģĨä¸ãåã baseline ã§åˇŽåå¯žčąĄãĢåĢãã:
|
||||
|
||||
- `packages/backend/src/server/api/endpoint-list.ts`
|
||||
- `packages/backend/test/e2e/**` (ã¨ããĢ `endpoints.ts` 㨠`<area>.ts`)
|
||||
- `packages/misskey-js/src/autogen/**`
|
||||
- `CHANGELOG.md`
|
||||
|
||||
åˇŽåå¯žčąĄãįŠēãĒãããŦããĨãŧå¯žčąĄãŽ API ã¨ãŗããã¤ãŗã夿´ãĒããã¨įãå ąåããĻįĩäēã
|
||||
|
||||
## ãã§ãã¯ãĒãšã
|
||||
|
||||
### 1. SPDX ããããŧ (Critical)
|
||||
|
||||
æ°čĻ `.ts` ããĄã¤ãĢåé ãĢäģĨä¸ãããã:
|
||||
|
||||
```
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
```
|
||||
|
||||
æŦ čŊãã㨠CI ㎠`spdx` ã¸ã§ããčŊãĄãã
|
||||
|
||||
### 2. `meta` ãŽåŋ
é ã쿍åĨ¨ããŖãŧãĢã (Major)
|
||||
|
||||
[endpoints.ts ãŽååŽįžŠ](../../packages/backend/src/server/api/endpoints.ts) ãįã¨ããã
|
||||
|
||||
- `tags`: OpenAPI ãŋã° (æŠčŊé å)ã
|
||||
- `requireCredential`: æį¤ēåŋ
é (boolean)ã
|
||||
- `kind`: OAuth scopeã`requireCredential: true` ãŽã¨ãåŋ
é (`read:account` / `write:notes` į)ã
|
||||
- `requireModerator` / `requireAdmin`: 樊éåļéãčĻããã
|
||||
- `prohibitMoved`: į§ģčĄæ¸ãĸãĢãĻãŗããæåĻããã (write įŗģã§čĻæ¤č¨)ã
|
||||
- `limit`: ãŦãŧãåļé `{ duration, max, key?, minInterval? }`ãæ¸ãčžŧãŋįŗģ / ãŗãšãéĢãåĻįã§æĒæåŽãĒãææã
|
||||
- `errors`: ã¨ãŠãŧåŽįžŠãåčĻį´ ãĢ `message` / `code` / `id` (UUID v4) ãæãŖãĻãããã
|
||||
- `res`: JSON Schema ãžã㯠`ref: '<EntityName>'`ãåãããããŖãĢ `optional` / `nullable` ã **æį¤ē** ãããĻãããã
|
||||
- `requireFile` / `secure` / `allowGet` / `cacheSec` / `description`: 芲åŊããã¨ãŗããã¤ãŗãã§äŊŋãåããĻãããã
|
||||
|
||||
### 3. `meta.errors` ㎠UUID æ¤č¨ŧ (Critical)
|
||||
|
||||
å `errors[*].id` ã:
|
||||
|
||||
1. UUID v4 åŊĸåŧ (`xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx`) ã
|
||||
2. æĸåã¨ãŗããã¤ãŗã㎠`id` ã¨éč¤ããĻããĒãã
|
||||
|
||||
é褿¤æģ:
|
||||
|
||||
```bash
|
||||
grep -rn "id: '<įæããã UUID>'" packages/backend/src/server/api/endpoints/
|
||||
```
|
||||
|
||||
æ°čĻã¨ãŗããã¤ãŗããŽå
¨ `id` ãæŊåēããĻčĄįĒãįĸēčĒããã
|
||||
|
||||
### 4. `paramDef` (Major)
|
||||
|
||||
- JSON Schema åŊĸåŧ (`type: 'object'`, `properties`, `required`)
|
||||
- ID æåå㯠`format: 'misskey:id'`
|
||||
- `required` é
åã§åŋ
é ãããããŖãæį¤ē
|
||||
- `as const` ãžã㯠`as const satisfies Schema` ã§åæ¨čĢãåšããã (æĸååŽčŖ
ã¯åč
夿°ã`as const` čĒäŊãįĄã `Schema` åæŗ¨éããĒãå ´åãŽãŋææ)
|
||||
|
||||
### 5. ã¨ãŗããã¤ãŗãåŽčŖ
æŦäŊ (Major)
|
||||
|
||||
- `Endpoint<typeof meta, typeof paramDef>` ãįļæŋããĻãããã
|
||||
- `@Injectable()` ããŗãŦãŧãŋ + `export default class` åŊĸåŧã (`// eslint-disable-line import/no-default-export` ãåŋ
čĻ)ã
|
||||
- DI 㯠`@Inject(DI.xxx)` åŊĸåŧãã
|
||||
- **ã¯ãŠã¤ãĸãŗããĢčŋããšã API ã¨ãŠãŧ㯠`throw new ApiError(meta.errors.<key>)`** ([error.ts](../../packages/backend/src/server/api/error.ts) åį
§)ã`meta.errors` ã§åŽįžŠããã¨ãŠãŧãąãŧãšã `throw new Error(...)` ã§æããĻãããĒãææããã
|
||||
- é˛åžĄįãĸãĩãŧãˇã§ãŗãģãčĩˇããã¯ãããĒããå
é¨ä¸æ´åãģããšã፠ENV ãŦãŧãį㎠**æŗåŽå¤ãã§ã¤ãĢããĄãšã** 㯠`throw new Error('...')` ã§æ§ããĒããæĸååŽčŖ
ã§ã `admin/reset-password.ts` ãĒãŠãæĄį¨ããĻããããŋãŧãŗ (äž: `cannot reset password of root`)ã`meta.errors` ãĢ寞åŋããĒã `throw new Error` ãä¸åžã§ææããĒãã
|
||||
- åæ `throw` ã¯č¨ąåŽšãéåæåĻįã§ãŽäžå¤äŧæŦãįĸēčĒããã
|
||||
|
||||
### 6. â
`endpoint-list.ts` ã¸ãŽįģé˛ (Critical)
|
||||
|
||||
æãåŋããããã**åŋãã㨠404**ã[endpoint-list.ts](../../packages/backend/src/server/api/endpoint-list.ts) ãĢ 1 čĄčŋŊå ãããĻããã:
|
||||
|
||||
```ts
|
||||
export * as '<category>/<name>' from './endpoints/<category>/<name>.js';
|
||||
```
|
||||
|
||||
æ°čĻã¨ãŗããã¤ãŗããæŊåēããåã
ã `endpoint-list.ts` ãĢåå¨ããã grep ã§įĸēčĒãã:
|
||||
|
||||
```bash
|
||||
grep -F "'<category>/<name>'" packages/backend/src/server/api/endpoint-list.ts
|
||||
```
|
||||
|
||||
**ä¸Ļãŗé ãŽčŖčļŗ**: ããĄã¤ãĢå
¨äŊã¯åŗå¯ãĒãĸãĢããĄãããé ã§ã¯ä¸Ļãã§ããããåãĢãã´ãĒå
(`admin/queue/*` ãĒãŠ) ã§ãčŋŊå ãããįĩ᎝ãŠãããŽé ãĢãĒãŖãĻããįŽæãå¤ãã**é åēé¸čąã¯æææ šæ ãĢããĒã** (čǤæ¤įĨãŽå
)ããčĄãåå¨ãããããŽãŋã Critical čĻŗįšã¨ããĻæąãã
|
||||
|
||||
### 7. `misskey-js` åįæ (Critical)
|
||||
|
||||
`meta` / `paramDef` / `res` ã夿´ããããPR / ããŠãŗããĢ `packages/misskey-js/src/autogen/` é
ä¸ãŽåˇŽåãåĢãžããĻãããįĸēčĒãã:
|
||||
|
||||
```bash
|
||||
BASE=$(git merge-base origin/develop HEAD)
|
||||
git diff --name-only "$BASE"...HEAD -- packages/misskey-js/src/autogen/
|
||||
```
|
||||
|
||||
åˇŽåãŧããĒã `pnpm build-misskey-js-with-types` ãŽåŽčĄæŧããCI ㎠`check-misskey-js-autogen` ã¸ã§ãã§åŋ
ãčŊãĄããã Critical æąãã
|
||||
|
||||
### 8. e2e ããšã (Major)
|
||||
|
||||
[test/e2e/endpoints.ts](../../packages/backend/test/e2e/endpoints.ts) ãžã㯠`test/e2e/<area>.ts` (`note.ts`, `users.ts` į) é
ä¸ãĢã寞åŋãã `api('<category>/<name>', ...)` åŧãŗåēããåĢã `test(...)` ãąãŧãšãčŋŊå ãããĻãããįĸēčĒãããč¤éãĒåå˛ (樊éãã§ãã¯ãģã¨ãŠãŧãąãŧãš) ãŽįļ˛įž
ãįĸēčĒããã
|
||||
|
||||
**describe ãŠããĢãŽåŊĸåŧã¯åããĒã**: æĸåããšã㯠`describe('Note', () => { test('æį¨ŋã§ãã', ...) })` ãŽãããĢäēēéå¯čĒãŠããĢã§æ§é åãããĻããã`<category>/<name>` åŊĸåŧ㎠describe ã¯äŊŋãããĻããĒããdescribe åãŽčĻį´éåã¨ããĻã¯ææããĒãã
|
||||
|
||||
### 9. CHANGELOG ã¨ãŗããĒ (Minor)
|
||||
|
||||
ãĻãŧãļãŧåŊąéŋããã (æ°ã¨ãŗããã¤ãŗã / æĸåæå夿´) å ´åã`CHANGELOG.md` ㎠`## Unreleased` â `### Server` ãĢ 1 čĄčŋŊå ãããĻãããįĸēčĒããã
|
||||
|
||||
```
|
||||
- Feat: /api/<category>/<name> ãčŋŊå
|
||||
```
|
||||
|
||||
į´į˛ãĒå
é¨ãĒããĄã¯ãŋãĒãä¸čĻã
|
||||
|
||||
## åēååŊĸåŧ
|
||||
|
||||
åĒå
åēĻåĨãĢäģĨä¸ãŽããŠãŧãããã§åēåããã
|
||||
|
||||
```
|
||||
## đ´ Critical
|
||||
- packages/backend/src/server/api/endpoints/foo/bar.ts:23
|
||||
meta.errors.fooError.id ã UUID v4 åŊĸåŧã§ã¯ãĒã (åŽå¤: 'xxx-xxx')ã
|
||||
`node -e "console.log(crypto.randomUUID())"` ã§åįæãããã¨ã
|
||||
|
||||
## đĄ Major
|
||||
- ...
|
||||
|
||||
## đĩ Minor
|
||||
- ...
|
||||
```
|
||||
|
||||
åéĄãŽãĒããã§ãã¯é
įŽãĢã¯č§ĻããĒããå
¨é
įŽã¯ãĒãĸãĒã `â
ãŦããĨãŧčĻŗįšä¸ãŽææãĒã` ã¨įãčŋãã
|
||||
|
||||
## åį
§
|
||||
|
||||
- [.claude/skills/add-api-endpoint/SKILL.md](../skills/add-api-endpoint/SKILL.md) â åŽčŖ
å´ãŽčĻį´ (æŦã¨ãŧã¸ã§ãŗããŽæ šæ )
|
||||
- [endpoints.ts (meta/paramDef ååŽįžŠ)](../../packages/backend/src/server/api/endpoints.ts)
|
||||
- [endpoint-list.ts (â
įģé˛å
)](../../packages/backend/src/server/api/endpoint-list.ts)
|
||||
- [endpoint-base.ts (Endpoint åēåēã¯ãŠãš)](../../packages/backend/src/server/api/endpoint-base.ts)
|
||||
- [error.ts (ApiError)](../../packages/backend/src/server/api/error.ts)
|
||||
- [test/e2e/endpoints.ts](../../packages/backend/test/e2e/endpoints.ts)
|
||||
- [AGENTS.md](../../AGENTS.md) â SPDX / ãã¤ã°ãŦãŧãˇã§ãŗåąĨæ´ / CHANGELOG æ¸åŧãĒãŠãŽæäŊéãĢãŧãĢ (Codex / Copilot ã¨å
ąé)
|
||||
@@ -1,176 +0,0 @@
|
||||
---
|
||||
name: vue-component-reviewer
|
||||
description: Misskey ãããŗãã¨ãŗã (packages/frontend/src/components/ / pages/) ㎠Vue 3 SFC 夿´ãå°éãŦããĨãŧãããSPDX (HTML ãŗãĄãŗã) / Mk* åŊå / <script lang="ts" setup> / type-only defineProps / <style lang="scss" module> / CSS 夿° / i18n.ts 㨠i18n.tsx ãŽäŊŋãåã / os.* įĩįą / a11y / Storybook (*.stories.impl.ts) ãæŠæĸ°įãĢãã§ãã¯ããããŗãã¨ãŗã㎠.vue 夿´ãåĢã PR ãŦããĨãŧã§åŧãŗåēãã
|
||||
tools: Read, Grep, Glob, Bash
|
||||
---
|
||||
|
||||
# Misskey Vue ãŗãŗããŧããŗããŦããĨãĸãŧ
|
||||
|
||||
Misskey ãããŗãã¨ãŗã (`packages/frontend`) ㎠Vue 3 SFC 夿´ãæŠæĸ°įãĢãŦããĨãŧããå°éã¨ãŧã¸ã§ãŗããčĻį´ãŽæ šæ 㯠[.claude/skills/add-mk-component/SKILL.md](../skills/add-mk-component/SKILL.md)ã
|
||||
|
||||
## åŊšå˛
|
||||
|
||||
`packages/frontend/src/components/` ãããŗ `packages/frontend/src/pages/` é
ä¸ãŽ `.vue` 夿´ãå¯žčąĄãĢãåŊåãģi18nãģãšãŋã¤ãĢãģãĸã¯ãģãˇããĒããŖãģStorybook äŊĩč¨ãŽčĻį´é¸čąãæŊåēãããč¯ãįšãĢã¯č§Ļãããæšåãåŋ
čĻãĒįŽæãŽãŋå ąåããã
|
||||
|
||||
## ãŦããĨãŧå¯žčąĄãŽįšåŽ
|
||||
|
||||
åŧãŗåēãå
ããæį¤ēįãĢããĄã¤ãĢãæ¸ĄãããããããåĒå
ãããæ¸ĄãããĒããŖãå ´å㯠**PR / ããŠãŗãå
¨äŊãŽåˇŽå** ãååžãã (æĒãŗãããåˇŽåãŽãŋã§ã¯ãĒããã¨ãĢæŗ¨æ)ã
|
||||
|
||||
```bash
|
||||
BASE=$(git merge-base origin/develop HEAD)
|
||||
{ git diff --name-only "$BASE"...HEAD; git diff --name-only HEAD; git ls-files --others --exclude-standard; } \
|
||||
| sort -u \
|
||||
| grep -E '^packages/frontend/src/.*\.vue$'
|
||||
```
|
||||
|
||||
`origin/develop` ãįĄãį°åĸã§ã¯ `develop` ãžã㯠`master` ãĢããŠãŧãĢããã¯ããã
|
||||
|
||||
`.ts` ãä¸åžã§åĢããã¨æŦã¨ãŧã¸ã§ãŗããŽåŽåį¯å˛å¤ (composable / store / service åą¤) ãžã§åˇģãčžŧãã§čǤæ¤įĨãåĸãããããå¯žčąĄã¯ `.vue` ãŽãŋã¨ããStorybook äŊĩč¨ãã§ãã¯ãŽãããĢäģĨä¸ã **åĨãĒãšã** ã¨ããĻčŋŊå ãã:
|
||||
|
||||
- `locales/*.yml` (ã¨ããĢ `ja-JP.yml` äģĨå¤ãŽå¤æ´ã¯åŗ Critical)
|
||||
- `packages/frontend/src/components/**/*.stories.impl.ts`
|
||||
- `CHANGELOG.md`
|
||||
|
||||
åˇŽåå¯žčąĄãįŠēãĒãããŦããĨãŧå¯žčąĄãŽ Vue ãŗãŗããŧããŗã夿´ãĒããã¨įãå ąåããĻįĩäēã
|
||||
|
||||
## ãã§ãã¯ãĒãšã
|
||||
|
||||
### 1. SPDX ããããŧ (Critical)
|
||||
|
||||
`.vue` ããĄã¤ãĢåé 㯠**HTML ãŗãĄãŗãåŊĸåŧ** ã§åŋ
é :
|
||||
|
||||
```html
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
```
|
||||
|
||||
`/* ... */` (TS åŊĸåŧ) ã¯įĻæĸãæĸå SFC ãŽæ
ŖįŋãģSFC å
é ã¨ããĻčĒįļãĒåŊĸåŧãĢįĩąä¸ãããã (CI ㎠`spdx` ã¸ã§ãã¯ãŗãĄãŗãåŊĸåŧã§ã¯ãĒã SPDX æååãŽæįĄãŽãŋãæ¤æģãããããåŊĸåŧãéãŖãĻã CI ã¯éãããčĻį´éåã¨ããĻææãã)ã
|
||||
|
||||
### 2. åŊåčĻį´ (Major)
|
||||
|
||||
- å
ąæ / ååŠį¨ãŗãŗããŧããŗã (`packages/frontend/src/components/` é
ä¸ããĩãããŖãŦã¯ããĒåĢã) 㯠`Mk` ããŦããŖãã¯ãšåŋ
é (äž: `MkButton.vue`, `global/MkAvatar.vue`, `grid/MkGrid.vue`)ã
|
||||
- ããŧã¸åēæãŽããŽã¯ `pages/` é
ä¸ãĢįŊŽãã`Mk` ããŦããŖãã¯ãšã¯ä¸čĻã
|
||||
|
||||
> `<script setup>` SFC 㯠named export ãæããĒãããããããĄã¤ãĢå㨠export åãŽä¸č´ããæŠæĸ°įãĢæ¤æģãããã¨ã¯ã§ããĒããSFC ãŽãããŠãĢãã¨ã¯ãšããŧãã¯ãŗãŗãã¤ãŠįæãĒãŽã§ãããĄã¤ãĢåčĻį´ãŽãŋãåēæēãĢããã
|
||||
|
||||
### 3. `<script>` ãŋã° (Major)
|
||||
|
||||
- `<script lang="ts" setup>` ãžã㯠`<script setup lang="ts">` ãŽãŠãĄãã§ããã (æĸåãŗãŧãã¯å¤æ°æ´žãåč
ã ããåžč
ã `MkThemePreview.vue` įã§äŊŋãããĻãã)ãåąæ§é ã¯ææããĒãã`lang="ts"` ã **įĄã** ããŽã¯ææããã
|
||||
- åã¸ã§ããĒãã¯ãåŋ
čĻãĒã `generic="T extends ..."` åąæ§ãå ãã (é åēåãã)ã
|
||||
- `defineProps<{ ... }>()` / `defineEmits<{ ... }>()` 㯠**type-only** åŊĸåŧãruntime ㎠object åŊĸåŧ (`defineProps({ ... })`) ã¯äŊŋããĒãã
|
||||
- Options API (`export default { data() { ... } }`) ã¯įĻæĸã
|
||||
|
||||
### 4. i18n ãŽäŊŋãåã (Critical)
|
||||
|
||||
- æååãĒããŠãĢãŽį´æ¸ãįĻæĸ (ããŗããŦãŧã / JS 严æš)ã
|
||||
- åŧæ°ãĒã: `i18n.ts.<path>` (äž: `i18n.ts.deleted`)ã
|
||||
- åŧæ°ãã: `i18n.tsx.<path>(...)` (éĸæ°åŧãŗåēããäž: `i18n.tsx.takeOverConfirm({ name })`)ã
|
||||
- æ°čĻ i18n ããŧ㯠`locales/ja-JP.yml` **ãŽãŋ** ãĢčŋŊå ã
|
||||
- **`locales/ja-JP.yml` äģĨå¤ãŽ `.yml` 夿´ãããã°åŗ Critical** (`en-US.yml` į㯠Crowdin čĒåé
äŋĄå
ã§ãæåᎍéããã¨ä¸æ¸ãåĒå¤ąãã)ã
|
||||
|
||||
åˇŽåæ¤åē:
|
||||
|
||||
```bash
|
||||
BASE=$(git merge-base origin/develop HEAD)
|
||||
git diff --name-only "$BASE"...HEAD -- 'locales/*.yml' | grep -v 'ja-JP.yml'
|
||||
```
|
||||
|
||||
### 5. ãšãŋã¤ãĢ (Major)
|
||||
|
||||
- `<style lang="scss" module>` ãæĸåŽã¨ãã`:class="$style.foo"` ã§åį
§ããã
|
||||
- æ°čĻã§ `<style scoped>` (module ãĒã) ã¯äŊŋããĒã (legacy)ã
|
||||
- **CSS 夿°ãŽäŊŋį¨åŋ
é ** (č˛ãģäŊįŊãģč§ä¸¸ãĒãŠ):
|
||||
- ããŧãč˛: `var(--MI_THEME-*)` (äž: `var(--MI_THEME-panel)`)
|
||||
- UI å
ąé: `var(--MI-*)` (äž: `var(--MI-radius)`)
|
||||
- į´æĨ㎠`#fff` / `rgb(...)` / `rgba(...)` ããŧããŗãŧãã¯įĻæĸ
|
||||
|
||||
ããŧããŗãŧãæ¤åē:
|
||||
|
||||
```bash
|
||||
BASE=$(git merge-base origin/develop HEAD)
|
||||
git diff "$BASE"...HEAD -- 'packages/frontend/src/**/*.vue' \
|
||||
| grep -E '^\+' | grep -E '#[0-9a-fA-F]{3,8}\b|rgba?\('
|
||||
```
|
||||
|
||||
### 6. UI æäŊ㯠`os.*` įĩįą (Critical)
|
||||
|
||||
- į´æĨ㎠`alert()` / `confirm()` / `window.prompt()` / `window.alert()` ã¯įĻæĸã
|
||||
- `os.alert` / `os.confirm` / `os.popup` / `os.toast` / `os.popupMenu` / `os.contextMenu` / `os.form` / `os.apiWithDialog` ãäŊŋã ([os.ts](../../packages/frontend/src/os.ts) åį
§)ã
|
||||
|
||||
æ¤åē:
|
||||
|
||||
```bash
|
||||
BASE=$(git merge-base origin/develop HEAD)
|
||||
git diff "$BASE"...HEAD -- 'packages/frontend/src/**/*.vue' \
|
||||
| grep -E '^\+' | grep -E '\b(alert|confirm|prompt)\s*\('
|
||||
```
|
||||
|
||||
### 7. ãĸã¯ãģãˇããĒããŖ (Major)
|
||||
|
||||
- ã¯ãĒãã¯å¯čŊčĻį´ ã¯ `<button>` ãã`role="button"` + `tabindex="0"` + ããŧããŧãããŗã㊠(`@keydown.enter` į) ãåŽčŖ
ããã
|
||||
- čŖ
éŖžäģĨå¤ãŽ `<div @click>` ã§ a11y é
æ
ŽããĒãããŽã¯ææããã
|
||||
- ããŠãŧã čĻį´ ãĢã¯å¯žåŋãã `<label>` ãžã㯠`aria-label` ãäģããã
|
||||
- `:disabled` ãã¤ãŗãã `aria-disabled` ãŽæ´åæ§ãįĸēčĒããã
|
||||
|
||||
### 8. Storybook äŊĩč¨ (Major)
|
||||
|
||||
- å
ąæ `Mk*` ãŗãŗããŧããŗããæ°čĻčŋŊå ããå ´åã`Mk<Name>.stories.impl.ts` ãåéåą¤ãĢäŊĩč¨ãããĻããã (ãĩãããŖãŦã¯ããĒåĢããäž: `components/global/MkAvatar.stories.impl.ts`, `components/grid/MkGrid.stories.impl.ts`)ã
|
||||
- **ããĄã¤ãĢå㯠`.stories.impl.ts` åēåŽ** (`.stories.ts` ã¯čǤã)ã
|
||||
- æĸå [MkButton.stories.impl.ts](../../packages/frontend/src/components/MkButton.stories.impl.ts) ãéåŊĸäžã¨ããĻåį
§ããã
|
||||
|
||||
æ¤åē (æ°čĻčŋŊå ããã `Mk*.vue` ããĩãããŖãŦã¯ããĒåĢããĻæžã):
|
||||
|
||||
```bash
|
||||
BASE=$(git merge-base origin/develop HEAD)
|
||||
git diff --name-only --diff-filter=A "$BASE"...HEAD -- \
|
||||
'packages/frontend/src/components/**/Mk*.vue' \
|
||||
| sed 's/\.vue$/.stories.impl.ts/' \
|
||||
| xargs -I {} sh -c 'test -f {} || echo "missing: {}"'
|
||||
```
|
||||
|
||||
### 9. ãĸã¤ãŗãŗ (Minor)
|
||||
|
||||
- ãĸã¤ãŗãŗã¯ Tabler icons ã¯ãŠãš (`<i class="ti ti-info-circle">` į) ãäŊŋãã
|
||||
- ã¤ãŗãŠã¤ãŗ SVG ãåĨãĸã¤ãŗãŗãģããã¯ååäŊŋããĒã (æĸåããŋãŧãŗãĢåããã)ã
|
||||
|
||||
### 10. CHANGELOG ã¨ãŗããĒ (Minor)
|
||||
|
||||
ãĻãŧãļãŧåŊąéŋããã夿´ãĒãã`CHANGELOG.md` ㎠`## Unreleased` â `### Client` ãĢ 1 čĄčŋŊå ãããĻãããįĸēčĒããã
|
||||
|
||||
```
|
||||
- Enhance: <component> ㎠<æå> ãæšå
|
||||
- Fix: <component> ㎠<ä¸å
ˇå> ãäŋŽæŖ
|
||||
```
|
||||
|
||||
į´į˛ãĒå
é¨ãĒããĄã¯ãŋãĒãä¸čĻã
|
||||
|
||||
## åēååŊĸåŧ
|
||||
|
||||
åĒå
åēĻåĨãĢäģĨä¸ãŽããŠãŧãããã§åēåããã
|
||||
|
||||
```
|
||||
## đ´ Critical
|
||||
- packages/frontend/src/components/MkFoo.vue:1
|
||||
SPDX ããããŧã HTML ãŗãĄãŗãåŊĸåŧã§ã¯ãĒã TS åŊĸåŧãĢãĒãŖãĻããã
|
||||
`<!-- ... -->` ã§æ¸ãį´ããã¨ã
|
||||
|
||||
## đĄ Major
|
||||
- ...
|
||||
|
||||
## đĩ Minor
|
||||
- ...
|
||||
```
|
||||
|
||||
åéĄãŽãĒããã§ãã¯é
įŽãĢã¯č§ĻããĒããå
¨é
įŽã¯ãĒãĸãĒã `â
ãŦããĨãŧčĻŗįšä¸ãŽææãĒã` ã¨įãčŋãã
|
||||
|
||||
## åį
§
|
||||
|
||||
- [.claude/skills/add-mk-component/SKILL.md](../skills/add-mk-component/SKILL.md) â åŽčŖ
å´ãŽčĻį´ (æŦã¨ãŧã¸ã§ãŗããŽæ šæ )
|
||||
- [.claude/skills/add-i18n-key/SKILL.md](../skills/add-i18n-key/SKILL.md) â i18n ããŧčŋŊå ãŽãĢãŧãĢ
|
||||
- [os.ts](../../packages/frontend/src/os.ts) â UI æäŊ API
|
||||
- [MkButton.vue](../../packages/frontend/src/components/MkButton.vue)
|
||||
- [MkInput.vue](../../packages/frontend/src/components/MkInput.vue) â generic SFC äž
|
||||
- [MkButton.stories.impl.ts](../../packages/frontend/src/components/MkButton.stories.impl.ts) â Storybook éåŊĸ
|
||||
- [AGENTS.md](../../AGENTS.md) â SPDX / locales ᎍéåļé / CHANGELOG æ¸åŧãĒãŠãŽæäŊéãĢãŧãĢ (Codex / Copilot ã¨å
ąé)
|
||||
@@ -1,38 +0,0 @@
|
||||
# `.claude/commands/` â ããã¸ã§ã¯ãåēæãŽãšãŠããˇãĨãŗããŗã
|
||||
|
||||
Misskey éįēã§įš°ãčŋãäŊŋãã¯ãŧã¯ãããŧã `/command-name` ã§åŧãŗåēããããã`.claude/commands/<name>.md` åŊĸåŧã§é
įŊŽããĻããã
|
||||
|
||||
## åŽčŖ
æ¸ãŋãŗããŗã
|
||||
|
||||
### Misskey ãĒãĒã¸ããĢ
|
||||
|
||||
| ãŗããŗã | į¨é | å
¸åãĻãŧãšãąãŧãš |
|
||||
| --- | --- | --- |
|
||||
| [`/check-misskey-js`](./check-misskey-js.md) | `pnpm build-misskey-js-with-types` ãčĩ°ããã`packages/misskey-js/src/autogen/` ãŽåˇŽåãå ąå | backend ㎠API endpoint ãčŋŊå ãģ夿´ããį´åž |
|
||||
| [`/changelog-add`](./changelog-add.md) | `CHANGELOG.md` ㎠`## Unreleased` é
ä¸ã寞åŋãããĩããģã¯ãˇã§ãŗãĢ 1 čĄčŋŊč¨ | ãĻãŧãļãŧåŊąéŋãŽãã夿´ããŗãããããį´å |
|
||||
| [`/migrate-new`](./migrate-new.md) | TypeORM `migration:create` ãŽčããŠãããŧ (æĄåŧĩå夿 + SPDX äģä¸ + `check-migrations` ã§ pending DDL æ¤åē) | ææ¸ã SQL / ããŧãŋį§ģčĄį¨ãĢįŠēéåŊĸãæŦ˛ããæ |
|
||||
|
||||
### ECC ([everything-claude-code](https://github.com/affaan-m/everything-claude-code)) įąæĨ (MIT)
|
||||
|
||||
ECC ㎠MIT ãŠã¤ãģãŗãšããĄã¤ãĢã Misskey ãŽčĻį´ãĢåãããĻåæ§æããããŽãåēå
¸ã¯ [.claude/THIRD_PARTY_LICENSES.md](../THIRD_PARTY_LICENSES.md) ãåį
§ã
|
||||
|
||||
| ãŗããŗã | į¨é | å
¸åãĻãŧãšãąãŧãš |
|
||||
| --- | --- | --- |
|
||||
| [`/quality-gate`](./quality-gate.md) | `pnpm lint` + åãããąãŧã¸ãŽ unit test ãé æŦĄåŽčĄããčģŊéåčŗĒã˛ãŧã | åŽäēåãŽčģŊéãã§ã㯠(éã E2E 㯠CI å´ãĢå§č˛) |
|
||||
| [`/harness-audit`](./harness-audit.md) | `.claude/` ããŧããšã 7 ãĢãã´ãĒã§æĄįšãæšååĒå
åēĻãæį¤ē | č¨åŽãŽį𿤠/ æ°ãã skill / agent / hook ãå
Ĩããåž |
|
||||
|
||||
## äŊŋãåã
|
||||
|
||||
- **`/migrate-new` vs [`create-migration` skill](../skills/create-migration/SKILL.md)**:
|
||||
- éåŊĸã ãį´ æŠãæŦ˛ãã â `/migrate-new`
|
||||
- ã¨ãŗããŖããŖåˇŽåããčĒåįæããžã㯠CONCURRENTLY ãĒãŠãŽæŗ¨æįšãåĢããĻåŽå
¨ãĢčĒå°ããĻãģãã â `create-migration` skill (`migration:generate`)
|
||||
- **`/changelog-add` vs æåᎍé**:
|
||||
- ãĩããģã¯ãˇã§ãŗãŽ placeholder `-` įŊŽæããéåģãĒãĒãŧãšãģã¯ãˇã§ãŗã¸ãŽčǤᎍéãéŋãããããååãŗããŗããäŊŋãã
|
||||
- **`/quality-gate` ãŽãšãŗãŧã**:
|
||||
- ᎍééä¸ãŽčģŊéãã§ã㯠(lint + unit test) 㯠`/quality-gate` ã§ååãéã e2e / federation / Cypress 㯠CI å´ã§åŽčĄããããããããŧãĢãĢã§ã¯åååããĒãã
|
||||
|
||||
## æ°čĻčŋŊå æãŽæšé
|
||||
|
||||
- æĸå㎠`superpowers` / `pr-review-toolkit` ãĒãŠãŽããŠã°ã¤ãŗæäžãšãŠããˇãĨãŗããŗãã§čļŗããå ´åã¯æ°čĻčŋŊå ããĒãã
|
||||
- frontmatter ãĢã¯æäŊé `description` ãæåŽããåŧæ°ãåããĒã `argument-hint`ãå¯čŊãĒã `allowed-tools` ãæåŽãã (permission prompt ãæå°åãããã)ã
|
||||
- 鎿éããĢã (2 åčļ
) ãäŧ´ããŗããŗãã¯ã¤ãŗãŠã¤ãŗ `` !`<cmd>` `` ãäŊŋãããæŦæã§ `Bash` ããŧãĢåŧãŗåēãæãŽ `timeout` ãæį¤ēããã
|
||||
@@ -1,49 +0,0 @@
|
||||
---
|
||||
description: CHANGELOG.md ㎠Unreleased ãģã¯ãˇã§ãŗãĢ 1 čĄčŋŊč¨ãã
|
||||
argument-hint: <general|client|server> <Prefix>: <description>
|
||||
allowed-tools: Bash(awk:*), Bash(git diff:*), Read, Edit
|
||||
---
|
||||
|
||||
## åŧæ°
|
||||
|
||||
åŧæ°: `$ARGUMENTS`
|
||||
|
||||
## įžå¨ãŽ Unreleased ãģã¯ãˇã§ãŗ
|
||||
|
||||
!`awk '/^## Unreleased/,/^## [0-9]/' CHANGELOG.md`
|
||||
|
||||
## ãŋãšã¯
|
||||
|
||||
1. **åŧæ°ãŽč§Ŗæ**
|
||||
`$ARGUMENTS` ãäģĨä¸ãŽåŊĸåŧã¨ããĻč§Ŗéãã:
|
||||
- įŦŦ 1 ããŧã¯ãŗ: scope = `general` / `client` / `server` ãŽãããã (case-insensitive)
|
||||
- æŽã: ã¨ãŗããĒæŦæã`Enhance:` / `Fix:` / `Feat:` ãŽããããã§å§ãžãåæ
|
||||
- 䏿ŖãĒ scope ããPrefix ãčĻåŊãããĒãå ´åã¯ã¨ãŠãŧįĩäēãããĻãŧãļãŧãĢ `argument-hint` ãŽæ¸åŧãæį¤ēãã
|
||||
|
||||
scope ã¯æŦĄãŽãããĢčĻåēããĢ夿ãã: `general` â `### General` / `client` â `### Client` / `server` â `### Server`ã
|
||||
|
||||
2. **å¯žčąĄãĩããģã¯ãˇã§ãŗãŽįļæ
å¤åŽ**
|
||||
ä¸ãŽ context (įžå¨ãŽ Unreleased ãģã¯ãˇã§ãŗ) ãčĻãĻãå¯žčąĄãĩããģã¯ãˇã§ãŗãäģĨä¸ãŽãŠãĄãããå¤åŽãã:
|
||||
- **įŠē (placeholder ãŽãŋ)**: čĻåēãį´ä¸ãĢ `-` åįŦčĄãŽãŋãããįļæ
|
||||
- **æĸåã¨ãŗããĒãã**: `- Enhance: ...` / `- Fix: ...` / `- Feat: ...` ãŽčĄã 1 ã¤äģĨä¸ããįļæ
|
||||
|
||||
3. **CHANGELOG.md ãŽįˇ¨é**
|
||||
`Read` ã§ CHANGELOG.md å
¨äŊãįĸēčĒããåžã`Edit` ããŧãĢã§äģĨä¸ãŽãããĢæ´æ°ãã:
|
||||
|
||||
- **įŠēãŽå ´å**: 芲åŊãĩããģã¯ãˇã§ãŗãŽ placeholder `-` čĄã `- <æ´åŊĸæ¸ãŋã¨ãŗããĒ>` ã§įŊŽæãããäž: `### General\n-\n` â `### General\n- Enhance: æ°ããæŠčŊ\n`
|
||||
- **æĸåãããŽå ´å**: æĸåã¨ãŗããĒįž¤ãŽ **æĢå°ž** (æŦĄãŽįŠēčĄį´å) ãĢæ°ã¨ãŗããĒã **append** ãããé åēå
Ĩãæŋãã¯ããĒãã
|
||||
|
||||
`Edit` ㎠`old_string` ãĢã¯ãįŊŽæå¯žčąĄãŽãĩããģã¯ãˇã§ãŗäģčŋãŽãĻããŧã¯ãĒæč (čĻåēã + į´åžãŽæ°čĄ) ãåĢããčǤããããé˛ãã
|
||||
|
||||
4. **ä¸å¯äžĩãŽåžšåē**
|
||||
- `## Unreleased` äģĨä¸ãŽå¯žčąĄãĩããģã¯ãˇã§ãŗãŽãŋᎍéããã
|
||||
- `## 2026.x.x` äģĨä¸ãŽéåģãĒãĒãŧãšãģã¯ãˇã§ãŗã¯įĩļ寞ãĢ夿´ããĒã ([AGENTS.md §CHANGELOG](../../AGENTS.md#changelog) åį
§)ã
|
||||
|
||||
5. **įĩæįĸēčĒ**
|
||||
`git diff CHANGELOG.md` ãåŽčĄããæŗåŽéã 1 čĄãŽãŋčŋŊå ãããĻãããã¨ã襨į¤ēããĻããĻãŧãļãŧãĢįĸēčĒãããã
|
||||
|
||||
## äž
|
||||
|
||||
- `/changelog-add server Fix: éįĨãé
åģļããåéĄãäŋŽæŖ` â `### Server` æĢå°žãĢčŋŊč¨
|
||||
- `/changelog-add client Enhance: ããŧããŽčĄ¨į¤ēãæšå` â `### Client` æĢå°žãĢčŋŊč¨
|
||||
- `/changelog-add general Feat: æ°æŠčŊãŽčŋŊå ` â `### General` æĢå°žãĢčŋŊč¨ (placeholder įŊŽæ)
|
||||
@@ -1,42 +0,0 @@
|
||||
---
|
||||
description: backend ㎠API 夿´åžãĢ misskey-js ãåįæããįæįŠãŽåˇŽåãå ąåãã
|
||||
allowed-tools: Bash(pnpm build-misskey-js-with-types:*), Bash(git status:*), Bash(git diff:*), Bash(git branch:*)
|
||||
---
|
||||
|
||||
## æĻčĻ
|
||||
|
||||
backend ㎠API endpoint ããšããŧãã夿´ããåžã`packages/misskey-js/src/autogen/` ãŽčĒåįæåãææ°åãããããŽãŗããŗããå
é¨ã§ `pnpm build-misskey-js-with-types` (backend build â `api.json` įæ â misskey-js åįæ â ããĢã â API extractor) ã䏿ŦåŽčĄããã
|
||||
|
||||
## įžå¨ãŽįļæ
(åįæå)
|
||||
|
||||
- įžããŠãŗã: !`git branch --show-current`
|
||||
- æĸå㎠misskey-js éĸéŖå¤æ´: !`git status --short -- packages/misskey-js/`
|
||||
|
||||
## ãŋãšã¯
|
||||
|
||||
äģĨä¸ãŽæé ãé įĒãĢåŽčĄããĻãã ããã
|
||||
|
||||
1. **åįæãŽåŽčĄ**
|
||||
`Bash` ããŧãĢã§äģĨä¸ãŽãŗããŗãã `timeout: 600000` (10 å) ãæåŽããĻåŽčĄãããå
é¨ã§ backend ããĢãã¨ååįæãčĄãããããããŠãĢã㎠2 åãŋã¤ã ãĸãĻãã§ã¯ä¸čļŗããã
|
||||
|
||||
```bash
|
||||
pnpm build-misskey-js-with-types
|
||||
```
|
||||
|
||||
2. **åˇŽåãŽįĸēčĒ**
|
||||
åŽäēåžãäģĨä¸ãåŽčĄããĻ `packages/misskey-js/src/autogen/` ãŽåˇŽåãįĸēčĒãã (`built/` 㯠`.gitignore` å¯žčąĄãĒãŽã§čŋŊčˇĄå¯žčąĄå¤):
|
||||
|
||||
```bash
|
||||
git status --short -- packages/misskey-js/
|
||||
git diff --stat -- packages/misskey-js/src/autogen/
|
||||
```
|
||||
|
||||
3. **įĩæå ąå**
|
||||
- **åˇŽåãĒã** â ãbackend ãŽå¤æ´ã¯ misskey-js ãŽå
ŦéåãĢåŊąéŋããĻããžãããã¨å ąåãããčŋŊå ãŗãããã¯ä¸čĻã
|
||||
- **åˇŽåãã** â 夿´ããĄã¤ãĢä¸čϧããĻãŧãļãŧãĢį¤ēãã`git add packages/misskey-js/src/autogen/` ã§åįæįŠããŗãããå¯žčąĄãĢåĢããããæĄå
ããã`api.json` ãŽåˇŽåã大ããå ´åã¯ãAPI endpoint å´ãŽ `meta` / `paramDef` / `res` åŽįžŠãįĸēčĒããããäŋãã
|
||||
|
||||
## æŗ¨æ
|
||||
|
||||
- ããŽãŗããŗã㯠**backend ᎍéåžãŽįĸēčĒ** ãįŽįãbackend ã夿´ããĻããĒããŽãĢčĩ°ãããã¨ãããĢãããŖããˇãĨæŦĄįŦŦã§ no-op ãĢãĒãã
|
||||
- åŽčĄä¸ã¯ `packages/backend/built/` ã `packages/misskey-js/built/` ãĒãŠãŽä¸éįæįŠãæ´æ°ãããããããã㯠`.gitignore` å¯žčąĄã
|
||||
- įæįŠäģĨå¤ (`packages/misskey-js/src/` ãŽããĄ `autogen/` äģĨå¤) ãĢäēæããŦåˇŽåãåēãå ´åã¯ãããŧãĢãĢãŽįˇ¨éãæˇˇå
ĨããĻããå¯čŊæ§ãããããã䏿Ļ䏿ĸããĻåå ãčĒŋæģããã
|
||||
@@ -1,146 +0,0 @@
|
||||
---
|
||||
description: Misskey ㎠.claude/ ããŧããš (skills/agents/commands) ã 7 ãĢãã´ãĒã§æĄįšããįĸēåŽįãĒįŖæģã
|
||||
argument-hint: "[repo|skills|commands|agents]"
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: MIT
|
||||
SPDX-FileCopyrightText: 2026 Affaan Mustafa and everything-claude-code contributors
|
||||
|
||||
åēå
¸ (upstream): https://github.com/affaan-m/everything-claude-code (v2.0.0-rc.1)
|
||||
upstream path: commands/harness-audit.md
|
||||
upstream license: MIT â https://github.com/affaan-m/everything-claude-code/blob/main/LICENSE
|
||||
project-level notice: see .claude/THIRD_PARTY_LICENSES.md (Misskey å
ãĩãŧãããŧããŖä¸čϧ + MIT å
¨æ)
|
||||
|
||||
Imported into Misskey .claude/ on 2026-05-10. The 7-category rubric and output contract are derived from the upstream ECC version (MIT). The runtime layer was substantially reimplemented for Misskey: the upstream relies on scripts/harness-audit.js to mechanically score, while this version asks Claude to score directly with pnpm/git/grep, and adds Misskey-specific evaluation axes (SPDX coverage / endpoint-list įģ鞿ŧã / migration é åē / ja-JP.yml æ´å).
|
||||
|
||||
note: å
ECC į㯠scripts/harness-audit.js (å°į¨ Node ãšã¯ãĒãã) ã§æŠæĸ°æĄįšããĻããããMisskey 㯠ECC plugin runtime ãĢäžåããĒãæšéãĒãŽã§ãClaude ãį´æĨããĄã¤ãĢãčĒãã§æĄįšããæåéį¨įãĢæ¸ãæãããMisskey åēæãŽéčĻčĻŗįš (SPDX éŠį¨į / endpoint-list įģ鞿ŧã / migration é åē / ja-JP.yml æ´å) ãčŠäžĄčģ¸ã¨ããĻæį¤ēįãĢįĩãŋčžŧãã§ããã
|
||||
-->
|
||||
|
||||
# /harness-audit â Misskey ããŧããšįŖæģ
|
||||
|
||||
Misskey ãĒãã¸ããĒ㎠`.claude/` æ§æã 7 ãĢãã´ãĒã§æĄįšããæšååĒå
åēĻãæį¤ēããã
|
||||
|
||||
## Usage
|
||||
|
||||
`/harness-audit [scope]`
|
||||
|
||||
- `scope` (äģģæ): `repo` (default) / `skills` / `commands` / `agents`
|
||||
|
||||
## čŠäžĄãĢãã´ãĒ (å 0-10)
|
||||
|
||||
| # | ãĢãã´ãĒ | čŠäžĄčģ¸ |
|
||||
| --- | --- | --- |
|
||||
| 1 | Tool Coverage | skill / agent / command ãŽæ°ãæŦ ããĻããã¯ãŧã¯ãããŧæŽĩãéč¤ãĒã |
|
||||
| 2 | Context Efficiency | frontmatter description ãŽåéˇåēĻãSKILL.md ãŽéˇãåå¸ãé褿
å ąãCLAUDE.md ãŽčĨ大å |
|
||||
| 3 | Quality Gates | Stop / PreToolUse / PostToolUse hook ãŽæ´åã`/quality-gate` įãŽåŽäēåã˛ãŧããŽæįĄãčĒå lint/typecheck |
|
||||
| 4 | Memory Persistence | docs/* ãŽåæįļæ
ãčŠäžĄãããã¸ã§ã¯ãå´ `.claude/memory/` ã¯æĒæĄį¨æšé (auto-memory ã¯ãĻãŧãļãŧããŧã å´ã§čĒåéį¨) ãŽããããããæĄįščĩˇįšãĢããæĸåŽ 5/10 ããéå§ãã |
|
||||
| 5 | Eval Coverage | testing.md ãŽįļ˛įž
ãMisskey åēæãŽ e2e/fed/Storybook/Cypress éŠį¨ãŦã¤ã |
|
||||
| 6 | Security Guardrails | SPDX čĻį´éŠį¨ãmigration ä¸å¤æ§ãĢãŧãĢãja-JP.yml éåŽįˇ¨éãĢãŧãĢãsecrets æ¤åē |
|
||||
| 7 | Cost Efficiency | enabledPlugins ãŽéč¤ãģéå°ãcontext-budget ãŽæ´åãMCP éå°įģé˛ãĒã |
|
||||
|
||||
## Misskey åēæãŽįĸēčĒé
įŽ (æĄįšæ šæ ãŗããŗã)
|
||||
|
||||
æĄįšæãĢäģĨä¸ãåŽãŗããŗãã§įĸēčĒãããåé
įŽãŽ **åąãããĢãã´ãĒ** ã¯é
įŽå
ãĢæč¨ãã (#1-#3 㯠Security Guardrailsã#4 㯠Tool Coverageã#5 㯠Quality Gates):
|
||||
|
||||
```bash
|
||||
# 1. [Security Guardrails] SPDX éŠį¨į (æ°čĻããĄã¤ãĢæŗåŽãŽæąį¨ãã§ãã¯)
|
||||
# - node_modules ã prune ã§é¤å¤
|
||||
# - packages/misskey-js 㯠MIT ãĩããããąãŧã¸ãĒãŽã§ AGPL ããããŧãæããĒã (AGENTS.md §1) â é¤å¤
|
||||
# - built/ ãĒãŠãé¤å¤
|
||||
# åčŖãĢã¯ãĒã *.config.{ts,js} / *eslint* / *.d.ts ãŽãããĒ CI ä¸ SPDX å¯žčąĄå¤
|
||||
# (.github/workflows/check-spdx-license-id.yml ㎠exclude åį
§) ãæˇˇããããã
|
||||
# ä¸äŊãĢåēãããĄã¤ãĢããæ°čĻčŋŊå ããåŽãŗãŧããããŠããã¯įŽčĻå¤åŽããã
|
||||
find packages \
|
||||
\( -type d \( -name node_modules -o -name built -o -name dist -o -path 'packages/misskey-js' \) -prune \) \
|
||||
-o -type f \( -name '*.ts' -o -name '*.js' -o -name '*.vue' -o -name '*.scss' \) -print \
|
||||
| xargs -r grep -L 'SPDX-License-Identifier: AGPL-3.0-only' | head -20
|
||||
# â ä¸äŊãĢæ°čĻåŽãŗãŧããįĄããã°æēįš
|
||||
|
||||
# 2. [Security Guardrails] ja-JP.yml äģĨå¤ãŽ locales ãį´čŋã§æåᎍéãããĻããĒãã
|
||||
# --pretty=format: ã§ãŗããããããčĄãææĸããããĄã¤ãĢåčĄãŽãŋãæŽããĻãã grep ããã
|
||||
# Crowdin ãŽčĒååæ commit ã§ãäģč¨čĒ yml ã¯æ´æ°ããããããåēåã 0 čĄãĢãĒããã¨ã¯å°ãĒãã
|
||||
# åēåãããŖãå ´åã¯ãauthor / commit message ãįĸēčĒã Crowdin įąæĨãæåᎍéããå¤åŽãã:
|
||||
# git log --since='30 days ago' --pretty=format:'%h %an %s' -- locales/<file>.yml
|
||||
git log --since='30 days ago' --pretty=format: --name-only -- 'locales/*.yml' \
|
||||
| grep -v '^$' | grep -v 'ja-JP.yml' | sort -u
|
||||
# â åēåãįĄãããžãã¯å
¨ãĻ Crowdin įąæĨ commit ãĒãæēįš
|
||||
|
||||
# 3. [Security Guardrails] migration ㎠pending DDL æ¤æģ (TypeORM schema builder)
|
||||
pnpm --filter backend check-migrations
|
||||
# â 0 errors (= "All migrations are clean.") ãĒãæēįš
|
||||
|
||||
# 4. [Tool Coverage] endpoint-list.ts įģ鞿ŧã (æ°čĻ endpoint ããĒãšããĢãĒãå ´å)
|
||||
# endpoints/ ã¯å帰æ§é (notes/create.ts, admin/announcements/create.ts į) ã§ 400+ ããĄã¤ãĢããããã
|
||||
# endpoint-list.ts ã `export * as '<category>/<name>' from './endpoints/<category>/<name>.js';` åŊĸåŧã§
|
||||
# 1 ããĄã¤ãĢ 1 čĄįģé˛ãããã严č
ãŽčĄæ°ããå帰 .ts æ°ãã¨ãexport * as čĄæ°ãã§æ¯čŧããã
|
||||
# e2e / åäŊããšã㯠endpoint ã§ã¯ãĒããŽã§ *.test.ts ãé¤å¤ããã
|
||||
endpoint_files=$(find packages/backend/src/server/api/endpoints -type f -name '*.ts' ! -name '*.test.ts' | wc -l)
|
||||
list_entries=$(grep -cE "^export \* as " packages/backend/src/server/api/endpoint-list.ts)
|
||||
echo "endpoints (recursive): $endpoint_files / endpoint-list.ts entries: $list_entries"
|
||||
# åˇŽåã 0 ãĒãæēįšãåˇŽåãåēãããįģ鞿ŧããŽå
ˇäŊįšåŽ:
|
||||
comm -23 \
|
||||
<(find packages/backend/src/server/api/endpoints -type f -name '*.ts' ! -name '*.test.ts' \
|
||||
| sed -E 's|.*/endpoints/||;s|\.ts$||' | sort -u) \
|
||||
<(grep -oE "^export \* as '[^']+'" packages/backend/src/server/api/endpoint-list.ts \
|
||||
| sed -E "s/^export \* as '([^']+)'/\1/" | sort -u)
|
||||
# åēåãããčĄãįģ鞿ŧã㎠endpointã0 čĄãĒãæēįšã
|
||||
|
||||
# 5. [Quality Gates] console.log ãŽæˇˇå
Ĩ
|
||||
grep -rn 'console\.\(log\|debug\)' packages/backend/src packages/frontend/src 2>/dev/null \
|
||||
| grep -v 'node_modules\|test\|.spec\.\|.test\.' | wc -l
|
||||
# â 0 ãįæŗ
|
||||
```
|
||||
|
||||
## åēååĨį´
|
||||
|
||||
äģĨä¸ãčŋã:
|
||||
|
||||
1. `overall_score` / `max_score` (repo 㯠70 įšæēįš)
|
||||
2. ãĢãã´ãĒãã¨ãŽãšãŗãĸ + å
ˇäŊįãĒæ šæ
|
||||
3. å¤ąæãã§ãã¯é
įŽã¨čОåŊããĄã¤ãĢããš
|
||||
4. Top 3 æšåãĸã¯ãˇã§ãŗ
|
||||
5. æŦĄãĢéŠį¨ãæ¨åĨ¨ãã skill / æé
|
||||
|
||||
## ãĩãŗããĢåēå
|
||||
|
||||
```text
|
||||
Harness Audit (repo): 55/70
|
||||
|
||||
Tool Coverage: 9/10 (skills 5, agents 2, commands 5 â åããĒã)
|
||||
Context Efficiency: 8/10 (description åšŗå 3-5 čĄãčĨ大ãĒã)
|
||||
Quality Gates: 5/10 (Stop hook å
ąæč¨åŽãĢæĒįģé˛ / `/quality-gate` ãã)
|
||||
Memory Persistence: 5/10 (ããã¸ã§ã¯ãå´ memory/ æĒæĄį¨æšé = æĸåŽå¤)
|
||||
Eval Coverage: 7/10 (testing.md įļ˛įž
ãStorybook ä¸é¨æã)
|
||||
Security Guardrails: 10/10 (SPDX 100%, locales OK, migrations clean)
|
||||
Cost Efficiency: 8/10 (context-budget å°å
Ĩæ¸ / MCP 0)
|
||||
|
||||
Failed Checks:
|
||||
- packages/frontend/src/.../X.vue ã§ SPDX æŦ čŊ (Security Guardrails)
|
||||
- console.log ã backend ãĢ 3 äģļ (Quality Gates)
|
||||
- å
ąæ Stop hook ãĒã (Quality Gates) â å contributor ã `.claude/settings.local.json` ã§ opt-in ããæšéãĒãæ¸įšããĒããĻč¯ã
|
||||
|
||||
Top 3 Actions:
|
||||
1) [Security Guardrails] SPDX æŦ čŊ 1 ããĄã¤ãĢãäŋŽæŖ:
|
||||
packages/frontend/src/.../X.vue
|
||||
2) [Quality Gates] backend ㎠console.log 3 äģļã logger ãĢįŊŽæã
|
||||
git grep "console\.log" packages/backend/src
|
||||
3) [Cost Efficiency] enabledPlugins ããæĒäŊŋį¨ãŽããŽãå¤ãã
|
||||
.claude/docs/plugins.md ã¨į
§åã
|
||||
|
||||
Suggested next skills to apply:
|
||||
- /quality-gate ã§åŽäēåãĢ lint + unit test ãåã
|
||||
- context-budget ã§ plugin įąæĨ㎠overhead ãįĸēčĒ
|
||||
```
|
||||
|
||||
## æĄįšãŽäŋĄé ŧæ§
|
||||
|
||||
- įĸēåŽį: åã commit / åã `.claude/` æ§æãĒãåããšãŗãĸ
|
||||
- ããĨãŧãĒãšããŖã¯ãš: ãdescription ãŽåéˇåēĻããŽãããĒä¸ģčĻŗé
įŽã¯åä¸åēæēã§æŠæĸ°įãĢå¤åŽ
|
||||
- ãšã¯ãĒããä¸čĻ: `pnpm` 㨠`git`ã`grep`/`find` įãŽæ¨æēããŧãĢãŽãŋ
|
||||
|
||||
## åč: ECC ãĒãĒã¸ããĢã¨ãŽåˇŽå
|
||||
|
||||
- ECC į㯠`node scripts/harness-audit.js` ãį´åŠãããéį¨ã§ãECC ãĒãã¸ããĒå
¨äŊãĢéããæĄįšã ãŖãã
|
||||
- Misskey į㯠**Misskey ãŽčĻį´ (SPDX/migration/locales/endpoint-list)** ã Security æĄįšãĢįĩãŋčžŧãŋã`pnpm` ããŧãšãŽåŽãŗããŗãã§æ šæ ãåãæšåŧãĢåč¨č¨ã
|
||||
- įĩæã¨ããĻ ECC ã¸ãŽäžåã¯ãŧãã
|
||||
@@ -1,81 +0,0 @@
|
||||
---
|
||||
description: TypeORM migration ãŽįŠēéåŊĸãįæããããšããŧãåˇŽåããčĒåįæãããæã¯ create-migration skill ãäŊŋããã¨
|
||||
argument-hint: <PascalCaseName>
|
||||
allowed-tools: Bash(pnpm:*), Bash(ls:*), Bash(test:*), Bash(head:*), Read, Edit
|
||||
---
|
||||
|
||||
## åŧæ°
|
||||
|
||||
åŧæ°: `$ARGUMENTS`
|
||||
|
||||
## ãŋãšã¯
|
||||
|
||||
1. **PascalCaseName ãŽæ¤č¨ŧ**
|
||||
`$ARGUMENTS` ã `^[A-Z][A-Za-z0-9]+$` ãĢä¸č´ãããįĸēčĒãããä¸č´ããĒãå ´åã¯ã¨ãŠãŧįĩäēãã`AddFooBar` / `BirthdayIndex` ãŽãããĒåŊĸåŧãæĄå
ããã
|
||||
|
||||
2. **æĸåããĄã¤ãĢãŽåå¨įĸēčĒ**
|
||||
|
||||
```bash
|
||||
ls packages/backend/migration/*$ARGUMENTS.{js,ts} 2>/dev/null
|
||||
```
|
||||
|
||||
æĸãĢåå (ãŋã¤ã ãšãŋãŗãéã) ãŽããĄã¤ãĢãåå¨ããå ´åã䏿¸ããããĻãŧãļãŧãĢåĨåãäŋãã
|
||||
|
||||
3. **TypeORM å
Ŧåŧ CLI ã§įŠēéåŊĸãįæ (`-o --esm` åŋ
é )**
|
||||
`create-migration` skill ãŽæšéãĢåžãã`Date.now()` ãææ¸ããããŽã§ã¯ãĒã TypeORM CLI ãäŊŋãã`-o --esm` ã§ **æåãã JS(ESM) ãįæ** ãããåžįļ㎠`.ts â .js` 夿ã `import { MigrationInterface }` åé¤ã¨ããŖã TS åēææ§æãŽé¤åģãä¸čĻãĢãã (`-o --esm` ãäģããĒã㨠`.ts` + CommonJS / `implements MigrationInterface` äģãã§įæãããMisskey ㎠`ormconfig.js` (`migration/*.js` ãŽãŋããŧã) ã¨æĸå migration ãšãŋã¤ãĢãĢåããĒã):
|
||||
|
||||
```bash
|
||||
pnpm --filter backend exec typeorm migration:create -o --esm migration/$ARGUMENTS
|
||||
```
|
||||
|
||||
åēå: `packages/backend/migration/<UnixMs>-<PascalCaseName>.js`
|
||||
|
||||
4. **įæããĄã¤ãĢããšãŽååž**
|
||||
åžįļãšãããã§äŊŋãããšã夿°ãĢåãã (`<ms>` ãææ¸ãããĒã):
|
||||
|
||||
```bash
|
||||
dst=$(ls -t packages/backend/migration/*$ARGUMENTS.js | head -1)
|
||||
```
|
||||
|
||||
äģĨéãŽãšãããã§ã¯ `$dst` ãᎍéå¯žčąĄã¨ããĻæąããåŽæåžãŽå
¸åįãĒåŊĸã¯æŦĄãŽãããĢãĒã (åč: [packages/backend/migration/1767169026317-birthday-index.js](../../packages/backend/migration/1767169026317-birthday-index.js)):
|
||||
|
||||
```js
|
||||
export class <PascalCaseName><ms> {
|
||||
name = '<PascalCaseName><ms>'
|
||||
|
||||
async up(queryRunner) {
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
5. **SPDX ããããŧãŽčŋŊå **
|
||||
`Edit` ããŧãĢã§ãããĄã¤ãĢåé ãĢäģĨä¸ãæŋå
ĨãããCI ㎠`spdx` ã¸ã§ããå¤ąæããããåŋ
é :
|
||||
|
||||
```js
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
```
|
||||
|
||||
6. **migration ㎠pending DDL æ¤æģ**
|
||||
|
||||
```bash
|
||||
pnpm --filter backend check-migrations
|
||||
```
|
||||
|
||||
TypeORM schema builder ã§ pending DDL ãæ¤åēããæ¤æģ ([scripts/check_migrations_clean.js](../../packages/backend/scripts/check_migrations_clean.js))ãįŠēéåŊĸãäŊãŖãã ããŽæŽĩéã§ã¯ã¨ãŗããŖããŖåˇŽåã¨ãŽä¸æ´åãæŽãå ´åãããããã`up`/`down` ãåããåžãĢãååŽčĄããĻ 0 äģļãĢãĒããįĸēčĒããã
|
||||
|
||||
7. **įĩæå ąå**
|
||||
- įæããĄã¤ãĢããšãį¤ēãã
|
||||
- `up()` / `down()` ãŽä¸čēĢãįŠēã§ãããã¨ãäŧããSQL ãæ¸ãåŋ
čĻãããã¨æĄå
ããã
|
||||
- `down()` ãįŠēãŽãžãžæžįŊŽããã¨æŦįĒããŧãĢããã¯æãĢ芰ããããåŋ
ã `up` ãŽåŽå
¨ãĒåˇģãæģããåŽčŖ
ããããäŋãã
|
||||
- čŠŗį´°ãĒæé (`migration:generate` ãäŊŋããšããąãŧãšãCONCURRENTLY ãĒãŠãŽæŗ¨æįš) 㯠`create-migration` skill ãåį
§ããããæĄå
ããã
|
||||
|
||||
## æŗ¨æ
|
||||
|
||||
- ããŽãŗããŗã㯠**įŠēéåŊĸãį´ æŠãåēããĻææ¸ããã** į¨éãã¨ãŗããŖããŖ (`packages/backend/src/models/*.ts`) ã夿´ããåˇŽåãã SQL ãčĒåįæãããå ´åã¯ãããŽãŗããŗãã§ã¯ãĒã `create-migration` skill įĩįąã§ `migration:generate` ãäŊŋããã¨ã
|
||||
- ããŧã¸æ¸ãŋ migration ããĄã¤ãĢã¯įĩļ寞ãĢᎍéããĒã ([AGENTS.md §3](../../AGENTS.md#3-ããŧã¸æ¸ãŋ-migration-ãįĩļ寞ãĢᎍéããĒã))ã
|
||||
@@ -1,122 +0,0 @@
|
||||
---
|
||||
description: Misskey ㎠lint / typecheck / éĢéããšããé ãĢåŽčĄããĻåčŗĒã˛ãŧããéããŗããŗããåŽäēåãŽčģŊ鿤č¨ŧį¨ã
|
||||
argument-hint: "[repo|backend|frontend|<path/to/file.ts>]"
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: MIT
|
||||
SPDX-FileCopyrightText: 2026 Affaan Mustafa and everything-claude-code contributors
|
||||
|
||||
åēå
¸ (upstream): https://github.com/affaan-m/everything-claude-code (v2.0.0-rc.1)
|
||||
upstream path: commands/quality-gate.md
|
||||
upstream license: MIT â https://github.com/affaan-m/everything-claude-code/blob/main/LICENSE
|
||||
project-level notice: see .claude/THIRD_PARTY_LICENSES.md (Misskey å
ãĩãŧãããŧããŖä¸čϧ + MIT å
¨æ)
|
||||
|
||||
Imported into Misskey .claude/ on 2026-05-10. Pipeline æĻåŋĩ (lint â typecheck â test) 㯠upstream ECC įããå፠(MIT)ãåŽãŗããŗãåą¤ã¯ Misskey ㎠pnpm + tsgo + ESLint + Vitest ãĢåēåŽããformatter (Prettier/Biome) ãã§ãŧãēã¯åé¤ããã
|
||||
|
||||
note: å
ECC įã¯č¨čĒčĒåå¤åŽ + format/lint/type ãŽã¸ã§ããĒãã¯įã ãŖãããMisskey å°į¨ãĢ pnpm + tsgo + ESLint + Vitest ãŽįĩãŋåãããĢåēåŽãéã test:e2e / test:fed ã¯åĢãžãĒã (CI å´ã§åŽčĄããã)ã
|
||||
-->
|
||||
|
||||
# /quality-gate â Misskey čģŊéåčŗĒã˛ãŧã
|
||||
|
||||
`/quality-gate [scope]`
|
||||
|
||||
åŽäēå㎠**čģŊé** åčŗĒãã§ãã¯ãéã E2E / éŖåããšã (test:e2e / test:fed / Cypress) 㯠CI å´ã§åŽčĄããããããæŦãŗããŗããĢã¯åĢããĒãã
|
||||
|
||||
## Scope
|
||||
|
||||
- `repo` (default) â å
¨ãããąãŧã¸
|
||||
- `backend` â `packages/backend` ãŽãŋ
|
||||
- `frontend` â `packages/frontend` ãŽãŋ
|
||||
- `path/to/file.ts` â åä¸ããĄã¤ãĢã¸ãŽ ESLint --fix ãŽãŋ
|
||||
|
||||
## Pipeline
|
||||
|
||||
### Repo scope (å
¨é¨)
|
||||
|
||||
åãããąãŧã¸ãŽ `lint` ãšã¯ãĒããåŽäŊ㯠`pnpm typecheck && pnpm eslint` ([packages/backend/package.json](../../packages/backend/package.json), [packages/frontend/package.json](../../packages/frontend/package.json)) ã§ããĢãŧã㎠`pnpm lint` 㯠`pnpm --no-bail -r lint` (= å
¨ãããąãŧã¸ã§ lint ã `--no-bail` ã§åŽčĄ)ã**typecheck 㯠lint ãĢåĢãžããĻãã**ãããé常ã¯ã㎠2 ãŗããŗãã§åå:
|
||||
|
||||
```bash
|
||||
# 1. Lint (= typecheck + ESLintãå
¨ãããąãŧã¸ã--no-bail ã§æåãŽå¤ąæã§æĸãžããå
¨įĩæãéãã)
|
||||
pnpm lint
|
||||
|
||||
# 2. Unit test (éĢéãe2e ã¯åĢãžãĒã)
|
||||
pnpm --filter backend test
|
||||
pnpm --filter frontend test
|
||||
```
|
||||
|
||||
#### čŠŗį´°ãåããĻčĻããæãŽãŋ (optional)
|
||||
|
||||
lint ããžã¨ããĻå¤ąæããĻããĻ typecheck ãŽįĩæã ãåįŦã§čĻããå ´åã¯ãäģĨä¸ãååĨãĢåãã**é常ã¯ä¸čĻ** (lint ãŽåēåãčĒãã°čļŗãã):
|
||||
|
||||
```bash
|
||||
pnpm --filter backend typecheck # tsgo åäŊ
|
||||
pnpm --filter frontend typecheck # vue-tsc åäŊ (Vue SFC ãŽåãčĻããã)
|
||||
```
|
||||
|
||||
### Backend scope
|
||||
|
||||
`pnpm --filter backend lint` ã¯å
é¨ã§ `pnpm typecheck && pnpm eslint` ãåŽčĄãã ([packages/backend/package.json](../../packages/backend/package.json)) ãŽã§ã`lint` ãåãã° typecheck ãįĩãããčģŊéã˛ãŧãã§ã¯ typecheck ãŽäēéåŽčĄãéŋãããã `lint` + `test` ãŽãŋ:
|
||||
|
||||
```bash
|
||||
pnpm --filter backend lint
|
||||
pnpm --filter backend test
|
||||
```
|
||||
|
||||
`tsgo` ãŽåēåãåįŦã§čĻããæãŽãŋ optional ã§ `pnpm --filter backend typecheck` ãåĨéåãã
|
||||
|
||||
### Frontend scope
|
||||
|
||||
`pnpm --filter frontend lint` ãå
é¨ã§ `pnpm typecheck && pnpm eslint` ãåŽčĄãã ([packages/frontend/package.json](../../packages/frontend/package.json)) ãããčģŊéã˛ãŧãã§ã¯ Backend åæ§ãĢ `lint` + `test` ãŽãŋ:
|
||||
|
||||
```bash
|
||||
pnpm --filter frontend lint
|
||||
pnpm --filter frontend test
|
||||
```
|
||||
|
||||
`vue-tsc` ãŽåēåãåįŦã§čĻããæãŽãŋ optional ã§ `pnpm --filter frontend typecheck` ãåĨéåãã
|
||||
|
||||
### Single file scope
|
||||
|
||||
```bash
|
||||
pnpm exec eslint --fix <path>
|
||||
```
|
||||
|
||||
## Output
|
||||
|
||||
åŽčĄãããã§ãŧãē㎠pass/fail ã¨äģļæ°ãéč¨ãããæ¨æēãã¤ããŠã¤ãŗã¯ `pnpm lint` (typecheck å
å
) 㨠unit test ãŽãŋãĒãŽã§ããããŠãĢããŽåēåã¯äģĨä¸ãŽãããĢãĒã:
|
||||
|
||||
```text
|
||||
Quality Gate (repo):
|
||||
|
||||
Lint: PASS (0 errors, 2 warnings)
|
||||
Backend ut: PASS (412/412)
|
||||
Frontend ut: PASS (87/87)
|
||||
|
||||
â åŽäēåãŽčģŊéãã§ã㯠OKãéã e2e / éŖåããšã㯠CI å´ã§åŽčĄãããã
|
||||
```
|
||||
|
||||
`#### čŠŗį´°ãåããĻčĻããæãŽãŋ (optional)` ã§ååĨ typecheck (`pnpm --filter backend typecheck` / `pnpm --filter frontend typecheck`) ãåããå ´åãŽãŋãããŽįĩæãčŋŊå čĄã¨ããĻ襨į¤ēãã:
|
||||
|
||||
```text
|
||||
Quality Gate (repo):
|
||||
|
||||
Lint: PASS (0 errors, 2 warnings)
|
||||
Backend tc: PASS (0 errors) # optional åŽčĄæãŽãŋ
|
||||
Frontend tc: PASS (0 errors) # optional åŽčĄæãŽãŋ
|
||||
Backend ut: PASS (412/412)
|
||||
Frontend ut: PASS (87/87)
|
||||
```
|
||||
|
||||
å¤ąææã¯æåãĢčŊãĄããã§ãŧãēã§åæĸããĻčŠŗį´°ãčĻããã
|
||||
|
||||
## éĸéŖ skill / ãŗããŗã
|
||||
|
||||
- `/check-misskey-js` ãŗããŗã â API 夿´æãŽ misskey-js åįæ
|
||||
- [AGENTS.md §åŋ
é ãŗããŗã](../../AGENTS.md#åŋ
é ãŗããŗã) â pnpm ãŗããŗãä¸čĻ§ãŽæŖå
¸
|
||||
|
||||
## å
ECC įã¨ãŽåˇŽå
|
||||
|
||||
- ã¸ã§ããĒãã¯ãĒč¨čĒčĒåå¤åŽãæé¤ããMisskey åēåŽ pipeline ãĢã
|
||||
- formatter ãã§ãŧãēãĒã (Misskey 㯠ESLint --fix ãŽãŋæĄį¨)ã
|
||||
- e2e / federation / Cypress ã¯éãããé¤å¤ã CI å´ãĢå§č˛ã
|
||||
@@ -1,18 +0,0 @@
|
||||
# Misskey â Claude Code čŖåŠãããĨãĄãŗã
|
||||
|
||||
ãĢãŧã `CLAUDE.md` ãĢã¯æ¸ãããĻããĒãããéįēæãĢåį
§ããã¨äžŋåŠãĒæ
å ąãåéåĨãĢãžã¨ããĻããã**Claude ã¯åŋ
čĻãĢãĒãŖããŋã¤ããŗã°ã§čОåŊããĄã¤ãĢã Read ããã°č¯ã** (auto-load ããĒã)ã
|
||||
|
||||
## į´ĸåŧ
|
||||
|
||||
| ããĄã¤ãĢ | ãã¤čĒãã |
|
||||
|---|---|
|
||||
| [architecture.md](./architecture.md) | ãããąãŧã¸æ§æãģããĢãæ§é ãææĄãããæ / æ°ãããąãŧã¸ã表ã夿´ãč¨įģããæ |
|
||||
| [backend.md](./backend.md) | `packages/backend` ãᎍéããæ (NestJS / TypeORM / API endpoint / migration) |
|
||||
| [frontend.md](./frontend.md) | `packages/frontend` ãᎍéããæ (Vue 3 / Mk* / i18n / SCSS Modules / `os.ts`) |
|
||||
| [testing.md](./testing.md) | ããšããæ¸ããģčĩ°ãããæ (Vitest æ§æãCypressãStorybook) |
|
||||
| [plugins.md](./plugins.md) | æåšåæ¸ãŽ Claude Code ããŠã°ã¤ãŗãŽį¨éãįĸēčĒãããæ |
|
||||
|
||||
## čŖčļŗ: ãĢãŧãĢ vs ãããĨãĄãŗã
|
||||
|
||||
- äēæ
į´įĩãĢãŧãĢ (SPDX / locales / migration) ã¨åŋ
é ãŗããŗããģCHANGELOG æ¸åŧã¯ããĒãã¸ããĒãĢãŧã㎠[AGENTS.md](../../AGENTS.md) ãĢéį´ãããĻãããClaude Code 㯠CLAUDE.md ãã㎠`@AGENTS.md` ã§å¸¸æãŗãŗãããšããĢäšãããCodex / Copilot ãåãããĄã¤ãĢãčĒãã
|
||||
- `.claude/docs/*.md` (ããŽããŖãŦã¯ããĒ) 㯠**ãĒãŗãããŗãåį
§**ãClaude ããįĨãŖãĻãããæšãč¯ãã常ãĢæã¤åŋ
čĻã¯ãĒããå
厚ããããĢįŊŽãã
|
||||
@@ -1,47 +0,0 @@
|
||||
# ãĸãŧããã¯ããŖæĻčĻ
|
||||
|
||||
## ãĸããŦãæ§æ (pnpm workspaces)
|
||||
|
||||
pnpm workspace ãŽæŖã¯ [pnpm-workspace.yaml](../../pnpm-workspace.yaml) ã§ãäģĨä¸ 11 ãããąãŧã¸ã¨ã`packages/misskey-js` å
㎠sub-workspace `packages/misskey-js/generator` (åįæį¨ãŽå
é¨ã¸ã§ããŦãŧãŋãį´æĨᎍéããĒã) ã§æ§æãããã`package.json` ㎠`workspaces` é
åãäŊĩč¨ããĻããããåŽäŊ㯠pnpm-workspace.yaml ãčĒãžãã:
|
||||
|
||||
| ãããąãŧ㸠| åŊšå˛ |
|
||||
|---|---|
|
||||
| `packages/backend` | NestJS 11 + Fastify 5 + TypeORM 0.3 (PostgreSQL) + RedisãHTTP/WebSocket/ActivityPub ãĩãŧããŧæŦäŊã |
|
||||
| `packages/frontend` | Vue 3.5 + ViteãWeb ã¯ãŠã¤ãĸãŗãæŦäŊã |
|
||||
| `packages/frontend-embed` | åãčžŧãŋå°į¨ããĨãŧ (ããŧãåäŊããŦããĨãŧį)ã |
|
||||
| `packages/frontend-shared` | frontend 㨠frontend-embed ã§å
ąæãããĻãŧããŖãĒããŖãģãŗãŗããŧããŗãã |
|
||||
| `packages/frontend-builder` | ãããŗãã¨ãŗãããĢãæ¯æ´ (Vite plugin ãĒãŠ)ã |
|
||||
| `packages/sw` | Service Workerã |
|
||||
| `packages/misskey-js` | JS/TS ã¯ãŠã¤ãĸãŗã SDK (MIT ãĩããããąãŧã¸)ã`src/autogen/` é
ä¸ãŽãŋ backend ㎠OpenAPI ãã `pnpm build-misskey-js-with-types` ã§čĒåįæãããããäģĨå¤ (`src/index.ts` / `src/api.ts` į) ã¯ææ¸ãäŋåŽãããautogen é
ä¸ãį´æĨᎍéããĒããã¨ã |
|
||||
| `packages/misskey-reversi` | å
čĩãĒããŧãˇã˛ãŧã ãŽãã¸ãã¯ã |
|
||||
| `packages/misskey-bubble-game` | å
čĩãããĢã˛ãŧã ãŽãã¸ãã¯ã |
|
||||
| `packages/i18n` | locales čĒãŋčžŧãŋ/åįæãŽãĩããŧãã |
|
||||
| `packages/icons-subsetter` | ãĸã¤ãŗãŗãŽãĩããģããåããŧãĢã |
|
||||
|
||||
ããŽäģãĢ `packages/shared` (workspaces ãĢã¯åĢãžããĒããå
ąæããĄã¤ãĢįŊŽãå ´) ãããã
|
||||
|
||||
## éčĻãĒäžåéĸäŋ
|
||||
|
||||
```
|
||||
frontend ââ misskey-js (auto-generated) ââ backend (OpenAPI)
|
||||
â˛
|
||||
âââ frontend-embed, sw ãäžå
|
||||
```
|
||||
|
||||
- backend ㎠API (meta / paramDef / response) ã夿´ããã **åŋ
ã** `pnpm build-misskey-js-with-types` ãåŽčĄããmisskey-js ãŽįæįŠãæ´æ°ãããåŋãã㨠CI ㎠`check-misskey-js-autogen` ã¸ã§ããčŊãĄãã
|
||||
|
||||
## ããĢãããŧãĢ
|
||||
|
||||
- **Backend**: `rolldown` (Rust čŖŊãģRollup äēæ API ãŽããŗããŠ) ã§ããŗããĢãåãã§ãã¯ã¯ `tsgo` (TypeScript native preview)ã
|
||||
- **Frontend**: Viteãåãã§ãã¯ã¯ `vue-tsc`ã
|
||||
- **Lint**: ESLint 9 (Flat Config) + `@misskey-dev/eslint-plugin`ã
|
||||
|
||||
## åŊéå
|
||||
|
||||
- `locales/` į´ä¸ãĢ 40 č¨čĒ㎠YAML (ja-JP.yml + äģ 39 č¨čĒ)ã
|
||||
- **`ja-JP.yml` ãŽãŋæåᎍéå¯** (Crowdin įĩįąã§äģč¨čĒã¸čĒåé
äŋĄ)ã
|
||||
- ãããŗãã¨ãŗããããŽåį
§ã¯åŧæ°ãĒããåŧæ°ãããã§äŊŋãåãããčŠŗį´°ã¯ [frontend.md](./frontend.md#åŊéå-i18n)ã
|
||||
|
||||
## ãŠã¤ãģãŗãš
|
||||
|
||||
ãĒãã¸ããĒæŦäŊ㯠AGPL-3.0-onlyã**AGPL-3.0-only įŽĄčŊã㤠SPDX CI å¯žčąĄããŖãŦã¯ããĒ** ãŽæ°čĻ `.ts` / `.js` / `.cjs` / `.mjs` / `.vue` / `.scss` / `.html` ããĄã¤ãĢãĢã¯åé ãĢ SPDX ããããŧåŋ
é ã`packages/misskey-js` 㯠MIT ãĩããããąãŧã¸ãĒãŽã§ AGPL ããããŧãä¸åžãĢäģããĒããæĄäģļã¨é¤å¤ãŽčŠŗį´°ã¯ [AGENTS.md §1](../../AGENTS.md#1-spdx-ããããŧåŋ
é ) åį
§ã
|
||||
@@ -1,124 +0,0 @@
|
||||
# Backend (`packages/backend`) čĻį´
|
||||
|
||||
NestJS 11 + Fastify 5 + TypeORM 0.3 (PostgreSQL) + Redisã
|
||||
|
||||
## ãĸãŧããã¯ããŖ
|
||||
|
||||
- **DI ãŗãŗãã**: NestJS ㎠`@Injectable()` ãĩãŧããš + Repository (TypeORM) ããŋãŧãŗã
|
||||
- **DI ããŧã¯ãŗ**: `@/di-symbols.js` ㎠`DI` ãã `@Inject(DI.xxx)` ã§æŗ¨å
Ĩã
|
||||
- **ããĢã**: `rolldown -c` ã§ `built/` ãĢããŗããĢãåãã§ãã¯ã¯ `tsgo`ã
|
||||
|
||||
## API ã¨ãŗããã¤ãŗã
|
||||
|
||||
### é
įŊŽ
|
||||
|
||||
`packages/backend/src/server/api/endpoints/<category>/<name>.ts` (ä¸é¨ã¯ãããį´ä¸)ã
|
||||
|
||||
### ä¸įšãģãã (`endpoints/ping.ts` åį
§)
|
||||
|
||||
åã¨ãŗããã¤ãŗãããĄã¤ãĢã¯äģĨä¸ãŽ 3 ã¤ã export ãã:
|
||||
|
||||
```ts
|
||||
export const meta = {
|
||||
tags: ['<tag>'],
|
||||
requireCredential: true, // ãžã㯠false (åŋ
ãæį¤ē)
|
||||
requireModerator: false, // åŋ
čĻãĒã true
|
||||
kind: 'read:account', // OAuth scope
|
||||
res: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
properties: { /* ... */ },
|
||||
},
|
||||
errors: {
|
||||
sampleError: {
|
||||
message: 'Sample error message.',
|
||||
code: 'SAMPLE_ERROR',
|
||||
id: 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx', // UUID v4 (`x`=hex, `y`=8/9/a/b)ã`crypto.randomUUID()` ã§įæããäģã¨ãŗããã¤ãŗãã¨éč¤ãããĒã
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: { /* JSON Schema */ },
|
||||
required: [],
|
||||
} as const;
|
||||
|
||||
@Injectable()
|
||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||
constructor(
|
||||
// @Inject(DI.xxx) private xxxRepository: XxxRepository,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
// åŽčŖ
ãã¨ãŠãŧ㯠throw new ApiError(meta.errors.xxx);
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### æŗ¨æįš
|
||||
|
||||
- **å
Ŧé API ã¨ãŠãŧã¨ããĻã¯ãŠã¤ãĸãŗããĢčŋãããããŽã¯ `throw new ApiError(meta.errors.<key>)` ãäŊŋã**ã`meta.errors` ãĢåæããĻ `ApiError` ã§ãŠããããĒã㨠misskey-js å´ãŽåãĢåēãããŦãšããŗãšã 500 ãĢãĒãã
|
||||
- 䏿šã§ **æŗåŽå¤ãŽäžå¤ (DB 䏿´å / ä¸åą¤ãĩãŧããšãŽ bug į) ã¯æĄãæŊ°ããå throw ãã**ãæĸå endpoint ããæåž
ãããæĨåã¨ãŠãŧ㯠`ApiError` ãĢ夿ããããäģĨå¤ã¯ `throw err;` ã§å throwããŽäēæŽĩæ§ã (äž: [`endpoints/i/pin.ts`](../../packages/backend/src/server/api/endpoints/i/pin.ts) ㎠`catch` į¯)ãį `throw` ãå
¨éĸįĻæĸããã¨æĒįĨäžå¤ã 200 ã§æŊ°ããĻ debug å°éŖãĢãĒãã
|
||||
- `meta.errors.<key>.id` 㯠**UUID** åŊĸåŧãæ°čĻčŋŊå æã¯äģã¨ãŗããã¤ãŗãã¨éč¤ããĒãããįĸēčĒããã
|
||||
- `requireCredential` 㯠`true` / `false` ãåŋ
ãæį¤ēããã
|
||||
- æ°čĻã¨ãŗããã¤ãŗãčŋŊå åžã¯ **`pnpm build-misskey-js-with-types`** ãåŽčĄãã (`misskey-js` ãŽčĒåįæããĄã¤ãĢãæ´æ°)ã
|
||||
|
||||
### ãĢãŧãįģé˛
|
||||
|
||||
ã¨ãŗããã¤ãŗã㯠**glob čĒååéãããĒã**ãæ°čĻããĄã¤ãĢã `endpoints/<category>/<name>.ts` ãĢįŊŽããã ãã§ã¯ API ãĢãŧããŖãŗã°ãĢäšããã404 ãĢãĒãã`packages/backend/src/server/api/endpoint-list.ts` ãĢãĸãĢããĄãããé ã§ 1 čĄčŋŊå ãããŽãåŋ
é :
|
||||
|
||||
```ts
|
||||
export * as '<category>/<name>' from './endpoints/<category>/<name>.js';
|
||||
```
|
||||
|
||||
`EndpointsModule.ts` ãããŽããĄã¤ãĢãŽå
¨ã¨ã¯ãšããŧãã `Object.entries()` ã§å垊ããNestJS ㎠provider (`provide: 'ep:<path>'`) ãįæãããčŠŗį´°ã¯ [.claude/skills/add-api-endpoint/SKILL.md](../skills/add-api-endpoint/SKILL.md) ãŽãšããã 4 ãåį
§ã
|
||||
|
||||
## ãĸããĢ / Repository
|
||||
|
||||
- ã¨ãŗããŖããŖ: `packages/backend/src/models/<Name>.ts` (`@Entity` + `@Column`)ã
|
||||
- DI įĩįąã§æŗ¨å
Ĩããã Repository ãįĩįąããĻãĸã¯ãģãšã
|
||||
|
||||
## Migration
|
||||
|
||||
čŠŗį´°æé (ææ¸ãæšåŧ = AGENTS.md §3 ã¨æ´å):
|
||||
|
||||
> ã¨ãŗããŖããŖåˇŽåãããŽčĒåįæã `CREATE INDEX CONCURRENTLY` įãŽãĒããˇã§ãŗãäŊŋãããå ´å㯠[.claude/skills/create-migration/SKILL.md](../skills/create-migration/SKILL.md) ㎠TypeORM CLI æé ãäŊŋããææ¸ã / CLI ãŠãĄãã§ã `check-migrations` (pending DDL æ¤åē) ããéãã°į䞥ã
|
||||
|
||||
1. **ãŋã¤ã ãšãŋãŗãååž**: `node -e "console.log(Date.now())"`
|
||||
2. **ããĄã¤ãĢå**: `packages/backend/migration/{timestamp}-{PascalCaseName}.js` (æĄåŧĩå㯠`.js`)
|
||||
3. **éåŊĸ**:
|
||||
|
||||
```js
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export class PascalCaseName1234567890123 {
|
||||
name = 'PascalCaseName1234567890123'
|
||||
|
||||
async up(queryRunner) {
|
||||
// åé˛ãã¤ã°ãŦãŧãˇã§ãŗ
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
// up ãåŽå
¨ãĢåˇģãæģã
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
4. **æ¤č¨ŧ**:
|
||||
- `pnpm --filter backend check-migrations` (TypeORM schema builder ã§ pending DDL ãæ¤åēãããã¨ãŗããŖããŖã¨ migration ãŽä¸ä¸č´ãæŽãŖãĻããã¨ããã§éãŧãįĩäēãããåŽäŊ㯠[scripts/check_migrations_clean.js](../../packages/backend/scripts/check_migrations_clean.js))
|
||||
- `pnpm migrate` (ããŧãĢãĢ DB ãĢéŠį¨)
|
||||
- `pnpm revert` (ããŧãĢããã¯įĸēčĒ)
|
||||
5. **ã¨ãŗããŖããŖã¨ãŽæ´åæ§**: éĸéŖãã `src/models/*.ts` ㎠`@Column` / `@Entity` ãåæãĢæ´æ°ããã
|
||||
|
||||
> ããŧã¸æ¸ãŋ migration ãŽįˇ¨é㯠**įĩļ寞įĻæĸ** ([AGENTS.md §3](../../AGENTS.md#3-ããŧã¸æ¸ãŋ-migration-ãįĩļ寞ãĢᎍéããĒã))ã
|
||||
|
||||
## ããšã
|
||||
|
||||
- Unit: `pnpm --filter backend test` (`vitest.config.unit.ts`)
|
||||
- E2E: `pnpm --filter backend test:e2e` (`vitest.config.e2e.ts`)
|
||||
- Federation: `pnpm --filter backend test:fed` (`vitest.config.fed.ts`)
|
||||
- é
įŊŽ: `packages/backend/test/` é
ä¸ã
|
||||
@@ -1,76 +0,0 @@
|
||||
# Frontend (`packages/frontend`) čĻį´
|
||||
|
||||
Vue 3.5 + Vite + Storybook + Cypress E2Eã
|
||||
|
||||
## ãŗãŗããŧããŗãåŊå
|
||||
|
||||
- å
ąæ / ååŠį¨ãŗãŗããŧããŗã㯠**`Mk` ããŦããŖãã¯ãš** (äž: `MkButton.vue`, `MkInput.vue`, `MkAbuseReport.vue`)ã
|
||||
- ããŧã¸åäŊãŽããŽã¯ `packages/frontend/src/pages/` é
ä¸ãĢįŊŽãã
|
||||
|
||||
## SFC ãšãŋã¤ãĢ
|
||||
|
||||
Composition API + `<script setup lang="ts">` ãåēæŦã¨ãã (Options API ã¯æ°čĻå°å
ĨããĒã)ãååŽŖč¨ã module ãšãŗãŧããŽãĻãŧããŖãĒããŖãįŊŽãããæã¯ãsetup ãããã¯ã¨**äŊĩį¨**ããåŊĸã§čŋŊå ㎠`<script lang="ts">` ãããã¯ãįŊŽããĻæ§ããĒã (äž: [`MkInput.vue`](../../packages/frontend/src/components/MkInput.vue) 㯠`SupportedTypes` åãåĨãããã¯ã§åŽŖč¨ããĻãã setup ãæ¸ããĻãã)ãSCSS 㯠**CSS Modules** ã§æ¸ãã`<style lang="scss" module>` ãäŊŋã:
|
||||
|
||||
```vue
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div :class="$style.root">
|
||||
<!-- ... -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
// ...
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
/* ... */
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
## åŊéå (i18n)
|
||||
|
||||
- æååãĒããŠãĢãį´æ¸ãããĒãã
|
||||
- åŧæ°ãĒã: `i18n.ts.<path>` ã§åį
§ãã (äž: `i18n.ts.deleted`)ã
|
||||
- åŧæ°ãã: `i18n.tsx.<path>(...)` ã§éĸæ°åŧãŗåēããã (äž: `i18n.tsx.takeOverConfirm({ name })`)ã
|
||||
- æ°čĻããŧ㯠**`locales/ja-JP.yml` ãŽãŋ** ãĢčŋŊå ãã (äģč¨čĒ㯠Crowdin ã§čĒåé
äŋĄ)ã
|
||||
- `i18n` 㯠`packages/frontend/src/i18n.ts` (ãžãã¯å
ąæãĸã¸ãĨãŧãĢ) ãã import ããã
|
||||
|
||||
## ãĸãŧããĢ / éįĨ
|
||||
|
||||
- `os.ts` (`packages/frontend/src/os.ts`) įĩįąã§åŧãļã
|
||||
- `os.alert(...)` / `os.confirm(...)` / `os.popup(...)` / `os.success(...)` ãĒãŠã
|
||||
- ããŠãĻãᅪæē㎠`window.alert()` / `window.confirm()` ã **į´æĨåŧã°ãĒã**ã
|
||||
|
||||
## ãĸã¯ãģãˇããĒããŖ (PR ãŦããĨãŧã§ææãããããįš)
|
||||
|
||||
- ã¯ãĒãã¯ããŗããŠãäģãããĒã `<button>` ãäŊŋããã`role="button"` + `tabindex` ãäģããã
|
||||
- ããŠãŧã čĻį´ ãĢ㯠`<label>` ãžã㯠`aria-label` ãäģããã
|
||||
- ããŧããŧãæäŊå¯čŊã§ãããã¨ã
|
||||
|
||||
## Storybook
|
||||
|
||||
æ°čĻå
ąæãŗãŗããŧããŗããĢ㯠`<ComponentName>.stories.impl.ts` ãäŊĩč¨ãããŽãæ
Ŗįŋ (`MkButton.stories.impl.ts` įãŽäžå¤æ°)ã
|
||||
|
||||
```bash
|
||||
pnpm --filter frontend storybook-dev # localhost:6006
|
||||
```
|
||||
|
||||
## ããĢããģéįē
|
||||
|
||||
- éįē: `pnpm dev` (ãĢãŧã) ã§ backend + frontend ã watch ã§įĢãĄä¸ããã
|
||||
- ããĢã: `pnpm --filter frontend build`
|
||||
- åãã§ãã¯: `pnpm --filter frontend typecheck` (vue-tsc)
|
||||
- ESLint: `pnpm --filter frontend eslint`
|
||||
|
||||
## ããšã
|
||||
|
||||
- Unit (Vitest): `pnpm --filter frontend test`
|
||||
- Cypress E2E: `pnpm e2e` (ãĢãŧããã; `start-server-and-test` ã§čĩˇå)
|
||||
@@ -1,28 +0,0 @@
|
||||
# æåšåæ¸ Claude Code ããŠã°ã¤ãŗ
|
||||
|
||||
`.claude/settings.json` ã§ 14 ããŠã°ã¤ãŗãæåšåãããĻããããããããŽå
¸åįãĒåŠį¨ãˇãŧãŗã 1 čĄã§į¤ēãã
|
||||
|
||||
| ããŠã°ã¤ãŗ | į¨é |
|
||||
| --- | --- |
|
||||
| `frontend-design` | UI ãŗãŗããŧããŗã / ããŧã¸ãŽč¨č¨ãģããļã¤ãŗäŊæĨ (Vue 3 ᎍéãĢæåš) |
|
||||
| `superpowers` | TDDãģdebuggingãģbrainstormingãģplanning įãŽãĄãŋãšããĢįž¤ |
|
||||
| `context7` | OSS ãããĨãĄãŗããŽååž (Vue 3, NestJS, TypeORM, Vitest į) â č¨įˇ´ããŧãŋãŽå¤ããčŖã |
|
||||
| `code-review` | ãŗãŧããŦããĨãŧ (`/code-review`) |
|
||||
| `code-simplifier` | ãŗãŧãæ´į (`code-simplifier:code-simplifier` ãĩãã¨ãŧã¸ã§ãŗãįĩįą) |
|
||||
| `github` | GitHub PR / Issue æäŊ (gh ããŧãšã ãčŖåŠãŗããŗããã) |
|
||||
| `skill-creator` | æ°ãšããĢãŽäŊæãģæšåãģčŠäžĄ |
|
||||
| `feature-dev` | æŠčŊéįēãŦã¤ã (`/feature-dev:feature-dev` / å
é¨ãĢ `code-architect` / `code-explorer` / `code-reviewer` ãĩãã¨ãŧã¸ã§ãŗã) |
|
||||
| `claude-md-management` | CLAUDE.md ãŽäŊæãģæšå (`/claude-md-management:revise-claude-md` / `claude-md-improver` ã¨ãŧã¸ã§ãŗã) |
|
||||
| `typescript-lsp` | TypeScript LSP éŖæē (åæ
å ąãæ´ģį¨) |
|
||||
| `security-guidance` | ãģããĨãĒããŖãŦããĨãŧ (`/security-review`) |
|
||||
| `pr-review-toolkit` | PR ãŦããĨãŧä¸åŧããĩãã¨ãŧã¸ã§ãŗã: `code-reviewer` / `code-simplifier` / `comment-analyzer` / `pr-test-analyzer` / `silent-failure-hunter` / `type-design-analyzer` |
|
||||
| `claude-code-setup` | Claude Code čĒååãģãããĸããææĄ |
|
||||
| `playwright` | ããŠãĻãļčĒåæäŊ (ãããŗãã¨ãŗãåäŊįĸēčĒæãĢæį¨) |
|
||||
|
||||
## äŊŋãåããŽæé
|
||||
|
||||
- **API éĸéŖãŽčĒŋæģ**: `context7` ã§å¯žčąĄãŠã¤ããŠãĒãŽãããĨãĄãŗããååž â ᎍéã
|
||||
- **PR äŊæå**: `pr-review-toolkit` ãŽåã¨ãŧã¸ã§ãŗã (code-reviewer / silent-failure-hunter į) ãä¸Ļåã§čĩ°ãããã
|
||||
- **æ°æŠčŊãŽč¨č¨**: `feature-dev` â brainstorming â åŽčŖ
ãŽæĩãã
|
||||
- **UI įĸēčĒ**: `playwright` ã§ `pnpm dev` ãŽįģéĸãį´æĨæäŊã
|
||||
- **å°æĨčŋŊå æ¤č¨**: PostgreSQL MCP â TypeORM + 342 migration ãŽčĒŋæģåšįåãread-only ããŧãĢã§įģé˛ããæĨįļå
(`misskey` DB) ã¨æ¨ŠéåéĸãĢæŗ¨æããã
|
||||
@@ -1,69 +0,0 @@
|
||||
# ããšãæ§æ
|
||||
|
||||
## Backend å
¨čŦãŽåæ: `.config/test.yml`
|
||||
|
||||
backend ãŽããšããšã¯ãĒãã (`test` / `test:e2e` / `test:fed`) ã¯ããšãĻå
é¨ã§ `cross-env NODE_ENV=test pnpm compile-config` ãåŽčĄãã`.config/test.yml` ãčĒãŋčžŧã ([packages/backend/package.json](../../packages/backend/package.json), [packages/backend/scripts/compile_config.js](../../packages/backend/scripts/compile_config.js))ã**æĒäŊæã ã¨ããšãčĒäŊãčĩˇåããĒãã**
|
||||
|
||||
æĒäŊæãĒãäģĨä¸ã 1 åã ãæåãŗããŧãã (ãŠãĄãã§ãå¯):
|
||||
|
||||
```bash
|
||||
ncp .github/misskey/test.yml .config/test.yml
|
||||
# ãžãã¯
|
||||
cp .github/misskey/test.yml .config/test.yml
|
||||
```
|
||||
|
||||
čŖčļŗ:
|
||||
|
||||
- ãĢãŧã㎠`pnpm start:test` (Cypress į¨ãĢããšããĩãŧããŧãčĩˇåãããŗããŗã) ãäŊŋãįĩ莝ã§ã¯åŽčĄæãĢ `ncp` ã§čĒåãŗããŧããã ([package.json](../../package.json))ãããäģĨå¤ã§ backend ããšããį´æĨčĩ°ãããæã¯ä¸č¨ãŽæåãŗããŧãåŋ
čĻã
|
||||
- ãã§ãĢ `.config/test.yml` ãããã°åããšããšã¯ãĒãããŽå
é¨ `compile-config` ã§ååãĒãŽã§ãčŋŊå ã§ `pnpm --filter backend compile-config` ãåŠãåŋ
čĻã¯ãĒãã
|
||||
- `pnpm start:test` 㯠backend e2e ããšã (`pnpm --filter backend test:e2e`) ãŽåæã§ã¯ãĒã (ããŧãįĢļåãŽå
ãĢãĒãããäŊŋããĒããã¨)ã
|
||||
|
||||
## Backend (Vitest 4, 3 č¨åŽ)
|
||||
|
||||
| į¨ŽåĨ | č¨åŽããĄã¤ãĢ | åŽčĄãŗããŗã |
|
||||
| --- | --- | --- |
|
||||
| Unit | `packages/backend/vitest.config.unit.ts` | `pnpm --filter backend test` |
|
||||
| E2E (HTTP / DB) | `packages/backend/vitest.config.e2e.ts` | `pnpm --filter backend test:e2e` |
|
||||
| Federation | `packages/backend/vitest.config.fed.ts` | `pnpm --filter backend test:fed` |
|
||||
|
||||
- é
įŊŽ: `packages/backend/test/`
|
||||
- äēåæēå㯠[§Backend å
¨čŦãŽåæ: `.config/test.yml`](#backend-å
¨čŦãŽåæ-configtestyml) ãåį
§ã
|
||||
- ãĢããŦãã¸: `pnpm --filter backend test-and-coverage`
|
||||
|
||||
## Frontend (Vitest)
|
||||
|
||||
```bash
|
||||
pnpm --filter frontend test # 1 ååŽčĄ
|
||||
pnpm --filter frontend test-and-coverage # ãĢããŦãã¸äģã
|
||||
```
|
||||
|
||||
- ä¸ģãĒé
įŊŽ: `packages/frontend/test/*.test.ts` (äž: `i18n.test.ts`, `theme.test.ts`, `is-birthday.test.ts`)ã
|
||||
- ããĢãããŧãĢå¨ããĒãŠå¯žčąĄãŗãŧãã¨éŖæĨãããæšãåãããããããšãã¯ããŗãŧãã¨åãããŖãŦã¯ããĒãĢ `*.test.ts` ã¨ããĻįŊŽã (äž: [`packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts`](../../packages/frontend/lib/rollup-plugin-unwind-css-module-class-name.test.ts))ã
|
||||
- å
ąæãŗãŗããŧããŗã (`MkX.vue`) ãŽãĻãããããšãã¯įžįļå°ãĒãã`*.spec.ts` / `__tests__/` åŊĸåŧã¯æĄį¨ããĻããĒã (Storybook + Cypress ã§ãĢããŧ)ã
|
||||
|
||||
## E2E (Cypress)
|
||||
|
||||
ãĢãŧãããåŽčĄãã:
|
||||
|
||||
```bash
|
||||
pnpm e2e # start:test ãĩãŧããŧãįĢãĻãĻ Cypress run
|
||||
pnpm cy:open # å¯žčŠąįãĢéã
|
||||
```
|
||||
|
||||
- č¨åŽ: ãĢãŧã `cypress.config.ts`ãããšãæŦäŊ㯠`cypress/` é
ä¸ã
|
||||
|
||||
## Storybook (frontend)
|
||||
|
||||
```bash
|
||||
pnpm --filter frontend storybook-dev # http://localhost:6006
|
||||
pnpm --filter frontend build-storybook # éįããĢã
|
||||
```
|
||||
|
||||
- åãŗãŗããŧããŗãæ¨ĒãĢ `*.stories.impl.ts` ãäŊĩč¨ããæ
Ŗįŋ (äž: `MkButton.stories.impl.ts`)ã
|
||||
- Chromatic (`pnpm --filter frontend chromatic`) ã§čĻčĻå帰ãã§ãã¯ã
|
||||
|
||||
## ããŧãĢãĢ DB / Redis (ããšããģéįēå
ąé)
|
||||
|
||||
```bash
|
||||
docker compose -f compose.local-db.yml up -d
|
||||
```
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"enabledPlugins": {
|
||||
"frontend-design@claude-plugins-official": true,
|
||||
"superpowers@claude-plugins-official": true,
|
||||
"context7@claude-plugins-official": true,
|
||||
"code-review@claude-plugins-official": true,
|
||||
"code-simplifier@claude-plugins-official": true,
|
||||
"github@claude-plugins-official": true,
|
||||
"skill-creator@claude-plugins-official": true,
|
||||
"feature-dev@claude-plugins-official": true,
|
||||
"claude-md-management@claude-plugins-official": true,
|
||||
"typescript-lsp@claude-plugins-official": true,
|
||||
"security-guidance@claude-plugins-official": true,
|
||||
"pr-review-toolkit@claude-plugins-official": true,
|
||||
"claude-code-setup@claude-plugins-official": true,
|
||||
"playwright@claude-plugins-official": true
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
# `.claude/skills/` â ããã¸ã§ã¯ãåēæãŽãĢãšãŋã ãšããĢ
|
||||
|
||||
Misskey åēæãŽįš°ãčŋããŋãšã¯ã Claude ãĢãšã ãŧãēãĢåŽčĄããããã㎠**ãĢãšãŋã ãšããĢ** ã `.claude/skills/<name>/SKILL.md` åŊĸåŧã§é
įŊŽããã
|
||||
|
||||
frontmatter (`name` + `description`) ã¯ãClaude ã **čĒåã§ãšããĢãåŧãŗåēãã夿ãã** å¯ä¸ãŽæããããĢãĒãã`description` ãĢã¯į¨éãå
ˇäŊįãã¤įļ˛įž
įãĢæ¸ã (åčŠ + å¯žčąĄ + ããĒãŦãŧæĄäģļ)ã
|
||||
|
||||
## åŽčŖ
æ¸ãšããĢ
|
||||
|
||||
### Misskey åēæ (æŦãĒãã¸ããĒåãæ¸ãčĩˇãã)
|
||||
|
||||
| ãšããĢå | åŊšå˛ | åĒå
åēĻ |
|
||||
| --- | --- | --- |
|
||||
| [create-migration](create-migration/SKILL.md) | TypeORM CLI (`migration:generate` / `migration:create`) ã§ãã¤ã°ãŦãŧãˇã§ãŗãįæããSPDX / up-down / `check-migrations` ãžã§čĒå° | éĢ (342 æĸå / čĻį´åŗãã) |
|
||||
| [add-api-endpoint](add-api-endpoint/SKILL.md) | NestJS DI + meta/paramDef čĻį´ã§ API ã¨ãŗããã¤ãŗãčŋŊå ã`endpoint-list.ts` įģé˛ã¨ `misskey-js` åįæãåĢã | éĢ |
|
||||
| [add-i18n-key](add-i18n-key/SKILL.md) | `locales/ja-JP.yml` ãŽãŋᎍéããčŖåŠãå㯠`packages/i18n` ãčĒååįæ | ä¸ |
|
||||
| [add-mk-component](add-mk-component/SKILL.md) | `Mk*` åŊå + SPDX (HTML) + SCSS module + `*.stories.impl.ts` äŊĩč¨ãŽ Vue ãŗãŗããŧããŗãã䏿ŦãšããŖããŠãŧãĢã | ä¸ |
|
||||
|
||||
### ECC (everything-claude-code) įąæĨ â MIT ãģãŦã¯ãã¤ãŗããŧã
|
||||
|
||||
[.claude/THIRD_PARTY_LICENSES.md](../THIRD_PARTY_LICENSES.md) §1 ãĢåēå
¸ãģæšå¤ãĄãĸãģMIT å
¨æãéį´ã
|
||||
|
||||
| ãšããĢå | åŊšå˛ | åĒå
åēĻ |
|
||||
| --- | --- | --- |
|
||||
| [context-budget](context-budget/SKILL.md) | agents / skills / MCP / CLAUDE.md ㎠token overhead ãčĻããåããčĨ大ãŗãŗããŧããŗããæ¤åē | ä¸ |
|
||||
|
||||
č¨č¨æšé: `create-migration` ã¯æå㎠`Date.now()` åŊåã§ã¯ãĒã TypeORM å
Ŧåŧ CLI (`migration:generate` / `migration:create`) ãæĄį¨ãStorybook ããĄã¤ãĢå㯠`*.stories.impl.ts` čĻį´ãĢæēæ ããã
|
||||
|
||||
## æ°čĻãšããĢãčŋŊå ããå ´å
|
||||
|
||||
- `.claude/skills/<name>/SKILL.md` ãĢ YAML frontmatter (`name` + `description`) ã¨æŦæ Markdown ãæ¸ãã
|
||||
- `disable-model-invocation: true` ã¯äģããĒã (auto-invoke ãããããã)ã
|
||||
- ä¸ģčĻåį
§ããĄã¤ãĢã¸ãŽãĒãŗã¯ã¯ããĒãã¸ããĒãĢãŧããããŽį¸å¯žããš (äž: `../../packages/backend/...`) ã§č˛ŧããįĩļ寞ããšã¯ contributor ãŽããŧã ããŖãŦã¯ããĒäžåãĢãĒããŽã§äŊŋããĒãã
|
||||
- åŽæãããã㎠README ãŽčĄ¨ãĢã 1 čĄčŋŊå ããã
|
||||
@@ -1,253 +0,0 @@
|
||||
---
|
||||
name: add-api-endpoint
|
||||
description: Misskey ㎠REST API ã¨ãŗããã¤ãŗã (/api/<category>/<name>) ã NestJS DI + meta/paramDef čĻį´ã§čŋŊå ãããããã¯ã¨ãŗããĢæ°ãã API ãĢãŧããčļŗãæãĢåŋ
ãäŊŋããendpoint-list.ts ã¸ãŽæåįģé˛ãe2e ããšããmisskey-js åįæãCHANGELOG ãžã§ãŽä¸éŖãŽæé ãåĢãã
|
||||
---
|
||||
|
||||
# Misskey API ã¨ãŗããã¤ãŗãčŋŊå ãšããĢ
|
||||
|
||||
`packages/backend/src/server/api/endpoints/<category>/<name>.ts` ãĢæ°čĻã¨ãŗããã¤ãŗããčŋŊå ãããããŽã¯ãŧã¯ãããŧã**æé 4 (endpoint-list.ts įģé˛) ãåŋãã㨠404 ãĢãĒã** įšãĢæå¤§ãŽæŗ¨æãæãã
|
||||
|
||||
## æéčĻäēåŽ (čĻčŊã¨ãã¨åŖãã)
|
||||
|
||||
1. ã¨ãŗããã¤ãŗã㯠**glob čĒååéãããĒã**ã[packages/backend/src/server/api/endpoint-list.ts](../../../packages/backend/src/server/api/endpoint-list.ts) ã¸ãŽ 1 čĄčŋŊå ãåŋ
é ã
|
||||
2. `meta` / `paramDef` ãå¤ããã **misskey-js ãŽåįæãåŋ
é **ã`pnpm build-misskey-js-with-types` ãåŋãã㨠CI ㎠`check-misskey-js-autogen` ã§åŋ
ãčŊãĄãã
|
||||
3. `meta.errors` ãŽå `id` 㯠**UUID**ãéč¤ãããĒã (æĸåå
¨ UUID ã¨čĄįĒįĸēčĒ)ã
|
||||
|
||||
## ãšããã 1: ããĄã¤ãĢé
įŊŽã¨ SPDX
|
||||
|
||||
`packages/backend/src/server/api/endpoints/<category>/<name>.ts` ãĢæ°čĻäŊæããã`<category>` ã¯æŠčŊé å (äž: `notes`, `users`, `admin/announcements`)ã
|
||||
|
||||
åé ãĢ SPDX ããããŧãåŋ
ãäģãã:
|
||||
|
||||
```ts
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
```
|
||||
|
||||
## ãšããã 2: æå°ããŗããŦãŧã (ãˇãŗããĢ read įŗģ)
|
||||
|
||||
[endpoints/ping.ts](../../../packages/backend/src/server/api/endpoints/ping.ts) ãããŧãšãĢæ¸ããčĒč¨ŧä¸čĻãģããŠãĄãŧãŋãĒããģå°ããĒãŦãšããŗãšãŽäž:
|
||||
|
||||
```ts
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['<tag>'],
|
||||
requireCredential: false,
|
||||
|
||||
res: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
properties: {
|
||||
// ...
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: {},
|
||||
required: [],
|
||||
} as const;
|
||||
|
||||
@Injectable()
|
||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||
constructor(
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
// åŽčŖ
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## ãšããã 3: čĒč¨ŧäģã / DI / errors ãåĢãããŗããŦãŧã
|
||||
|
||||
[endpoints/notes/create.ts](../../../packages/backend/src/server/api/endpoints/notes/create.ts) ãåį
§ãããčĻįš:
|
||||
|
||||
```ts
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||
import { ApiError } from '@/server/api/error.js';
|
||||
import { DI } from '@/di-symbols.js';
|
||||
// import ms from 'ms'; // limit.duration ãĢ ms('1hour') įãæ¸Ąãã¨ã (default import)
|
||||
|
||||
export const meta = {
|
||||
tags: ['notes'],
|
||||
requireCredential: true, // čĒč¨ŧåŋ
é ãĒã true
|
||||
prohibitMoved: false, // moved user ãæåĻããã
|
||||
kind: 'write:notes', // OAuth scope (requireCredential æãĢåŋ
é )
|
||||
limit: {
|
||||
duration: 3600000, // ms('1hour')
|
||||
max: 300,
|
||||
},
|
||||
errors: {
|
||||
noSuchNote: {
|
||||
message: 'No such note.',
|
||||
code: 'NO_SUCH_NOTE',
|
||||
id: 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx', // â
UUID v4 ãåŋ
ãįæ (`x`=hex, `y`=8/9/a/b)ãä¸ãŽãUUID įæããåį
§
|
||||
},
|
||||
},
|
||||
res: {
|
||||
type: 'object',
|
||||
optional: false, nullable: false,
|
||||
ref: 'Note', // packed entity ãĢæããå ´å
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
noteId: { type: 'string', format: 'misskey:id' },
|
||||
},
|
||||
required: ['noteId'],
|
||||
} as const;
|
||||
|
||||
@Injectable()
|
||||
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
|
||||
constructor(
|
||||
@Inject(DI.notesRepository)
|
||||
private notesRepository: NotesRepository,
|
||||
) {
|
||||
super(meta, paramDef, async (ps, me) => {
|
||||
const note = await this.notesRepository.findOneBy({ id: ps.noteId });
|
||||
if (note == null) throw new ApiError(meta.errors.noSuchNote);
|
||||
// åŽčŖ
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### meta ããŖãŧãĢãæŠčĻ襨
|
||||
|
||||
| ããŖãŧãĢã | į¨é |
|
||||
|---|---|
|
||||
| `tags` | OpenAPI ãŋã° (æŠčŊé å) |
|
||||
| `requireCredential` | čĒč¨ŧåŋ
é ã |
|
||||
| `requireModerator` / `requireAdmin` | 樊éåļé |
|
||||
| `prohibitMoved` | ãĸãĢãĻãŗãį§ģčĄæ¸ãĻãŧãļãŧãæåĻ |
|
||||
| `kind` | OAuth scope (`read:notes` / `write:notes` į)ã`requireCredential: true` æåŋ
é |
|
||||
| `limit` | ãŦãŧãåļé (`{ duration, max, key?, minInterval? }`) |
|
||||
| `errors` | ã¨ãŠãŧåŽįžŠãåčĻį´ ãĢ `message` / `code` / `id` (UUID v4) åŋ
é |
|
||||
| `res` | JSON Schema or `ref: '<EntityName>'` (packed entity åį
§) |
|
||||
| `requireFile` | ããĄã¤ãĢãĸããããŧãåŋ
é |
|
||||
| `secure` | secure cookie åŋ
čĻ |
|
||||
| `allowGet` | GET ãĄãŊããč¨ąå¯ |
|
||||
| `cacheSec` | ãŦãšããŗãšããŖããˇãĨį§æ° |
|
||||
| `description` | OpenAPI čĒŦæ |
|
||||
|
||||
čŠŗį´°ã¯ [endpoints.ts](../../../packages/backend/src/server/api/endpoints.ts) ãŽååŽįžŠ (lines 11-125) ãåį
§ã
|
||||
|
||||
### paramDef ãŽįšæŽããŠãŧããã
|
||||
|
||||
JSON Schema (AJV) ããŧãšã ããMisskey æĄåŧĩãäŊŋãã:
|
||||
|
||||
- `format: 'misskey:id'` â ID æååããĒããŧãˇã§ãŗ
|
||||
- `allOf` / `anyOf` / `oneOf` â č¤åæĄäģļ
|
||||
- `default` â ãããŠãĢãå¤
|
||||
|
||||
čŠŗį´°ã¯ [endpoint-base.ts](../../../packages/backend/src/server/api/endpoint-base.ts) ãåį
§ã
|
||||
|
||||
### ã¨ãŠãŧ throw
|
||||
|
||||
**ãå
Ŧé API ã¨ãŠãŧã¨ããĻ API ã¯ãŠã¤ãĸãŗããĢčŋãããããŽãã¯åŋ
ã `throw new ApiError(meta.errors.<key>)` ãäŊŋã**ã`meta.errors` ãĢåæããä¸ã§ `ApiError` ã§ãŠããããĒãã¨ãmisskey-js å´ãŽåæ
å ąãĢåēãããŦãšããŗãšã 500 ãĢãĒããįŦŦ 2 åŧæ°ã§čŋŊå æ
å ąãæ¸Ąãã:
|
||||
|
||||
```ts
|
||||
throw new ApiError(meta.errors.invalidParam, { reason: 'too short' });
|
||||
```
|
||||
|
||||
䏿šã§ã**æŗåŽå¤ãŽäžå¤ (DB 䏿´å / ä¸åą¤ãĩãŧããšãŽ bug ãĒãŠ) ãæĄãæŊ°ããããĢ `try/catch` ã§ `ApiError` ãĢ夿ãããŽã¯éŋãã**ãæĸå endpoint ããæåž
ãããæĨåã¨ãŠãŧ㯠`ApiError` ãĢ夿ããããäģĨå¤ã¯ `throw err;` ã§å throw ãããã¨ããäēæŽĩæ§ããĢãĒãŖãĻããã`packages/backend/src/server/api/endpoints/notes/create.ts` ㎠`catch` ᝠ(æĢ尞㎠`throw err;`) ãåį
§ãį㎠`throw` ãå
¨éĸįĻæĸããã¨æĒįĨäžå¤ã 200 ã§æŊ°ããĻ debug ãå°éŖãĢãĒããŽã§ãããŽããŠãŗãšãäŋã¤ã
|
||||
|
||||
čŠŗį´°ã¯ [error.ts](../../../packages/backend/src/server/api/error.ts) ㎠`ApiError` ã¯ãŠãšãåį
§ã
|
||||
|
||||
### UUID įæ
|
||||
|
||||
```bash
|
||||
node -e "console.log(crypto.randomUUID())"
|
||||
```
|
||||
|
||||
ã㎠UUID ãäģãŽã¨ãŗããã¤ãŗã㎠`id` ã¨čĄįĒããĻããĒããåŋ
ãįĸēčĒ:
|
||||
|
||||
```bash
|
||||
grep -r "id: '<įæãã UUID>'" packages/backend/src/server/api/endpoints/
|
||||
```
|
||||
|
||||
## ãšããã 4: â
åŋ
é â endpoint-list.ts ãĢįģé˛
|
||||
|
||||
[packages/backend/src/server/api/endpoint-list.ts](../../../packages/backend/src/server/api/endpoint-list.ts) ãŽåãĢãã´ãĒæĢå°žãĢ 1 čĄčŋŊå ããīŧæĸåãŽä¸Ļãŗãå´ŠããĒãīŧ:
|
||||
|
||||
```ts
|
||||
export * as '<category>/<name>' from './endpoints/<category>/<name>.js';
|
||||
```
|
||||
|
||||
ããĄã¤ãĢåé ãŽãŗãĄãŗã (`When you add new endpoint, you should add it to this file.`) ãŽéããããŽãĒãšãã API ãĢãŧããŖãŗã°ãŽåä¸ãŽįåŽã**åŋãã㨠404**ã
|
||||
|
||||
`EndpointsModule.ts` ãããŽããĄã¤ãĢãŽå
¨ã¨ã¯ãšããŧãã `Object.entries()` ã§å垊ããNestJS provider (`provide: 'ep:<path>'`) ãįæããã
|
||||
|
||||
## ãšããã 5: e2e ããšãčŋŊå
|
||||
|
||||
[packages/backend/test/e2e/endpoints.ts](../../../packages/backend/test/e2e/endpoints.ts) ãĢ寞åŋãã `describe` / `test` ãčŋŊå ããã`api()` ããĢããŧã§åŠã:
|
||||
|
||||
```ts
|
||||
describe('<category>/<name>', () => {
|
||||
test('æŖå¸¸įŗģ', async () => {
|
||||
const res = await api('<category>/<name>', { /* params */ }, alice);
|
||||
assert.strictEqual(res.status, 200);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
åŽčĄ: `pnpm --filter backend test:e2e`
|
||||
|
||||
## ãšããã 6: misskey-js åįæ (â
åŋ
é )
|
||||
|
||||
`meta` / `paramDef` / `res` ãå¤ãããåŋ
ãåŽčĄãã:
|
||||
|
||||
```bash
|
||||
pnpm build-misskey-js-with-types
|
||||
```
|
||||
|
||||
ããã§äģĨä¸ãæ´æ°ããã:
|
||||
|
||||
- `packages/backend/built/api.json` (OpenAPI spec)
|
||||
- `packages/misskey-js/generator/api.json`
|
||||
- `packages/misskey-js/src/autogen/*.ts` (TypeScript å)
|
||||
|
||||
PR ãĢ `packages/misskey-js/src/autogen/` é
ä¸ãŽåˇŽåãåĢãžããĻããĒãã¨ãCI ㎠`check-misskey-js-autogen` ã§čŊãĄãã
|
||||
|
||||
## ãšããã 7: Lint 㨠typecheck
|
||||
|
||||
```bash
|
||||
pnpm --filter backend lint
|
||||
```
|
||||
|
||||
(typecheck = `tsgo --noEmit` / ESLint = `eslint`)
|
||||
|
||||
## ãšããã 8: CHANGELOG
|
||||
|
||||
ãĻãŧãļãŧåŊąéŋããã (æ°æŠčŊ / æĸåæå夿´) ãĒãã`CHANGELOG.md` ㎠`## Unreleased` â `### Server` ãĢ 1 čĄčŋŊå ãã ([AGENTS.md §CHANGELOG](../../../AGENTS.md#changelog) åį
§):
|
||||
|
||||
```
|
||||
- Feat: /api/<category>/<name> ãčŋŊå
|
||||
```
|
||||
|
||||
į´į˛ãĒãĒããĄã¯ãŋãå
é¨į¨ãĒãä¸čĻã
|
||||
|
||||
## åį
§ããĄã¤ãĢ
|
||||
|
||||
- [endpoints.ts (meta/paramDef ååŽįžŠ)](../../../packages/backend/src/server/api/endpoints.ts)
|
||||
- [endpoint-base.ts (Endpoint åēåēã¯ãŠãš)](../../../packages/backend/src/server/api/endpoint-base.ts)
|
||||
- [endpoint-list.ts (â
ãããĢįģé˛)](../../../packages/backend/src/server/api/endpoint-list.ts)
|
||||
- [error.ts (ApiError)](../../../packages/backend/src/server/api/error.ts)
|
||||
- [endpoints/ping.ts (æå°äž)](../../../packages/backend/src/server/api/endpoints/ping.ts)
|
||||
- [endpoints/notes/create.ts (DI + errors ãŽå
¸å)](../../../packages/backend/src/server/api/endpoints/notes/create.ts)
|
||||
- [test/e2e/endpoints.ts (ããšãäž)](../../../packages/backend/test/e2e/endpoints.ts)
|
||||
- [scripts/generate_api_json.js (misskey-js įæå
)](../../../packages/backend/scripts/generate_api_json.js)
|
||||
@@ -1,117 +0,0 @@
|
||||
---
|
||||
name: add-i18n-key
|
||||
description: Misskey ㎠i18n ããŧãčŋŊå ãģäŋŽæŖãããlocales/ja-JP.yml ãŽãŋᎍéå¯čŊã§ãäģč¨čĒããĄã¤ãĢ (en-US.yml į 39 č¨čĒ) 㯠Crowdin ãŽčĒåé
äŋĄå
ãŽããįĩļ寞ãĢč§ĻããĒããå㯠packages/i18n ã ja-JP.yml ããčĒååįæãããfrontend ãã㯠i18n.ts.<key> ãžã㯠i18n.tsx.<key>(...) ã§åį
§ããã
|
||||
---
|
||||
|
||||
# Misskey i18n ããŧčŋŊå ãšããĢ
|
||||
|
||||
UI æč¨ãŽčŋŊå ãģ夿´ãčĄãéãŽčĻį´ã**æåᎍéããĻč¯ããŽã¯ `locales/ja-JP.yml` ãŽãŋã**
|
||||
|
||||
## å¤§åæ (įĩļ寞 NG)
|
||||
|
||||
- **`locales/<lang>.yml` (ja-JP.yml äģĨå¤) ãŽįˇ¨éã¯įĻæĸ**ãããã㯠Crowdin ãŽčĒåé
äŋĄå
ã§ãæåᎍéããã¨æŦĄãŽåæã§ä¸æ¸ãåĒå¤ąãã ([locales/README.md](../../../locales/README.md), [crowdin.yml](../../../crowdin.yml))ã
|
||||
- æååãĒããŠãĢã SFC ãĢį´æ¸ãããĒã (`<span>ãããĢãĄã¯</span>` į)ãåŋ
ã `i18n.ts.<key>` ãįĩįąããã
|
||||
- æĸåããŧãŽį ´åŖįãĒããŧã 㯠Crowdin įŋģ荺čŗįŖãééŖããĢãĒããŽã§æ
éãĢãčŋŊå ãģæšåäŊĩ፠(æ°ããŧčŋŊå â į§ģčĄ â æ§ããŧåé¤) ãæ¤č¨ããã
|
||||
|
||||
## ãšããã 1: ja-JP.yml ãĢããŧãčŋŊå
|
||||
|
||||
[locales/ja-JP.yml](../../../locales/ja-JP.yml) ãᎍéãããYAML ãŽéåą¤æ§é ãįļæããéĸéŖãããģã¯ãˇã§ãŗãĢé
įŊŽãã:
|
||||
|
||||
```yaml
|
||||
# ããããŦããĢåį´ããŧ
|
||||
save: "äŋå"
|
||||
|
||||
# ããšããããĢãã´ãĒ (ãĸãŗããŧãšãŗãĸæĨé čžã¯å
é¨ãĢãã´ãĒ)
|
||||
_settings:
|
||||
general: "å
¨čŦ"
|
||||
appearance: "å¤čĻŗ"
|
||||
|
||||
# ããŠãĄãŧãŋäģã (åį´ãĒããŦãŧãšããĢãįŊŽæ)
|
||||
# ICU MessageFormat ㎠plural / select / number / date ãĒãŠã¯é寞åŋ
|
||||
# äŊŋãããŽã¯ `{name}` ãŽãããĒåį´ãĒįŊŽæãŽãŋ
|
||||
greeting: "ãããĢãĄã¯ã{name}ãã"
|
||||
```
|
||||
|
||||
### åŊåãŽãäŊæŗ
|
||||
|
||||
- åį´ããŧ: lowerCamelCase (äž: `saveChanges`, `confirmDelete`)ã
|
||||
- ãĢãã´ãĒ: ãĸãŗããŧãšãŗãĸæĨé čž (äž: `_settings`, `_abuseUserReport`)ã
|
||||
- æĸåãģã¯ãˇã§ãŗå
ãĢįŊŽãå ´åã¯ãĸãĢããĄãããé ãįļæãã (æ°ãģã¯ãˇã§ãŗå
¨äŊãæĢå°žãĢčŋŊå ãããŽã¯å¯)ã
|
||||
|
||||
## ãšããã 2: ååŽįžŠãŽčĒååįæ
|
||||
|
||||
`packages/i18n/build.ts` ã `ja-JP.yml` ãč§ŖæããTypeScript ã¤ãŗãŋãŧãã§ãŧãšã [packages/i18n/src/autogen/locale.ts](../../../packages/i18n/src/autogen/locale.ts) ãĢåēåããã
|
||||
|
||||
### čĒå (æ¨åĨ¨)
|
||||
|
||||
`pnpm dev` åŽčĄä¸ãĒãã`packages/i18n` ㎠watch ãšã¯ãĒããã yml ãŽå¤æ´ãæ¤įĨããĻčĒååįæããã
|
||||
|
||||
### æå
|
||||
|
||||
```bash
|
||||
pnpm --filter i18n generate
|
||||
```
|
||||
|
||||
åŽäŊ㯠`tsx scripts/generateLocaleInterface.ts`ã
|
||||
|
||||
### å¤ąæããŋãŧãŗ
|
||||
|
||||
ãããåŽčĄãããĢ frontend å´ã§ `i18n.ts.<newKey>` ãåį
§ããã¨ã`Locale` ã¤ãŗãŋãŧãã§ãŧãšãĢčŋŊå ãããĻããĒããããtypecheck ã§ãProperty '<newKey>' does not exist on type 'Locale'ãã¨ããã¨ãŠãŧãĢãĒãã`pnpm --filter frontend lint` ã§įēčĻããã
|
||||
|
||||
## ãšããã 3: frontend ã§ãŽåį
§
|
||||
|
||||
```ts
|
||||
import { i18n } from '@/i18n.js';
|
||||
```
|
||||
|
||||
| į¨é | æ¸ãæš |
|
||||
|---|---|
|
||||
| åį´æåå | `i18n.ts.save` |
|
||||
| ããšã | `i18n.ts._settings.general` |
|
||||
| ããŠãĄãŧãŋäģã | `i18n.tsx.greeting({ name: userName })` |
|
||||
| Vue ããŗããŦãŧãå
| `{{ i18n.ts.save }}` / `{{ i18n.tsx.greeting({ name }) }}` |
|
||||
|
||||
`i18n.ts` ã¯åäģãæååã`i18n.tsx` 㯠MessageFormat éĸæ°ã
|
||||
|
||||
## ãšããã 4: æ¤č¨ŧ
|
||||
|
||||
```bash
|
||||
# i18n ãããąãŧã¸ãŽååįæ + typecheck
|
||||
pnpm --filter i18n lint
|
||||
|
||||
# frontend ã§æ°ããŧåį
§įŽæãŽåãã§ãã¯
|
||||
pnpm --filter frontend lint
|
||||
```
|
||||
|
||||
## äž: ãããŧããåé¤ããžããīŧãįĸēčĒãã¤ãĸãã°ãčŋŊå ãã
|
||||
|
||||
1. `locales/ja-JP.yml`:
|
||||
```yaml
|
||||
_notes:
|
||||
deleteConfirm: "ããŽããŧããåé¤ããžããīŧ"
|
||||
```
|
||||
2. `pnpm --filter i18n generate` (ãžã㯠`pnpm dev` ã§ watch ä¸)
|
||||
3. SFC:
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { i18n } from '@/i18n.js';
|
||||
import * as os from '@/os.js';
|
||||
|
||||
async function onDelete() {
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'warning',
|
||||
text: i18n.ts._notes.deleteConfirm,
|
||||
});
|
||||
if (canceled) return;
|
||||
// åé¤åĻį
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
## åį
§ããĄã¤ãĢ
|
||||
|
||||
- [locales/README.md (â
ᎍéããĒãˇãŧæ šæ )](../../../locales/README.md)
|
||||
- [locales/ja-JP.yml](../../../locales/ja-JP.yml)
|
||||
- [packages/i18n/build.ts](../../../packages/i18n/build.ts)
|
||||
- [packages/i18n/src/autogen/locale.ts (įæįŠ)](../../../packages/i18n/src/autogen/locale.ts)
|
||||
- [packages/frontend/src/i18n.ts](../../../packages/frontend/src/i18n.ts)
|
||||
@@ -1,174 +0,0 @@
|
||||
---
|
||||
name: add-mk-component
|
||||
description: Misskey ãããŗãã¨ãŗããŽæ°čĻ Vue 3 ãŗãŗããŧããŗããčŋŊå ãããMk* åŊå / SPDX (HTML ãŗãĄãŗã) / <script setup lang="ts"> / <style lang="scss" module> / *.stories.impl.ts äŊĩč¨ãŽčĻį´ããžã¨ããĻéŠį¨ãããæ°ããå
ąæ UI ãŗãŗããŧããŗãã packages/frontend/src/components/ ãĢäŊãæãĢäŊŋãã
|
||||
---
|
||||
|
||||
# Misskey Vue ãŗãŗããŧããŗãčŋŊå ãšããĢ
|
||||
|
||||
`packages/frontend/src/components/` ãĢæ°ããå
ąæãŗãŗããŧããŗããčŋŊå ãããããŽčĻį´ã
|
||||
|
||||
## 大åæ
|
||||
|
||||
- å
ąæ / ååŠį¨ãŗãŗããŧããŗã㯠**åŋ
ã `Mk` ããŦããŖãã¯ãš** (äž: `MkButton`, `MkInput`)ãããŧã¸åēæé¨åãĒ㊠`Mk` ããŦããŖãã¯ãšã§ãĒãããŽã¯åå `pages/` å´ãĢįŊŽãã
|
||||
- æ°čĻã§ã¯ `<style lang="scss" module>` (CSS Modules) ãæĸåŽã¨ãããå¤ã `scoped` åŊĸåŧãæˇˇå¨ããĻããããæ°čĻã§ã¯äŊŋããĒãã
|
||||
- æååãĒããŠãĢãŽį´æ¸ãã¯įĻæĸãæč¨ã¯åŋ
ã `i18n.ts.<key>` įĩįąã§åį
§ãã (æ°ããŧ㯠`add-i18n-key` ãšããĢãåį
§)ã
|
||||
- `alert()` / `confirm()` / `window.prompt()` ã¯äŊŋããĒãã`os.alert` / `os.confirm` / `os.popup` ãĒãŠãäŊŋãã
|
||||
|
||||
## ãšããã 1: ããĄã¤ãĢé
įŊŽ
|
||||
|
||||
`packages/frontend/src/components/Mk<Name>.vue` ãĢæ°čĻäŊæããã
|
||||
|
||||
ãšããŧãĒãŧãåŋ
čĻ (= ãģãŧ常ãĢåŋ
čĻ) ãĒããåéåą¤ãĢ `Mk<Name>.stories.impl.ts` ãäŊããStorybook ãŽčĻį´ã¯ `*.stories.impl.ts` ã§ããŖãĻã`*.stories.ts` ã§ã¯ãĒãã
|
||||
|
||||
## ãšããã 2: SPDX ããããŧ (HTML ãŗãĄãŗãåŊĸåŧ)
|
||||
|
||||
`.vue` ããĄã¤ãĢåé ãĢåŋ
é :
|
||||
|
||||
```html
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
```
|
||||
|
||||
`/* ... */` (TS / JS åŊĸåŧ) ã§ã¯ãĒã **HTML ãŗãĄãŗã** ã§æ¸ããã¨ãæĸå㎠`.vue` ããĄã¤ãĢãããšãĻ HTML ãŗãĄãŗãåŊĸåŧãäŊŋãŖãĻãããSFC ãŽå
é ã¨ããĻčĒįļãĒåŊĸåŧãĢįĩąä¸ãããã (CI ㎠`spdx` ã¸ã§ãã¯ãŗãĄãŗãåŊĸåŧã§ã¯ãĒã SPDX æååãŽæįĄãŽãŋãæ¤æģãã)ã
|
||||
|
||||
## ãšããã 3: æå°ããŗããŦãŧã
|
||||
|
||||
[MkInfo.vue](../../../packages/frontend/src/components/MkInfo.vue) ãããŧãšãĢãã (ãˇãŗããĢãĒ襨į¤ēãŗãŗããŧããŗã):
|
||||
|
||||
```vue
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<div :class="$style.root">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
const props = defineProps<{
|
||||
variant?: 'primary' | 'secondary';
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(ev: 'click'): void;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
padding: 12px 14px;
|
||||
border-radius: var(--MI-radius);
|
||||
background: var(--MI_THEME-panel);
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
### čĻį´ãã¤ãŗã
|
||||
|
||||
| é
įŽ | čĻį´ |
|
||||
|---|---|
|
||||
| `<script>` | `<script lang="ts" setup>`ãåããŠãĄãŧãŋãåŋ
čĻãĒã `generic="T extends ..."` ãäģãã ([MkInput.vue åį
§](../../../packages/frontend/src/components/MkInput.vue)) |
|
||||
| `defineProps` / `defineEmits` | **type-only** (`<{ ... }>`) åŊĸåŧãruntime ㎠object åŊĸåŧã¯äŊŋããĒã |
|
||||
| `<style>` | `lang="scss" module` ãæĸåŽãã¯ãŠãšåį
§ã¯ `:class="$style.foo"` |
|
||||
| CSS 夿° | `var(--MI_THEME-...)` (ããŧã) / `var(--MI-radius)` (UI å
ąé) â ããŧããŗãŧãããĒã |
|
||||
| ãĸã¤ãŗãŗ | Tabler icons ãŽã¯ãŠãš (`<i class="ti ti-info-circle">`) ãäŊŋã |
|
||||
|
||||
## ãšããã 4: i18n 㨠os ãŽåŠį¨
|
||||
|
||||
```vue
|
||||
<script lang="ts" setup>
|
||||
import { i18n } from '@/i18n.js';
|
||||
import * as os from '@/os.js';
|
||||
|
||||
async function onClick() {
|
||||
const { canceled } = await os.confirm({
|
||||
type: 'warning',
|
||||
text: i18n.ts._notes.deleteConfirm,
|
||||
});
|
||||
if (canceled) return;
|
||||
os.toast(i18n.ts.deleted);
|
||||
}
|
||||
</script>
|
||||
```
|
||||
|
||||
### `os` ãŽä¸ģãĒããĢããŧ (čŠŗį´°ã¯ [os.ts](../../../packages/frontend/src/os.ts))
|
||||
|
||||
| éĸæ° | į¨é |
|
||||
|---|---|
|
||||
| `os.alert({ type, title?, text })` | åæšåãĸãŠãŧã |
|
||||
| `os.confirm({ type, title, text })` | yes/no įĸēčĒ (`{ canceled }` ãčŋã) |
|
||||
| `os.toast(message)` | 䏿éįĨ |
|
||||
| `os.popup(component, props, handlers)` | äģģæãŗãŗããŧããŗããŽéåæããããĸãã |
|
||||
| `os.popupMenu(items, anchor?)` | ãŗãŗãããšããĄããĨãŧ |
|
||||
| `os.form(title, fields)` | ããŠãŧã ãã¤ãĸãã° |
|
||||
| `os.apiWithDialog(endpoint, data)` | API åŧåēã + ã¨ãŠãŧæãã¤ãĸãã°čĄ¨į¤ē |
|
||||
|
||||
## ãšããã 5: Storybook ãšããŧãĒãŧäŊĩč¨
|
||||
|
||||
[MkButton.stories.impl.ts](../../../packages/frontend/src/components/MkButton.stories.impl.ts) ãéåŊĸã¨ããĻåčãĢããã`.stories.impl.ts` ã `packages/frontend/src/` é
ä¸ãŽ `.ts` ããĄã¤ãĢãĒãŽã§ [AGENTS.md §1 SPDX ããããŧåŋ
é ](../../../AGENTS.md#1-spdx-ããããŧåŋ
é ) ãŽå¯žčąĄã§ãããåé ãĢ SPDX ããããŧãåŋ
ãäģãã (HTML ãŗãĄãŗãåŊĸåŧã§ã¯ãĒã `/* */` åŊĸåŧ)ãåŊĸåŧ (äģĨä¸ãŽ `MkXxx` ã¯åŽéãŽãŗãŗããŧããŗãåãĢįŊŽæãã):
|
||||
|
||||
```ts
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
/* eslint-disable import/no-default-export */
|
||||
import type { StoryObj } from '@storybook/vue3';
|
||||
import MkXxx from './MkXxx.vue';
|
||||
|
||||
export const Default = {
|
||||
render(args) {
|
||||
return {
|
||||
components: { MkXxx },
|
||||
setup() {
|
||||
return { args };
|
||||
},
|
||||
template: '<MkXxx v-bind="args">slot content</MkXxx>',
|
||||
};
|
||||
},
|
||||
args: {
|
||||
variant: 'primary',
|
||||
},
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
},
|
||||
} satisfies StoryObj<typeof MkXxx>;
|
||||
```
|
||||
|
||||
`Vue` SFC 㯠default export ãĒãŽã§ã`import MkXxx from './MkXxx.vue';` ãŽãããĢååäģã import ã§ã¯ãĒã default import ã§æ¸ããåŽčĄįĸēčĒ㯠`pnpm --filter frontend storybook-dev`ã
|
||||
|
||||
## ãšããã 6: Lint 㨠typecheck
|
||||
|
||||
```bash
|
||||
pnpm --filter frontend lint
|
||||
```
|
||||
|
||||
(typecheck = vue-tsc įãESLint = `@misskey-dev/eslint-plugin` åĢã)
|
||||
|
||||
ESLint --fix ãããŗãã¤ãŗãã§:
|
||||
|
||||
```bash
|
||||
pnpm exec eslint --fix packages/frontend/src/components/Mk<Name>.vue
|
||||
```
|
||||
|
||||
## ãšããã 7: æĸåãŗãŗããŧããŗãã¨ãŽæ´åæ§įĸēčĒ
|
||||
|
||||
- äŧŧãį¨éãŽæĸå `Mk*` ãŗãŗããŧããŗããåčãĢããšãŋã¤ãĢãããããåŊåãæããã
|
||||
- `_button` / `_panel` / `_selectable` ãĒãŠãŽ **å
ąé utility class** (ã°ããŧããĢãšãŋã¤ãĢãĢãã) ãæ´ģį¨ã§ãããįĸēčĒããã
|
||||
- 大ããĒæŠčŊãĒããStorybook stories ã§åããĒã¨ãŧãˇã§ãŗãįļ˛įž
ããã
|
||||
|
||||
## åį
§ããĄã¤ãĢ
|
||||
|
||||
- [MkInfo.vue (ãˇãŗããĢäž)](../../../packages/frontend/src/components/MkInfo.vue)
|
||||
- [MkButton.vue (æąį¨ããŋãŗäž)](../../../packages/frontend/src/components/MkButton.vue)
|
||||
- [MkInput.vue (generics + 夿ŠčŊäž)](../../../packages/frontend/src/components/MkInput.vue)
|
||||
- [MkButton.stories.impl.ts (Storybook éåŊĸ)](../../../packages/frontend/src/components/MkButton.stories.impl.ts)
|
||||
- [packages/frontend/src/os.ts](../../../packages/frontend/src/os.ts)
|
||||
- [packages/frontend/src/i18n.ts](../../../packages/frontend/src/i18n.ts)
|
||||
@@ -1,148 +0,0 @@
|
||||
---
|
||||
name: context-budget
|
||||
description: Claude Code ãģããˇã§ãŗãŽãŗãŗãããšãįĒæļč˛ģã agents/skills/MCP/rules/CLAUDE.md ãã¨ãĢčĻããåããčĨ大åã¨åéˇãŗãŗããŧããŗããæ¤åēããĻį¯į´åčŖãæį¤ēããã"ãŗãŗãããšãæļč˛ģãčĻããĻ"ã"context budget"ã"context audit"ã"ããŧã¯ãŗå
荺"ã"ããäģĨä¸ MCP å
Ĩãīŧ" įãŽįē芹ã§čĩˇåããã
|
||||
---
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: MIT
|
||||
SPDX-FileCopyrightText: 2026 Affaan Mustafa and everything-claude-code contributors
|
||||
|
||||
åēå
¸ (upstream): https://github.com/affaan-m/everything-claude-code (v2.0.0-rc.1)
|
||||
upstream path: skills/context-budget/SKILL.md
|
||||
upstream origin frontmatter: ECC
|
||||
upstream license: MIT â https://github.com/affaan-m/everything-claude-code/blob/main/LICENSE
|
||||
project-level notice: see .claude/THIRD_PARTY_LICENSES.md (Misskey å
ãĩãŧãããŧããŖä¸čϧ + MIT å
¨æ)
|
||||
|
||||
Imported into Misskey .claude/ on 2026-05-10 as a standalone copy (no dependency on the ECC plugin runtime). description was rewritten in Japanese and a "Misskey åēæãĄãĸ" section was appended; body content remains MIT-licensed.
|
||||
|
||||
note: Misskey ㎠skills/agents æ°ã¯å°ãĒããŽã§ãMCP / CLAUDE.md / ããŠã°ã¤ãŗįąæĨ㎠overhead ãæ¯é
įãĢãĒããããįšãĢįæã
|
||||
-->
|
||||
|
||||
# Context Budget
|
||||
|
||||
ãģããˇã§ãŗå
ãĢčĒãŋčžŧãžãããŗãŗããŧããŗã (agents / skills / rules / MCP servers / CLAUDE.md) ㎠token overhead ãåæããįŠēã context ãå垊ããå
ˇäŊįãæį¤ēããã
|
||||
|
||||
## äŊŋãå ´éĸ
|
||||
|
||||
- ãģããˇã§ãŗãéããģåēååčŗĒãčŊãĄãĻããæčĻããã
|
||||
- į´čŋã§ skills / agents / MCP server ã夿°čŋŊå ãã
|
||||
- æŽã㎠context headroom ãįĨããã
|
||||
- čŋŊå ãŗãŗããŧããŗããå
ĨããåãĢįŠēããįĸēčĒããã
|
||||
- ãcontext-budgetããtoken å
荺ãįãŽããŧã¯ãŧãã§ãĻãŧãļãŧãæį¤ēįãĢčĻčĢããæ (Misskey ãĒãã¸ããĒãĢã¯ããŽååãŽãšãŠããˇãĨãŗããŗãã¯įģé˛ããĻããĒã â æŦ skill ã¯åå / description ãããã§ auto-invoke ãããæŗåŽãåŽčŖ
æ¸ãŽ slash command ä¸čĻ§ã¯ [.claude/commands/](../../commands/) ãåį
§)
|
||||
|
||||
## äģįĩãŋ
|
||||
|
||||
### Phase 1: Inventory
|
||||
|
||||
åãŗãŗããŧããŗããčĩ°æģããĻ token ãæ¨åŽããã
|
||||
|
||||
**Agents** (`.claude/agents/*.md`)
|
||||
- čĄæ°ã¨ããŧã¯ãŗæ° (`words à 1.3`) ãč¨įŽ
|
||||
- frontmatter `description` ãŽéˇããæŊåē
|
||||
- ããŠã°: 200 čĄčļ
(éã)ãdescription 30 word čļ
(frontmatter čĨ大)
|
||||
|
||||
**Skills** (`.claude/skills/*/SKILL.md`)
|
||||
- SKILL.md ãã¨ãĢ token ãč¨įŽ
|
||||
- ããŠã°: 400 čĄčļ
|
||||
- `.agents/skills/` įãŽéč¤ãŗããŧã¯é¤å¤
|
||||
|
||||
**Rules** (ãĒãã¸ããĒãĢãŧã㎠`AGENTS.md` + `.claude/` ãã `@-import` ãããããĄã¤ãĢ)
|
||||
- ããĄã¤ãĢåäŊã§ token č¨įŽ
|
||||
- ããŠã°: 100 čĄčļ
|
||||
- åä¸č¨čĒãĸã¸ãĨãŧãĢå
ãŽå
厚éč¤ãæ¤åē
|
||||
|
||||
**MCP Servers** (`.mcp.json` ãžãã¯æåš MCP č¨åŽ)
|
||||
- server æ°ã¨įˇ tool æ°
|
||||
- schema overhead ãããŧãĢããã ~500 token ã§čĻįŠãã
|
||||
- ããŠã°: 20 tool čļ
ãŽãĩãŧããŧã`gh` / `git` / `npm` į㎠CLI ãåį´ãŠããããã ããŽãĩãŧããŧ
|
||||
|
||||
**CLAUDE.md** (project + user-level)
|
||||
- ããĄã¤ãĢãã¨ãĢ token ãč¨įŽ
|
||||
- ããŠã°: åč¨ 300 čĄčļ
|
||||
|
||||
### Phase 2: Classify
|
||||
|
||||
| ããąãã | å¤åŽåēæē | čĄå |
|
||||
|--------------------|-------------------------------------------------------------|-----------------------------------|
|
||||
| **Always needed** | CLAUDE.md ããåį
§ãããĻãã / æåšãŗããŗããŽčŖ / įžããã¸ã§ã¯ãã¨ä¸č´ | įļæ |
|
||||
| **Sometimes needed** | ããĄã¤ãŗäžå (äž: č¨čĒããŋãŧãŗ)ãCLAUDE.md åį
§ãĒã | ãĒãŗãããŗãæåšåãæ¤č¨ |
|
||||
| **Rarely needed** | ãŗããŗãåį
§ãĒããå
厚éč¤ãæįĸēãĒį¨éãĒã | åé¤ãžã㯠lazy-load |
|
||||
|
||||
### Phase 3: Detect Issues
|
||||
|
||||
- **Bloated agent description** â frontmatter description ã 30 word čļ
ã ã¨ãTask ããŧãĢčĩˇåãŽããŗãĢæ¯åããŧãããã
|
||||
- **Heavy agents** â 200 čĄčļ
㯠Task ããŧãĢ㎠context ãæ¯åč¨ããžãã
|
||||
- **Redundant components** â agent ãã¸ãã¯ãéč¤ãã skillãCLAUDE.md ã¨éč¤ãã rule
|
||||
- **MCP over-subscription** â 10 server čļ
ããžã㯠CLI äģŖį¨å¯čŊãĒãĩãŧããŧ
|
||||
- **CLAUDE.md bloat** â åéˇčĒŦæãå¤ããģã¯ãˇã§ãŗãrule ãĢį§ģããšãæį¤ē
|
||||
|
||||
### Phase 4: Report
|
||||
|
||||
```
|
||||
Context Budget Report
|
||||
âââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
Total estimated overhead: ~XX,XXX tokens
|
||||
Context model: <įžå¨ãĸããĢå> (<window>K window) â äž: Claude Opus 4.7 (1M), Claude Sonnet (200K)
|
||||
Effective available context: ~XXX,XXX tokens (XX%)
|
||||
|
||||
Component Breakdown:
|
||||
âââââââââââââââââââŦâââââââââŦââââââââââââ
|
||||
â Component â Count â Tokens â
|
||||
âââââââââââââââââââŧâââââââââŧââââââââââââ¤
|
||||
â Agents â N â ~X,XXX â
|
||||
â Skills â N â ~X,XXX â
|
||||
â Rules â N â ~X,XXX â
|
||||
â MCP tools â N â ~XX,XXX â
|
||||
â CLAUDE.md â N â ~X,XXX â
|
||||
âââââââââââââââââââ´âââââââââ´ââââââââââââ
|
||||
|
||||
WARNING: Issues Found (N):
|
||||
[token į¯į´éãŽéé ]
|
||||
|
||||
Top 3 Optimizations:
|
||||
1. [action] â save ~X,XXX tokens
|
||||
2. [action] â save ~X,XXX tokens
|
||||
3. [action] â save ~X,XXX tokens
|
||||
|
||||
Potential savings: ~XX,XXX tokens (XX% of current overhead)
|
||||
```
|
||||
|
||||
verbose mode ã§ã¯ãããĢããĄã¤ãĢãã¨ãŽ token å
荺ãæéããĄã¤ãĢãŽčĄåäŊããŦãŧã¯ããĻãŗãéč¤čĄãŽå¯žæ¯ãMCP tool ä¸čϧ + tool ãã¨ãŽ schema ãĩã¤ã翍åŽãåēãã
|
||||
|
||||
## äž
|
||||
|
||||
**åēæŦįŖæģ**
|
||||
```
|
||||
User: ãŗãŗãããšãæļč˛ģãčĻããĻ
|
||||
Skill: 16 agents (12,400 tokens), 28 skills (6,200), 87 MCP tools (43,500), 2 CLAUDE.md (1,200)
|
||||
Flags: éã agent 3 åãCLI äģŖį¨å¯čŊãĒ MCP 3 å
|
||||
Top saving: MCP 3 ååé¤ â -27,500 tokens (overhead ㎠47% 忏)
|
||||
```
|
||||
|
||||
**Verbose**
|
||||
```
|
||||
User: ããŧã¯ãŗå
荺ãããĄã¤ãĢåäŊã§
|
||||
Skill: ä¸č¨ãŦããŧããĢå ããĻãplanner.md (213 lines, 1,840 tokens) ãŽãããĒ
|
||||
per-file čĄå
荺ãMCP tool ãã¨ãŽãĩã¤ãēãrule ãŽéč¤čĄã side-by-side ã§čĄ¨į¤ē
|
||||
```
|
||||
|
||||
**čŋŊå åãã§ãã¯**
|
||||
```
|
||||
User: MCP server ã 5 åčŋŊå ãããããįŠēãããīŧ
|
||||
Skill: įžįļ 33% â 5 server (â 50 tools) čŋŊå ã§ +25,000 tokens â 45% ãĢå°é
|
||||
æ¨åĨ¨: CLI äģŖį¨å¯čŊãĒ server 2 åãå
ãĢå¤ããĻ 40% äģĨä¸ãįļæ
|
||||
```
|
||||
|
||||
## ããšãããŠã¯ããŖãš
|
||||
|
||||
- **ããŧã¯ãŗæ¨åŽ**: prose 㯠`words à 1.3`ãcode ä¸ģäŊ㯠`chars / 4`
|
||||
- **MCP ã¯æå¤§ãŽãŦããŧ**: tool ããã ~500 tokenã30-tool server ã˛ã¨ã¤ã§å
¨ skill ãã大ãã
|
||||
- **agent description ã¯å¸¸æããŧã**: åŧã°ããĒã agent ã§ã description ã¯æ¯ Task æå
Ĩ
|
||||
- **verbose 㯠debug į¨**: æŽæŽĩã¯äŊŋããĒã
|
||||
- **夿´åžã¯įŖæģ**: agent/skill/MCP čŋŊå į´åžãĢčĩ°ãããĻ creep ãæŠæįēčĻ
|
||||
|
||||
## Misskey åēæãĄãĸ
|
||||
|
||||
- Misskey 㯠MCP server ãããã¸ã§ã¯ãã§æį¤ēįģé˛ããĻããĒããã (`.mcp.json` ä¸å¨)ãįžįļ overhead ãŽæ¯é
é
㯠CLAUDE.md ã¨å
ŦåŧããŠã°ã¤ãŗįž¤ãŽ skills / agents description ã§ããã
|
||||
- ECC ããŠã°ã¤ãŗããĻãŧãļãŧãšãŗãŧãã§ `installed_plugins.json` ãĢåå¨ãããããããã¸ã§ã¯ãã§ `enabledPlugins` ãĢčŋŊå ããĻããĒããĻã system reminder ãĢ 200+ skill ãįžãããããã㯠description ãįããŽã§ååĨ overhead ã¯å°ããããåč¨å¤ãŽįĸēčĒãĢæŦ skill ãäŊŋãã
|
||||
@@ -1,156 +0,0 @@
|
||||
---
|
||||
name: create-migration
|
||||
description: Misskey ㎠TypeORM ãã¤ã°ãŦãŧãˇã§ãŗãå
Ŧåŧ CLI (migration:generate / migration:create) ã§æŖããįæããSPDX ããããŧäģä¸ãģup/down æ´åãģcheck-migrations įĸēčĒãžã§čĒå°ãããã¨ãŗããŖããŖãŽãšããŧã夿´ãåĢããããã DB 夿´ããžãã¯ææ¸ã SQL ãĢããããŧãŋį§ģčĄãåŋ
čĻãĒæãĢäŊŋį¨ããã
|
||||
---
|
||||
|
||||
# Misskey ãã¤ã°ãŦãŧãˇã§ãŗäŊæãšããĢ
|
||||
|
||||
`packages/backend/migration/` ãĢæ°čĻ TypeORM ãã¤ã°ãŦãŧãˇã§ãŗãčŋŊå ãããããŽã¯ãŧã¯ãããŧã
|
||||
|
||||
## å¤§åæ (įĩļ寞 NG)
|
||||
|
||||
- **æĸãĢããŧã¸æ¸ãŋ (develop / master) ãŽãã¤ã°ãŦãŧãˇã§ãŗããĄã¤ãĢãᎍéããĒã** ([AGENTS.md §3](../../../AGENTS.md#3-ããŧã¸æ¸ãŋ-migration-ãįĩļ寞ãĢᎍéããĒã))ãæŦįĒåąĨæ´ãŽæšå¤ã¯æˇąåģãĒããŧãŋ䏿´åãåŧãčĩˇããããšããŧã夿´ã¯ **常ãĢæ°ãããŋã¤ã ãšãŋãŗãã§æ°čĻããĄã¤ãĢ** ãäŊãã
|
||||
- ããĄã¤ãĢåãŽãŋã¤ã ãšãŋãŗãé¨åãåžããæ¸ãæããĒã (é åēãåŖãã)ã
|
||||
|
||||
> äŊãæšã¯ AGENTS.md §3 ãŽã`Date.now()` ã§ UNIX ms ãååž â `{ms}-{PascalName}.js` ãææ¸ãããæäŊãŠã¤ãŗãã¨ãŗããŖããŖåˇŽåããčĒåįæããã (= TypeORM ㎠`migration:generate` ãäŊŋã) å ´åã¯æŦ skill ãŽæé ãĢåžãã**ãŠãĄãã§ãæ§ããĒã**ããã¨ãŗããŖããŖå¤æ´ãäŧ´ãæã¯ CLI įĩįąãŽãģããåãæŧããæ¸ããŽã§æ¨åĨ¨ã
|
||||
|
||||
## ãšããã 1: ãŠãĄããŽæšåŧãäŊŋããæąēãã
|
||||
|
||||
| įļæŗ | æšåŧ |
|
||||
|---|---|
|
||||
| ã¨ãŗããŖããŖ (`packages/backend/src/models/*.ts`) ã `@Column` / `@Index` / `@Entity` įã§å
ãĢ夿´ããåˇŽåããčĒåįæããã | `typeorm migration:generate` (æŦ skill ãŽæé ) |
|
||||
| ææ¸ã SQL / ããŧãŋį§ģčĄ / `CREATE INDEX CONCURRENTLY` ãĒãŠãã¨ãŗããŖããŖåˇŽåã§ã¯čĄ¨įžã§ããĒã夿´ | `typeorm migration:create` ã§įŠēéåŊĸãäŊããã`migrate-new` command ã§ææ¸ãéåŊĸãäŊã |
|
||||
| åčŋŊå 1 æŦãŽãããĒå°čĻæ¨Ąå¤æ´ã§ãæĸåããĄã¤ãĢããŗããŧããæšãéã | AGENTS.md §3 ãŽæé (`Date.now()` + ææ¸ã) ã§ãã |
|
||||
|
||||
čŋˇãŖãã **ãžãã¨ãŗããŖããŖã夿´ â `migration:generate`** ãååãæĸå 342 ããĄã¤ãĢãŽãģãŧããšãĻã `queryRunner.query(\`SQL...\`)` ㎠raw SQL ãĒãŽã§ãCLI åēåã§ãææ¸ãã§ããšãŋã¤ãĢã¯æãã
|
||||
|
||||
## ãšããã 2: CLI åŽčĄ
|
||||
|
||||
ãĢãŧãããŖãŦã¯ããĒããäģĨä¸ãåŽčĄããã`<PascalName>` ã¯å¤æ´å
厚ã襨ã PascalCase (äž: `AddBirthdayIndex`, `AddCategoryToAvatarDecorations`)ã
|
||||
|
||||
### 2-A. ã¨ãŗããŖããŖåˇŽåããįæ
|
||||
|
||||
[CONTRIBUTING.md §MigrationäŊææšæŗ](../../../CONTRIBUTING.md#migrationäŊææšæŗ) ãĢč¨čŧãŽåēæŦåŊĸ:
|
||||
|
||||
```bash
|
||||
# packages/backend ããŖãŦã¯ããĒã§åŽčĄããå ´å (CONTRIBUTING.md č¨čŧåŊĸåŧ)
|
||||
pnpm dlx typeorm migration:generate -d ormconfig.js -o --esm <PascalName>
|
||||
```
|
||||
|
||||
**ãĒãã¸ããĒãĢãŧãããåŽčĄããå ´å** (AI ãäŊŋãæ¨åĨ¨åŊĸåŧã`pnpm --filter backend exec` ãäŊŋã㨠backend ㎠TypeORM ããŧã¸ã§ãŗã¨ä¸č´ããããįĸēåŽ):
|
||||
|
||||
```bash
|
||||
pnpm --filter backend exec typeorm migration:generate -d ormconfig.js -o --esm migration/<PascalName>
|
||||
```
|
||||
|
||||
> **`--esm` ãĢã¤ããĻ**: `-o` / `--outputJs` ã¯ãTS ã§ã¯ãĒã JS ãåēåããããĒããˇã§ãŗã`--esm` ã¯ãESM åŊĸåŧ (`export class ...`) ã§åēåããããĒããˇã§ãŗãMisskey ãŽæĸå migration ã¯ããšãĻ ESM JS ã§ãããã **严æšãåŋ
é **ã`--esm` ãįįĨãã㨠CommonJS åŊĸåŧ㎠JS ãįæãããšãŋã¤ãĢãæããĒãã
|
||||
|
||||
äēåæēå:
|
||||
|
||||
- `pnpm build-pre` ãåŽčĄããĻ `built/meta.json` ãįæãã (`loadConfig()` ã `built/meta.json` ãåŋ
é ã¨ããããã`pnpm build` æ¸ãŋã§ããã°ä¸čĻ)ã
|
||||
- `.config/default.yml` ãåå¨ããã㨠(ãĒããã° `.config/example.yml` ãåčãĢäŊæãã)ã
|
||||
- `pnpm --filter backend compile-config` ãåŽčĄããĻ `built/.config.json` ãįæãã (`ormconfig.js` ã `loadConfig()` įĩįąã§åŋ
é ã¨ãããæĒåŽčĄã 㨠"Compiled configuration file not found." ã¨ãŠãŧãĢãĒã)ã
|
||||
- `pnpm --filter backend build` ã§ã¨ãŗããŖããŖãææ°ããĢã (CLI 㯠`built/` ãčĒã)ã
|
||||
- ããŧãĢãĢ DB ãčĩˇåãã (`docker compose -f compose.local-db.yml up -d`)ã
|
||||
|
||||
### 2-B. įŠēãŽææ¸ããã¤ã°ãŦãŧãˇã§ãŗ
|
||||
|
||||
```bash
|
||||
pnpm --filter backend exec typeorm migration:create -o --esm migration/<PascalName>
|
||||
```
|
||||
|
||||
ããŧãĢãĢ DB ãŽčĩˇåã¨ããĢãã¯ä¸čĻãįŠē㎠`up` / `down` ã ããįæãããã
|
||||
|
||||
> `-o --esm` ã **åŋ
ãäģãã**ããããįĄã㨠`<UnixMs>-<PascalName>.ts` (CommonJS / TS åēå) ãįæãããããMisskey ㎠`ormconfig.js` 㯠`migration/*.js` ã ããčĒãŋãæĸåãŽäģ migration ãå
¨ãĻ `export class ... { async up(queryRunner) {...} }` ㎠ESM JS åŊĸåŧãĒãŽã§ãåžã§æäŊæĨã§ `.ts â .js` ãĒããŧã + `import { MigrationInterface }` åé¤ + `class ... implements MigrationInterface` åé¤ãããĒãã¨čĩ°ããĒãã`-o --esm` ãäģããã°ããŽãžãž `.js` ESM ã§åēããŽã§ãåžåĻį㯠SPDX ããããŧäģä¸ (ãšããã 3) ã ãã§æ¸ãã
|
||||
|
||||
## ãšããã 3: SPDX ããããŧäģä¸
|
||||
|
||||
CLI åēåãĢ㯠SPDX ããããŧãåĢãžããĒãã**åŋ
ãåé ãĢčŋŊå ãã** (CI ㎠`spdx` ã¸ã§ããå¤ąæãããã)ã
|
||||
|
||||
```js
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
```
|
||||
|
||||
## ãšããã 4: up / down ãŽæ´åįĸēčĒ
|
||||
|
||||
- `up()` ãŽåãšããŧããĄãŗããĢ寞ãã`down()` ã§åŽå
¨ãĢåˇģãæģãããã¨ã
|
||||
- åčŋŊå (`ADD COLUMN`) â ååé¤ (`DROP COLUMN`)ãããŧããĢäŊæ â ããŧããĢåé¤ã
|
||||
FK čŋŊå â FK åé¤ãã¤ãŗããã¯ãšäŊæ â ã¤ãŗããã¯ãšåé¤ ãåŋ
ãããĸã§æ¸ãã
|
||||
- `down()` ãįŠēãŽãžãžæŽããĒããæŦįĒããŧãĢããã¯æãĢ芰ãã
|
||||
|
||||
### ã¤ãŗããã¯ãščŋŊå æãŽæŗ¨æ (CREATE INDEX CONCURRENTLY)
|
||||
|
||||
大čĻæ¨ĄããŧããĢã¸ãŽ `CREATE INDEX` ã¯æŦįĒã§éˇæéããã¯ããæããããã`CONCURRENTLY` ã§įēčĄããã¨ã㯠**migration å´ãĢã寞åŋãåŋ
čĻ**: PostgreSQL 㯠`CREATE INDEX CONCURRENTLY` ã transaction å
ã§åŽčĄã§ããĒããããmigration class ãĢäģĨä¸ãäģčžŧãã§ TypeORM ãĢãã㎠migration 㯠transaction ãåŧĩããĒããã¨æį¤ēããã
|
||||
|
||||
åį
§åŽčŖ
: [packages/backend/migration/1745378064470-composite-note-index.js](../../../packages/backend/migration/1745378064470-composite-note-index.js)ã
|
||||
|
||||
```js
|
||||
const isConcurrentIndexMigrationEnabled = process.env.MISSKEY_MIGRATION_CREATE_INDEX_CONCURRENTLY === '1';
|
||||
|
||||
export class CompositeNoteIndex1745378064470 {
|
||||
name = 'CompositeNoteIndex1745378064470';
|
||||
transaction = isConcurrentIndexMigrationEnabled ? false : undefined;
|
||||
|
||||
async up(queryRunner) {
|
||||
const concurrently = isConcurrentIndexMigrationEnabled;
|
||||
if (concurrently) {
|
||||
// CREATE INDEX CONCURRENTLY ...
|
||||
} else {
|
||||
// CREATE INDEX ...
|
||||
}
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
// åæ§ãĢį°åĸ夿°ã§åå˛
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
čĻįš:
|
||||
|
||||
- **`transaction = isConcurrentIndexMigrationEnabled ? false : undefined;`** ãåŋ
é ãããããĒã㨠`CREATE INDEX CONCURRENTLY` ã transaction å
ã§åŽčĄãããĻ `ERROR: CREATE INDEX CONCURRENTLY cannot run inside a transaction block` ã§å¤ąæããã
|
||||
- į°åĸ夿° `MISSKEY_MIGRATION_CREATE_INDEX_CONCURRENTLY=1` ããããŠãĢã OFFãOFF ãŽã¨ãã¯æŽé㎠`CREATE INDEX` (transaction å
) ã§åãåŋ
čĻãããã`up`/`down` åæšãį°åĸ夿°ã§åå˛ãããã
|
||||
- `ormconfig.js` ㎠`migrationsTransactionMode` 㯠**į°åĸ夿°ã§åãæŋãã**: `MISSKEY_MIGRATION_CREATE_INDEX_CONCURRENTLY=1` ãŽã¨ãã ã `'each'` (å migration ãååĨ transaction)ãæĒč¨åŽæã¯ `'all'` (å
¨ migration ã 1 ã¤ãŽ transaction ã§ãŠãã) ([ormconfig.js:19](../../../packages/backend/ormconfig.js#L19))ãæŽæŽĩ㯠`'all'` åæãĒãŽã§ãCONCURRENTLY ãäŊŋã migration ãæ¸ãæã ãããŽããŠã°ãŽåå¨ãæčããã°č¯ãã
|
||||
|
||||
### éĸéŖã¨ãŗããŖããŖã¨ãŽä¸č´
|
||||
|
||||
`migration:generate` ãäŊŋãŖãå ´åãã¨ãŗããŖããŖå´ãŽ `@Column` / `@Entity` äŋŽæŖã¨ DB ãšããŧããéŖãéãã¨ããĢãå
¨äŊããēãŦããįæåžãĢ芲åŊã¨ãŗããŖããŖã¨ SQL ãŽå¯žåŋãįŽčĻįĸēčĒãããã¨ã
|
||||
|
||||
## ãšããã 5: æ¤č¨ŧ
|
||||
|
||||
ãĢãŧãããåŽčĄ:
|
||||
|
||||
```bash
|
||||
# æĒåæ ãŽåˇŽåãįĄãã (æ°čĻ migration ãįæããšã DDL ãåãéããĻããĒãã)
|
||||
pnpm --filter backend check-migrations
|
||||
|
||||
# ããŧãĢãĢ DB ãĢéŠį¨
|
||||
pnpm migrate
|
||||
|
||||
# ããŧãĢãã㯠(down ãåŖããĻããĒãã)
|
||||
pnpm revert
|
||||
|
||||
# åéŠį¨ (é æšåãĢããä¸åēĻéã)
|
||||
pnpm migrate
|
||||
```
|
||||
|
||||
`check-migrations` ãŽåŽäŊ㯠[scripts/check_migrations_clean.js](../../../packages/backend/scripts/check_migrations_clean.js)ãTypeORM ㎠`dataSource.driver.createSchemaBuilder().log()` ã§ pending DDL ãååžãã`upQueries` / `downQueries` ãŽãããããæŽãŖãĻããã°éãŧãįĩäēããã**é å翤æģã§ã¯ãĒã**ãã¨ãŗããŖããŖã¨ migration ãåæããĻãããããŽæ¤æģã
|
||||
|
||||
## ãšããã 6: æĸåããĄã¤ãĢåį
§ããŗããŦ
|
||||
|
||||
æ°čĻããĄã¤ãĢãæ¸ãã¨ãã¯ã夿´ããŋãŧãŗãčŋãæĸåããĄã¤ãĢã **åŋ
ãã˛ã¨ã¤éããĻä¸ĻãšãĻæ¸ã**ããšãŋã¤ãĢãæŋãããēãŦã PR ã¯åˇŽãæģãããããã
|
||||
|
||||
| ããŋãŧãŗ | åį
§ããĄã¤ãĢ |
|
||||
|---|---|
|
||||
| ã¤ãŗããã¯ãščŋŊå + éĸæ°åŽįžŠ | [packages/backend/migration/1767169026317-birthday-index.js](../../../packages/backend/migration/1767169026317-birthday-index.js) |
|
||||
| åčŋŊå ãŽãŋ | [packages/backend/migration/1766652173085-add-category-to-avatar-decorations.js](../../../packages/backend/migration/1766652173085-add-category-to-avatar-decorations.js) |
|
||||
| ããŧããĢæ°čĻäŊæ + FK | [packages/backend/migration/1761569941833-add-channel-muting.js](../../../packages/backend/migration/1761569941833-add-channel-muting.js) |
|
||||
|
||||
ã¯ãŠãšåŊåčĻå㯠**PascalCase å + 13 æĄãŋã¤ã ãšãŋãŗã** (äž: `class BirthdayIndex1767169026317`)ã`name` ãããããŖãã¯ãŠãšåã¨å䏿ååãĢããã
|
||||
|
||||
## ãšããã 7: CHANGELOG (ãĻãŧãļãŧåŊąéŋãããå ´å)
|
||||
|
||||
ãšããŧã夿´ããĻãŧãļãŧãĢčĻããæåãįãå ´åãŽãŋã`CHANGELOG.md` ㎠`## Unreleased` â `### Server` ãžã㯠`### General` ãĢ 1 čĄčŋŊå ãã ([AGENTS.md §CHANGELOG](../../../AGENTS.md#changelog) åį
§)ãå
é¨ãĒããĄã¯ãŋãį´į˛ãĒã¤ãŗããã¯ãščŋŊå ã¯ä¸čĻã
|
||||
@@ -165,11 +165,6 @@ id: 'aidx'
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
#sentryForFrontend:
|
||||
# vueIntegration:
|
||||
# tracingOptions:
|
||||
# trackComponents: true
|
||||
# browserTracingIntegration:
|
||||
# replayIntegration:
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
@@ -182,9 +177,6 @@ id: 'aidx'
|
||||
# Number of worker processes
|
||||
#clusterLimit: 1
|
||||
|
||||
# Number of threads of extra thread pool for CPU-intensive tasks (per worker)
|
||||
#threadPoolSize: 1
|
||||
|
||||
# Job concurrency per worker
|
||||
# deliverJobConcurrency: 128
|
||||
# inboxJobConcurrency: 16
|
||||
@@ -218,9 +210,20 @@ proxyBypassHosts:
|
||||
# Media Proxy
|
||||
#mediaProxy: https://example.com/proxy
|
||||
|
||||
# Proxy remote files (default: true)
|
||||
proxyRemoteFiles: true
|
||||
|
||||
# Sign to ActivityPub GET request (default: true)
|
||||
signToActivityPubGet: true
|
||||
|
||||
allowedPrivateNetworks: [
|
||||
'127.0.0.1/32'
|
||||
]
|
||||
|
||||
# Disable automatic redirect for ActivityPub object lookup. (default: false)
|
||||
# This is a strong defense against potential impersonation attacks if the viewer instance has inadequate validation.
|
||||
# However it will make it impossible for other instances to lookup third-party user and notes through your URL.
|
||||
#disallowExternalApRedirect: true
|
||||
|
||||
# Upload or download file size limits (bytes)
|
||||
#maxFileSize: 262144000
|
||||
|
||||
@@ -177,11 +177,6 @@ id: 'aidx'
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
#sentryForFrontend:
|
||||
# vueIntegration:
|
||||
# tracingOptions:
|
||||
# trackComponents: true
|
||||
# browserTracingIntegration:
|
||||
# replayIntegration:
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
@@ -194,9 +189,6 @@ id: 'aidx'
|
||||
# Number of worker processes
|
||||
#clusterLimit: 1
|
||||
|
||||
# Number of threads of extra thread pool for CPU-intensive tasks (per worker)
|
||||
#threadPoolSize: 1
|
||||
|
||||
# Job concurrency per worker
|
||||
# deliverJobConcurrency: 128
|
||||
# inboxJobConcurrency: 16
|
||||
@@ -230,6 +222,12 @@ proxyBypassHosts:
|
||||
# Media Proxy
|
||||
#mediaProxy: https://example.com/proxy
|
||||
|
||||
# Proxy remote files (default: true)
|
||||
proxyRemoteFiles: true
|
||||
|
||||
# Sign to ActivityPub GET request (default: true)
|
||||
signToActivityPubGet: true
|
||||
|
||||
# For security reasons, uploading attachments from the intranet is prohibited,
|
||||
# but exceptions can be made from the following settings. Default value is "undefined".
|
||||
# Read changelog to learn more (Improvements of 12.90.0 (2021/09/04)).
|
||||
@@ -237,6 +235,11 @@ proxyBypassHosts:
|
||||
# '127.0.0.1/32'
|
||||
#]
|
||||
|
||||
# Disable automatic redirect for ActivityPub object lookup. (default: false)
|
||||
# This is a strong defense against potential impersonation attacks if the viewer instance has inadequate validation.
|
||||
# However it will make it impossible for other instances to lookup third-party user and notes through your URL.
|
||||
#disallowExternalApRedirect: true
|
||||
|
||||
# Upload or download file size limits (bytes)
|
||||
#maxFileSize: 262144000
|
||||
|
||||
|
||||
@@ -105,54 +105,6 @@ port: 3000
|
||||
# socket: /path/to/misskey.sock
|
||||
# chmodSocket: '777'
|
||||
|
||||
# Proxy trust settings
|
||||
#
|
||||
# Specifies the IP addresses that Misskey will use as trusted
|
||||
# reverse proxies (e.g., nginx, Cloudflare). This affects how
|
||||
# Misskey determines the source IP for each request and is used
|
||||
# for important rate limiting and security features. If the value
|
||||
# is not set correctly, Misskey may use the IP address of the
|
||||
# reverse proxy instead of the actual source IP, which may lead to
|
||||
# unintended rate limiting or security vulnerabilities.
|
||||
# By default, the loopback network and private network address
|
||||
# ranges shown below are trusted.
|
||||
# If you are using a single reverse proxy and it is on the same
|
||||
# machine or the same private network as Misskey, it is unlikely you
|
||||
# need to change this setting, and the default setting is fine.
|
||||
# Also, if you are using multiple reverse proxy servers and they are
|
||||
# all on the same private network as Misskey, the default setting
|
||||
# is fine.
|
||||
# However, if you are using a reverse proxy server that accesses
|
||||
# Misskey web servers and streaming servers via public IP addresses
|
||||
# (for example, Cloudflare), you must set this variable.
|
||||
# When changing this setting, you can use one of the following values:
|
||||
#
|
||||
# - true: Trust all proxies
|
||||
# - false: Do not trust any proxies
|
||||
# - IP address, IP address range, or array of them: Trust hops that
|
||||
# match the specified criteria.
|
||||
# - Integer: Trust the nth hop from the front-facing proxy server as
|
||||
# the client.
|
||||
# For more information on how to configure this setting, please refer
|
||||
# to the Fastify documentation:
|
||||
# https://fastify.dev/docs/latest/Reference/Server/#trustproxy
|
||||
#
|
||||
# Note that if this variable is set, it overrides the default range,
|
||||
# so if you have both an external reverse proxy and a proxy on the
|
||||
# local host, you must include both IPs (or IP ranges).
|
||||
#
|
||||
#trustProxy:
|
||||
# - '10.0.0.0/8'
|
||||
# - '172.16.0.0/12'
|
||||
# - '192.168.0.0/16'
|
||||
# - '127.0.0.1/32'
|
||||
# - '::1/128'
|
||||
# - 'fc00::/7'
|
||||
# # Example: If you are using some external reverse proxies like CDNs,
|
||||
# # you may need to add the CDN IP ranges here.
|
||||
# # If you're using Cloudflare, you can find IP Ranges at:
|
||||
# # https://www.cloudflare.com/ips/
|
||||
|
||||
# ââââââââââââââââââââââââââââ
|
||||
#ââââ PostgreSQL configuration âââââââââââââââââââââââââââââââââ
|
||||
|
||||
@@ -307,11 +259,6 @@ id: 'aidx'
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
#sentryForFrontend:
|
||||
# vueIntegration:
|
||||
# tracingOptions:
|
||||
# trackComponents: true
|
||||
# browserTracingIntegration:
|
||||
# replayIntegration:
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
@@ -321,16 +268,9 @@ id: 'aidx'
|
||||
# Whether disable HSTS
|
||||
#disableHsts: true
|
||||
|
||||
# Enable internal IP-based rate limiting (default: true)
|
||||
# To configure them in reverse proxy instead, set this to false.
|
||||
#enableIpRateLimit: true
|
||||
|
||||
# Number of worker processes
|
||||
#clusterLimit: 1
|
||||
|
||||
# Number of threads of extra thread pool for CPU-intensive tasks (per worker)
|
||||
#threadPoolSize: 1
|
||||
|
||||
# Job concurrency per worker
|
||||
#deliverJobConcurrency: 128
|
||||
#inboxJobConcurrency: 16
|
||||
@@ -374,12 +314,19 @@ proxyBypassHosts:
|
||||
# * Perform image compression (on a different server resource than the main process)
|
||||
#mediaProxy: https://example.com/proxy
|
||||
|
||||
# Proxy remote files (default: true)
|
||||
# Proxy remote files by this instance or mediaProxy to prevent remote files from running in remote domains.
|
||||
proxyRemoteFiles: true
|
||||
|
||||
# Movie Thumbnail Generation URL
|
||||
# There is no reference implementation.
|
||||
# For example, Misskey will point to the following URL:
|
||||
# https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4
|
||||
#videoThumbnailGenerator: https://example.com
|
||||
|
||||
# Sign to ActivityPub GET request (default: true)
|
||||
signToActivityPubGet: true
|
||||
|
||||
# For security reasons, uploading attachments from the intranet is prohibited,
|
||||
# but exceptions can be made from the following settings. Default value is "undefined".
|
||||
# Read changelog to learn more (Improvements of 12.90.0 (2021/09/04)).
|
||||
@@ -387,6 +334,11 @@ proxyBypassHosts:
|
||||
# '127.0.0.1/32'
|
||||
#]
|
||||
|
||||
# Disable automatic redirect for ActivityPub object lookup. (default: false)
|
||||
# This is a strong defense against potential impersonation attacks if the viewer instance has inadequate validation.
|
||||
# However it will make it impossible for other instances to lookup third-party user and notes through your URL.
|
||||
#disallowExternalApRedirect: true
|
||||
|
||||
# Upload or download file size limits (bytes)
|
||||
#maxFileSize: 262144000
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
FROM mcr.microsoft.com/devcontainers/javascript-node:4.0.3-24-trixie
|
||||
FROM mcr.microsoft.com/devcontainers/javascript-node:0-18
|
||||
|
||||
@@ -28,7 +28,7 @@ services:
|
||||
|
||||
db:
|
||||
restart: unless-stopped
|
||||
image: postgres:18-alpine
|
||||
image: postgres:15-alpine
|
||||
networks:
|
||||
- internal_network
|
||||
environment:
|
||||
@@ -36,7 +36,7 @@ services:
|
||||
POSTGRES_PASSWORD: postgres
|
||||
POSTGRES_DB: misskey
|
||||
volumes:
|
||||
- postgres-data:/var/lib/postgresql
|
||||
- postgres-data:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
|
||||
interval: 5s
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
"workspaceFolder": "/workspace",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": "22.15.0"
|
||||
"version": "22.11.0"
|
||||
},
|
||||
"ghcr.io/devcontainers-extra/features/pnpm:2": {
|
||||
"version": "10.10.0"
|
||||
"version": "10.6.1"
|
||||
}
|
||||
},
|
||||
"forwardPorts": [3000],
|
||||
@@ -19,6 +19,7 @@
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"Vue.volar",
|
||||
"Orta.vscode-jest",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"mrmlnc.vscode-json5"
|
||||
]
|
||||
|
||||
@@ -152,11 +152,6 @@ id: 'aidx'
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
#sentryForFrontend:
|
||||
# vueIntegration:
|
||||
# tracingOptions:
|
||||
# trackComponents: true
|
||||
# browserTracingIntegration:
|
||||
# replayIntegration:
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
@@ -169,9 +164,6 @@ id: 'aidx'
|
||||
# Number of worker processes
|
||||
#clusterLimit: 1
|
||||
|
||||
# Number of threads of extra thread pool for CPU-intensive tasks (per worker)
|
||||
#threadPoolSize: 1
|
||||
|
||||
# Job concurrency per worker
|
||||
# deliverJobConcurrency: 128
|
||||
# inboxJobConcurrency: 16
|
||||
@@ -205,6 +197,12 @@ proxyBypassHosts:
|
||||
# Media Proxy
|
||||
#mediaProxy: https://example.com/proxy
|
||||
|
||||
# Proxy remote files (default: true)
|
||||
proxyRemoteFiles: true
|
||||
|
||||
# Sign to ActivityPub GET request (default: true)
|
||||
signToActivityPubGet: true
|
||||
|
||||
allowedPrivateNetworks: [
|
||||
'127.0.0.1/32'
|
||||
]
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
Dockerfile
|
||||
build/
|
||||
built/
|
||||
src-js/
|
||||
db/
|
||||
.devcontainer/compose.yml
|
||||
node_modules/
|
||||
|
||||
@@ -13,7 +13,3 @@ trim_trailing_whitespace = false
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_style = space
|
||||
|
||||
[packages/backend/migration/*.js]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
6
.github/ISSUE_TEMPLATE/01_bug-report.yml
vendored
6
.github/ISSUE_TEMPLATE/01_bug-report.yml
vendored
@@ -54,7 +54,7 @@ body:
|
||||
* Model and OS of the device(s): MacBook Pro (14inch, 2021), macOS Ventura 13.4
|
||||
* Browser: Chrome 113.0.5672.126
|
||||
* Server URL: misskey.example.com
|
||||
* Misskey: 2026.x.x
|
||||
* Misskey: 2025.x.x
|
||||
value: |
|
||||
* Model and OS of the device(s):
|
||||
* Browser:
|
||||
@@ -74,9 +74,9 @@ body:
|
||||
|
||||
Examples:
|
||||
* Installation Method or Hosting Service: docker compose, k8s/docker, systemd, "Misskey install shell script", development environment
|
||||
* Misskey: 2026.x.x
|
||||
* Misskey: 2025.x.x
|
||||
* Node: 20.x.x
|
||||
* PostgreSQL: 18.x.x
|
||||
* PostgreSQL: 15.x.x
|
||||
* Redis: 7.x.x
|
||||
* OS and Architecture: Ubuntu 24.04.2 LTS aarch64
|
||||
value: |
|
||||
|
||||
54
.github/copilot-instructions.md
vendored
54
.github/copilot-instructions.md
vendored
@@ -1,54 +0,0 @@
|
||||
# Copilot Instructions for Misskey
|
||||
|
||||
ããŽããĄã¤ãĢ㯠GitHub Copilot ㎠repository-wide instructions ã¨ããĻäŊŋããããCopilot code review ã§ã¯ `AGENTS.md` ãčĒãžããĒãį°åĸãããããããŦããĨãŧãčģŊ垎ãĒåŽčŖ
夿ãĢåŋ
čĻãĒčĻį´ã¯ããŽããĄã¤ãĢåäŊã§æēãããã¨ã
|
||||
|
||||
ããŽãĒãã¸ããĒ㯠Misskey ㎠pnpm workspace ãĸããŦããä¸ģčĻãĒåŽčŖ
㯠`packages/backend` (NestJS / TypeORM) 㨠`packages/frontend` (Vue 3) ãĢãããããčŠŗãããŦã¤ãã¯ãĒãã¸ããĒãĢãŧã㎠`AGENTS.md` ãåį
§ããĻããããããŽããĄã¤ãĢãŽčĻäģļãįįĨããĻããĄãã¸ãŽåį
§ã ãã§æ¸ãžããĒããã¨ã
|
||||
|
||||
## Always follow
|
||||
|
||||
- AGPL-3.0-only įŽĄčŊã㤠SPDX CI å¯žčąĄããŖãŦã¯ããĒãĢæ°čĻ `.ts` / `.js` / `.cjs` / `.mjs` / `.scss` ããĄã¤ãĢãčŋŊå ããå ´åã¯ãåŋ
ãæŦĄãŽ SPDX ããããŧãäģãããčŠŗį´°ãĒå¯žčąĄå¤åŽã¯ `AGENTS.md` 㨠`.github/workflows/check-spdx-license-id.yml` ãåį
§ãããã¨ã
|
||||
|
||||
```text
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
```
|
||||
|
||||
- AGPL-3.0-only įŽĄčŊã㤠SPDX CI å¯žčąĄããŖãŦã¯ããĒãĢæ°čĻ `.vue` / `.html` ããĄã¤ãĢãčŋŊå ããå ´åã¯ãåŋ
ãæŦĄãŽ SPDX ããããŧãäģããã
|
||||
|
||||
```text
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
```
|
||||
|
||||
`packages/misskey-js` 㯠MIT ãŠã¤ãģãŗãšãŽãĩããããąãŧã¸ãĒãŽã§ãã㎠AGPL ããããŧãä¸åžãĢäģããĒãããĩããããąãŧã¸åēæãŽ `package.json` / `LICENSE` / æĸåããĄã¤ãĢãŽããããŧãĢåžãã
|
||||
|
||||
- `locales/` é
ä¸ãŽ YAML 㯠`ja-JP.yml` ãŽãŋæåᎍéããĻãããäģč¨čĒ㯠Crowdin ãŽčĒåé
äŋĄå
ãĒãŽã§æåᎍéããĒããã¨ã
|
||||
- `packages/backend/migration/{timestamp}-*.js` ãŽããĄãæĸãĢããŧã¸æ¸ãŋ㎠migration ã¯įĩļ寞ãĢᎍéããĒãããšããŧã夿´ãåŋ
čĻãĒå ´åã¯æ°ãã timestamp ã§ migration ãčŋŊå ãã`up()` 㨠`down()` ãŽä¸ĄæšãåŽčŖ
ãããã¨ã
|
||||
- ãĻãŧãļãŧåŊąéŋãŽãã夿´ã¯ `CHANGELOG.md` ㎠`## Unreleased` é
ä¸ãŽ `### General` / `### Client` / `### Server` ãŽãããããĢ 1 čĄčŋŊå ãããå
é¨ãĒããĄã¯ãŋãŽãŋãĒãä¸čĻã
|
||||
- API 夿´æã¯ `pnpm build-misskey-js-with-types` ãŽåŽčĄãåŋ
čĻãĢãĒãã
|
||||
|
||||
## Validation
|
||||
|
||||
- å
¨äŊããĢã: `pnpm build`
|
||||
- å
¨äŊ lint / typecheck: `pnpm lint`
|
||||
- Backend unit test: `pnpm --filter backend test`
|
||||
- Backend e2e test: `pnpm --filter backend test:e2e`
|
||||
- Backend federation test: `pnpm --filter backend test:fed`
|
||||
- Frontend test: `pnpm --filter frontend test`
|
||||
- Migration åˇŽåæ¤æģ: `pnpm --filter backend check-migrations`
|
||||
|
||||
> **backend ããšã (`test` / `test:e2e` / `test:fed`) åŽčĄåãĢ `.config/test.yml` ãåŋ
čĻã** æĒäŊæãŽå ´å㯠`ncp .github/misskey/test.yml .config/test.yml` (ãžã㯠`cp .github/misskey/test.yml .config/test.yml`) ãåŽčĄããĻããčĩ°ããããåããšããšã¯ãĒãããå
é¨ã§ `cross-env NODE_ENV=test pnpm compile-config` ãåŧãļããããŗããŧæ¸ãŋã§ããã°čŋŊå ㎠compile-config ã¯ä¸čĻã
|
||||
|
||||
夿´į¯å˛ãĢåŋããĻæãčŋããŗããŗãããåĒå
ããĻæ¤č¨ŧããåŋ
čĻãĒãå
¨äŊãŗããŗããĢåēãããã¨ã
|
||||
|
||||
## Editing hints
|
||||
|
||||
- Backend ㎠API / migration / TypeORM 夿´ã¯ `packages/backend` ãčĻãã
|
||||
- Frontend ㎠Vue ãŗãŗããŧããŗããããŧã¸å¤æ´ã¯ `packages/frontend` ãčĻãã
|
||||
- `AGENTS.md` å
ãŽį¸å¯žãĒãŗã¯ã¯ãĒãã¸ããĒãĢãŧãčĩˇįšã§č§ŖæąēããæŗåŽã
|
||||
|
||||
> `AGENTS.md` ã¯ããčŠŗį´°ãĒæŖå
¸ã ããCopilot code review ã§ã¯ããŽããĄã¤ãĢãä¸ģãĒå
ĨåŖãĢãĒãã严æšãčĒãžããį°åĸã§ã¯ `AGENTS.md` ãčŖåŠæ
å ąã¨ããĻäŊŋãŖãĻããã
|
||||
6
.github/dependabot.yml
vendored
6
.github/dependabot.yml
vendored
@@ -24,6 +24,9 @@ updates:
|
||||
aws-sdk:
|
||||
patterns:
|
||||
- "@aws-sdk/*"
|
||||
bull-board:
|
||||
patterns:
|
||||
- "@bull-board/*"
|
||||
nestjs:
|
||||
patterns:
|
||||
- "@nestjs/*"
|
||||
@@ -34,6 +37,9 @@ updates:
|
||||
patterns:
|
||||
- "storybook*"
|
||||
- "@storybook/*"
|
||||
swc-core:
|
||||
patterns:
|
||||
- "@swc/core*"
|
||||
typescript-eslint:
|
||||
patterns:
|
||||
- "@typescript-eslint/*"
|
||||
|
||||
1
.github/min.node-version
vendored
1
.github/min.node-version
vendored
@@ -1 +0,0 @@
|
||||
22.15.0
|
||||
2
.github/misskey/test.yml
vendored
2
.github/misskey/test.yml
vendored
@@ -15,5 +15,3 @@ redis:
|
||||
host: 127.0.0.1
|
||||
port: 56312
|
||||
id: aidx
|
||||
|
||||
proxyRemoteFiles: true
|
||||
|
||||
6
.github/workflows/api-misskey-js.yml
vendored
6
.github/workflows/api-misskey-js.yml
vendored
@@ -16,13 +16,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v4.2.2
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
|
||||
4
.github/workflows/changelog-check.yml
vendored
4
.github/workflows/changelog-check.yml
vendored
@@ -12,9 +12,9 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout head
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v4.2.2
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
|
||||
|
||||
24
.github/workflows/check-misskey-js-autogen.yml
vendored
24
.github/workflows/check-misskey-js-autogen.yml
vendored
@@ -18,18 +18,18 @@ jobs:
|
||||
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
|
||||
- name: setup pnpm
|
||||
uses: pnpm/action-setup@v6
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: setup node
|
||||
id: setup-node
|
||||
uses: actions/setup-node@v6.4.0
|
||||
uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: pnpm
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
|
||||
# packages/misskey-js/generator/built/autogen
|
||||
- name: Upload Generated
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: generated-misskey-js
|
||||
path: packages/misskey-js/generator/built/autogen
|
||||
@@ -66,14 +66,14 @@ jobs:
|
||||
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
|
||||
- name: Upload From Merged
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: actual-misskey-js
|
||||
path: packages/misskey-js/src/autogen
|
||||
@@ -86,13 +86,13 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: download generated-misskey-js
|
||||
uses: actions/download-artifact@v8
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: generated-misskey-js
|
||||
path: misskey-js-generated
|
||||
|
||||
- name: download actual-misskey-js
|
||||
uses: actions/download-artifact@v8
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: actual-misskey-js
|
||||
path: misskey-js-actual
|
||||
@@ -113,9 +113,9 @@ jobs:
|
||||
|
||||
- name: send message
|
||||
if: steps.check-changes.outputs.changes == 'true'
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
with:
|
||||
comment-tag: check-misskey-js-autogen
|
||||
comment_tag: check-misskey-js-autogen
|
||||
message: |-
|
||||
Thank you for sending us a great Pull Request! đ
|
||||
Please regenerate misskey-js type definitions! đ
|
||||
@@ -127,9 +127,9 @@ jobs:
|
||||
|
||||
- name: send message
|
||||
if: steps.check-changes.outputs.changes == 'false'
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
with:
|
||||
comment-tag: check-misskey-js-autogen
|
||||
comment_tag: check-misskey-js-autogen
|
||||
mode: delete
|
||||
message: "Thank you!"
|
||||
create_if_not_exists: false
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v4.2.2
|
||||
- name: Check version
|
||||
run: |
|
||||
if [ "$(jq -r '.version' package.json)" != "$(jq -r '.version' packages/misskey-js/package.json)" ]; then
|
||||
|
||||
4
.github/workflows/check-spdx-license-id.yml
vendored
4
.github/workflows/check-spdx-license-id.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v4.2.2
|
||||
- name: Check
|
||||
run: |
|
||||
counter=0
|
||||
@@ -50,7 +50,6 @@ jobs:
|
||||
"packages/backend/test"
|
||||
"packages/frontend-shared/@types"
|
||||
"packages/frontend-shared/js"
|
||||
"packages/frontend-builder"
|
||||
"packages/frontend/.storybook"
|
||||
"packages/frontend/@types"
|
||||
"packages/frontend/lib"
|
||||
@@ -59,7 +58,6 @@ jobs:
|
||||
"packages/frontend/test"
|
||||
"packages/frontend-embed/@types"
|
||||
"packages/frontend-embed/src"
|
||||
"packages/icons-subsetter/src"
|
||||
"packages/misskey-bubble-game/src"
|
||||
"packages/misskey-reversi/src"
|
||||
"packages/sw/src"
|
||||
|
||||
2
.github/workflows/check_copyright_year.yml
vendored
2
.github/workflows/check_copyright_year.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
check_copyright_year:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- run: |
|
||||
if [ "$(grep Copyright COPYING | sed -e 's/.*2014-\([0-9]*\) .*/\1/g')" -ne "$(date +%Y)" ]; then
|
||||
echo "Please change copyright year!"
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
wait_time: ${{ steps.get-wait-time.outputs.wait_time }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v4.2.2
|
||||
|
||||
- name: Check allowed users
|
||||
id: check-allowed-users
|
||||
|
||||
16
.github/workflows/docker-develop.yml
vendored
16
.github/workflows/docker-develop.yml
vendored
@@ -27,17 +27,17 @@ jobs:
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v4.2.2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v4
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build and push by digest
|
||||
id: build
|
||||
uses: docker/build-push-action@v7
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
@@ -66,15 +66,15 @@ jobs:
|
||||
- build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v8
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digests-*
|
||||
merge-multiple: true
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v4
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
20
.github/workflows/docker.yml
vendored
20
.github/workflows/docker.yml
vendored
@@ -32,23 +32,23 @@ jobs:
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v4.2.2
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v6
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY_IMAGE }}
|
||||
tags: ${{ env.TAGS }}
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v4
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build and Push to Docker Hub
|
||||
id: build
|
||||
uses: docker/build-push-action@v7
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
@@ -77,21 +77,21 @@ jobs:
|
||||
- build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v8
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digests-*
|
||||
merge-multiple: true
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v4
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v6
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY_IMAGE }}
|
||||
tags: ${{ env.TAGS }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v4
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
45
.github/workflows/dockle.yml
vendored
45
.github/workflows/dockle.yml
vendored
@@ -11,43 +11,22 @@ on:
|
||||
jobs:
|
||||
dockle:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
DOCKER_CONTENT_TRUST: 1
|
||||
DOCKLE_VERSION: 0.4.15
|
||||
|
||||
DOCKLE_VERSION: 0.4.14
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- name: Download and install dockle v${{ env.DOCKLE_VERSION }}
|
||||
run: |
|
||||
set -eux
|
||||
curl -L -o dockle.deb "https://github.com/goodwithtech/dockle/releases/download/v${DOCKLE_VERSION}/dockle_${DOCKLE_VERSION}_Linux-64bit.deb"
|
||||
sudo dpkg -i dockle.deb
|
||||
|
||||
- name: Build web image (docker build)
|
||||
run: |
|
||||
set -eux
|
||||
docker build -t "misskey-web:ci" .
|
||||
docker image ls
|
||||
|
||||
- name: Mount tmpfs for Dockle tar
|
||||
env:
|
||||
TMPFS_SIZE: 8G
|
||||
run: |
|
||||
set -eux
|
||||
sudo mkdir -p /mnt/dockle-tmp
|
||||
sudo mount -t tmpfs -o size=${{ env.TMPFS_SIZE }} tmpfs /mnt/dockle-tmp
|
||||
free -h
|
||||
df -h
|
||||
|
||||
- name: Save image tar into tmpfs
|
||||
run: |
|
||||
set -eux
|
||||
docker save misskey-web:ci -o /mnt/dockle-tmp/misskey-web.tar
|
||||
ls -lh /mnt/dockle-tmp/misskey-web.tar
|
||||
|
||||
- name: Run Dockle Scan (tar input)
|
||||
run: |
|
||||
set -eux
|
||||
dockle --exit-code 1 --input /mnt/dockle-tmp/misskey-web.tar
|
||||
- run: |
|
||||
cp .config/docker_example.env .config/docker.env
|
||||
cp ./compose_example.yml ./compose.yml
|
||||
- run: |
|
||||
docker compose up -d web
|
||||
docker tag "$(docker compose images web | awk 'OFS=":" {print $4}' | tail -n +2)" misskey-web:latest
|
||||
- run: |
|
||||
cmd="dockle --exit-code 1 misskey-web:latest ${image_name}"
|
||||
echo "> ${cmd}"
|
||||
eval "${cmd}"
|
||||
|
||||
15
.github/workflows/get-api-diff.yml
vendored
15
.github/workflows/get-api-diff.yml
vendored
@@ -17,6 +17,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [22.11.0]
|
||||
api-json-name: [api-base.json, api-head.json]
|
||||
include:
|
||||
- api-json-name: api-base.json
|
||||
@@ -25,16 +26,16 @@ jobs:
|
||||
ref: refs/pull/${{ github.event.number }}/merge
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
ref: ${{ matrix.ref }}
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
@@ -48,7 +49,7 @@ jobs:
|
||||
- name: Copy API.json
|
||||
run: cp packages/backend/built/api.json ${{ matrix.api-json-name }}
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: api-artifact-${{ matrix.api-json-name }}
|
||||
path: ${{ matrix.api-json-name }}
|
||||
@@ -61,7 +62,7 @@ jobs:
|
||||
PR_NUMBER: ${{ github.event.number }}
|
||||
run: |
|
||||
echo "$PR_NUMBER" > ./pr_number
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: api-artifact-pr-number
|
||||
path: pr_number
|
||||
|
||||
87
.github/workflows/get-backend-memory.yml
vendored
87
.github/workflows/get-backend-memory.yml
vendored
@@ -1,87 +0,0 @@
|
||||
# this name is used in report-backend-memory.yml so be careful when change name
|
||||
name: Get backend memory usage
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
paths:
|
||||
- packages/backend/**
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/get-backend-memory.yml
|
||||
|
||||
jobs:
|
||||
get-memory-usage:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
memory-json-name: [memory-base.json, memory-head.json]
|
||||
include:
|
||||
- memory-json-name: memory-base.json
|
||||
ref: ${{ github.base_ref }}
|
||||
- memory-json-name: memory-head.json
|
||||
ref: refs/pull/${{ github.event.number }}/merge
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
redis:
|
||||
image: redis:8
|
||||
ports:
|
||||
- 56312:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
ref: ${{ matrix.ref }}
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
- name: Copy Configure
|
||||
run: cp .github/misskey/test.yml .config/default.yml
|
||||
- name: Compile Configure
|
||||
run: pnpm compile-config
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
- name: Run migrations
|
||||
run: pnpm --filter backend migrate
|
||||
- name: Measure memory usage
|
||||
run: |
|
||||
# Start the server and measure memory usage
|
||||
node packages/backend/scripts/measure-memory.mjs > ${{ matrix.memory-json-name }}
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: memory-artifact-${{ matrix.memory-json-name }}
|
||||
path: ${{ matrix.memory-json-name }}
|
||||
|
||||
save-pr-number:
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
steps:
|
||||
- name: Save PR number
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.number }}
|
||||
run: |
|
||||
echo "$PR_NUMBER" > ./pr_number
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: memory-artifact-pr-number
|
||||
path: pr_number
|
||||
2
.github/workflows/labeler.yml
vendored
2
.github/workflows/labeler.yml
vendored
@@ -11,6 +11,6 @@ jobs:
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v6
|
||||
- uses: actions/labeler@v5
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
32
.github/workflows/lint.yml
vendored
32
.github/workflows/lint.yml
vendored
@@ -9,9 +9,7 @@ on:
|
||||
- packages/backend/**
|
||||
- packages/frontend/**
|
||||
- packages/frontend-shared/**
|
||||
- packages/frontend-builder/**
|
||||
- packages/frontend-embed/**
|
||||
- packages/icons-subsetter/**
|
||||
- packages/sw/**
|
||||
- packages/misskey-js/**
|
||||
- packages/misskey-bubble-game/**
|
||||
@@ -23,9 +21,7 @@ on:
|
||||
- packages/backend/**
|
||||
- packages/frontend/**
|
||||
- packages/frontend-shared/**
|
||||
- packages/frontend-builder/**
|
||||
- packages/frontend-embed/**
|
||||
- packages/icons-subsetter/**
|
||||
- packages/sw/**
|
||||
- packages/misskey-js/**
|
||||
- packages/misskey-bubble-game/**
|
||||
@@ -36,13 +32,13 @@ jobs:
|
||||
pnpm_install:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- uses: actions/setup-node@v6.4.0
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
@@ -58,9 +54,7 @@ jobs:
|
||||
- backend
|
||||
- frontend
|
||||
- frontend-shared
|
||||
- frontend-builder
|
||||
- frontend-embed
|
||||
- icons-subsetter
|
||||
- sw
|
||||
- misskey-js
|
||||
- misskey-bubble-game
|
||||
@@ -69,19 +63,19 @@ jobs:
|
||||
eslint-cache-version: v1
|
||||
eslint-cache-path: ${{ github.workspace }}/node_modules/.cache/eslint-${{ matrix.workspace }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- uses: actions/setup-node@v6.4.0
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Restore eslint cache
|
||||
uses: actions/cache@v5.0.5
|
||||
uses: actions/cache@v4.2.2
|
||||
with:
|
||||
path: ${{ env.eslint-cache-path }}
|
||||
key: eslint-${{ env.eslint-cache-version }}-${{ matrix.workspace }}-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ github.ref_name }}-${{ github.sha }}
|
||||
@@ -96,20 +90,22 @@ jobs:
|
||||
matrix:
|
||||
workspace:
|
||||
- backend
|
||||
- frontend
|
||||
- sw
|
||||
- misskey-js
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- uses: actions/setup-node@v6.4.0
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- run: pnpm --filter "${{ matrix.workspace }}^..." run build
|
||||
- run: pnpm --filter misskey-js run build
|
||||
if: ${{ matrix.workspace == 'backend' || matrix.workspace == 'sw' }}
|
||||
- run: pnpm --filter misskey-reversi run build
|
||||
if: ${{ matrix.workspace == 'backend' }}
|
||||
- run: pnpm --filter ${{ matrix.workspace }} run typecheck
|
||||
|
||||
29
.github/workflows/locale.yml
vendored
29
.github/workflows/locale.yml
vendored
@@ -3,12 +3,10 @@ name: Lint
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- packages/i18n/**
|
||||
- locales/**
|
||||
- .github/workflows/locale.yml
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/i18n/**
|
||||
- locales/**
|
||||
- .github/workflows/locale.yml
|
||||
jobs:
|
||||
@@ -16,18 +14,15 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: ".node-version"
|
||||
cache: "pnpm"
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- run: pnpm --filter i18n build
|
||||
- name: Verify Locales
|
||||
working-directory: ./packages/i18n
|
||||
run: pnpm run verify
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- run: cd locales && node verify.js
|
||||
|
||||
18
.github/workflows/on-release-created.yml
vendored
18
.github/workflows/on-release-created.yml
vendored
@@ -15,22 +15,22 @@ jobs:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [22.11.0]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
# see https://docs.github.com/actions/use-cases-and-examples/publishing-packages/publishing-nodejs-packages#publishing-packages-to-the-npm-registry
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
# Ensure npm 11.5.1 or later is installed
|
||||
- name: Update npm
|
||||
run: npm install -g npm@latest
|
||||
- name: Publish package
|
||||
run: |
|
||||
pnpm i --frozen-lockfile
|
||||
|
||||
2
.github/workflows/release-edit-with-push.yml
vendored
2
.github/workflows/release-edit-with-push.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
edit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
# headã$GITHUB_REF_NAME, baseã$STABLE_BRANCHãã¤openãŽPRã1ã¤ååž
|
||||
- name: Get PR
|
||||
run: |
|
||||
|
||||
2
.github/workflows/release-with-dispatch.yml
vendored
2
.github/workflows/release-with-dispatch.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
outputs:
|
||||
pr_number: ${{ steps.get_pr.outputs.pr_number }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
# headã$GITHUB_REF_NAME, baseã$STABLE_BRANCHãã¤openãŽPRã1ã¤ååž
|
||||
- name: Get PRs
|
||||
run: |
|
||||
|
||||
24
.github/workflows/report-api-diff.yml
vendored
24
.github/workflows/report-api-diff.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
# api-artifact
|
||||
steps:
|
||||
- name: Download artifact
|
||||
uses: actions/github-script@v9
|
||||
uses: actions/github-script@v7.0.1
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
@@ -60,7 +60,7 @@ jobs:
|
||||
- name: Echo full diff
|
||||
run: cat ./api-full.json.diff
|
||||
- name: Upload full diff to Artifact
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: api-artifact
|
||||
path: |
|
||||
@@ -73,9 +73,9 @@ jobs:
|
||||
HEADER="ããŽPRãĢããapi.jsonãŽåˇŽå"
|
||||
FOOTER="[Get diff files from Workflow Page](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})"
|
||||
DIFF_BYTES="$(stat ./api.json.diff -c '%s' | tr -d '\n')"
|
||||
|
||||
|
||||
echo "$HEADER" > ./output.md
|
||||
|
||||
|
||||
if (( "$DIFF_BYTES" <= 1 )); then
|
||||
echo 'åˇŽåã¯ãããžããã' >> ./output.md
|
||||
else
|
||||
@@ -87,18 +87,18 @@ jobs:
|
||||
echo '```' >> ./output.md
|
||||
echo '</details>' >> .output.md
|
||||
fi
|
||||
|
||||
|
||||
echo "$FOOTER" >> ./output.md
|
||||
- uses: thollander/actions-comment-pull-request@v3
|
||||
- uses: thollander/actions-comment-pull-request@v2
|
||||
with:
|
||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment-tag: show_diff
|
||||
file-path: ./output.md
|
||||
pr_number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment_tag: show_diff
|
||||
filePath: ./output.md
|
||||
- name: Tell error to PR
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
if: failure() && steps.load-pr-num.outputs.pr-number
|
||||
with:
|
||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment-tag: show_diff_error
|
||||
pr_number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment_tag: show_diff_error
|
||||
message: |
|
||||
api.jsonãŽåˇŽåäŊæä¸ãĢã¨ãŠãŧãįēįããžãããčŠŗį´°ã¯[WorkflowãŽãã°](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})ãįĸēčĒããĻãã ããã
|
||||
|
||||
177
.github/workflows/report-backend-memory.yml
vendored
177
.github/workflows/report-backend-memory.yml
vendored
@@ -1,177 +0,0 @@
|
||||
name: Report backend memory
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
types: [completed]
|
||||
workflows:
|
||||
- Get backend memory usage # get-backend-memory.yml
|
||||
|
||||
jobs:
|
||||
compare-memory:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Download artifact
|
||||
uses: actions/github-script@v9
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: context.payload.workflow_run.id,
|
||||
});
|
||||
let matchArtifacts = allArtifacts.data.artifacts.filter((artifact) => {
|
||||
return artifact.name.startsWith("memory-artifact-") || artifact.name == "memory-artifact"
|
||||
});
|
||||
await Promise.all(matchArtifacts.map(async (artifact) => {
|
||||
let download = await github.rest.actions.downloadArtifact({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
artifact_id: artifact.id,
|
||||
archive_format: 'zip',
|
||||
});
|
||||
await fs.promises.writeFile(`${process.env.GITHUB_WORKSPACE}/${artifact.name}.zip`, Buffer.from(download.data));
|
||||
}));
|
||||
- name: Extract all artifacts
|
||||
run: |
|
||||
find . -mindepth 1 -maxdepth 1 -type f -name '*.zip' -exec unzip {} -d artifacts ';'
|
||||
ls -la artifacts/
|
||||
- name: Load PR Number
|
||||
id: load-pr-num
|
||||
run: echo "pr-number=$(cat artifacts/pr_number)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Output base
|
||||
run: cat ./artifacts/memory-base.json
|
||||
- name: Output head
|
||||
run: cat ./artifacts/memory-head.json
|
||||
- name: Compare memory usage
|
||||
id: compare
|
||||
run: |
|
||||
BASE_MEMORY=$(cat ./artifacts/memory-base.json)
|
||||
HEAD_MEMORY=$(cat ./artifacts/memory-head.json)
|
||||
|
||||
variation() {
|
||||
calc() {
|
||||
BASE=$(echo "$BASE_MEMORY" | jq -r ".${1}.${2} // 0")
|
||||
HEAD=$(echo "$HEAD_MEMORY" | jq -r ".${1}.${2} // 0")
|
||||
|
||||
DIFF=$((HEAD - BASE))
|
||||
if [ "$BASE" -gt 0 ]; then
|
||||
DIFF_PERCENT=$(echo "scale=2; ($DIFF * 100) / $BASE" | bc)
|
||||
else
|
||||
DIFF_PERCENT=0
|
||||
fi
|
||||
|
||||
# Convert KB to MB for readability
|
||||
BASE_MB=$(echo "scale=2; $BASE / 1024" | bc)
|
||||
HEAD_MB=$(echo "scale=2; $HEAD / 1024" | bc)
|
||||
DIFF_MB=$(echo "scale=2; $DIFF / 1024" | bc)
|
||||
|
||||
JSON=$(jq -c -n \
|
||||
--argjson base "$BASE_MB" \
|
||||
--argjson head "$HEAD_MB" \
|
||||
--argjson diff "$DIFF_MB" \
|
||||
--argjson diff_percent "$DIFF_PERCENT" \
|
||||
'{base: $base, head: $head, diff: $diff, diff_percent: $diff_percent}')
|
||||
|
||||
echo "$JSON"
|
||||
}
|
||||
|
||||
JSON=$(jq -c -n \
|
||||
--argjson VmRSS "$(calc $1 VmRSS)" \
|
||||
--argjson VmHWM "$(calc $1 VmHWM)" \
|
||||
--argjson VmSize "$(calc $1 VmSize)" \
|
||||
--argjson VmData "$(calc $1 VmData)" \
|
||||
'{VmRSS: $VmRSS, VmHWM: $VmHWM, VmSize: $VmSize, VmData: $VmData}')
|
||||
|
||||
echo "$JSON"
|
||||
}
|
||||
|
||||
JSON=$(jq -c -n \
|
||||
--argjson beforeGc "$(variation beforeGc)" \
|
||||
--argjson afterGc "$(variation afterGc)" \
|
||||
--argjson afterRequest "$(variation afterRequest)" \
|
||||
'{beforeGc: $beforeGc, afterGc: $afterGc, afterRequest: $afterRequest}')
|
||||
|
||||
echo "res=$JSON" >> "$GITHUB_OUTPUT"
|
||||
- id: build-comment
|
||||
name: Build memory comment
|
||||
env:
|
||||
RES: ${{ steps.compare.outputs.res }}
|
||||
run: |
|
||||
HEADER="## Backend memory usage comparison"
|
||||
FOOTER="[See workflow logs for details](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})"
|
||||
|
||||
echo "$HEADER" > ./output.md
|
||||
echo >> ./output.md
|
||||
|
||||
table() {
|
||||
echo "| Metric | base (MB) | head (MB) | Diff (MB) | Diff (%) |" >> ./output.md
|
||||
echo "|--------|------:|------:|------:|------:|" >> ./output.md
|
||||
|
||||
line() {
|
||||
METRIC=$2
|
||||
BASE=$(echo "$RES" | jq -r ".${1}.${2}.base")
|
||||
HEAD=$(echo "$RES" | jq -r ".${1}.${2}.head")
|
||||
DIFF=$(echo "$RES" | jq -r ".${1}.${2}.diff")
|
||||
DIFF_PERCENT=$(echo "$RES" | jq -r ".${1}.${2}.diff_percent")
|
||||
|
||||
if (( $(echo "$DIFF_PERCENT > 0" | bc -l) )); then
|
||||
DIFF="+$DIFF"
|
||||
DIFF_PERCENT="+$DIFF_PERCENT"
|
||||
fi
|
||||
|
||||
# highlight VmRSS
|
||||
if [ "$2" = "VmRSS" ]; then
|
||||
METRIC="**${METRIC}**"
|
||||
BASE="**${BASE}**"
|
||||
HEAD="**${HEAD}**"
|
||||
DIFF="**${DIFF}**"
|
||||
DIFF_PERCENT="**${DIFF_PERCENT}**"
|
||||
fi
|
||||
|
||||
echo "| ${METRIC} | ${BASE} MB | ${HEAD} MB | ${DIFF} MB | ${DIFF_PERCENT}% |" >> ./output.md
|
||||
}
|
||||
|
||||
line $1 VmRSS
|
||||
line $1 VmHWM
|
||||
line $1 VmSize
|
||||
line $1 VmData
|
||||
}
|
||||
|
||||
echo "### Before GC" >> ./output.md
|
||||
table beforeGc
|
||||
echo >> ./output.md
|
||||
|
||||
echo "### After GC" >> ./output.md
|
||||
table afterGc
|
||||
echo >> ./output.md
|
||||
|
||||
echo "### After Request" >> ./output.md
|
||||
table afterRequest
|
||||
echo >> ./output.md
|
||||
|
||||
# Determine if this is a significant change (more than 5% increase)
|
||||
if [ "$(echo "$RES" | jq -r '.afterGc.VmRSS.diff_percent | tonumber > 5')" = "true" ]; then
|
||||
echo "â ī¸ **Warning**: Memory usage has increased by more than 5%. Please verify this is not an unintended change." >> ./output.md
|
||||
echo >> ./output.md
|
||||
fi
|
||||
|
||||
echo "$FOOTER" >> ./output.md
|
||||
- uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment-tag: show_memory_diff
|
||||
file-path: ./output.md
|
||||
- name: Tell error to PR
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
if: failure() && steps.load-pr-num.outputs.pr-number
|
||||
with:
|
||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment-tag: show_memory_diff_error
|
||||
message: |
|
||||
An error occurred while comparing backend memory usage. See [workflow logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details.
|
||||
51
.github/workflows/request-release-review.yml
vendored
51
.github/workflows/request-release-review.yml
vendored
@@ -1,51 +0,0 @@
|
||||
name: Request release review
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
reply:
|
||||
if: github.event.comment.body == '/request-release-review'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Reply
|
||||
uses: actions/github-script@v9
|
||||
with:
|
||||
script: |
|
||||
const body = `To dev team (@misskey-dev/dev):
|
||||
|
||||
ãĒãĒãŧãšãææĄãããĻããžã :rocket:
|
||||
|
||||
GOãŽå ´åã¯approveãNO GOãŽå ´åã¯ããŽæ¨ãŗãĄãŗãããéĄãããããžãã
|
||||
|
||||
夿ãĢãããŖãĻčæ
ŽããšãčĻŗįšã¯ã
|
||||
|
||||
- ããæŽãããã¨ã¯ãĒããīŧ
|
||||
- CHANGELOGã¯éä¸čļŗãĒããīŧ
|
||||
- ããŧã¸ã§ãŗãĢåéĄã¯ãĒããīŧ(æčˇ¨ãã§ãããŽãĢæ´æ°åŋããĻãããĒãŠ)
|
||||
- åčããšãäģæ§ãģåŽčŖ
ã¯ãĒããīŧ
|
||||
- ããŧãŋįãæ¤č¨ŧãããĩãŧããŧããä¸å
ˇåãŽå ąåįã¯ä¸ããŖãĻãĒããīŧ
|
||||
- (ãģããĨãĒããŖãŽäŋŽæŖãéčĻãĒãã°äŋŽæŖãĒãŠãŽãã)ãĒãĒãŧãšãæĨãã æšãč¯ããīŧããã§ã¯ãĒããīŧ
|
||||
- ActionsãčŊãĄãĻããĒããīŧ
|
||||
|
||||
ãĒãŠãæããããžãã
|
||||
|
||||
ãååãããã¨ãããããžã :sparkles:
|
||||
`
|
||||
|
||||
const issue_number = context.payload.issue ? context.payload.issue.number : (context.payload.pull_request && context.payload.pull_request.number)
|
||||
if (!issue_number) {
|
||||
console.log('No issue or PR number found in payload; skipping')
|
||||
} else {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number,
|
||||
body,
|
||||
})
|
||||
}
|
||||
39
.github/workflows/storybook.yml
vendored
39
.github/workflows/storybook.yml
vendored
@@ -5,6 +5,7 @@ on:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- dev/storybook8 # for testing
|
||||
pull_request_target:
|
||||
branches-ignore:
|
||||
# Since pull requests targets master mostly is the "develop" branch.
|
||||
@@ -14,7 +15,7 @@ on:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# Chromatic is not likely to be available for fork repositories, so we disable for fork repositories.
|
||||
# chromatic is not likely to be available for fork repositories, so we disable for fork repositories.
|
||||
if: github.repository == 'misskey-dev/misskey'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -22,12 +23,12 @@ jobs:
|
||||
NODE_OPTIONS: "--max_old_space_size=7168"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v4.2.2
|
||||
if: github.event_name != 'pull_request_target'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v4.2.2
|
||||
if: github.event_name == 'pull_request_target'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
@@ -35,19 +36,22 @@ jobs:
|
||||
ref: "refs/pull/${{ github.event.number }}/merge"
|
||||
- name: Checkout actual HEAD
|
||||
if: github.event_name == 'pull_request_target'
|
||||
run: git checkout "$(git rev-list --parents -n1 HEAD | cut -d" " -f3)"
|
||||
id: rev
|
||||
run: |
|
||||
echo "base=$(git rev-list --parents -n1 HEAD | cut -d" " -f2)" >> $GITHUB_OUTPUT
|
||||
git checkout $(git rev-list --parents -n1 HEAD | cut -d" " -f3)
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- name: Use Node.js 20.x
|
||||
uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
- name: Build dependent packages
|
||||
run: pnpm -F misskey-js -F misskey-bubble-game -F misskey-reversi build
|
||||
- name: Build misskey-js
|
||||
run: pnpm --filter misskey-js build
|
||||
- name: Build storybook
|
||||
run: pnpm --filter frontend build-storybook
|
||||
- name: Publish to Chromatic
|
||||
@@ -78,19 +82,24 @@ jobs:
|
||||
if: github.event_name == 'pull_request_target'
|
||||
id: chromatic_pull_request
|
||||
run: |
|
||||
CHROMATIC_PARAMETER="$(node packages/frontend/.storybook/changes.js $(git diff --name-only origin/${GITHUB_BASE_REF}...origin/${GITHUB_HEAD_REF} | xargs))"
|
||||
DIFF="${{ steps.rev.outputs.base }} HEAD"
|
||||
if [ "$DIFF" = "0000000000000000000000000000000000000000 HEAD" ]; then
|
||||
DIFF="HEAD"
|
||||
fi
|
||||
CHROMATIC_PARAMETER="$(node packages/frontend/.storybook/changes.js $(git diff-tree --no-commit-id --name-only -r $(echo "$DIFF") | xargs))"
|
||||
if [ "$CHROMATIC_PARAMETER" = " --skip" ]; then
|
||||
echo "skip=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
BRANCH="${{ github.event.pull_request.head.user.login }}:$GITHUB_HEAD_REF"
|
||||
if [ "$BRANCH" = "misskey-dev:$GITHUB_HEAD_REF" ]; then
|
||||
BRANCH="$GITHUB_HEAD_REF"
|
||||
BRANCH="${{ github.event.pull_request.head.user.login }}:$HEAD_REF"
|
||||
if [ "$BRANCH" = "misskey-dev:$HEAD_REF" ]; then
|
||||
BRANCH="$HEAD_REF"
|
||||
fi
|
||||
pnpm --filter frontend chromatic --exit-once-uploaded -d storybook-static --branch-name "$BRANCH" $(echo "$CHROMATIC_PARAMETER")
|
||||
env:
|
||||
HEAD_REF: ${{ github.event.pull_request.head.ref }}
|
||||
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
||||
- name: Notify that Chromatic detects changes
|
||||
uses: actions/github-script@v9
|
||||
uses: actions/github-script@v7.0.1
|
||||
if: github.event_name != 'pull_request_target' && steps.chromatic_push.outputs.success == 'false'
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
@@ -102,7 +111,7 @@ jobs:
|
||||
body: 'Chromatic detects changes. Please [review the changes on Chromatic](https://www.chromatic.com/builds?appId=6428f7d7b962f0b79f97d6e4).'
|
||||
})
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: storybook
|
||||
path: packages/frontend/storybook-static
|
||||
|
||||
117
.github/workflows/test-backend.yml
vendored
117
.github/workflows/test-backend.yml
vendored
@@ -18,66 +18,35 @@ on:
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/test-backend.yml
|
||||
- .github/misskey/test.yml
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
force_ffmpeg_cache_update:
|
||||
description: 'Force update ffmpeg cache'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
unit:
|
||||
name: Unit tests (backend)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version-file:
|
||||
- .node-version
|
||||
- .github/min.node-version
|
||||
node-version: [22.11.0]
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
image: postgres:15
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
redis:
|
||||
image: redis:8
|
||||
image: redis:7
|
||||
ports:
|
||||
- 56312:6379
|
||||
meilisearch:
|
||||
image: getmeili/meilisearch:v1.42.1
|
||||
ports:
|
||||
- 57712:7700
|
||||
env:
|
||||
MEILI_NO_ANALYTICS: true
|
||||
MEILI_ENV: development
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Setup and Restore ffmpeg/ffprobe Cache
|
||||
id: cache-ffmpeg
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: |
|
||||
/usr/local/bin/ffmpeg
|
||||
/usr/local/bin/ffprobe
|
||||
# daily cache
|
||||
key: ${{ runner.os }}-ffmpeg-${{ steps.current-date.outputs.today }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-ffmpeg-${{ steps.current-date.outputs.today }}
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- name: Install FFmpeg
|
||||
if: steps.cache-ffmpeg.outputs.cache-hit != 'true' || github.event.inputs.force_ffmpeg_cache_update == true
|
||||
run: |
|
||||
for i in {1..3}; do
|
||||
echo "Attempt $i: Installing FFmpeg..."
|
||||
@@ -92,10 +61,10 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
@@ -107,7 +76,7 @@ jobs:
|
||||
- name: Test
|
||||
run: pnpm --filter backend test-and-coverage
|
||||
- name: Upload to Codecov
|
||||
uses: codecov/codecov-action@v6
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/backend/coverage/coverage-final.json
|
||||
@@ -115,36 +84,34 @@ jobs:
|
||||
e2e:
|
||||
name: E2E tests (backend)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version-file:
|
||||
- .node-version
|
||||
- .github/min.node-version
|
||||
node-version: [22.11.0]
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
image: postgres:15
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
redis:
|
||||
image: redis:8
|
||||
image: redis:7
|
||||
ports:
|
||||
- 56312:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
@@ -156,51 +123,7 @@ jobs:
|
||||
- name: Test
|
||||
run: pnpm --filter backend test-and-coverage:e2e
|
||||
- name: Upload to Codecov
|
||||
uses: codecov/codecov-action@v6
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/backend/coverage/coverage-final.json
|
||||
|
||||
migration:
|
||||
name: Migration tests (backend)
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version-file:
|
||||
- .node-version
|
||||
#- .github/min.node-version
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
- name: Copy Configure
|
||||
run: cp .github/misskey/test.yml .config
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
- name: Run migrations
|
||||
run: MISSKEY_CONFIG_YML=test.yml pnpm --filter backend migrate
|
||||
- name: Check no migrations are remaining
|
||||
run: MISSKEY_CONFIG_YML=test.yml pnpm --filter backend check-migrations
|
||||
|
||||
43
.github/workflows/test-federation.yml
vendored
43
.github/workflows/test-federation.yml
vendored
@@ -14,13 +14,6 @@ on:
|
||||
- packages/backend/**
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/test-federation.yml
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
force_ffmpeg_cache_update:
|
||||
description: 'Force update ffmpeg cache'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
test:
|
||||
@@ -28,31 +21,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version-file:
|
||||
- .node-version
|
||||
- .github/min.node-version
|
||||
node-version: [22.11.0]
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Setup and Restore ffmpeg/ffprobe Cache
|
||||
id: cache-ffmpeg
|
||||
uses: actions/cache@v5
|
||||
with:
|
||||
path: |
|
||||
/usr/local/bin/ffmpeg
|
||||
/usr/local/bin/ffprobe
|
||||
# daily cache
|
||||
key: ${{ runner.os }}-ffmpeg-${{ steps.current-date.outputs.today }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-ffmpeg-${{ steps.current-date.outputs.today }}
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- name: Install FFmpeg
|
||||
if: steps.cache-ffmpeg.outputs.cache-hit != 'true' || github.event.inputs.force_ffmpeg_cache_update == true
|
||||
run: |
|
||||
for i in {1..3}; do
|
||||
echo "Attempt $i: Installing FFmpeg..."
|
||||
@@ -67,10 +43,10 @@ jobs:
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
- name: Build Misskey
|
||||
run: |
|
||||
@@ -78,7 +54,6 @@ jobs:
|
||||
pnpm build
|
||||
- name: Setup
|
||||
run: |
|
||||
echo "NODE_VERSION=$(cat ${{ matrix.node-version-file }})" >> $GITHUB_ENV
|
||||
cd packages/backend/test-federation
|
||||
bash ./setup.sh
|
||||
sudo chmod 644 ./certificates/*.test.key
|
||||
@@ -96,16 +71,18 @@ jobs:
|
||||
docker compose logs | tail -n 300
|
||||
exit 1
|
||||
- name: Test
|
||||
id: test
|
||||
continue-on-error: true
|
||||
run: |
|
||||
cd packages/backend/test-federation
|
||||
docker compose run --no-deps tester
|
||||
- name: Log
|
||||
if: always()
|
||||
if: ${{ steps.test.outcome == 'failure' }}
|
||||
run: |
|
||||
cd packages/backend/test-federation
|
||||
docker compose logs
|
||||
exit 1
|
||||
- name: Stop servers
|
||||
if: always()
|
||||
run: |
|
||||
cd packages/backend/test-federation
|
||||
docker compose down
|
||||
|
||||
37
.github/workflows/test-frontend.yml
vendored
37
.github/workflows/test-frontend.yml
vendored
@@ -27,16 +27,20 @@ jobs:
|
||||
name: Unit tests (frontend)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [22.11.0]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
@@ -48,7 +52,7 @@ jobs:
|
||||
- name: Test
|
||||
run: pnpm --filter frontend test-and-coverage
|
||||
- name: Upload Coverage
|
||||
uses: codecov/codecov-action@v6
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/frontend/coverage/coverage-final.json
|
||||
@@ -60,23 +64,24 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version: [22.11.0]
|
||||
browser: [chrome]
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
image: postgres:15
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
redis:
|
||||
image: redis:8
|
||||
image: redis:7
|
||||
ports:
|
||||
- 56312:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
# https://github.com/cypress-io/cypress-docker-images/issues/150
|
||||
@@ -86,11 +91,11 @@ jobs:
|
||||
#- uses: browser-actions/setup-firefox@latest
|
||||
# if: ${{ matrix.browser == 'firefox' }}
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Copy Configure
|
||||
@@ -105,7 +110,7 @@ jobs:
|
||||
- name: Cypress install
|
||||
run: pnpm exec cypress install
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v7.1.9
|
||||
uses: cypress-io/github-action@v6
|
||||
timeout-minutes: 15
|
||||
with:
|
||||
install: false
|
||||
@@ -113,12 +118,12 @@ jobs:
|
||||
wait-on: 'http://localhost:61812'
|
||||
headed: true
|
||||
browser: ${{ matrix.browser }}
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: ${{ matrix.browser }}-cypress-screenshots
|
||||
path: cypress/screenshots
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
with:
|
||||
name: ${{ matrix.browser }}-cypress-videos
|
||||
|
||||
17
.github/workflows/test-misskey-js.yml
vendored
17
.github/workflows/test-misskey-js.yml
vendored
@@ -20,17 +20,22 @@ jobs:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [22.11.0]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.2
|
||||
uses: actions/checkout@v4.2.2
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
- name: Setup Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
@@ -48,7 +53,7 @@ jobs:
|
||||
CI: true
|
||||
|
||||
- name: Upload Coverage
|
||||
uses: codecov/codecov-action@v6
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/misskey-js/coverage/coverage-final.json
|
||||
|
||||
14
.github/workflows/test-production.yml
vendored
14
.github/workflows/test-production.yml
vendored
@@ -15,16 +15,20 @@ jobs:
|
||||
name: Production build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [22.11.0]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
|
||||
14
.github/workflows/validate-api-json.yml
vendored
14
.github/workflows/validate-api-json.yml
vendored
@@ -16,16 +16,20 @@ jobs:
|
||||
validate-api-json:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [22.11.0]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.2
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v6.0.3
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.4.0
|
||||
uses: pnpm/action-setup@v4.1.0
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
- name: Install Redocly CLI
|
||||
run: npm i -g @redocly/cli
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -46,7 +46,6 @@ docker-compose.yml
|
||||
built
|
||||
built-test
|
||||
js-built
|
||||
src-js
|
||||
/data
|
||||
/.cache-loader
|
||||
/db
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -0,0 +1,3 @@
|
||||
[submodule "fluent-emojis"]
|
||||
path = fluent-emojis
|
||||
url = https://github.com/misskey-dev/emojis.git
|
||||
|
||||
@@ -1 +1 @@
|
||||
22.15.0
|
||||
22.11.0
|
||||
|
||||
3
.npmrc
Normal file
3
.npmrc
Normal file
@@ -0,0 +1,3 @@
|
||||
engine-strict = true
|
||||
save-exact = true
|
||||
shell-emulator = true
|
||||
7
.vscode/settings.json
vendored
7
.vscode/settings.json
vendored
@@ -3,16 +3,11 @@
|
||||
"**/node_modules": true
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"files.associations": {
|
||||
"*.test.ts": "typescript"
|
||||
},
|
||||
"jest.jestCommandLine": "pnpm run jest",
|
||||
"jest.runMode": "on-demand",
|
||||
"jest.virtualFolders": [
|
||||
{ "name": "backend unit", "jestCommandLine": "pnpm -F backend run test" },
|
||||
{ "name": "backend e2e", "jestCommandLine": "pnpm -F backend run test:e2e"},
|
||||
{ "name": "misskey-js", "jestCommandLine": "pnpm -F misskey-js run jest" }
|
||||
],
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": "explicit"
|
||||
},
|
||||
|
||||
139
AGENTS.md
139
AGENTS.md
@@ -1,139 +0,0 @@
|
||||
# Misskey â AI Agent Guide
|
||||
|
||||
ããŽããĄã¤ãĢ㯠Misskey ãĒãã¸ããĒã§åã AI ãŗãŧããŖãŗã°ã¨ãŧã¸ã§ãŗã (Claude Code / OpenAI Codex / GitHub Copilot į) ãå
ąéã§åį
§ãã **æäŊéãŽãĢãŧãĢã¨į´ĸåŧ**ãæŦĄãŽ 3 įĩ莝ããåį
§ãģčĒãŋčžŧãŋããã:
|
||||
|
||||
- **Claude Code**: ãĢãŧã `CLAUDE.md` ãã `@AGENTS.md` ã§åãčžŧãžãã
|
||||
- **OpenAI Codex**: ãĢãŧã `AGENTS.md` ãį´æĨčĒãŋčžŧã
|
||||
- **GitHub Copilot**: `.github/copilot-instructions.md` (æŦããĄã¤ãĢãåį
§ãã¤ã¤ãCopilot code review åããĢåŋ
é čĻį´ã忞ããããĄã¤ãĢ) įĩįąã§åį
§ãã
|
||||
|
||||
äēēé contributor åããŽä¸čŦčĻį´ (Issue / PR ãŽåēãæšãActivityPub æĄåŧĩãĒãŠ) 㯠[CONTRIBUTING.md](CONTRIBUTING.md) ãåį
§ãæŦããĄã¤ãĢ㯠AI ã **ãŗãŧããæ¸ããģį´ã** éãĢč¸ãŋå¤ããĻã¯ãããĒãäēé
ãĢįĩãŖãĻããã
|
||||
|
||||
---
|
||||
|
||||
## äēæ
į´įĩãĢãŧãĢ (åŋ
ãåŽã)
|
||||
|
||||
éåãã㨠CI å¤ąæãžãã¯æŦįĒäēæ
ãĢãĒããé åŽãããã¨ã
|
||||
|
||||
### 1. SPDX ããããŧåŋ
é
|
||||
|
||||
AGPL-3.0-only įŽĄčŊã㤠SPDX CI å¯žčąĄããŖãŦã¯ããĒãĢæ°čĻ `.ts` / `.js` / `.cjs` / `.mjs` / `.vue` / `.scss` / `.html` ããĄã¤ãĢãčŋŊå ããå ´åãåé ãĢäģĨä¸ãåŋ
ãäģãããæŦ čŊãã㨠CI (`spdx` ã¸ã§ã) ãå¤ąæãããCI ãŽå¯žčąĄå¤åŽã¯ [.github/workflows/check-spdx-license-id.yml](.github/workflows/check-spdx-license-id.yml) ㎠`directories` é
åãåį
§ (`*.config.{ts,js,cjs,mjs}` 㨠`*eslint*` ã¯é¤å¤)ã
|
||||
|
||||
`packages/misskey-js` 㯠MIT ãŠã¤ãģãŗãšãŽãĩããããąãŧã¸ãĒãŽã§ãã㎠AGPL ããããŧãä¸åžãĢäģããĒãããĩããããąãŧã¸åēæãŽ `package.json` / `LICENSE` / æĸåããĄã¤ãĢãŽããããŧãĢåžãã
|
||||
|
||||
`.ts` / `.js` / `.cjs` / `.mjs` / `.scss`:
|
||||
|
||||
```text
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
```
|
||||
|
||||
`.vue` / `.html` (HTML ãŗãĄãŗãåŊĸåŧ):
|
||||
|
||||
```text
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
```
|
||||
|
||||
### 2. locales/*.yml 㯠`ja-JP.yml` ãŽãŋᎍéå¯
|
||||
|
||||
`locales/` é
ä¸ãŽ YAML 㯠**`ja-JP.yml` ãŽãŋæåᎍéããĻãã**ãäģč¨čĒããĄã¤ãĢ (`en-US.yml` į) 㯠Crowdin ãŽčĒåé
äŋĄå
ã§ãæåᎍéããã¨ä¸æ¸ãã§å¤ąããããæ šæ : `locales/README.md` (ja-JP.yml äģĨå¤ãæåᎍéããĒãéį¨) 㨠`crowdin.yml` (`ja-JP.yml` â `locales/%locale%.yml` ãŽåæč¨åŽ)ã
|
||||
|
||||
### 3. ããŧã¸æ¸ãŋ migration ãįĩļ寞ãĢᎍéããĒã
|
||||
|
||||
`packages/backend/migration/{unixMs}-{PascalName}.js` ãŽããĄãæĸãĢ `develop` / `master` ãĢããŧã¸æ¸ãŋãŽããĄã¤ãĢ㯠**įĩļ寞ãĢ夿´ããĒã**ãæŦįĒį°åĸã§åąĨæ´æšå¤ãčĩˇããã¨æˇąåģãĒããŧãŋ䏿´åãåŧãčĩˇããã
|
||||
|
||||
ãšããŧã夿´ãåŋ
čĻãĒå ´å㯠**æ°ãããŋã¤ã ãšãŋãŗãã§æ°čĻããĄã¤ãĢ** ãäŊæãã:
|
||||
|
||||
- ããĄã¤ãĢå: `node -e "console.log(Date.now())"` ã§ UNIX ms ãååžãã`{ms}-<descriptive-name>.js` ã¨ããĻįŊŽããåŊåãšãŋã¤ãĢã¯æĸååąĨæ´ã§æˇˇå¨ããĻãã (`1716129964060-ChannelIdDenormalizedForMiPoll.js` ãŽãããĒ PascalCaseã`1721666053703-fixDriveUrl.js` ãŽãããĒ camelCaseã`1672704136584-remove-latestStatus.js` ãŽãããĒ kebab-case)ã夿´ã襨ãåä¸ãŽčąčĒåã§ããã°č¯ããã¯ãŠãšåå´ã¯ PascalCase + 13 æĄãŋã¤ã ãšãŋãŗã (`class FixDriveUrl1721666053703 { ... }`) ãåŋ
ãåŽããã¨ã
|
||||
- `up()` 㨠`down()` ãŽä¸Ąæšãåŋ
ãåŽčŖ
ãã (`down` 㯠`up` ãŽåŽå
¨ãĒåˇģãæģã)ã
|
||||
- `pnpm --filter backend check-migrations` ãéãããã㯠**TypeORM schema builder ã§ pending DDL ãæ¤åēãã** æ¤æģ ([packages/backend/scripts/check_migrations_clean.js](packages/backend/scripts/check_migrations_clean.js))ãã¨ãŗããŖããŖãŽ `@Column` / `@Entity` 夿´ã migration ãĢåãčžŧãžããĻããĒãã¨ããã§æ¤åēãããããŋã¤ã ãšãŋãŗããŽé åēčĒäŊãį´æĨæ¤æģããããã§ã¯ãĒã (é åēãåŖããå ´åãŽå¤ąæã¯åĨįĩ莝ã§åēã)ã
|
||||
|
||||
ã¨ãŗããŖããŖåˇŽåãã TypeORM CLI ã§čĒåįæããã / `CREATE INDEX CONCURRENTLY` įãŽãĒããˇã§ãŗãäŊŋãããå ´å㯠[.claude/skills/create-migration/SKILL.md](.claude/skills/create-migration/SKILL.md) ãåį
§ãææ¸ã / CLI ãŠãĄããŽæšåŧã§ãä¸č¨ 3 įš (åąĨæ´æšå¤įĻæĸ / `up`+`down` / `check-migrations`) ãæēãããã°č¯ãã
|
||||
|
||||
---
|
||||
|
||||
## åŋ
é ãŗããŗã
|
||||
|
||||
| į¨é | ãŗããŗã |
|
||||
| --- | --- |
|
||||
| å
¨äŊããĢã | `pnpm build` |
|
||||
| éįēãĩãŧããŧ (backend + frontend watch) | `pnpm dev` |
|
||||
| Lint (typecheck + eslint, å
¨ãããąãŧã¸) | `pnpm lint` (= `pnpm --no-bail -r lint`ãæåãŽå¤ąæã§æĸãžããå
¨ãããąãŧã¸ãŽįĩæãåéãã) |
|
||||
| Backend unit test (Vitest) | `pnpm --filter backend test` |
|
||||
| Backend e2e test | `pnpm --filter backend test:e2e` |
|
||||
| Backend federation test | `pnpm --filter backend test:fed` |
|
||||
| Frontend test (Vitest) | `pnpm --filter frontend test` |
|
||||
| Cypress E2E (čĻ `start:test`) | `pnpm e2e` |
|
||||
| Storybook dev (frontend) | `pnpm --filter frontend storybook-dev` |
|
||||
| Migration éŠį¨ | `pnpm migrate` |
|
||||
| Migration ããŧãĢãã㯠| `pnpm revert` |
|
||||
| Migration ㎠pending DDL æ¤æģ (ã¨ãŗããŖããŖåˇŽåãŽåãčžŧãŋæŧãæ¤åē) | `pnpm --filter backend check-migrations` |
|
||||
| `misskey-js` åįæ (API 夿´åžåŋ
é ) | `pnpm build-misskey-js-with-types` |
|
||||
|
||||
> Backend ㎠TypeScript åãã§ãã¯ã¯ `pnpm --filter backend typecheck` (tsgo)ã
|
||||
> ååĨããĄã¤ãĢã¸ãŽ ESLint --fix 㯠`pnpm exec eslint --fix <path>`ã
|
||||
> **backend ããšã (`test` / `test:e2e` / `test:fed`) åŽčĄåãĢ `.config/test.yml` ãåŋ
čĻ** (æĒäŊæã ã¨ããšãčĒäŊãčĩˇåããĒã)ããŗããŧæé ã¨čŠŗį´°ã¯ [.claude/docs/testing.md §Backend å
¨čŦãŽåæ](.claude/docs/testing.md#backend-å
¨čŦãŽåæ-configtestyml) ãåį
§ã
|
||||
|
||||
---
|
||||
|
||||
## CHANGELOG
|
||||
|
||||
ãĻãŧãļãŧåŊąéŋãŽãã夿´ (æŠčŊčŋŊå ãģäŋŽæŖãģæšå) 㯠`CHANGELOG.md` ãŽåé `## Unreleased` ãģã¯ãˇã§ãŗãĢ 1 čĄčŋŊå ããããĒããĄã¯ãŋãĒãŗã°įãŽå
é¨å¤æ´ã¯ä¸čĻã
|
||||
|
||||
### ãģã¯ãˇã§ãŗæ§é
|
||||
|
||||
`## Unreleased` é
ä¸ãĢ **3 ã¤ãŽãĩããģã¯ãˇã§ãŗ** ã፿ãããĻãã:
|
||||
|
||||
- `### General` â å
ąé / æ¨ĒæįãĒ夿´
|
||||
- `### Client` â `packages/frontend` įŗģ
|
||||
- `### Server` â `packages/backend` įŗģ
|
||||
|
||||
### ã¨ãŗããĒæ¸åŧ
|
||||
|
||||
芲åŊãĩããģã¯ãˇã§ãŗãĢ `- <Prefix>: <æĻčĻ>` ãŽåŊĸåŧã§čŋŊå ãPrefix ã¯å
é 大æåã
|
||||
|
||||
```text
|
||||
- Enhance: ããŧããŽčŠŗį´°čĄ¨į¤ēã§ãŽå
Ŧéį¯å˛ãŽčĄ¨į¤ēãæšå
|
||||
- Fix: éįĨãį´10į§é
åģļããåéĄãäŋŽæŖ
|
||||
- Feat: æ°æŠčŊãŽčŋŊå
|
||||
```
|
||||
|
||||
### č§ĻãŖãĻã¯ãããĒãį¯å˛
|
||||
|
||||
- `## Unreleased` **äģĨå¤** ãŽãģã¯ãˇã§ãŗ (éåģãĒãĒãŧãš) ã¯å¤æ´ããĒãã
|
||||
- `## Unreleased` ãŽčĻåēã㨠3 ã¤ãŽįŠēãĩããģã¯ãˇã§ãŗéǍæ ŧčĒäŊã¯įļæãã (ãĒãĒãŧãšãšã¯ãĒãããæåž
ããæ§é )ã
|
||||
|
||||
> åč: ãŗããããĄããģãŧã¸å´ã¯ `enhance(frontend): ...` / `fix(backend): ...` ãŽå°æå + ãšãŗãŧãåŊĸåŧ ([CONTRIBUTING.md](CONTRIBUTING.md) åį
§)ãCHANGELOG ã¨ã¯æ¸åŧãį°ãĒãįšãĢæŗ¨æã
|
||||
|
||||
---
|
||||
|
||||
## ãĒãŗãããŗãåį
§ (åŋ
čĻæãĢ Read ãããã¨)
|
||||
|
||||
äģĨä¸ã¯ AI ã **äŊæĨå¯žčąĄãĢåŋããĻåŋ
čĻãĒã¨ãã ã** éãčŠŗį´°ãããĨãĄãŗãã常æãŗãŗãããšããĢã¯čŧããĒãã
|
||||
|
||||
| äŊããããæ | åį
§å
|
|
||||
| --- | --- |
|
||||
| ãããąãŧã¸æ§æãģäžåéĸäŋãææĄããã | [.claude/docs/architecture.md](.claude/docs/architecture.md) |
|
||||
| `packages/backend` ãᎍéãã (NestJS / TypeORM / migration / API endpoint) | [.claude/docs/backend.md](.claude/docs/backend.md) |
|
||||
| `packages/frontend` ãᎍéãã (Vue 3 / Mk* / i18n / SCSS module / `os.ts`) | [.claude/docs/frontend.md](.claude/docs/frontend.md) |
|
||||
| ããšããæ¸ããģčĩ°ããã (Vitest / Cypress / Storybook) | [.claude/docs/testing.md](.claude/docs/testing.md) |
|
||||
| æåšåæ¸ Claude Code ããŠã°ã¤ãŗãŽį¨éãįĸēčĒ | [.claude/docs/plugins.md](.claude/docs/plugins.md) |
|
||||
|
||||
---
|
||||
|
||||
## ããŧãĢåēæãŽčŖåŠããĄã¤ãĢ
|
||||
|
||||
`.claude/` é
ä¸ã¯ Claude Code åēæãŽ skills / agents / slash commands ãéį´ããĻãã (Codex / Copilot ã¯čĒãŋéŖã°ããĻãã):
|
||||
|
||||
- `.claude/skills/` â įš°ãčŋããŋãšã¯į¨ãŽ skill åŽįžŠ (äž: `add-api-endpoint`, `create-migration`)
|
||||
- `.claude/agents/` â å°éãŦããĨãŧã¨ãŧã¸ã§ãŗã (äž: `misskey-api-reviewer`, `vue-component-reviewer`)
|
||||
- `.claude/commands/` â Claude Code ãŽãšãŠããˇãĨãŗããŗã (äž: `/check-misskey-js`, `/changelog-add`)
|
||||
- `.claude/docs/` â ãĒãŗãããŗãåį
§ãããĨãĄãŗã (ä¸č¨ãŽčĄ¨ã§į¤ēããããŽãCodex / Copilot ãããå
厚čĒäŊã¯čĒãã)
|
||||
- `.claude/settings.json` â Claude Code ãŽæåšããŠã°ã¤ãŗ (`enabledPlugins`) ãŽãŋãč¨čŧããå
ąæč¨åŽãhook ã¯æåŗįãĢįģé˛ããĒã (å contributor ã `.claude/settings.local.json` ã§ opt-in ããæšé)
|
||||
- `.claude/settings.local.json` â åäēēããŧãĢãĢč¨åŽ (`.gitignore` æ¸)
|
||||
|
||||
ãĩãŧãããŧããŖįąæĨ (everything-claude-code įąæĨ㎠MIT ãŠã¤ãģãŗãšããĄã¤ãĢį) ãŽåēå
¸ã¯ [.claude/THIRD_PARTY_LICENSES.md](.claude/THIRD_PARTY_LICENSES.md) ãåį
§ã
|
||||
888
CHANGELOG.md
888
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@@ -1,7 +0,0 @@
|
||||
# Misskey â Claude Code Guide
|
||||
|
||||
ãĢãŧãĢæŦäŊ㯠[AGENTS.md](AGENTS.md) (Codex / Copilot ã¨å
ąæããåä¸ãŊãŧãš)ãæŦããĄã¤ãĢ㯠Claude Code į¨ãŽčããŠãããŧã§ã`@AGENTS.md` æ§æã§æŦäŊčĻį´ããģããˇã§ãŗéå§æãĢãŗãŗãããšãã¸åąéããã
|
||||
|
||||
Claude Code åēæãŽčŖåŠ (skills / agents / slash commands / docs) 㯠`.claude/` é
ä¸ãĢãŗãããæ¸ãåäēēããŧãĢãĢč¨åŽã¯ `.claude/settings.local.json` ãĢãMCP čĒč¨ŧæ
å ąã¯ `.claude/.credentials.json` ãĢįŊŽã (ãããã `.gitignore` æ¸)ã
|
||||
|
||||
@AGENTS.md
|
||||
@@ -189,14 +189,6 @@ pnpm migrate
|
||||
|
||||
After finishing the migration, you can proceed.
|
||||
|
||||
#### Cloudflare tunnel
|
||||
Cloudflare tunnelãäŊŋãã¨ããŧãĢãĢãŽMisskeyãĩãŧããŧãã¤ãŗãŋãŧããããĢå
Ŧéã§ããžãã
|
||||
HTTPSã§ããåäŊããĒãæŠčŊãæ¤č¨ŧãããæãããšãããĒãŠåĨãŽããã¤ãšããããŧãĢãĢãŽMisskeyãĩãŧããŧãæ¤č¨ŧãããæãĢäžŋåŠã§ãã
|
||||
|
||||
##### Cloudflare warpã¨äŊĩį¨ããéãŽtips
|
||||
|
||||
> cloudflared (Cloudflare Tunnel) 㯠region1.v2.argotunnel.com / region2.v2.argotunnel.com ãĢ QUIC/HTTP2 ã§ãĸãĻãããĻãŗãæĨįļãããŽã§ãããWARP ãæåšåããã¨ããŽããŠããŖãã¯ã WARP įĩįąãĢãĒãŖãĻãĢãŧã/åæããžããããã 2 ããšãã WARP ãŽããŗããĢé¤å¤īŧsplit tunnelīŧãĢčŋŊå ãããã¨ã§ãcloudflared ã ã㯠WARP ããã¤ããšããĻį´æĨ Cloudflare ã¨ãã¸ã¸æĨįļã§ãããããĢãĒããžãã
|
||||
|
||||
### Start developing
|
||||
During development, it is useful to use the
|
||||
```
|
||||
@@ -266,12 +258,6 @@ Misskey uses Vue(v3) as its front-end framework.
|
||||
- **When creating a new component, please use the Composition API (with [setup sugar](https://v3.vuejs.org/api/sfc-script-setup.html) and [ref sugar](https://github.com/vuejs/rfcs/discussions/369)) instead of the Options API.**
|
||||
- Some of the existing components are implemented in the Options API, but it is an old implementation. Refactors that migrate those components to the Composition API are also welcome.
|
||||
|
||||
## Tabler Icons
|
||||
ãĸã¤ãŗãŗã¯ãProduction BuildæãĢäŊŋį¨ãããĻããĒãããŽãåé¤ããããããĢãĒãŖãĻããžãã
|
||||
|
||||
**ãĸã¤ãŗãŗãåįãĢč¨åŽããéãĢã¯ã `ti-${someVal}` ãŽãããĒããĸã¤ãŗãŗåãŽãŋãåįãĢå¤åãããåŽčŖ
ãčĄããĒãã§ãã ããã**
|
||||
åŋ
ã `ti-xxx` ãŽãããĒåŽå
¨ãĒã¯ãŠãšåãåĢãããããĢããĻãã ããã
|
||||
|
||||
## nirax
|
||||
niraxã¯ãMisskeyã§äŊŋį¨ããĻãããĒãĒã¸ããĢãŽãããŗãã¨ãŗããĢãŧããŖãŗã°ãˇãšãã ã§ãã
|
||||
**vue-routerããåŊąéŋãå¤å¤§ãĢåããĻãããŽã§ããžãã¯vue-routerãĢã¤ããĻåĻãļãã¨ããå§ãããžãã**
|
||||
@@ -287,6 +273,7 @@ niraxã¯ãMisskeyã§äŊŋį¨ããĻãããĒãĒã¸ããĢãŽãããŗãã¨ãŗã
|
||||
query?: Record<string, string>;
|
||||
loginRequired?: boolean;
|
||||
hash?: string;
|
||||
globalCacheKey?: string;
|
||||
children?: RouteDef[];
|
||||
}
|
||||
```
|
||||
@@ -583,12 +570,32 @@ enumãŽåæãŽå
厚ãŽåé¤ã¯ãããŽå¤ããã¤ãŦãŗãŧããå
¨ãĻå
|
||||
### MigrationäŊææšæŗ
|
||||
packages/backendã§:
|
||||
```sh
|
||||
pnpm dlx typeorm migration:generate -d ormconfig.js -o --esm <migration name>
|
||||
pnpm dlx typeorm migration:generate -d ormconfig.js -o <migration name>
|
||||
```
|
||||
|
||||
- įæåžãããĄã¤ãĢãmigrationä¸ãĢį§ģããĻãã ãã
|
||||
- äŊæããããšã¯ãĒããã¯ä¸åŋ
čĻãĒ夿´ãåĢãããé¤åģããĻãã ãã
|
||||
- `-o` (`--outputJs`) ã§ JS åŊĸåŧã`--esm` ã§ ESM åŊĸåŧãĢįæãããMisskey ãŽæĸå migration ã¯ããšãĻ ESM JS ãĒãŽã§ä¸ĄæšãŽãĒããˇã§ãŗãåŋ
čĻ
|
||||
|
||||
### JSON SchemaãŽobjectã§anyOfãäŊŋãã¨ã
|
||||
JSON Schemaã§ãobjectãĢ寞ããĻanyOfãäŊŋãå ´åãanyOfãŽä¸ã§propertiesãåŽįžŠããĒããã¨ã
|
||||
ããĒããŧãˇã§ãŗãåšããĒããããīŧSchemaTypeãããŽãããĢäŊãããĻãããobjectãŽanyOfå
ãŽpropertiesã¯æ¨ãĻãããžãīŧ
|
||||
https://github.com/misskey-dev/misskey/pull/10082
|
||||
|
||||
ãããšãhogeãããŗfugaãĢã¤ããĻãįæšãåŋ
é ã¨ãã¤ã¤ä¸ĄæšãŽæåŽãããããå ´å:
|
||||
|
||||
```ts
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hoge: { type: 'string', minLength: 1 },
|
||||
fuga: { type: 'string', minLength: 1 },
|
||||
},
|
||||
anyOf: [
|
||||
{ required: ['hoge'] },
|
||||
{ required: ['fuga'] },
|
||||
],
|
||||
} as const;
|
||||
```
|
||||
|
||||
### ãŗãã¯ãˇã§ãŗãĢã¯`markRaw`ãã
|
||||
**VueãŽãŗãŗããŧããŗããŽdataãĒããˇã§ãŗã¨ããĻ**misskey.jsãŽãŗãã¯ãˇã§ãŗãč¨åŽããã¨ããåŋ
ã`markRaw`ã§ãŠããããĻãã ãããã¤ãŗãšãŋãŗãšãä¸åŋ
čĻãĢãĒãĸã¯ããŖãåããããã¨ã§ãmisskey.jså
ãŽåĻįã§ä¸å
ˇåãįēįããã¨ã¨ããĢããããŠãŧããŗãšä¸ãŽåéĄãĢãįšããããĒããComposition APIãäŊŋãå ´åã¯ããŽéãã§ã¯ãĒã(ãĒãĸã¯ããŖãåã¯ãããĨãĸãĢãĒãã)ã
|
||||
@@ -627,23 +634,3 @@ color: hsl(from var(--MI_THEME-accent) h s calc(l - 10));
|
||||
color: color(from var(--MI_THEME-accent) srgb r g b / 0.5);
|
||||
```
|
||||
|
||||
## čãæš
|
||||
### DRYãĢåããããĒ
|
||||
åŋ
čĻãĒãŽã¯ä¸čŦåã§ã¯ãĒãæŊ蹥åã¨čããžãã
|
||||
į˛äŋĄãããčǤãŖããģä¸åŋ
čĻãĒå
ąéåã¯éŋãããããčĒįļã ã¨æããå ´åã¯éč¤ãããåæ°ãæãĄãžãããã
|
||||
|
||||
### Misskeyãč¤éãĢããĒãåŽčŖ
|
||||
ããããããč¤éã§ããŖãĻããMisskeyåēæãŽãŗãŗãããšãã¨éĸåŋãåéĸãããĻãã(ãããã¯äēåŽä¸åéĸãããĻããã¨čĻåããã¨ãã§ãã)åŽčŖ
ã§ããã°ãããã¯MisskeyãŽãŗãŧãããŧãšãĢ寞ããč¤éæ§ãĢåŊąéŋãä¸ããĒãã¨čããžãã
|
||||
|
||||
äžãããĒããVueãAiScriptã¨ããŖãMisskeyãäŊŋį¨ããĻãããŠã¤ããŠãĒãŽå
é¨åŽčŖ
ããããč¤éã ãŖãã¨ããĻããããããäŊŋį¨ããĻããããMisskeyãŽåŽčŖ
ã¯č¤éã§ãããã¨ãããã¨ãĢã¯ãĒããĒããŽã¨åãã§ãã
|
||||
|
||||
MisskeyãŽããĄã¤ãŗįĨčããéĸåŋãåéĸãããĻããã¨ãããã¨ã¯ãMisskeyãŽåŽčŖ
ãĢã¤ããĻčããæãĢããããŽå
é¨åŽčŖ
ãčæ
Žããåŋ
čĻãįĄããčĒįĨč˛ čˇãåĸãããĒãããã§ãã
|
||||
|
||||
ãžãéčĻãĒįšã¯ãããŽåŽčŖ
ããMisskeyãĒãã¸ããĒãŽå¤é¨ãĢããããģå
é¨ãĢãããã¨ãããã¨ããMisskeyããĄãŗãããŗãšããããŽããģįŦŦä¸č
ããĄãŗãããŗãšããããŽãã¨ããŖããã¨ã¯č¤éæ§ãčããä¸ã§ã¯ãģã¨ããŠįĄčĻã§ããã¨ããįšã§ãã
|
||||
|
||||
ããĄããããŽåŽčŖ
ãMisskeyãĒãã¸ããĒãĢãããMisskeyããĄãŗãããŗãšããĒããã°ãĒããĒãããŽã¯ãäŋåŽãŽãŗãšãã¯ããããžãã
|
||||
ããããMisskeyãŽæŦčŗĒįãĒč¨č¨ãģåŽčŖ
ã¨ããčĻŗįšã§čĻãã¨ãã¯ãããŽåŽčŖ
ã¯åŽčŗĒįãĢå¤é¨ãŠã¤ããŠãĒãŽãããĢæ¯ãčããžãã
|
||||
æč¨ããã°ãããžããžMisskeyãŽéįēč
ã¨åãäēēããĄããĄãŗãããŗãšããĻããããããžããžMisskeyãŽãĒãã¸ããĒå
ãĢįŊŽããĻããã ããŽå¤é¨ãŠã¤ããŠãĒãã§ãã
|
||||
|
||||
ããŽãããåŽčŖ
ããĒããšãMisskeyãŽããĄã¤ãŗįĨčããįŦįĢããããŽãĢããã°ãMisskeyãŽãŗãŧãããŧãšãŽč¤éæ§ãä¸ãããã¨ãĒãæŠčŊåŽčŖ
ãčĄããã¨ãã§ãããåžã§ããã¨č¨ããžãã
|
||||
ããĄãããããĢãã ããŖãĻãäēį´°ãĒåŽčŖ
ã§ãããŽãããĢåéĸããĻããžãã¨ãããŖãĻčĒįĨč˛ čˇãåĸããããåŽčŖ
éãåĸããĻãĄãĒãããããĄãĒãããä¸åãå ´åããããŽã§ããąãŧãšãã¤ãąãŧãšã§ã¯ãããžãã
|
||||
|
||||
9
COPYING
9
COPYING
@@ -1,8 +1,15 @@
|
||||
Unless otherwise stated this repository is
|
||||
Copyright Š 2014-2026 syuilo and contributors
|
||||
Copyright Š 2014-2025 syuilo and contributors
|
||||
|
||||
And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE.
|
||||
|
||||
|
||||
Misskey includes several third-party Open-Source softwares.
|
||||
|
||||
Emoji keywords for Unicode 11 and below by Mu-An Chiou
|
||||
License: MIT
|
||||
https://github.com/muan/emojilib/blob/master/LICENSE
|
||||
|
||||
RsaSignature2017 implementation by Transmute Industries Inc
|
||||
License: MIT
|
||||
https://github.com/transmute-industries/RsaSignature2017/blob/master/LICENSE
|
||||
|
||||
13
Dockerfile
13
Dockerfile
@@ -1,6 +1,6 @@
|
||||
# syntax = docker/dockerfile:1.23
|
||||
# syntax = docker/dockerfile:1.4
|
||||
|
||||
ARG NODE_VERSION=22.22.2-bookworm
|
||||
ARG NODE_VERSION=22.11.0-bookworm
|
||||
|
||||
# build assets & compile TypeScript
|
||||
|
||||
@@ -18,14 +18,10 @@ WORKDIR /misskey
|
||||
|
||||
COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
|
||||
COPY --link ["scripts", "./scripts"]
|
||||
COPY --link ["patches", "./patches"]
|
||||
COPY --link ["packages/backend/package.json", "./packages/backend/"]
|
||||
COPY --link ["packages/frontend-shared/package.json", "./packages/frontend-shared/"]
|
||||
COPY --link ["packages/frontend/package.json", "./packages/frontend/"]
|
||||
COPY --link ["packages/frontend-embed/package.json", "./packages/frontend-embed/"]
|
||||
COPY --link ["packages/frontend-builder/package.json", "./packages/frontend-builder/"]
|
||||
COPY --link ["packages/i18n/package.json", "./packages/i18n/"]
|
||||
COPY --link ["packages/icons-subsetter/package.json", "./packages/icons-subsetter/"]
|
||||
COPY --link ["packages/sw/package.json", "./packages/sw/"]
|
||||
COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"]
|
||||
COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"]
|
||||
@@ -56,7 +52,6 @@ WORKDIR /misskey
|
||||
|
||||
COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
|
||||
COPY --link ["scripts", "./scripts"]
|
||||
COPY --link ["patches", "./patches"]
|
||||
COPY --link ["packages/backend/package.json", "./packages/backend/"]
|
||||
COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"]
|
||||
COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"]
|
||||
@@ -74,8 +69,6 @@ FROM --platform=$TARGETPLATFORM node:${NODE_VERSION}-slim AS runner
|
||||
ARG UID="991"
|
||||
ARG GID="991"
|
||||
|
||||
ENV PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN=false
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ffmpeg tini curl libjemalloc-dev libjemalloc2 \
|
||||
@@ -104,7 +97,7 @@ COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-js/
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-reversi/built ./packages/misskey-reversi/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-bubble-game/built ./packages/misskey-bubble-game/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/built ./packages/backend/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/i18n/built ./packages/i18n/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/fluent-emojis /misskey/fluent-emojis
|
||||
COPY --chown=misskey:misskey . ./
|
||||
|
||||
ENV LD_PRELOAD=/usr/local/lib/libjemalloc.so
|
||||
|
||||
14
README.md
14
README.md
@@ -24,10 +24,6 @@
|
||||
<a href="https://www.patreon.com/syuilo">
|
||||
<img src="https://custom-icon-badges.herokuapp.com/badge/become_a-patron-F96854?logoColor=F96854&style=for-the-badge&logo=patreon&labelColor=363B40" alt="become a patron"/></a>
|
||||
|
||||
[](https://deepwiki.com/misskey-dev/misskey)
|
||||
|
||||
<a href="https://flatt.tech/oss/gmo/trampoline" target="_blank"><img src="https://flatt.tech/assets/images/badges/gmo-oss.svg" height="24px"/></a>
|
||||
|
||||
</div>
|
||||
|
||||
## Thanks
|
||||
@@ -51,13 +47,3 @@ Thanks to [Crowdin](https://crowdin.com/) for providing the localization platfor
|
||||
<a href="https://hub.docker.com/"><img src="https://user-images.githubusercontent.com/20679825/230148221-f8e73a32-a49b-47c3-9029-9a15c3824f92.png" height="30" alt="Docker" /></a>
|
||||
|
||||
Thanks to [Docker](https://hub.docker.com/) for providing the container platform that helps us run Misskey in production.
|
||||
|
||||
---
|
||||
|
||||
<div align="center">
|
||||
|
||||
Support us with a â !
|
||||
|
||||
[](https://star-history.com/#misskey-dev/misskey&Date)
|
||||
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,7 @@ Also, the later tasks are more indefinite and are subject to change as developme
|
||||
This is the phase we are at now. We need to make a high-maintenance environment that can withstand future development.
|
||||
|
||||
- ~~Make the number of type errors zero (backend)~~ â Done âī¸
|
||||
- ~~Make the number of type errors zero (frontend)~~ â Done âī¸
|
||||
- Make the number of type errors zero (frontend)
|
||||
- Improve CI
|
||||
- ~~Fix tests~~ â Done âī¸
|
||||
- Fix random test failures - https://github.com/misskey-dev/misskey/issues/7985 and https://github.com/misskey-dev/misskey/issues/7986
|
||||
|
||||
BIN
assets/about/drive.png
Normal file
BIN
assets/about/drive.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 94 KiB |
BIN
assets/about/post.png
Normal file
BIN
assets/about/post.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 317 KiB |
BIN
assets/about/reaction.png
Normal file
BIN
assets/about/reaction.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
BIN
assets/about/ui.png
Normal file
BIN
assets/about/ui.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
BIN
assets/ss/explore.jpg
Normal file
BIN
assets/ss/explore.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 238 KiB |
BIN
assets/ss/user.jpg
Normal file
BIN
assets/ss/user.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 148 KiB |
Binary file not shown.
@@ -173,11 +173,6 @@ id: "aidx"
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
#sentryForFrontend:
|
||||
# vueIntegration:
|
||||
# tracingOptions:
|
||||
# trackComponents: true
|
||||
# browserTracingIntegration:
|
||||
# replayIntegration:
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
@@ -190,9 +185,6 @@ id: "aidx"
|
||||
# Number of worker processes
|
||||
#clusterLimit: 1
|
||||
|
||||
# Number of threads of extra thread pool for CPU-intensive tasks (per worker)
|
||||
#threadPoolSize: 1
|
||||
|
||||
# Job concurrency per worker
|
||||
# deliverJobConcurrency: 128
|
||||
# inboxJobConcurrency: 16
|
||||
@@ -224,6 +216,9 @@ id: "aidx"
|
||||
# Media Proxy
|
||||
#mediaProxy: https://example.com/proxy
|
||||
|
||||
# Sign to ActivityPub GET request (default: true)
|
||||
signToActivityPubGet: true
|
||||
|
||||
#allowedPrivateNetworks: [
|
||||
# '127.0.0.1/32'
|
||||
#]
|
||||
|
||||
@@ -27,7 +27,7 @@ spec:
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
- name: postgres
|
||||
image: postgres:18-alpine
|
||||
image: postgres:15-alpine
|
||||
env:
|
||||
- name: POSTGRES_USER
|
||||
value: "example-misskey-user"
|
||||
|
||||
@@ -15,13 +15,13 @@ services:
|
||||
|
||||
db:
|
||||
restart: always
|
||||
image: postgres:18-alpine
|
||||
image: postgres:15-alpine
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env_file:
|
||||
- .config/docker.env
|
||||
volumes:
|
||||
- ./db:/var/lib/postgresql
|
||||
- ./db:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
|
||||
interval: 5s
|
||||
|
||||
@@ -37,13 +37,13 @@ services:
|
||||
|
||||
db:
|
||||
restart: always
|
||||
image: postgres:18-alpine
|
||||
image: postgres:15-alpine
|
||||
networks:
|
||||
- internal_network
|
||||
env_file:
|
||||
- .config/docker.env
|
||||
volumes:
|
||||
- ./db:/var/lib/postgresql
|
||||
- ./db:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
|
||||
interval: 5s
|
||||
|
||||
@@ -2,6 +2,11 @@ import { defineConfig } from 'cypress'
|
||||
|
||||
export default defineConfig({
|
||||
e2e: {
|
||||
// We've imported your old cypress plugins here.
|
||||
// You may want to clean this up later by importing these.
|
||||
setupNodeEvents(on, config) {
|
||||
return require('./cypress/plugins/index.js')(on, config)
|
||||
},
|
||||
baseUrl: 'http://localhost:61812',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -31,14 +31,6 @@ describe('Before setup instance', () => {
|
||||
// ãĒããåããĒã
|
||||
//cy.wait('@signup').should('have.property', 'response.statusCode');
|
||||
cy.wait('@signup');
|
||||
|
||||
cy.intercept('POST', '/api/admin/update-meta').as('update-meta');
|
||||
|
||||
cy.get('[data-cy-next]').click();
|
||||
cy.get('[data-cy-server-name] input').type('Testskey');
|
||||
cy.get('[data-cy-server-setup-wizard-apply]').click();
|
||||
|
||||
cy.wait('@update-meta');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -78,8 +70,6 @@ describe('After setup instance', () => {
|
||||
cy.get('[data-cy-signup-password] input').type('alice1234');
|
||||
cy.get('[data-cy-signup-submit]').should('be.disabled');
|
||||
cy.get('[data-cy-signup-password-retype] input').type('alice1234');
|
||||
cy.get('[data-cy-signup-submit]').should('be.disabled');
|
||||
cy.get('[data-cy-signup-invitation-code] input').type('test-invitation-code');
|
||||
cy.get('[data-cy-signup-submit]').should('not.be.disabled');
|
||||
cy.get('[data-cy-signup-submit]').click();
|
||||
|
||||
|
||||
22
cypress/plugins/index.js
Normal file
22
cypress/plugins/index.js
Normal file
@@ -0,0 +1,22 @@
|
||||
/// <reference types="cypress" />
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["dom"],
|
||||
"target": "esnext",
|
||||
"lib": ["dom", "es5"],
|
||||
"target": "es5",
|
||||
"types": ["cypress", "node"]
|
||||
},
|
||||
"include": ["./**/*.ts"]
|
||||
|
||||
1
fluent-emojis
Submodule
1
fluent-emojis
Submodule
Submodule fluent-emojis added at cae981eb4c
@@ -4,8 +4,8 @@
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
import { action } from 'storybook/actions';
|
||||
import type { StoryObj } from '@storybook/vue3';
|
||||
import { action } from '@storybook/addon-actions';
|
||||
import { StoryObj } from '@storybook/vue3';
|
||||
import { HttpResponse, http } from 'msw';
|
||||
import { abuseUserReport } from '../packages/frontend/.storybook/fakes.js';
|
||||
import { commonHandlers } from '../packages/frontend/.storybook/mocks.js';
|
||||
|
||||
@@ -1,232 +0,0 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<canvas ref="canvasEl" style="display: block; width: 100%; height: 100%; pointer-events: none;"></canvas>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, useTemplateRef } from 'vue';
|
||||
import isChromatic from 'chromatic/isChromatic';
|
||||
import { initShaderProgram } from '@/utility/webgl.js';
|
||||
|
||||
const VERTEX_SHADER = `#version 300 es
|
||||
in vec2 position;
|
||||
out vec2 in_uv;
|
||||
|
||||
void main() {
|
||||
in_uv = (position + 1.0) / 2.0;
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const FRAGMENT_SHADER = `#version 300 es
|
||||
precision mediump float;
|
||||
|
||||
const float PI = 3.141592653589793;
|
||||
const float TWO_PI = 6.283185307179586;
|
||||
const float HALF_PI = 1.5707963267948966;
|
||||
|
||||
in vec2 in_uv;
|
||||
uniform vec2 in_resolution;
|
||||
uniform float u_scale;
|
||||
uniform float u_time;
|
||||
uniform float u_seed;
|
||||
uniform float u_angle;
|
||||
uniform float u_radius;
|
||||
uniform vec3 u_color;
|
||||
uniform vec2 u_ripplePositions[16];
|
||||
uniform float u_rippleRadiuses[16];
|
||||
out vec4 out_color;
|
||||
|
||||
float getRipple(vec2 uv) {
|
||||
float strength = 0.0;
|
||||
float thickness = 0.05;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (u_rippleRadiuses[i] <= 0.0) continue;
|
||||
|
||||
float d = distance(uv, u_ripplePositions[i]);
|
||||
|
||||
// ãã
|
||||
if (d < u_rippleRadiuses[i] + thickness && d > u_rippleRadiuses[i] - thickness) {
|
||||
float gradate = abs(d - u_rippleRadiuses[i] + thickness) / thickness;
|
||||
strength += (1.0 - u_rippleRadiuses[i]) * gradate;
|
||||
}
|
||||
|
||||
// å
å´
|
||||
if (d < u_rippleRadiuses[i] + thickness) {
|
||||
strength += 0.25 * (1.0 - u_rippleRadiuses[i]);
|
||||
}
|
||||
}
|
||||
return strength;
|
||||
}
|
||||
|
||||
void main() {
|
||||
float x_ratio = min(in_resolution.x / in_resolution.y, 1.0);
|
||||
float y_ratio = min(in_resolution.y / in_resolution.x, 1.0);
|
||||
|
||||
float angle = -(u_angle * PI);
|
||||
vec2 centeredUv = (in_uv - vec2(0.5, 0.5)) * vec2(x_ratio, y_ratio);
|
||||
vec2 rotatedUV = vec2(
|
||||
centeredUv.x * cos(angle) - centeredUv.y * sin(angle),
|
||||
centeredUv.x * sin(angle) + centeredUv.y * cos(angle)
|
||||
);
|
||||
vec2 uv = rotatedUV;
|
||||
|
||||
float time = u_time * 0.00025;
|
||||
|
||||
float size = 1.0 / u_scale;
|
||||
float size_half = size / 2.0;
|
||||
float modX = mod(uv.x, size);
|
||||
float modY = mod(uv.y, size);
|
||||
|
||||
vec2 pixelated_uv = vec2(
|
||||
(size * (floor((uv.x - 0.5 - size) / size) + 0.5)),
|
||||
(size * (floor((uv.y - 0.5 - size) / size) + 0.5))
|
||||
) + vec2(0.5 + size, 0.5 + size);
|
||||
|
||||
float strength = getRipple(pixelated_uv);
|
||||
|
||||
float opacity = min(max(strength, 0.0), 1.0);
|
||||
|
||||
float threshold = ((u_radius / 2.0) / u_scale);
|
||||
if (length(vec2(modX - size_half, modY - size_half)) < threshold) {
|
||||
out_color = vec4(u_color.r, u_color.g, u_color.b, opacity);
|
||||
//out_color = vec4(1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
// debug
|
||||
//float a = min(max(getRipple(uv), 0.0), 1.0);
|
||||
//out_color = vec4(u_color.r, u_color.g, u_color.b, (opacity + a) / 2.0);
|
||||
|
||||
out_color = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const canvasEl = useTemplateRef('canvasEl');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
scale?: number;
|
||||
}>(), {
|
||||
scale: 48,
|
||||
});
|
||||
|
||||
let handle: ReturnType<typeof window['requestAnimationFrame']> | null = null;
|
||||
|
||||
onMounted(() => {
|
||||
const canvas = canvasEl.value!;
|
||||
let width = canvas.offsetWidth;
|
||||
let height = canvas.offsetHeight;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
const maybeGl = canvas.getContext('webgl2', { preserveDrawingBuffer: false, alpha: true, premultipliedAlpha: false, antialias: true });
|
||||
if (maybeGl == null) return;
|
||||
|
||||
const gl = maybeGl;
|
||||
|
||||
const VERTICES = new Float32Array([-1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1]);
|
||||
const vertexBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, VERTICES, gl.STATIC_DRAW);
|
||||
|
||||
//gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||
//gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
const shaderProgram = initShaderProgram(gl, VERTEX_SHADER, FRAGMENT_SHADER);
|
||||
|
||||
gl.useProgram(shaderProgram);
|
||||
|
||||
const positionLocation = gl.getAttribLocation(shaderProgram, 'position');
|
||||
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(positionLocation);
|
||||
|
||||
const in_resolution = gl.getUniformLocation(shaderProgram, 'in_resolution');
|
||||
gl.uniform2fv(in_resolution, [canvas.width, canvas.height]);
|
||||
|
||||
const u_time = gl.getUniformLocation(shaderProgram, 'u_time');
|
||||
const u_seed = gl.getUniformLocation(shaderProgram, 'u_seed');
|
||||
const u_scale = gl.getUniformLocation(shaderProgram, 'u_scale');
|
||||
const u_angle = gl.getUniformLocation(shaderProgram, 'u_angle');
|
||||
const u_radius = gl.getUniformLocation(shaderProgram, 'u_radius');
|
||||
const u_color = gl.getUniformLocation(shaderProgram, 'u_color');
|
||||
gl.uniform1f(u_seed, Math.random() * 1000);
|
||||
gl.uniform1f(u_scale, props.scale);
|
||||
gl.uniform1f(u_angle, 0.0);
|
||||
gl.uniform1f(u_radius, 0.15);
|
||||
gl.uniform3fv(u_color, [0.5, 1.0, 0]);
|
||||
|
||||
if (isChromatic()) {
|
||||
gl.uniform1f(u_time, 0);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
} else {
|
||||
let ripples = [] as { position: [number, number]; startTime: number; }[];
|
||||
const LIFE_TIME = 1000 * 4;
|
||||
|
||||
function render(timeStamp: number) {
|
||||
let sizeChanged = false;
|
||||
if (Math.abs(height - canvas.offsetHeight) > 2) {
|
||||
height = canvas.offsetHeight;
|
||||
canvas.height = height;
|
||||
sizeChanged = true;
|
||||
}
|
||||
if (Math.abs(width - canvas.offsetWidth) > 2) {
|
||||
width = canvas.offsetWidth;
|
||||
canvas.width = width;
|
||||
sizeChanged = true;
|
||||
}
|
||||
if (sizeChanged && gl) {
|
||||
gl.uniform2fv(in_resolution, [width, height]);
|
||||
gl.viewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
gl.uniform1f(u_time, timeStamp);
|
||||
|
||||
if (Math.random() < 0.01 && ripples.length < 16) {
|
||||
ripples.push({ position: [(Math.random() * 2) - 1, (Math.random() * 2) - 1], startTime: timeStamp });
|
||||
}
|
||||
|
||||
for (let i = 0; i < 16; i++) {
|
||||
const o = gl.getUniformLocation(shaderProgram, `u_ripplePositions[${i.toString()}]`);
|
||||
const r = gl.getUniformLocation(shaderProgram, `u_rippleRadiuses[${i.toString()}]`);
|
||||
const ripple = ripples[i];
|
||||
if (ripple == null) {
|
||||
gl.uniform2f(o, 0, 0);
|
||||
gl.uniform1f(r, 0.0);
|
||||
continue;
|
||||
}
|
||||
|
||||
const delta = timeStamp - ripple.startTime;
|
||||
|
||||
gl.uniform2f(o, ripple.position[0], ripple.position[1]);
|
||||
gl.uniform1f(r, delta / LIFE_TIME);
|
||||
}
|
||||
|
||||
ripples = ripples.filter(r => (timeStamp - r.startTime) < LIFE_TIME);
|
||||
if (ripples.length === 0) {
|
||||
ripples.push({ position: [(Math.random() * 2) - 1, (Math.random() * 2) - 1], startTime: timeStamp });
|
||||
}
|
||||
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
|
||||
handle = window.requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
handle = window.requestAnimationFrame(render);
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (handle) {
|
||||
window.cancelAnimationFrame(handle);
|
||||
}
|
||||
|
||||
// TODO: WebGLãĒãŊãŧãšãŽč§Ŗæž
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
</style>
|
||||
@@ -1,190 +0,0 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<canvas ref="canvasEl" style="display: block; width: 100%; height: 100%; pointer-events: none;"></canvas>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, useTemplateRef } from 'vue';
|
||||
import isChromatic from 'chromatic/isChromatic';
|
||||
import { GLSL_LIB_SNOISE, initShaderProgram } from '@/utility/webgl.js';
|
||||
|
||||
const VERTEX_SHADER = `#version 300 es
|
||||
in vec2 position;
|
||||
out vec2 in_uv;
|
||||
|
||||
void main() {
|
||||
in_uv = (position + 1.0) / 2.0;
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const FRAGMENT_SHADER = `#version 300 es
|
||||
precision mediump float;
|
||||
|
||||
const float PI = 3.141592653589793;
|
||||
const float TWO_PI = 6.283185307179586;
|
||||
const float HALF_PI = 1.5707963267948966;
|
||||
|
||||
${GLSL_LIB_SNOISE}
|
||||
|
||||
in vec2 in_uv;
|
||||
uniform vec2 in_resolution;
|
||||
uniform float u_scale;
|
||||
uniform float u_time;
|
||||
uniform float u_seed;
|
||||
uniform float u_angle;
|
||||
uniform float u_radius;
|
||||
uniform vec3 u_color;
|
||||
out vec4 out_color;
|
||||
|
||||
void main() {
|
||||
float x_ratio = min(in_resolution.x / in_resolution.y, 1.0);
|
||||
float y_ratio = min(in_resolution.y / in_resolution.x, 1.0);
|
||||
|
||||
float size = 1.0 / u_scale;
|
||||
float size_half = size / 2.0;
|
||||
|
||||
float angle = -(u_angle * PI);
|
||||
vec2 centeredUv = (in_uv - vec2(0.5, 0.5)) * vec2(x_ratio, y_ratio);
|
||||
vec2 rotatedUV = vec2(
|
||||
centeredUv.x * cos(angle) - centeredUv.y * sin(angle),
|
||||
centeredUv.x * sin(angle) + centeredUv.y * cos(angle)
|
||||
);
|
||||
vec2 uv = rotatedUV;
|
||||
|
||||
float modX = mod(uv.x, size);
|
||||
float modY = mod(uv.y, size);
|
||||
|
||||
vec2 pixelated_uv = vec2(
|
||||
(size * (floor((uv.x - 0.5 - size) / size) + 0.5)),
|
||||
(size * (floor((uv.y - 0.5 - size) / size) + 0.5))
|
||||
) + vec2(0.5 + size, 0.5 + size);
|
||||
|
||||
float time = u_time * 0.00025;
|
||||
|
||||
float noiseAScale = 1.0;
|
||||
float noiseAX = (pixelated_uv.x + u_seed) * (u_scale / noiseAScale);
|
||||
float noiseAY = (pixelated_uv.y + u_seed) * (u_scale / noiseAScale);
|
||||
float noiseA = snoise(vec3(noiseAX, noiseAY, time * 2.0));
|
||||
|
||||
float noiseBScale = 32.0;
|
||||
float noiseBX = (pixelated_uv.x + u_seed) * (u_scale / noiseBScale);
|
||||
float noiseBY = (pixelated_uv.y + u_seed) * (u_scale / noiseBScale);
|
||||
float noiseB = snoise(vec3(noiseBX, noiseBY, time));
|
||||
|
||||
float strength = 0.0;
|
||||
strength += noiseA * 0.2;
|
||||
strength += noiseB * 0.8;
|
||||
|
||||
float opacity = min(max(strength, 0.0), 1.0);
|
||||
|
||||
float threshold = ((u_radius / 2.0) / u_scale);
|
||||
if (length(vec2(modX - size_half, modY - size_half)) < threshold) {
|
||||
out_color = vec4(u_color.r, u_color.g, u_color.b, opacity);
|
||||
return;
|
||||
}
|
||||
|
||||
out_color = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const canvasEl = useTemplateRef('canvasEl');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
scale?: number;
|
||||
}>(), {
|
||||
scale: 48,
|
||||
});
|
||||
|
||||
let handle: ReturnType<typeof window['requestAnimationFrame']> | null = null;
|
||||
|
||||
onMounted(() => {
|
||||
const canvas = canvasEl.value!;
|
||||
let width = canvas.offsetWidth;
|
||||
let height = canvas.offsetHeight;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
const maybeGl = canvas.getContext('webgl2', { preserveDrawingBuffer: false, alpha: true, premultipliedAlpha: false, antialias: true });
|
||||
if (maybeGl == null) return;
|
||||
|
||||
const gl = maybeGl;
|
||||
|
||||
const VERTICES = new Float32Array([-1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1]);
|
||||
const vertexBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, VERTICES, gl.STATIC_DRAW);
|
||||
|
||||
//gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||
//gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
const shaderProgram = initShaderProgram(gl, VERTEX_SHADER, FRAGMENT_SHADER);
|
||||
|
||||
gl.useProgram(shaderProgram);
|
||||
|
||||
const positionLocation = gl.getAttribLocation(shaderProgram, 'position');
|
||||
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(positionLocation);
|
||||
|
||||
const in_resolution = gl.getUniformLocation(shaderProgram, 'in_resolution');
|
||||
gl.uniform2fv(in_resolution, [canvas.width, canvas.height]);
|
||||
|
||||
const u_time = gl.getUniformLocation(shaderProgram, 'u_time');
|
||||
const u_seed = gl.getUniformLocation(shaderProgram, 'u_seed');
|
||||
const u_scale = gl.getUniformLocation(shaderProgram, 'u_scale');
|
||||
const u_angle = gl.getUniformLocation(shaderProgram, 'u_angle');
|
||||
const u_radius = gl.getUniformLocation(shaderProgram, 'u_radius');
|
||||
const u_color = gl.getUniformLocation(shaderProgram, 'u_color');
|
||||
gl.uniform1f(u_seed, Math.random() * 1000);
|
||||
gl.uniform1f(u_scale, props.scale);
|
||||
gl.uniform1f(u_angle, 0.0);
|
||||
gl.uniform1f(u_radius, 0.15);
|
||||
gl.uniform3fv(u_color, [0.5, 1.0, 0]);
|
||||
|
||||
if (isChromatic()) {
|
||||
gl.uniform1f(u_time, 0);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
} else {
|
||||
function render(timeStamp: number) {
|
||||
let sizeChanged = false;
|
||||
if (Math.abs(height - canvas.offsetHeight) > 2) {
|
||||
height = canvas.offsetHeight;
|
||||
canvas.height = height;
|
||||
sizeChanged = true;
|
||||
}
|
||||
if (Math.abs(width - canvas.offsetWidth) > 2) {
|
||||
width = canvas.offsetWidth;
|
||||
canvas.width = width;
|
||||
sizeChanged = true;
|
||||
}
|
||||
if (sizeChanged && gl) {
|
||||
gl.uniform2fv(in_resolution, [width, height]);
|
||||
gl.viewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
gl.uniform1f(u_time, timeStamp);
|
||||
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
|
||||
handle = window.requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
handle = window.requestAnimationFrame(render);
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (handle) {
|
||||
window.cancelAnimationFrame(handle);
|
||||
}
|
||||
|
||||
// TODO: WebGLãĒãŊãŧãšãŽč§Ŗæž
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
</style>
|
||||
@@ -68,7 +68,7 @@ receiveFollowRequest: "ØĒŲŲŲØĒ ØˇŲØ¨ Ų
ØĒابؚ؊"
|
||||
followRequestAccepted: "ŲŲØ¨Ų ØˇŲØ¨ اŲŲ
ØĒابؚ؊"
|
||||
mention: "ØŖØ´Øą اŲŲ"
|
||||
mentions: "Ø§ŲØĨØ´Ø§ØąØ§ØĒ"
|
||||
directNotes: "ØąØŗØ§ŲØŠ ØŽØ§ØĩØŠ"
|
||||
directNotes: "اŲŲ
ŲØ§ØØ¸Ø§ØĒ اŲŲ
Ø¨Ø§Ø´ØąØŠ"
|
||||
importAndExport: "ØĨØŗØĒبਝ / ØĩØ¯Øą"
|
||||
import: "Ø§ØŗØĒŲØąØ§Ø¯"
|
||||
export: "ØĒØĩØ¯ŲØą"
|
||||
@@ -215,6 +215,7 @@ noUsers: "ŲŲØŗ ŲŲØ§Ų Ų
ØŗØĒ؎دŲ
ŲŲ"
|
||||
editProfile: "ØĒؚدŲŲ Ø§ŲŲ
ŲŲ Ø§ŲØĒØšØąŲŲŲ"
|
||||
noteDeleteConfirm: "ŲŲ ØĒØąŲØ¯ ØØ°Ų ŲØ°Ų اŲŲ
ŲØ§ØØ¸ØŠØ"
|
||||
pinLimitExceeded: "ŲØ§ ŲŲ
ŲŲŲ ØĒØĢØ¨ŲØĒ Ø§ŲŲ
ŲØ§ØØ¸Ø§ØĒ بؚد Ø§ŲØĸŲ."
|
||||
intro: "ŲŲØ¯ Ø§ŲØĒŲØĒ ØšŲ
ŲŲØŠ ØĒŲØĩŲØ¨ Misskey. Ø§ŲØąØŦØ§ØĄ ØĨŲØ´Ø§ØĄ ØØŗØ§Ø¨ ØĨØ¯Ø§ØąŲ."
|
||||
done: "ØĒŲ
Ų"
|
||||
processing: "اŲŲ
ØšØ§ŲØŦØŠ ØŦØ§ØąŲØŠ"
|
||||
preview: "Ų
ؚاŲŲØŠ"
|
||||
@@ -250,6 +251,7 @@ removeAreYouSure: "Ų
ØĒØŖŲØ¯ Ų
Ų ØŖŲŲ ØĒØąŲØ¯ ØØ°Ų {x}Ø"
|
||||
deleteAreYouSure: "Ų
ØĒØŖŲØ¯ Ų
Ų ØŖŲŲ ØĒØąŲØ¯ ØØ°Ų {x}Ø"
|
||||
resetAreYouSure: "ŲŲ ØĒØąŲØ¯ ØĨؚاد؊ Ø§ŲØĒØšŲŲŲØ"
|
||||
saved: "ØŲŲØ¸"
|
||||
messaging: "اŲŲ
ØØ§Ø¯ØĢØŠ"
|
||||
upload: "Ø§ØąŲØš"
|
||||
keepOriginalUploading: "Ø§Ø¨Ų Ø§ŲØĩŲØąØŠ Ø§ŲØŖØĩŲŲØŠ"
|
||||
keepOriginalUploadingDescription: "ŲØŲØ¸ Ø§ŲØĩŲØą Ø§ŲŲ
ØąŲŲØšØŠ ØšŲŲ ØØ§ŲØĒŲØ§ Ø§ŲØŖØĩŲŲØŠØ ŲØ§Ų ØšØˇŲŲ ØŗØĒŲŲØ¯ ŲØŗØŽØŠ Ų
ØŽØĩØĩØŠ Ų
Ų Ø§ŲØĩŲØąØŠ."
|
||||
@@ -262,6 +264,7 @@ uploadFromUrlMayTakeTime: "ØŗŲØŗØĒØēØąŲ Ø¨ØšØļ اŲŲŲØĒ ŲØ§ØĒŲ
اŲ
Ø§ŲØą
|
||||
explore: "Ø§ØŗØĒŲØ´Ø§Ų"
|
||||
messageRead: "Ų
ŲØąŲØĄØŠ"
|
||||
noMoreHistory: "ŲØ§ ŲŲØŦد اŲŲ
Ø˛ŲØ¯ Ų
Ų Ø§ŲØĒØ§ØąŲØŽ"
|
||||
startMessaging: "Ø§Ø¨Ø¯ØŖ Ų
ØØ§Ø¯ØĢØŠ"
|
||||
nUsersRead: "ŲØąØŖŲ {n}"
|
||||
agreeTo: "Ø§ŲØ§ŲŲ ØšŲŲ {0}"
|
||||
agree: "ØŖŲØ¨Ų"
|
||||
@@ -433,6 +436,8 @@ retype: "ØŖØšØ¯ اŲŲØĒØ§Ø¨ØŠ"
|
||||
noteOf: "Ų
ŲØ§ØØ¸Ø§ØĒ {user}"
|
||||
quoteAttached: "اŲŲØĒŲØ¨ØŗŲ"
|
||||
quoteQuestion: "ØŖØĒØąŲØ¯ ØĒØļŲ
ŲŲŲØ§ ŲØ§ŲØĒØ¨Ø§Øŗ"
|
||||
noMessagesYet: "ŲŲØŗ ŲŲØ§Ų ØąØŗØ§ØĻŲ Ø¨ØšØ¯"
|
||||
newMessageExists: "ŲŲØ¯ ØĒŲŲŲØĒ ØąØŗØ§ŲØŠ ØŦØ¯ŲØ¯ØŠ"
|
||||
onlyOneFileCanBeAttached: "ŲŲ
ŲŲŲ ØĨØąŲØ§Ų Ų
ŲŲ ŲØ§ØØ¯ Ø¨Ø§ŲØąØŗØ§ŲØŠ"
|
||||
signinRequired: "ØąØŦØ§ØĄŲ ŲŲØŦ"
|
||||
invitations: "Ø¯ØšŲØŠ"
|
||||
@@ -675,6 +680,7 @@ experimental: "ا؎ØĒØ¨Ø§ØąŲ"
|
||||
developer: "اŲŲ
ØˇŲØą"
|
||||
makeExplorable: "ØŖØ¸ŲØą Ø§ŲØØŗØ§Ø¨ ŲŲ ØĩŲØØŠ \"Ø§ØŗØĒŲØ´Ø§Ų\""
|
||||
makeExplorableDescription: "بØĒØšØˇŲŲ ŲØ°Ø§ Ø§ŲØŽŲØ§Øą ŲŲ ŲØ¸ŲØą ØØŗØ§Ø¨Ų ŲŲ ØĩŲØØŠ \"Ø§ØŗØĒŲØ´Ø§Ų\""
|
||||
showGapBetweenNotesInTimeline: "ØŖØ¸ŲØą ŲØŦŲØ§ØĒ بŲŲ Ø§ŲŲ
Ø´Ø§ØąŲØ§ØĒ ŲŲ Ø§ŲØŽŲØˇ Ø§ŲØ˛Ų
ŲŲ"
|
||||
left: "ŲØŗØ§Øą"
|
||||
center: "ŲØŗØˇ"
|
||||
wide: "ØšØąŲØļ"
|
||||
@@ -1006,25 +1012,6 @@ sourceCode: "Ø§ŲØ´ŲØąØŠ اŲŲ
ØĩØ¯ØąŲØŠ"
|
||||
flip: "اŲŲØ¨"
|
||||
lastNDays: "ØĸØŽØą {n} ØŖŲØ§Ų
"
|
||||
surrender: "ØŖŲØēŲ"
|
||||
postForm: "ØŖŲØ´ØĻ Ų
ŲØ§ØØ¸ØŠ"
|
||||
information: "ØšŲ"
|
||||
inMinutes: "د"
|
||||
inDays: "Ų"
|
||||
widgets: "Ø§ŲØĒØˇØ¨ŲŲØ§ØĒ اŲŲ
ŲØĩØēŲØąØŠ"
|
||||
presets: "ØĨؚداداØĒ Ų
ØŗØ¨ŲØŠ"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
filename: "Ø§ØŗŲ
اŲŲ
ŲŲ"
|
||||
_imageFrameEditor:
|
||||
font: "Ø§ŲØŽØˇ"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
_chat:
|
||||
invitations: "Ø¯ØšŲØŠ"
|
||||
noHistory: "Ø§ŲØŗØŦŲ ŲØ§ØąØē"
|
||||
members: "Ø§ŲØŖØšØļØ§ØĄ"
|
||||
home: "Ø§ŲØąØĻŲØŗŲ"
|
||||
send: "ØŖØąØŗŲ"
|
||||
_delivery:
|
||||
stop: "Ų
ŲØšŲŲŲ"
|
||||
_initialAccountSetting:
|
||||
@@ -1249,6 +1236,7 @@ _theme:
|
||||
shadow: "Ø§ŲØ¸Ų"
|
||||
navBg: "ØŽŲŲŲØŠ Ø§ŲØ´ØąŲØˇ Ø§ŲØŦØ§ŲØ¨Ų"
|
||||
navFg: "ŲØĩ Ø§ŲØ´ØąŲØˇ Ø§ŲØŦØ§ŲØ¨Ų"
|
||||
navHoverFg: "ŲØĩ Ø§ŲØ´ØąŲØˇ Ø§ŲØŦØ§ŲØ¨Ų (ØšŲØ¯ Ø§ŲØĒŲ
ØąŲØą ŲŲŲŲ)"
|
||||
link: "ØąØ§Ø¨Øˇ"
|
||||
hashtag: "ŲØŗŲ
"
|
||||
mention: "ØŖØ´Øą اŲŲ"
|
||||
@@ -1263,6 +1251,7 @@ _theme:
|
||||
buttonBg: "ØŽŲŲŲØŠ Ø§ŲØŖØ˛ØąØ§Øą"
|
||||
buttonHoverBg: "ØŽŲŲŲØŠ Ø§ŲØŖØ˛ØąØ§Øą (ØšŲØ¯ Ø§ŲØĒŲ
ØąŲØą ŲŲŲŲØ§)"
|
||||
inputBorder: "ØŲØ§Ų ØŲŲ Ø§ŲØĨد؎اŲ"
|
||||
driveFolderBg: "ØŽŲŲŲØŠ Ų
ØŦŲØ¯ ŲØąØĩ Ø§ŲØĒØŽØ˛ŲŲ"
|
||||
messageBg: "ØŽŲŲŲØŠ Ø§ŲŲ
ØØ§Ø¯ØĢØŠ"
|
||||
_sfx:
|
||||
note: "اŲŲ
ŲØ§ØØ¸Ø§ØĒ"
|
||||
@@ -1322,7 +1311,6 @@ _permissions:
|
||||
"read:gallery": "Ø§ØšØąØļ اŲŲ
ØšØąØļ"
|
||||
"write:gallery": "ؚدŲŲ Ø§ŲŲ
ØšØąØļ"
|
||||
"read:gallery-likes": "ŲØšØąØļ Ų
ا ØŖØšØŦØ¨Ų Ų
Ų Ų
Ø´Ø§ØąŲØ§ØĒ اŲŲ
ØšØąØļ"
|
||||
"write:chat": "Ø§ŲØĒØ¨ ØŖŲ Ø§ØØ°Ų ØąØŗØ§ØĻŲ Ų
ØØ§Ø¯ØĢØŠ"
|
||||
_auth:
|
||||
shareAccess: "ØŖØĒØąŲØ¯ Ø§ŲØĒŲŲŲØļ ŲŲ \"{name}\" باŲŲØĩŲŲ ŲØØŗØ§Ø¨ŲØ"
|
||||
shareAccessAsk: "ŲŲ ØĒØŽŲŲ ŲŲØ°Ø§ Ø§ŲØĒØˇØ¨ŲŲ Ø§ŲŲØĩŲŲ ŲØØŗØ§Ø¨ŲØ"
|
||||
@@ -1365,14 +1353,6 @@ _widgets:
|
||||
userList: "ŲØ§ØĻŲ
ØŠ اŲŲ
ØŗØĒ؎دŲ
ŲŲ"
|
||||
_userList:
|
||||
chooseList: "ا؎ØĒØą ŲØ§ØĻŲ
ØŠ"
|
||||
_widgetOptions:
|
||||
height: "Ø§ŲØĨØąØĒŲØ§Øš"
|
||||
_button:
|
||||
colored: "Ų
ŲŲŲŲ"
|
||||
_clock:
|
||||
size: "Ø§ŲØØŦŲ
"
|
||||
_birthdayFollowings:
|
||||
period: "اŲŲ
د؊"
|
||||
_cw:
|
||||
hide: "ØĨØŽŲØ§ØĄ"
|
||||
show: "ØšØąØļ اŲŲ
Ø˛ŲØ¯"
|
||||
@@ -1413,9 +1393,6 @@ _postForm:
|
||||
replyPlaceholder: "ØąØ¯ ØšŲŲ ŲØ°Ų اŲŲ
ŲØ§ØØ¸ØŠâĻ"
|
||||
quotePlaceholder: "Ø§ŲØĒØ¨Øŗ ŲØ°Ų اŲŲ
ŲØ§ØØ¸ØŠâĻ"
|
||||
channelPlaceholder: "Ø§ŲØ´Øą ŲŲ ŲŲØ§ØŠ..."
|
||||
_howToUse:
|
||||
visibility_title: "Ø§ŲØ¸ŲŲØą"
|
||||
menu_title: "اŲŲØ§ØĻŲ
ØŠ"
|
||||
_placeholders:
|
||||
a: "Ų
ا Ø§ŲØ°Ų ØĒŲŲŲ ŲØšŲŲØ"
|
||||
b: "Ų
اذا ŲØØ¯ØĢ ØŲŲŲ Ø"
|
||||
@@ -1611,21 +1588,3 @@ _search:
|
||||
searchScopeAll: "اŲŲŲ"
|
||||
searchScopeLocal: "اŲŲ
ØŲŲ"
|
||||
searchScopeUser: "Ų
ØŗØĒ؎دŲ
Ų
ØØ¯Ø¯"
|
||||
_watermarkEditor:
|
||||
opacity: "Ø§ŲØ´ŲاŲŲØŠ"
|
||||
scale: "Ø§ŲØØŦŲ
"
|
||||
text: "ŲØĩ"
|
||||
position: "اŲŲ
ŲØļØš"
|
||||
type: "ŲŲØš"
|
||||
image: "ØĩŲØą"
|
||||
advanced: "Ų
ØĒŲØ¯Ų
"
|
||||
_imageEffector:
|
||||
_fxProps:
|
||||
scale: "Ø§ŲØØŦŲ
"
|
||||
size: "Ø§ŲØØŦŲ
"
|
||||
offset: "اŲŲ
ŲØļØš"
|
||||
color: "اŲŲŲŲ"
|
||||
opacity: "Ø§ŲØ´ŲاŲŲØŠ"
|
||||
_qr:
|
||||
showTabTitle: "اŲŲ
Ø¸ŲØą"
|
||||
raw: "ŲØĩ"
|
||||
|
||||
@@ -215,6 +215,7 @@ noUsers: "āĻā§āύ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻāĻžāϰ⧠āύā§āĻ"
|
||||
editProfile: "āĻĒā§āϰā§āĻĢāĻžāĻāϞ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻāϰā§āύ"
|
||||
noteDeleteConfirm: "āĻāĻĒāύāĻŋ āĻāĻŋ āύā§āĻ āĻĄāĻŋāϞāĻŋāĻ āĻāϰāĻžāϰ āĻŦā§āϝāĻžāĻĒāĻžāϰ⧠āύāĻŋāĻļā§āĻāĻŋāϤ?"
|
||||
pinLimitExceeded: "āĻāĻĒāύāĻŋ āĻāϰ āĻā§āύ āύā§āĻ āĻĒāĻŋāύ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŦā§āύ āύāĻž"
|
||||
intro: "Misskey āĻāϰ āĻāύā§āϏāĻāϞā§āĻļāύ āϏāĻŽā§āĻĒāύā§āύ āĻšā§ā§āĻā§īŧāĻĻā§āĻž āĻāϰ⧠āĻ
ā§āϝāĻžāĻĄāĻŽāĻŋāύ āĻāĻāĻāĻžāϰ āϤā§āϰāĻŋ āĻāϰā§āύāĨ¤"
|
||||
done: "āϏāĻŽā§āĻĒāύā§āύ"
|
||||
processing: "āĻĒā§āϰāĻā§āϰāĻŋā§āĻžāϧā§āύ..."
|
||||
preview: "āĻĒā§āϰā§āĻŦāϰā§āĻĒ āĻĻā§āĻā§āύ"
|
||||
@@ -251,6 +252,7 @@ removeAreYouSure: "āĻāĻĒāύāĻŋ āĻāĻŋ \"{x}\" āϏāϰāĻžāύā§āϰ āĻŦā§āϝāĻž
|
||||
deleteAreYouSure: "āĻāĻĒāύāĻŋ āĻāĻŋ \"{x}\" āϏāϰāĻžāύā§āϰ āĻŦā§āϝāĻžāĻĒāĻžāϰ⧠āύāĻŋāĻļā§āĻāĻŋāϤ?"
|
||||
resetAreYouSure: "āϰāĻŋāϏā§āĻ āĻāϰāĻžāϰ āĻŦā§āϝāĻžāĻĒāĻžāϰ⧠āύāĻŋāĻļā§āĻāĻŋāϤ?"
|
||||
saved: "āϏāĻāϰāĻā§āώāĻŋāϤ āĻšā§ā§āĻā§"
|
||||
messaging: "āĻā§āϝāĻžāĻ"
|
||||
upload: "āĻāĻĒāϞā§āĻĄ"
|
||||
keepOriginalUploading: "āĻāϏāϞ āĻāĻŦāĻŋ āϰāĻžāĻā§āύ"
|
||||
keepOriginalUploadingDescription: "āĻāĻŦāĻŋāĻāĻŋ āĻāĻĒāϞā§āĻĄ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāϏāϞ āϏāĻāϏā§āĻāϰāĻŖāĻāĻŋ āϰāĻžāĻā§āύāĨ¤ āĻ
āĻĒāĻļāύāĻāĻŋ āĻŦāύā§āϧ āĻĨāĻžāĻāϞā§, āĻāĻĒāϞā§āĻĄā§āϰ āϏāĻŽāϝāĻŧ āĻāϝāĻŧā§āĻŦ āĻĒā§āϰāĻāĻžāĻļāύāĻžāϰ āĻāύā§āϝ āĻāĻŦāĻŋ āĻŦā§āϰāĻžāĻāĻāĻžāϰ⧠āϤā§āϰāĻŋ āĻāϰāĻž āĻšāĻŦā§āĨ¤"
|
||||
@@ -263,6 +265,7 @@ uploadFromUrlMayTakeTime: "URL āĻšāϤ⧠āĻāĻĒāϞā§āĻĄ āĻšāϤ⧠āĻāĻŋāĻā§
|
||||
explore: "āĻā§āϰ⧠āĻĻā§āĻā§āύ"
|
||||
messageRead: "āĻĒāĻĄāĻŧāĻž"
|
||||
noMoreHistory: "āĻāϰ āĻā§āύ āĻāϤāĻŋāĻšāĻžāϏ āύā§āĻ"
|
||||
startMessaging: "āĻā§āϝāĻžāĻ āĻļā§āϰ⧠āĻāϰā§āύ"
|
||||
nUsersRead: "{n} āĻāύ āĻĒā§ā§āĻā§āύ"
|
||||
agreeTo: "{0} āĻāϰ āĻĒā§āϰāϤāĻŋ āĻāĻŽāĻŋ āϏāĻŽā§āĻŽāϤ"
|
||||
start: "āĻļā§āϰ⧠āĻāϰā§āύ"
|
||||
@@ -424,6 +427,8 @@ retype: "āĻĒā§āύāĻ āĻĒā§āϰāĻŦā§āĻļ"
|
||||
noteOf: "{user} āĻāϰ āύā§āĻ"
|
||||
quoteAttached: "āĻāĻĻā§āϧā§āϤ"
|
||||
quoteQuestion: "āĻāĻĻā§āϧā§āϤāĻŋ āĻšāĻŋāϏāĻžāĻŦā§ āϏāĻāϝā§āĻā§āϤ āĻāϰāĻŦā§āύ?"
|
||||
noMessagesYet: "āĻā§āύ āĻŽā§āϏā§āĻ āύā§āĻ"
|
||||
newMessageExists: "āύāϤā§āύ āĻŽā§āϏā§āĻ āĻĒā§ā§ā§āĻā§āύ"
|
||||
onlyOneFileCanBeAttached: "āĻāĻĒāύāĻŋ āĻŽā§āϏā§āĻā§āϰ āϏāĻžāĻĨā§ āϏāϰā§āĻŦā§āĻā§āĻ āĻāĻāĻāĻŋ āĻĢāĻžāĻāϞ āϝā§āĻā§āϤ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŦā§āύ"
|
||||
signinRequired: "āĻĻāϝāĻŧāĻž āĻāϰ⧠āϞāĻ āĻāύ āĻāϰā§āύ"
|
||||
invitations: "āĻāĻŽāύā§āϤā§āϰāĻŖ"
|
||||
@@ -672,6 +677,7 @@ experimentalFeatures: "āĻĒāϰā§āĻā§āώāĻžāĻŽā§āϞāĻ āĻŦā§āĻļāĻŋāώā§āĻ
|
||||
developer: "āĻĄā§āĻā§āϞāĻĒāĻžāϰ"
|
||||
makeExplorable: "āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻ \"āĻā§āϰ⧠āĻĻā§āĻā§āύ\" āĻĒā§āώā§āĻ āĻžā§ āĻĻā§āĻāĻžāύ"
|
||||
makeExplorableDescription: "āĻāĻĒāύāĻŋ āĻāĻāĻŋ āĻŦāύā§āϧ āĻāϰāϞā§, āĻāĻĒāύāĻžāϰ āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻ \"āĻā§āϰ⧠āĻĻā§āĻā§āύ\" āĻĒā§āώā§āĻ āĻžā§ āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ āĻšāĻŦā§ āύāĻžāĨ¤"
|
||||
showGapBetweenNotesInTimeline: "āĻāĻžāĻāĻŽāϞāĻžāĻāύ āĻāĻŦāĻ āύā§āĻā§āϰ āĻŽāĻžāĻā§ āĻĢāĻžāĻāĻž āĻāĻžā§āĻāĻž āϰāĻžāĻā§āύ"
|
||||
duplicate: "āĻĒā§āϰāϤāĻŋāϰā§āĻĒ"
|
||||
left: "āĻŦāĻžāĻŽ"
|
||||
center: "āĻŽāĻžāĻāĻāĻžāύ"
|
||||
@@ -846,25 +852,6 @@ replies: "āĻāĻŦāĻžāĻŦ"
|
||||
renotes: "āϰāĻŋāύā§āĻ"
|
||||
sourceCode: "āϏā§āϰā§āϏ āĻā§āĻĄ"
|
||||
flip: "āĻāϞā§āĻāĻžāύ"
|
||||
postForm: "āύā§āĻ āϞāĻŋāĻā§āύ"
|
||||
information: "āĻāĻĒāύāĻžāϰ āϏāĻŽā§āĻĒāϰā§āĻā§"
|
||||
inMinutes: "āĻŽāĻŋāύāĻŋāĻ"
|
||||
inDays: "āĻĻāĻŋāύ"
|
||||
widgets: "āĻāĻāĻā§āĻāĻā§āϞāĻŋ"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
filename: "āĻĢāĻžāĻāϞā§āϰ āύāĻžāĻŽ"
|
||||
_imageFrameEditor:
|
||||
header: "āĻšā§āĻĄāĻžāϰ"
|
||||
font: "āĻĢāύā§āĻ"
|
||||
fontSerif: "āϏā§āϰāĻŋāĻĢ"
|
||||
fontSansSerif: "āϏā§āϝāĻžāύā§āϏ āϏā§āϰāĻŋāĻĢ"
|
||||
_chat:
|
||||
invitations: "āĻāĻŽāύā§āϤā§āϰāĻŖ"
|
||||
noHistory: "āĻā§āύ⧠āĻāϤāĻŋāĻšāĻžāϏ āύā§āĻ"
|
||||
members: "āϏāĻĻāϏā§āϝāĻŦā§āύā§āĻĻ"
|
||||
home: "āĻŽā§āϞ āĻĒāĻžāϤāĻž"
|
||||
send: "āĻĒāĻžāĻ āĻžāύ"
|
||||
_delivery:
|
||||
stop: "āϏā§āĻĨāĻāĻŋāϤ āĻāϰāĻž āĻšā§ā§āĻā§"
|
||||
_type:
|
||||
@@ -1007,6 +994,7 @@ _theme:
|
||||
header: "āĻšā§āĻĄāĻžāϰ"
|
||||
navBg: "āϏāĻžāĻāĻĄāĻŦāĻžāϰā§āϰ āĻĒāĻāĻā§āĻŽāĻŋ"
|
||||
navFg: "āϏāĻžāĻāĻĄāĻŦāĻžāϰā§āϰ āĻĒāĻžāĻ ā§āϝ"
|
||||
navHoverFg: "āϏāĻžāĻāĻĄāĻŦāĻžāϰā§āϰ āĻĒāĻžāĻ ā§āϝ (āĻšāĻāĻžāϰ)"
|
||||
navActive: "āϏāĻžāĻāĻĄāĻŦāĻžāϰā§āϰ āĻĒāĻžāĻ ā§āϝ (āĻ
ā§āϝāĻžāĻāĻāĻŋāĻ)"
|
||||
navIndicator: "āϏāĻžāĻāĻĄāĻŦāĻžāϰā§āϰ āĻāύāĻĄāĻŋāĻā§āĻāϰ"
|
||||
link: "āϞāĻŋāĻāĻ"
|
||||
@@ -1028,8 +1016,12 @@ _theme:
|
||||
buttonBg: "āĻŦāĻžāĻāύā§āϰ āĻĒāĻāĻā§āĻŽāĻŋ"
|
||||
buttonHoverBg: "āĻŦāĻžāĻāύā§āϰ āĻĒāĻāĻā§āĻŽāĻŋ (āĻšāĻāĻžāϰ)"
|
||||
inputBorder: "āĻāύāĻĒā§āĻ āĻĢāĻŋāϞā§āĻĄā§āϰ āĻŦāϰā§āĻĄāĻžāϰ"
|
||||
driveFolderBg: "āĻĄā§āϰāĻžāĻāĻ āĻĢā§āϞā§āĻĄāĻžāϰā§āϰ āĻĒāĻāĻā§āĻŽāĻŋ"
|
||||
wallpaperOverlay: "āĻāϝāĻŧāĻžāϞāĻĒā§āĻĒāĻžāϰ āĻāĻāĻžāϰāϞā§"
|
||||
badge: "āĻŦā§āϝāĻžāĻ"
|
||||
messageBg: "āĻā§āϝāĻžāĻā§āϰ āĻĒāĻāĻā§āĻŽāĻŋ"
|
||||
accentDarken: "āĻ
ā§āϝāĻžāĻāϏā§āύā§āĻ (āĻāĻžā§)"
|
||||
accentLighten: "āĻ
ā§āϝāĻžāĻāϏā§āύā§āĻ (āĻšāĻžāϞā§āĻāĻž)"
|
||||
fgHighlighted: "āĻšāĻžāĻāϞāĻžāĻāĻ āĻāϰāĻž āĻĒāĻžāĻ ā§āϝ"
|
||||
_sfx:
|
||||
note: "āύā§āĻāĻā§āϞāĻŋ"
|
||||
@@ -1092,7 +1084,6 @@ _permissions:
|
||||
"write:gallery": "āĻā§āϝāĻžāϞāĻžāϰ⧠āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻāϰā§āύ"
|
||||
"read:gallery-likes": "āĻā§āϝāĻžāϞāĻžāϰā§āϰ āĻĒāĻāύā§āĻĻāĻā§āϞāĻŋ āĻĻā§āĻā§āύ"
|
||||
"write:gallery-likes": "āĻā§āϝāĻžāϞāĻžāϰā§āϰ āĻĒāĻāύā§āĻĻāĻā§āϞāĻŋ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻāϰā§āύ"
|
||||
"write:chat": "āĻā§āϝāĻžāĻāĻā§āϞāĻŋ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻāϰā§āύ"
|
||||
_auth:
|
||||
shareAccess: "\"{name}\" āĻā§ āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻā§āϰ āĻ
ā§āϝāĻžāĻā§āϏā§āϏ āĻĻāĻŋāĻŦā§āύ?"
|
||||
shareAccessAsk: "āĻ
ā§āϝāĻžāĻĒā§āϞāĻŋāĻā§āĻļāύāĻāĻŋāĻā§ āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻā§āϰ āĻ
ā§āϝāĻžāĻā§āϏā§āϏ āĻĻāĻŋāĻŦā§āύ?"
|
||||
@@ -1137,14 +1128,6 @@ _widgets:
|
||||
aichan: "āĻāĻ āĻāĻžāύ"
|
||||
_userList:
|
||||
chooseList: "āϞāĻŋāϏā§āĻ āύāĻŋāϰā§āĻŦāĻžāĻāύ āĻāϰā§āύ"
|
||||
_widgetOptions:
|
||||
height: "āĻāĻā§āĻāϤāĻž"
|
||||
_button:
|
||||
colored: "āϰāĻā§āĻāĻŋāύ"
|
||||
_clock:
|
||||
size: "āĻāĻāĻžāϰ"
|
||||
_birthdayFollowings:
|
||||
period: "āĻŦā§āϝāĻžāĻĒā§āϤāĻŋāĻāĻžāϞ"
|
||||
_cw:
|
||||
hide: "āϞā§āĻāĻžāύ"
|
||||
show: "āĻāϰāĻ āĻĻā§āĻā§āύ"
|
||||
@@ -1185,9 +1168,6 @@ _postForm:
|
||||
replyPlaceholder: "āύā§āĻāĻāĻŋāϰ āĻāĻŦāĻžāĻŦ āĻĻāĻŋāύ..."
|
||||
quotePlaceholder: "āύā§āĻāĻāĻŋāĻā§ āĻāĻĻā§āϧā§āϤ āĻāϰā§āύ..."
|
||||
channelPlaceholder: "āĻā§āϝāĻžāύā§āϞ⧠āĻĒā§āϏā§āĻ āĻāϰā§āύ..."
|
||||
_howToUse:
|
||||
visibility_title: "āĻĻā§āĻļā§āϝāĻŽāĻžāύāϤāĻž"
|
||||
menu_title: "āĻŽā§āύā§"
|
||||
_placeholders:
|
||||
a: "āĻāĻĒāύāĻŋ āĻāĻāύ āĻāĻŋ āĻāϰāĻā§āύ?"
|
||||
b: "āĻāĻĒāύāĻžāϰ āĻāĻļā§ āĻĒāĻžāĻļā§ āĻāĻŋ āĻšāĻā§āĻā§?"
|
||||
@@ -1371,19 +1351,3 @@ _remoteLookupErrors:
|
||||
_search:
|
||||
searchScopeAll: "āϏāĻŦāĻā§āϞā§"
|
||||
searchScopeLocal: "āϏā§āĻĨāĻžāύā§āϝāĻŧ"
|
||||
_watermarkEditor:
|
||||
opacity: "āĻ
āϏā§āĻŦāĻā§āĻāϤāĻž"
|
||||
scale: "āĻāĻāĻžāϰ"
|
||||
text: "āϞā§āĻāĻž"
|
||||
image: "āĻāĻŦāĻŋ"
|
||||
advanced: "āĻāύā§āύāϤ"
|
||||
_imageEffector:
|
||||
_fxProps:
|
||||
scale: "āĻāĻāĻžāϰ"
|
||||
size: "āĻāĻāĻžāϰ"
|
||||
color: "āϰāĻ"
|
||||
opacity: "āĻ
āϏā§āĻŦāĻā§āĻāϤāĻž"
|
||||
lightness: "āĻāĻā§āĻā§āĻŦāϞ āĻāϰā§āύ"
|
||||
_qr:
|
||||
showTabTitle: "āĻĒā§āϰāĻĻāϰā§āĻļāύ"
|
||||
raw: "āϞā§āĻāĻž"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user