LCOV - code coverage report
Current view: top level - src - middleware.dart Coverage Total Hit
Test: lcov.info Lines: 100.0 % 17 17
Test Date: 2026-04-30 18:23:23 Functions: - 0 0

            Line data    Source code
       1              : import 'package:flutter/foundation.dart';
       2              : 
       3              : /// Base class for all background task middleware.
       4              : ///
       5              : /// Middleware allows you to intercept and modify task configurations
       6              : /// globally before they are executed by the native engine.
       7              : @immutable
       8              : abstract class Middleware {
       9            2 :   const Middleware();
      10              : 
      11              :   /// Convert to map for platform channel.
      12              :   Map<String, dynamic> toMap();
      13              : }
      14              : 
      15              : /// Middleware that adds HTTP headers to all matching requests.
      16              : ///
      17              : /// Use this to globally inject authentication tokens or custom
      18              : /// user-agent strings into native HTTP workers.
      19              : class HeaderMiddleware extends Middleware {
      20            1 :   const HeaderMiddleware({
      21              :     required this.headers,
      22              :     this.urlPattern,
      23              :   });
      24              : 
      25              :   /// Map of headers to add.
      26              :   final Map<String, String> headers;
      27              : 
      28              :   /// Optional regex pattern to match URLs.
      29              :   ///
      30              :   /// If provided, headers are only added to HTTP workers whose URL
      31              :   /// matches this pattern. If null, applies to all HTTP workers.
      32              :   final String? urlPattern;
      33              : 
      34            2 :   @override
      35              :   Map<String, dynamic> toMap() {
      36            2 :     return {
      37              :       'type': 'header',
      38            2 :       'headers': headers,
      39            2 :       'urlPattern': urlPattern,
      40              :     };
      41              :   }
      42              : }
      43              : 
      44              : /// Middleware that POSTs task execution metadata to a custom endpoint
      45              : /// after each task completes (success or failure).
      46              : ///
      47              : /// Unlike [HeaderMiddleware] and [RemoteConfigMiddleware] (which modify worker
      48              : /// config before execution), `LoggingMiddleware` is a **post-execution hook**.
      49              : /// It fires a fire-and-forget HTTP POST and never affects the worker result.
      50              : ///
      51              : /// ## Payload
      52              : ///
      53              : /// ```json
      54              : /// {
      55              : ///   "taskId": "my-sync-task",
      56              : ///   "workerClassName": "HttpDownloadWorker",
      57              : ///   "success": true,
      58              : ///   "timestamp": 1712345678000,
      59              : ///   "durationMs": 1234,
      60              : ///   "message": "Downloaded 5.2 MB",
      61              : ///   "workerConfig": { ... }   // only when includeConfig: true
      62              : /// }
      63              : /// ```
      64              : ///
      65              : /// ## Usage
      66              : ///
      67              : /// ```dart
      68              : /// await NativeWorkManager.registerMiddleware(
      69              : ///   LoggingMiddleware(
      70              : ///     logUrl: 'https://logs.example.com/tasks',
      71              : ///     includeConfig: false,
      72              : ///   ),
      73              : /// );
      74              : /// ```
      75              : ///
      76              : /// Network errors from the log POST are silently swallowed — a logging
      77              : /// failure never causes a task to be marked as failed.
      78              : class LoggingMiddleware extends Middleware {
      79            1 :   const LoggingMiddleware({
      80              :     required this.logUrl,
      81              :     this.includeConfig = false,
      82              :   });
      83              : 
      84              :   /// URL to POST execution logs to after each task completes.
      85              :   final String logUrl;
      86              : 
      87              :   /// Whether to include the worker configuration map in the log payload.
      88              :   ///
      89              :   /// Disable (default) to avoid leaking sensitive config values (URLs,
      90              :   /// credentials, file paths) to your logging endpoint.
      91              :   final bool includeConfig;
      92              : 
      93            2 :   @override
      94              :   Map<String, dynamic> toMap() {
      95            2 :     return {
      96              :       'type': 'logging',
      97            2 :       'logUrl': logUrl,
      98            2 :       'includeConfig': includeConfig,
      99              :     };
     100              :   }
     101              : }
     102              : 
     103              : /// Middleware that injects remote configuration values into worker configs
     104              : /// at execution time.
     105              : ///
     106              : /// Use this to control worker behaviour dynamically at runtime — no app
     107              : /// update required. Values can come from any source: Firebase Remote Config,
     108              : /// AWS AppConfig, LaunchDarkly, or a plain REST endpoint.
     109              : ///
     110              : /// ## Usage
     111              : ///
     112              : /// ```dart
     113              : /// // 1. Fetch values from your config source (e.g. Firebase Remote Config)
     114              : /// final rc = FirebaseRemoteConfig.instance;
     115              : /// await rc.fetchAndActivate();
     116              : ///
     117              : /// // 2. Register middleware once at startup (or refresh on config change)
     118              : /// await NativeWorkManager.registerMiddleware(
     119              : ///   RemoteConfigMiddleware(
     120              : ///     values: {
     121              : ///       'timeout': rc.getInt('download_timeout_seconds'),
     122              : ///       'maxRetries': rc.getInt('max_retries'),
     123              : ///     },
     124              : ///     workerType: 'HttpDownload', // optional: only targets HttpDownloadWorker
     125              : ///   ),
     126              : /// );
     127              : /// ```
     128              : ///
     129              : /// To refresh the config (e.g. after a Remote Config fetch), simply call
     130              : /// `registerMiddleware` again with updated [values] — the native side
     131              : /// replaces the previous entry for the `remoteConfig` type.
     132              : ///
     133              : /// ## How it works
     134              : ///
     135              : /// Each key in [values] is injected directly into the native worker config
     136              : /// map, overriding any existing value with the same name. If [workerType]
     137              : /// is provided, the middleware only applies to workers whose class name
     138              : /// contains that string (case-insensitive substring match).
     139              : class RemoteConfigMiddleware extends Middleware {
     140            2 :   const RemoteConfigMiddleware({
     141              :     required this.values,
     142              :     this.workerType,
     143              :   });
     144              : 
     145              :   /// Config values to inject into matching worker configurations.
     146              :   ///
     147              :   /// Keys map directly to worker config fields. Supported value types:
     148              :   /// `String`, `int`, `double`, `bool`. Nested maps are not supported.
     149              :   final Map<String, dynamic> values;
     150              : 
     151              :   /// Optional worker class name filter (case-insensitive substring match).
     152              :   ///
     153              :   /// When set, only workers whose class name contains this string receive
     154              :   /// the injected values. For example, `'HttpDownload'` targets only
     155              :   /// `HttpDownloadWorker`. When `null`, all workers are affected.
     156              :   final String? workerType;
     157              : 
     158            3 :   @override
     159            3 :   Map<String, dynamic> toMap() => {
     160            3 :         'type': 'remoteConfig',
     161            6 :         'values': values,
     162            9 :         if (workerType != null) 'workerType': workerType,
     163              :       };
     164              : }
        

Generated by: LCOV version 2.4-0