Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

バックエンドが生成するapi.jsonからmisskey-jsの型を作成する #12434

Merged

Conversation

samunohito
Copy link
Member

@samunohito samunohito commented Nov 24, 2023

What

#12410 の対応です。
この対応により、misskey-jsの型情報をバックエンドに追従させやすくなります。

Why

fix #12410

Additional info (optional)

  1. openapi-typescriptを使用してapi.jsonから型情報を作成
  2. api.jsonからエンドポイントの各パラメータやschema配下の定義を取得
  3. 1と2をあわせ、型のエイリアスを定義するファイルを生成
  4. misskey-jsで3をexport

…みたいな感じで進めています。

backend/frontendにも変更ファイルが多数存在していますが、その内訳は以下のとおりです。型に関する内容が中心で、トランスパイル後の動きに影響があるものはほぼ無いと思われます(ロジックに手を入れた所は差分にコメントします)

  • backend →各インターフェースに不足していたリクエスト/レスポンスの記述を補強
  • frontend →上記4で作成された型を使うように変更(バックエンド側のスキーマ定義と違う型名だった場合)

Checklist

  • Read the contribution guide
  • Test working in a local environment
  • (If needed) Add story of storybook
  • (If needed) Update CHANGELOG.md
  • (If possible) Add tests

@kakkokari-gtyih kakkokari-gtyih marked this pull request as draft November 24, 2023 11:45
@kakkokari-gtyih
Copy link
Contributor

(WIPとのことなのでDraftにしておきました!準備ができればReady for reviewを押してください)

@github-actions github-actions bot added the packages/frontend Client side specific issue/PR label Nov 25, 2023
@samunohito
Copy link
Member Author

samunohito commented Nov 25, 2023

めも

自動生成したやつにない

Instance federation/instances
Invite invite/list
AuthSession
AdminInstanceMetadata 'admin/meta'
DetailedInstanceMetadata 'meta'
LiteInstanceMetadata 'meta'
InstanceMetadata
CustomEmoji 'emojis'

### schema化したほうがいい
export type OriginType = 'combined' | 'local' | 'remote';
export type UserSorting =
| '+follower'
| '-follower'
| '+createdAt'
| '-createdAt'
| '+updatedAt'
| '-updatedAt';
Notification.type

↑api.jsonの生成ロジックとAjvのロジックが噛み合わなくて辛かったのでやめた

@samunohito
Copy link
Member Author

メモ
UserGroup不要 #9931
MessagingMessage不要 #9919

@github-actions github-actions bot added packages/backend Server side specific issue/PR packages/misskey-js:test labels Nov 25, 2023
Copy link

codecov bot commented Nov 26, 2023

Codecov Report

Attention: 17 lines in your changes are missing coverage. Please review.

Comparison is base (238e8ce) 78.71% compared to head (3a64cf7) 78.76%.
Report is 1 commits behind head on develop.

Files Patch % Lines
packages/frontend/src/scripts/api.ts 18.75% 13 Missing ⚠️
...d/src/server/api/endpoints/federation/instances.ts 87.50% 3 Missing ⚠️
packages/frontend/src/custom-emojis.ts 66.66% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop   #12434      +/-   ##
===========================================
+ Coverage    78.71%   78.76%   +0.04%     
===========================================
  Files          951      954       +3     
  Lines       103427   103792     +365     
  Branches      8330     8327       -3     
===========================================
+ Hits         81417    81754     +337     
- Misses       22010    22038      +28     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Copy link
Contributor

github-actions bot commented Nov 26, 2023

このPRによるapi.jsonの差分

