From ff72a72f9cf0d907f1b922c6ab2cc8dbcff1dc6e Mon Sep 17 00:00:00 2001 From: librarian <57712678+LibraryLibrarian@users.noreply.github.com> Date: Tue, 19 Aug 2025 06:32:33 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20MisskeyHttpClient=E3=81=AE=E6=A9=9F?= =?UTF-8?q?=E8=83=BD=E5=BC=B7=E5=8C=96=E3=81=A8=E3=82=A8=E3=82=AF=E3=82=B9?= =?UTF-8?q?=E3=83=9D=E3=83=BC=E3=83=88=E3=81=AE=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - MisskeyHttpClientにexceptionMapperを追加し、エラー処理を柔軟に対応 - 新たにFunctionLoggerクラスを実装し、ロギング機能を強化 - 不要なエクスポートを整理し、必要なエクスポートを追加 - MetaClientのgetMetaメソッドにrefreshオプションを追加し、キャッシュの動作を改善 - テストケースを追加し、各機能の動作を検証 --- lib/misskey_api_core.dart | 5 +- lib/src/core/auth/token_provider.dart | 4 +- lib/src/core/http/misskey_http_client.dart | 20 ++++-- lib/src/core/logging/function_logger.dart | 22 +++++++ lib/src/meta/meta_client.dart | 12 ++-- test/http_baseurl_public_test.dart | 17 +++++ test/http_error_mapping_test.dart | 4 +- test/http_exception_mapper_test.dart | 65 +++++++++++++++++++ test/http_i_injection_test.dart | 4 +- test/http_retry_test.dart | 4 +- test/meta_client_refresh_test.dart | 75 ++++++++++++++++++++++ test/meta_client_test.dart | 2 +- test/misskey_api_core_test.dart | 3 +- 13 files changed, 216 insertions(+), 21 deletions(-) create mode 100644 lib/src/core/logging/function_logger.dart create mode 100644 test/http_baseurl_public_test.dart create mode 100644 test/http_exception_mapper_test.dart create mode 100644 test/meta_client_refresh_test.dart diff --git a/lib/misskey_api_core.dart b/lib/misskey_api_core.dart index 83192e8..accb62c 100644 --- a/lib/misskey_api_core.dart +++ b/lib/misskey_api_core.dart @@ -1,8 +1,9 @@ -export 'src/core/config/misskey_api_config.dart'; export 'src/core/auth/token_provider.dart'; +export 'src/core/config/misskey_api_config.dart'; +export 'src/core/error/misskey_api_exception.dart'; export 'src/core/http/misskey_http_client.dart'; export 'src/core/http/request_options.dart'; -export 'src/core/error/misskey_api_exception.dart'; +export 'src/core/logging/function_logger.dart'; export 'src/core/logging/logger.dart'; export 'src/meta/meta_client.dart'; export 'src/models/meta.dart'; diff --git a/lib/src/core/auth/token_provider.dart b/lib/src/core/auth/token_provider.dart index 3f698ea..1c0fa0a 100644 --- a/lib/src/core/auth/token_provider.dart +++ b/lib/src/core/auth/token_provider.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + /// 認可トークンを提供するための型 /// 同期/非同期のいずれにも対応できるように `FutureOr` を返す関数型を利用する想定 -typedef TokenProvider = Future Function(); +typedef TokenProvider = FutureOr Function(); diff --git a/lib/src/core/http/misskey_http_client.dart b/lib/src/core/http/misskey_http_client.dart index b5a0b46..73a1ac5 100644 --- a/lib/src/core/http/misskey_http_client.dart +++ b/lib/src/core/http/misskey_http_client.dart @@ -1,12 +1,13 @@ import 'dart:async'; import 'package:dio/dio.dart'; -import 'package:retry/retry.dart'; import 'package:flutter/foundation.dart' show kDebugMode; +import 'package:retry/retry.dart'; import '../auth/token_provider.dart'; import '../config/misskey_api_config.dart'; import '../error/misskey_api_exception.dart'; +import '../logging/function_logger.dart'; import '../logging/logger.dart'; import 'request_options.dart' as ro; @@ -15,15 +16,21 @@ class MisskeyHttpClient { final MisskeyApiConfig config; final TokenProvider? tokenProvider; final Logger? logger; + final Object Function(Object error)? exceptionMapper; + + /// 公開ベースURL(`/api` 付与前の元URL) + Uri get baseUrl => config.baseUrl; late final Dio _dio; MisskeyHttpClient({ required this.config, this.tokenProvider, - this.logger, + Logger? logger, + this.exceptionMapper, + void Function(String level, String message)? loggerFn, HttpClientAdapter? httpClientAdapter, - }) { + }) : logger = logger ?? (loggerFn != null ? FunctionLogger(loggerFn) : null) { final baseOptions = BaseOptions( baseUrl: _ensureApiBase(config.baseUrl).toString(), connectTimeout: config.timeout, @@ -65,6 +72,7 @@ class MisskeyHttpClient { randomizationFactor: 0.25, ); + // リトライオプションに従い、Dioを使ってHTTPリクエストを送信し、必要に応じてリトライを行う処理 try { final result = await r.retry( () async { @@ -88,9 +96,11 @@ class MisskeyHttpClient { ); return result.data as T; } on DioException catch (e) { - throw _mapDioError(e); + final err = _mapDioError(e); + throw exceptionMapper != null ? exceptionMapper!(err) : err; } catch (e) { - throw MisskeyApiException(message: 'Unexpected error', raw: e); + final err = MisskeyApiException(message: 'Unexpected error', raw: e); + throw exceptionMapper != null ? exceptionMapper!(err) : err; } } diff --git a/lib/src/core/logging/function_logger.dart b/lib/src/core/logging/function_logger.dart new file mode 100644 index 0000000..5c60633 --- /dev/null +++ b/lib/src/core/logging/function_logger.dart @@ -0,0 +1,22 @@ +import 'logger.dart'; + +/// 関数ベースのロガーを `Logger` IF へアダプトする軽量ラッパー +class FunctionLogger implements Logger { + final void Function(String level, String message) _fn; + const FunctionLogger(this._fn); + + @override + void debug(String message) => _fn('debug', message); + + @override + void info(String message) => _fn('info', message); + + @override + void warn(String message) => _fn('warn', message); + + @override + void error(String message, [Object? error, StackTrace? stackTrace]) { + final m = error == null ? message : '$message error=$error'; + _fn('error', m); + } +} diff --git a/lib/src/meta/meta_client.dart b/lib/src/meta/meta_client.dart index 203be7e..ddce7c8 100644 --- a/lib/src/meta/meta_client.dart +++ b/lib/src/meta/meta_client.dart @@ -1,5 +1,5 @@ -import '../core/http/request_options.dart'; import '../core/http/misskey_http_client.dart'; +import '../core/http/request_options.dart'; import '../models/meta.dart'; /// `/api/meta` を取得するクライアント @@ -9,8 +9,12 @@ class MetaClient { MetaClient(this.http); - Future getMeta() async { - if (_cached != null) return _cached!; + /// Misskeyサーバの `/api/meta` エンドポイントからメタ情報を取得する + /// + /// [refresh] を `true` にするとキャッシュを無視して常に最新の情報を取得する + /// デフォルトでは、一度取得したメタ情報をキャッシュし、2回目以降はキャッシュを返す + Future getMeta({bool refresh = false}) async { + if (!refresh && _cached != null) return _cached!; final res = await http.send>( '/meta', method: 'POST', @@ -21,7 +25,7 @@ class MetaClient { return _cached!; } - /// 簡易な能力検出(キー存在で判定) + /// 簡易なサーバーの能力検出(キー存在で判定) bool supports(String keyPath) { final meta = _cached; if (meta == null) return false; diff --git a/test/http_baseurl_public_test.dart b/test/http_baseurl_public_test.dart new file mode 100644 index 0000000..2629b67 --- /dev/null +++ b/test/http_baseurl_public_test.dart @@ -0,0 +1,17 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:misskey_api_core/misskey_api_core.dart' as core; + +void main() { + /// MisskeyHttpClientの `baseUrl` プロパティが、 + /// `/api` 正規化前の元のベースURL(MisskeyApiConfigで指定したもの)を + /// 正しく公開していることを検証するテスト + /// + /// - `baseUrl` には `/api` が付与されていない元のURLがそのまま格納されていること + test('MisskeyHttpClientのbaseUrlは元のURL(/api付与前)を公開する', () { + final base = Uri.parse('https://host.example/app'); + final http = core.MisskeyHttpClient( + config: core.MisskeyApiConfig(baseUrl: base), + ); + expect(http.baseUrl, base); + }); +} diff --git a/test/http_error_mapping_test.dart b/test/http_error_mapping_test.dart index 621a152..0d6a68a 100644 --- a/test/http_error_mapping_test.dart +++ b/test/http_error_mapping_test.dart @@ -34,7 +34,7 @@ class _ErrorAdapter implements dio.HttpClientAdapter { void main() { /// `{ error: { code, message } }` 形式のMisskeyエラーが /// `MisskeyApiException(code, message, statusCode)` に正規化されることを検証 - test('maps Misskey error format with nested error object', () async { + test('Misskeyエラーフォーマットが正規化されることを検証', () async { final client = core.MisskeyHttpClient( config: core.MisskeyApiConfig(baseUrl: Uri.parse('https://example.com')), httpClientAdapter: _ErrorAdapter(400, { @@ -55,7 +55,7 @@ void main() { /// `{ code, message }` のフラットなエラーフォーマットも /// 同様に正規化されることを検証する - test('maps flat error format too', () async { + test('フラットなエラーフォーマットも正規化されることを検証', () async { final client = core.MisskeyHttpClient( config: core.MisskeyApiConfig(baseUrl: Uri.parse('https://example.com')), httpClientAdapter: _ErrorAdapter(403, { diff --git a/test/http_exception_mapper_test.dart b/test/http_exception_mapper_test.dart new file mode 100644 index 0000000..dc58855 --- /dev/null +++ b/test/http_exception_mapper_test.dart @@ -0,0 +1,65 @@ +import 'dart:convert'; + +import 'package:dio/dio.dart' as dio; +import 'package:flutter_test/flutter_test.dart'; +import 'package:misskey_api_core/misskey_api_core.dart' as core; + +class _ErrorAdapter implements dio.HttpClientAdapter { + final int statusCode; + _ErrorAdapter(this.statusCode); + + @override + void close({bool force = false}) {} + + @override + Future fetch( + dio.RequestOptions options, + Stream>? requestStream, + Future? cancelFuture, + ) async { + return dio.ResponseBody.fromBytes( + utf8.encode( + jsonEncode({ + 'error': {'code': 'SOME', 'message': 'oops'}, + }), + ), + statusCode, + headers: { + dio.Headers.contentTypeHeader: ['application/json'], + }, + ); + } +} + +class MyUnifiedException implements Exception { + final String message; + const MyUnifiedException(this.message); +} + +void main() { + /// `exceptionMapper` フックが MisskeyApiException をカスタム例外に変換できることを検証するテスト + /// + /// - MisskeyHttpClient の `exceptionMapper` に、MisskeyApiException を受け取った際に + /// 独自の MyUnifiedException に変換する関数を指定する + /// - サーバーが 500 エラー(Misskey 形式のエラー)を返す状況を模擬し、 + /// send() 実行時に MyUnifiedException が投げられることを確認する + test('exceptionMapperでMisskeyApiExceptionをカスタム例外に変換できる', () async { + final http = core.MisskeyHttpClient( + config: core.MisskeyApiConfig(baseUrl: Uri.parse('https://example.com')), + httpClientAdapter: _ErrorAdapter(500), + exceptionMapper: (Object error) { + if (error is core.MisskeyApiException) { + return MyUnifiedException( + 'HTTP:${error.statusCode} ${error.message}', + ); + } + return error; + }, + ); + + expect( + () async => http.send('/x', body: const {}), + throwsA(isA()), + ); + }); +} diff --git a/test/http_i_injection_test.dart b/test/http_i_injection_test.dart index c1ccc82..63cbffc 100644 --- a/test/http_i_injection_test.dart +++ b/test/http_i_injection_test.dart @@ -33,7 +33,7 @@ class _CapturingAdapter implements dio.HttpClientAdapter { void main() { /// authRequiredがtrueのPOSTでは、JSON bodyにトークン`i`が自動注入されることを検証 - test('injects i when authRequired=true (POST)', () async { + test('authRequired=true のPOSTでは、JSON bodyにトークン`i`が自動注入されることを検証', () async { final adapter = _CapturingAdapter(); final client = core.MisskeyHttpClient( config: core.MisskeyApiConfig(baseUrl: Uri.parse('https://example.com')), @@ -55,7 +55,7 @@ void main() { }); /// authRequiredがfalseのPOSTでは、`i`が注入されないことを検証 - test('does not inject i when authRequired=false (POST)', () async { + test('authRequired=false のPOSTでは、`i`が注入されないことを検証', () async { final adapter = _CapturingAdapter(); final client = core.MisskeyHttpClient( config: core.MisskeyApiConfig(baseUrl: Uri.parse('https://example.com')), diff --git a/test/http_retry_test.dart b/test/http_retry_test.dart index 42623b0..326d0f1 100644 --- a/test/http_retry_test.dart +++ b/test/http_retry_test.dart @@ -38,7 +38,7 @@ class _FlakyAdapter implements dio.HttpClientAdapter { void main() { /// idempotent=true の場合、503など一時エラーで所定回数だけリトライして成功することを検証 - test('retries when idempotent=true and server errors', () async { + test('idempotent=true の場合、503など一時エラーで所定回数だけリトライして成功することを検証', () async { final adapter = _FlakyAdapter(2); final client = core.MisskeyHttpClient( config: core.MisskeyApiConfig( @@ -63,7 +63,7 @@ void main() { }); /// idempotent=false の場合、リトライせずに例外を投げることを検証 - test('does not retry when idempotent=false', () async { + test('idempotent=false の場合、リトライせずに例外を投げることを検証', () async { final adapter = _FlakyAdapter(1); final client = core.MisskeyHttpClient( config: core.MisskeyApiConfig( diff --git a/test/meta_client_refresh_test.dart b/test/meta_client_refresh_test.dart new file mode 100644 index 0000000..0de0b15 --- /dev/null +++ b/test/meta_client_refresh_test.dart @@ -0,0 +1,75 @@ +import 'dart:convert'; + +import 'package:dio/dio.dart' as dio; +import 'package:flutter_test/flutter_test.dart'; +import 'package:misskey_api_core/misskey_api_core.dart' as core; + +/// テスト用の可変レスポンスを返すHttpClientAdapter +/// +/// このクラスはDioの[HttpClientAdapter]を実装し、 +/// [response]プロパティで指定されたMapをJSONとして返すダミーのHTTPクライアントアダプタ +/// fetchが呼ばれるたびに[calls]がインクリメントされ、 +/// サーバーレスポンスを動的に書き換えてテストできるようにする +class _MutableMetaAdapter implements dio.HttpClientAdapter { + /// 現在返すレスポンス(JSONとしてシリアライズされる) + Map response; + + /// fetchが呼ばれた回数 + int calls = 0; + + /// [response]で初期化 + _MutableMetaAdapter(this.response); + + @override + void close({bool force = false}) {} + + @override + Future fetch( + dio.RequestOptions options, + Stream>? requestStream, + Future? cancelFuture, + ) async { + calls++; + return dio.ResponseBody.fromBytes( + utf8.encode(jsonEncode(response)), + 200, + headers: { + dio.Headers.contentTypeHeader: ['application/json'], + }, + ); + } +} + +void main() { + /// MetaClientのキャッシュ挙動とrefreshオプションの動作を検証するテスト + /// + /// - 最初のgetMeta()呼び出しでサーバーからメタ情報を取得し、キャッシュされることを確認する + /// - 2回目のgetMeta()呼び出しではキャッシュが利用され、サーバーへのリクエストが発生しないことを確認する + /// - サーバーレスポンスを書き換えた後、getMeta(refresh: true)でキャッシュを無視して再取得し、 + /// 新しい値が取得されることとリクエスト回数が増えることを確認する + test('MetaClient getMeta(refresh: true) でキャッシュを無視して再取得できることを検証', () async { + final adapter = _MutableMetaAdapter({'version': 'v1', 'name': 'example'}); + final http = core.MisskeyHttpClient( + config: core.MisskeyApiConfig(baseUrl: Uri.parse('https://example.com')), + httpClientAdapter: adapter, + ); + final metaClient = core.MetaClient(http); + + final meta1 = await metaClient.getMeta(); + expect(meta1.version, 'v1'); + expect(adapter.calls, 1); + + // 通常呼び出しはキャッシュ + final meta2 = await metaClient.getMeta(); + expect(identical(meta1, meta2), true); + expect(adapter.calls, 1); + + // サーバーレスポンスが変わった想定 + adapter.response = {'version': 'v2', 'name': 'example'}; + + // refresh指定で再取得 + final meta3 = await metaClient.getMeta(refresh: true); + expect(meta3.version, 'v2'); + expect(adapter.calls, 2); + }); +} diff --git a/test/meta_client_test.dart b/test/meta_client_test.dart index 07df020..cf424fe 100644 --- a/test/meta_client_test.dart +++ b/test/meta_client_test.dart @@ -34,7 +34,7 @@ class _MetaAdapter implements dio.HttpClientAdapter { void main() { /// `MetaClient.getMeta()` が結果をキャッシュし、 /// `supports()` で機能有無が正しく判定できることを検証する - test('MetaClient caches and supports() works', () async { + test('MetaClient がキャッシュを効かせて機能有無を正しく判定できることを検証', () async { final adapter = _MetaAdapter({ 'version': '2024.12.0', 'name': 'misskey.example', diff --git a/test/misskey_api_core_test.dart b/test/misskey_api_core_test.dart index 7a2305a..1296ae5 100644 --- a/test/misskey_api_core_test.dart +++ b/test/misskey_api_core_test.dart @@ -1,11 +1,10 @@ import 'package:flutter_test/flutter_test.dart'; - import 'package:misskey_api_core/misskey_api_core.dart'; void main() { /// 公開APIのスモークテスト /// 必要最小のエクスポート(Config/HttpClient)が利用可能であることを確認 - test('exports exist', () { + test('MisskeyApiCore が必要最小のエクスポートを提供することを検証', () { final config = MisskeyApiConfig(baseUrl: Uri.parse('https://example.com')); final client = MisskeyHttpClient(config: config); expect(client, isNotNull); From 21f2d940b5193bb4b54c32c04706b4ab9f6724cf Mon Sep 17 00:00:00 2001 From: librarian <57712678+LibraryLibrarian@users.noreply.github.com> Date: Tue, 19 Aug 2025 06:38:18 +0900 Subject: [PATCH 2/4] =?UTF-8?q?doc:=20=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7?= =?UTF-8?q?=E3=83=B30.0.2-beta=E3=81=AE=E3=83=AA=E3=83=AA=E3=83=BC?= =?UTF-8?q?=E3=82=B9=E3=81=AE=E7=82=BAdoc=E3=81=A8pubspec=E6=9B=B4?= =?UTF-8?q?=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 11 +++++++++++ README.md | 30 ++++++++++++++++++++++++++---- pubspec.yaml | 2 +- 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 003117b..40ab1e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.0.2-beta] - 2025-08-19 + +### Added +- Expose `MisskeyHttpClient.baseUrl` (original base, before `/api` normalization). +- Add `exceptionMapper` hook to `MisskeyHttpClient` to customize thrown exceptions. +- Add `loggerFn` (function-style logger) accepted by `MisskeyHttpClient` and adapt to existing `Logger` interface. +- `MetaClient.getMeta({bool refresh = false})` to force-refresh cache when needed. + +### Changed +- Generalize `TokenProvider` to `FutureOr Function()` to support both sync/async token sources. + ## [0.0.1-beta] - 2025-08-18 ### Added diff --git a/README.md b/README.md index d94e412..27cfdb9 100644 --- a/README.md +++ b/README.md @@ -9,9 +9,14 @@ Misskey API Core is a Dart/Flutter package that provides the core building block ### Key Features - HTTP foundation: base URL handling (/api), timeouts, idempotent retries (429/5xx/network), request/response logging (debug-only) +- Base URL exposure: access original base URL via `client.baseUrl` for derived services - Auth token injection: automatically injects `i` into POST JSON bodies when `authRequired` is true +- Flexible token providers: support both sync and async token sources via `FutureOr` - Unified error: normalize Misskey error response to `MisskeyApiException(statusCode/code/message)` +- Customizable error handling: map exceptions via `exceptionMapper` for unified error policies +- Flexible logging: use `loggerFn` for function-style logging or existing `Logger` interface - Meta capability: `/api/meta` client with a tiny cache and `supports()` helper +- Meta refresh: force-refresh cached meta data with `getMeta(refresh: true)` - JSON serialization: `json_serializable`-ready common model(s) ### Install @@ -20,7 +25,7 @@ Add to `pubspec.yaml`: ```yaml dependencies: - misskey_api_core: ^0.0.1-beta + misskey_api_core: ^0.0.2-beta ``` Then: @@ -41,11 +46,14 @@ void main() async { timeout: const Duration(seconds: 10), enableLog: true, // logs only in debug mode ), - tokenProvider: () async => 'YOUR_TOKEN', + tokenProvider: () async => 'YOUR_TOKEN', // or sync: () => 'TOKEN' ); // Fetch meta (no auth) final meta = await MetaClient(client).getMeta(); + + // Force refresh meta data + final freshMeta = await MetaClient(client).getMeta(refresh: true); // Example POST (token `i` will be injected automatically) final res = await client.send>( @@ -53,6 +61,9 @@ void main() async { body: {'limit': 10}, options: const RequestOptions(idempotent: true), ); + + // Access base URL for derived services (e.g., streaming) + final origin = client.baseUrl; } ``` @@ -73,9 +84,14 @@ Misskey API Core は、Misskeyサーバーと連携するためのDart/Flutter ### 機能 - HTTP基盤: ベースURL(/api付与)・タイムアウト・冪等時の自動リトライ(429/5xx/ネットワーク)・デバッグ時のみログ +- ベースURL公開: `client.baseUrl` で元URLにアクセス(派生サービス用) - 認証: POSTのJSONボディに `i` を自動注入(`authRequired`で制御) +- 柔軟なトークン供給: 同期・非同期両方に対応(`FutureOr`) - 共通例外: Misskeyのエラーを `MisskeyApiException(statusCode/code/message)` に正規化 +- カスタマイズ可能な例外処理: `exceptionMapper` で例外を一元変換 +- 柔軟なログ出力: 関数ベースロガー(`loggerFn`)または既存Logger IF - メタ/能力検出: `/api/meta` の取得と簡易キャッシュ、`supports()` ヘルパー +- メタ更新: `getMeta(refresh: true)` でキャッシュを強制更新 - JSONシリアライズ: `json_serializable`対応の共通モデル ### インストール @@ -84,7 +100,7 @@ Misskey API Core は、Misskeyサーバーと連携するためのDart/Flutter ```yaml dependencies: - misskey_api_core: ^0.0.1-beta + misskey_api_core: ^0.0.2-beta ``` 実行: @@ -104,18 +120,24 @@ final client = MisskeyHttpClient( timeout: const Duration(seconds: 10), enableLog: true, // デバッグ時のみ ), - tokenProvider: () async => 'YOUR_TOKEN', + tokenProvider: () async => 'YOUR_TOKEN', // または同期: () => 'TOKEN' ); // 認証不要 final meta = await MetaClient(client).getMeta(); +// メタデータを強制更新 +final freshMeta = await MetaClient(client).getMeta(refresh: true); + // 読み取り系POST(`i`は自動注入) final list = await client.send>( '/notes/timeline', body: {'limit': 10}, options: const RequestOptions(idempotent: true), ); + +// 派生サービス用にベースURLにアクセス(例: ストリーミング) +final origin = client.baseUrl; ``` サンプルアプリ(`/example`)では、`misskey_auth` を使った認証、ノート投稿、ホームタイムライン、フォロー中/フォロワーの取得まで一通り確認できます。 diff --git a/pubspec.yaml b/pubspec.yaml index dfa781f..b723d5a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: misskey_api_core description: "A library to make it easy to use the Misskey API in your Flutter and Dart apps." -version: 0.0.1-beta +version: 0.0.2-beta homepage: https://librarylibrarian.com/ repository: https://github.com/LibraryLibrarian/misskey_api_core issue_tracker: https://github.com/LibraryLibrarian/misskey_api_core/issues From 1c8a05ebf4c2a04f698644d51b6cf85b8b67e8e4 Mon Sep 17 00:00:00 2001 From: librarian <57712678+LibraryLibrarian@users.noreply.github.com> Date: Tue, 19 Aug 2025 06:47:48 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20pubspec.yaml=E3=81=ABfile=E3=83=91?= =?UTF-8?q?=E3=83=83=E3=82=B1=E3=83=BC=E3=82=B8=E3=81=AE=E4=BE=9D=E5=AD=98?= =?UTF-8?q?=E9=96=A2=E4=BF=82=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ciにてfilepackage6.0.0が利用されていて不一致によりエラーが起きていた為、明示 --- pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/pubspec.yaml b/pubspec.yaml index b723d5a..2107491 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -35,6 +35,7 @@ dev_dependencies: flutter_lints: ^6.0.0 build_runner: ^2.7.0 json_serializable: ^6.10.0 + file: ^7.0.1 # For information on the generic Dart part of this file, see the # following page: https://dart.dev/tools/pub/pubspec From ee7f35eb41e7e6af047723081d0bf3f8b91e0d2a Mon Sep 17 00:00:00 2001 From: librarian <57712678+LibraryLibrarian@users.noreply.github.com> Date: Tue, 19 Aug 2025 06:55:05 +0900 Subject: [PATCH 4/4] =?UTF-8?q?fix:=20CI=E3=83=AF=E3=83=BC=E3=82=AF?= =?UTF-8?q?=E3=83=95=E3=83=AD=E3=83=BC=E3=81=AE=E3=82=B3=E3=83=BC=E3=83=89?= =?UTF-8?q?=E7=94=9F=E6=88=90=E3=82=B3=E3=83=9E=E3=83=B3=E3=83=89=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - build_runnerの実行コマンドをdartからflutterに変更し、正しい環境でのコード生成を実施 --- .github/workflows/ci.yaml | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e58218a..8f104ad 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -66,10 +66,23 @@ jobs: if: ${{ hashFiles('test/**/*_test.dart') != '' }} run: flutter test - name: Codegen verify (only latest) - if: matrix.flutter == '3.32.x' + if: matrix.flutter == '3.32.x' && matrix.resolution == 'max' run: | + set -euo pipefail + # build_runner が無い場合はスキップ + if ! grep -q 'build_runner:' pubspec.yaml; then + echo 'build_runner not found; skipping codegen verify' + exit 0 + fi + flutter pub get dart run build_runner build -d --build-filter="lib/**" - git diff --exit-code || (echo 'Codegen produced changes. Please commit generated files.' && exit 1) + # 生成物に差分があれば失敗 + git update-index -q --refresh + if ! git diff --quiet --exit-code -- lib/; then + echo 'Codegen produced changes. Please commit generated files.' + git --no-pager diff -- lib/ | cat + exit 1 + fi example-android: needs: changes