🕌

SwiftでAT Protocolライブラリを作った

2023/12/10に公開

swift-atprotoとは

https://github.com/nnabeyang/swift-atproto
swift-atprotoには、コード生成をするswift-atprotoコマンドとSwiftAtprotoライブラリの2つから成っています。
nnabeyang/swiftskyapi/appbskyapp/comatprotoにあるコードはswift-atprotoから生成したものになります。
https://github.com/nnabeyang/swiftsky
生成したコードを呼び出すためには、XRPCClientProtocolに適合するクライアントを実装する必要があります。swiftskyではXRPCBaseClientを継承して、refreshSessionだけ定義しています。
https://github.com/nnabeyang/swiftsky/blob/715e608ba1be61d6f9d2951873a75b02d6aba06e/swiftsky/api/api.swift#L34-L52
refreshSessionが呼び出しているcomatprototypes.ServerRefreshSessionはlexiconから生成したコードなのでSwiftAtprotoから参照することは出来ません。

また、AT protocolで型がUnknownの場合があります。この場合は$typeフィールドから、どの型にデコードする必要があるのか判断するのですが、$typeの値とSwiftの型を紐付ける必要があります。
swift-atprotostatic func registerLexiconTypes()を生成しているので、それを呼び出せば紐付けができます。
https://github.com/nnabeyang/swiftsky/blob/be44144160d759fc606e2d9c59f25de933ec6417/swiftsky/api/appbsky/appbskytypes.swift#L10-L22
XRPCClientにイニシャライザで実行しています。
https://github.com/nnabeyang/swiftsky/blob/main/swiftsky/api/api.swift#L34-L44

現状の制限

今の所、BlueSky用のコード生成にしか使えません。lexiconという型定義をもとにコード生成するのですが、lexicon自身に依存関係を解決する仕組みがなく、以下のようにハードコーディングしています。
https://github.com/nnabeyang/swift-atproto/blob/main/Sources/SwiftAtprotoLex/SwiftAtprotoLex.swift#L23
もちろん、設定ファイルで外から与えることもできるのですが、公式のGo実装のbluesky-social/indigoも同様の状態です。

作った感想

swiftのコード生成に利用しているswift-syntaxのSwiftSyntaxBuilderの使い方を調べるのに苦労しました。いまだに使い方を調べる良い方法がわかっていません。

Discussion