差分はこちら
--- base
+++ head
@@ -347,6 +347,82 @@
                     "notesPerOneAd": {
                       "type": "number",
                       "nullable": false
+                    },
+                    "backgroundImageUrl": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "deeplAuthKey": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "deeplIsPro": {
+                      "type": "boolean",
+                      "nullable": false
+                    },
+                    "defaultDarkTheme": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "defaultLightTheme": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "description": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "disableRegistration": {
+                      "type": "boolean",
+                      "nullable": false
+                    },
+                    "impressumUrl": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "maintainerEmail": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "maintainerName": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "name": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "objectStorageS3ForcePathStyle": {
+                      "type": "boolean",
+                      "nullable": false
+                    },
+                    "privacyPolicyUrl": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "repositoryUrl": {
+                      "type": "string",
+                      "nullable": false
+                    },
+                    "summalyProxy": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "themeColor": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "tosUrl": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "uri": {
+                      "type": "string",
+                      "nullable": false
+                    },
+                    "version": {
+                      "type": "string",
+                      "nullable": false
                     }
                   },
                   "required": [
@@ -419,7 +495,26 @@
                     "perRemoteUserUserTimelineCacheMax",
                     "perUserHomeTimelineCacheMax",
                     "perUserListTimelineCacheMax",
-                    "notesPerOneAd"
+                    "notesPerOneAd",
+                    "backgroundImageUrl",
+                    "deeplAuthKey",
+                    "deeplIsPro",
+                    "defaultDarkTheme",
+                    "defaultLightTheme",
+                    "description",
+                    "disableRegistration",
+                    "impressumUrl",
+                    "maintainerEmail",
+                    "maintainerName",
+                    "name",
+                    "objectStorageS3ForcePathStyle",
+                    "privacyPolicyUrl",
+                    "repositoryUrl",
+                    "summalyProxy",
+                    "themeColor",
+                    "tosUrl",
+                    "uri",
+                    "version"
                   ]
                 }
               }
@@ -30342,7 +30437,24 @@
                     "default": 0
                   },
                   "sort": {
-                    "type": "string"
+                    "type": "string",
+                    "nullable": true,
+                    "enum": [
+                      "+pubSub",
+                      "-pubSub",
+                      "+notes",
+                      "-notes",
+                      "+users",
+                      "-users",
+                      "+following",
+                      "-following",
+                      "+followers",
+                      "-followers",
+                      "+firstRetrievedAt",
+                      "-firstRetrievedAt",
+                      "+latestRequestReceivedAt",
+                      "-latestRequestReceivedAt"
+                    ]
                   }
                 }
               }
@@ -30535,7 +30647,24 @@
                     "default": 0
                   },
                   "sort": {
-                    "type": "string"
+                    "type": "string",
+                    "nullable": true,
+                    "enum": [
+                      "+pubSub",
+                      "-pubSub",
+                      "+notes",
+                      "-notes",
+                      "+users",
+                      "-users",
+                      "+following",
+                      "-following",
+                      "+followers",
+                      "-followers",
+                      "+firstRetrievedAt",
+                      "-firstRetrievedAt",
+                      "+latestRequestReceivedAt",
+                      "-latestRequestReceivedAt"
+                    ]
                   }
                 }
               }
@@ -41970,6 +42099,33 @@
                         "objectStorage",
                         "serviceWorker"
                       ]
+                    },
+                    "backgroundImageUrl": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "impressumUrl": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "logoImageUrl": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "privacyPolicyUrl": {
+                      "type": "string",
+                      "nullable": true
+                    },
+                    "serverRules": {
+                      "type": "array",
+                      "nullable": false,
+                      "items": {
+                        "type": "string"
+                      }
+                    },
+                    "themeColor": {
+                      "type": "string",
+                      "nullable": true
                     }
                   },
                   "required": [
@@ -42011,7 +42167,13 @@
                     "enableServiceWorker",
                     "translatorAvailable",
                     "proxyAccountName",
-                    "mediaProxy"
+                    "mediaProxy",
+                    "backgroundImageUrl",
+                    "impressumUrl",
+                    "logoImageUrl",
+                    "privacyPolicyUrl",
+                    "serverRules",
+                    "themeColor"
                   ]
                 }
               }

Get diff files from Workflow Page

@samunohito
Copy link
Member Author

(CIめっちゃこけてる)

suspended = instance?.isSuspended ?? false;
isBlocked = instance?.isBlocked ?? false;
isSilenced = instance?.isSilenced ?? false;
faviconUrl = getProxiedImageUrlNullable(instance?.faviconUrl, 'preview') ?? getProxiedImageUrlNullable(instance?.iconUrl, 'preview');
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

federation/show-instanceは204を返すこともあるので、bodyが空だった時に初期値を入れるようにしています

await os.api('admin/update-meta', {
silencedHosts: isSilenced ? meta.silencedHosts.concat([host]) : meta.silencedHosts.filter(x => x !== host),
silencedHosts: isSilenced ? silencedHosts.concat([host]) : silencedHosts.filter(x => x !== host),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

silencedHostsは型定義上undefinedになりえるので、その場合はデフォルト値として空配列を使用する措置をしました

return '';
}

return getProxiedImageUrl(instance.iconUrl, 'preview');
Copy link
Member Author

@samunohito samunohito Nov 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iconUrlはDB定義上nullになりえるのでこうしています
(呼び元にてv-ifで制御されている)

data: P = {} as any,
token?: string | null | undefined,
signal?: AbortSignal,
): Promise<Misskey.api.SwitchCaseResponseType<E, P>> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

misskey-js側で定義されていたものをexport typeして持ち込みました。
$switch/$caseを使った特殊な型定義で、リクエストによりレスポンスの型定義が動的に切り替わる仕組みです。

res.requests.received.splice(0, 1);
chartValues = res.requests.received;
res['requests.received'].splice(0, 1);
chartValues = res['requests.received'];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

返ってくる値の形が↓のようになっており、エラーとなっていましたので値の参照方法を変えています
https://github.com/samunohito/misskey/blob/c2370a1be631355e709c47d3b5e9469906116b84/packages/backend/src/core/chart/charts/entities/instance.ts

messagingChannel.on('message', message => {
expectType<Misskey.entities.MessagingMessage>(message);
});
});
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

messagingは既に存在しないので削除しています
#9919

id: MessagingMessage['id'];
};
};
};
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

メッセージ機能は廃止になった経緯を観測したので削除しています(未使用の型定義整理の一環)
#9919

@samunohito samunohito changed the title [WIP] バックエンドが生成するapi.jsonからmisskey-jsの型を作成する バックエンドが生成するapi.jsonからmisskey-jsの型を作成する Nov 28, 2023
@samunohito samunohito marked this pull request as ready for review November 28, 2023 00:16
@syuilo
Copy link
Member

syuilo commented Dec 2, 2023

readyということはもうレビューしてもよい状態ということで合ってるかしら?

@samunohito
Copy link
Member Author

@syuilo
大丈夫です
お願いします:pray:

@syuilo
Copy link
Member

syuilo commented Dec 2, 2023

例えばこんな感じに書いても型エラーにならないのは仕様?
image

@samunohito
Copy link
Member Author

こっちも型エラーが出なくて???でしたが、IDEを再起動したところ出るようになりました。
急激に構成が変わるのでエディタ側のキャッシュが追い付いてないのかもしれないです

image

@samunohito
Copy link
Member Author

VSCodeでも確認しました
image

@syuilo syuilo merged commit 3364162 into misskey-dev:develop Dec 2, 2023
18 checks passed
@syuilo
Copy link
Member

syuilo commented Dec 2, 2023

🙏🏻 🙏🏻 🙏🏻 🙏🏻 🙏🏻

function generateVersionHeaderComment(openApiDocs: OpenAPIV3.Document): string {
const contents = {
version: openApiDocs.info.version,
generatedAt: new Date().toISOString(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

生成日時がコメントで入るようになっていますが、コンフリクト解消の手間を考えると無くても良い気がします。いかがでしょうか?

camilla-ett pushed a commit to kaseiski/misskey that referenced this pull request Jan 2, 2024
* ひとまず生成できるところまで

* ファイル構成整理

* 生成コマンド整理

* misskey-jsへの組み込み

* fix generator.ts

* wip

* fix generator.ts

* fix package.json

* 生成ロジックの調整

* 型レベルでのswitch-case機構をmisskey-jsからfrontendに持ち込めるようにした

* 型チェック用のtsconfig.jsonを作成

* 他のエンドポイントを呼ぶ関数にも適用

* 未使用エンティティなどを削除

* misskey-js側で手動定義されていた型を自動生成された型に移行(ただしapi.jsonがvalidでなくなってしまったので後で修正する)

* messagingは廃止されている(テストのビルドエラー解消)

* validなapi.jsonを出力できるように修正

* 修正漏れ対応

* Ajvに怒られて起動できなかったところを修正

* fix ci(途中)

* パラメータenumをやめる

* add command

* add api.json

* 都度自動生成をやめる

* 一気通貫スクリプト修正

* fix ci

* 生成ロジック修正

* フロントの型チェックは結局やらなかったので戻しておく

* fix pnpm-lock.yaml

* add README.md

---------

Co-authored-by: osamu <[email protected]>
Co-authored-by: syuilo <[email protected]>
@samunohito samunohito deleted the enhance/misskey-js-type-autogen branch January 11, 2024 00:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
packages/backend Server side specific issue/PR packages/frontend Client side specific issue/PR packages/misskey-js:test packages/misskey-js
Projects
None yet
Development

Successfully merging this pull request may close these issues.

バックエンドから出力されたapi.jsonを使ってmisskey-jsの型生成を行いたい
4 participants