LCOV - code coverage report
Current view: top level - repository - repository.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 32 38 84.2 %
Date: 2021-12-09 18:46:36 Functions: 0 0 -

          Line data    Source code
       1             : part of flutter_data;
       2             : 
       3             : /// Thin wrapper on the [RemoteAdapter] API
       4             : class Repository<T extends DataModel<T>> with _Lifecycle {
       5             :   final Reader _read;
       6           1 :   Repository(this._read);
       7             : 
       8             :   var _isInit = false;
       9             : 
      10           2 :   String get _internalType => DataHelpers.getType<T>();
      11             : 
      12             :   final _adapters = <String, RemoteAdapter>{};
      13             : 
      14             :   /// Obtain the [RemoteAdapter] for this type.
      15           1 :   RemoteAdapter<T> get remoteAdapter =>
      16           3 :       _adapters[_internalType]! as RemoteAdapter<T>;
      17             : 
      18             :   /// Type for the [RemoteAdapter]
      19           0 :   @nonVirtual
      20           0 :   String get type => remoteAdapter.type;
      21             : 
      22             :   /// Initializes this [Repository]. Nothing will work without this.
      23             :   /// In standard scenarios this initialization is done by the framework.
      24             :   @mustCallSuper
      25           1 :   FutureOr<Repository<T>> initialize(
      26             :       {bool? remote,
      27             :       bool? verbose,
      28             :       required Map<String, RemoteAdapter> adapters}) async {
      29           1 :     if (isInitialized) return this;
      30           2 :     _adapters.addAll(adapters);
      31           3 :     await remoteAdapter.initialize(
      32             :       remote: remote,
      33             :       verbose: verbose,
      34             :       adapters: adapters,
      35           1 :       read: _read,
      36             :     );
      37           1 :     _isInit = true;
      38             :     return this;
      39             :   }
      40             : 
      41             :   /// Returns whether this [Repository] is initialized
      42             :   /// (when its underlying [RemoteAdapter] is).
      43           1 :   @override
      44           3 :   bool get isInitialized => _isInit && remoteAdapter.isInitialized;
      45             : 
      46             :   /// Disposes this [Repository] and everything that depends on it.
      47           1 :   @override
      48             :   void dispose() {
      49           1 :     if (isInitialized) {
      50           2 :       remoteAdapter.dispose();
      51           1 :       _isInit = false;
      52             :     }
      53             :   }
      54             : 
      55             :   // Public API
      56             : 
      57             :   /// Returns all models of type [T].
      58             :   ///
      59             :   /// If [_RemoteAdapter.shouldLoadRemoteAll] (function of [remote]) is `true`,
      60             :   /// it will initiate an HTTP call.
      61             :   /// Otherwise returns all models of type [T] in local storage.
      62             :   ///
      63             :   /// Arguments [params] and [headers] will be merged with
      64             :   /// [_RemoteAdapter.defaultParams] and [_RemoteAdapter.defaultHeaders], respectively.
      65             :   ///
      66             :   /// For local storage of type [T] to be synchronized to the exact resources
      67             :   /// returned from the remote source when using `findAll`, pass `syncLocal: true`.
      68             :   /// This call would, for example, reflect server-side resource deletions.
      69             :   /// The default is `syncLocal: false`.
      70             :   ///
      71             :   /// See also: [_RemoteAdapter.urlForFindAll], [_RemoteAdapter.methodForFindAll].
      72           1 :   Future<List<T>> findAll({
      73             :     bool? remote,
      74             :     Map<String, dynamic>? params,
      75             :     Map<String, String>? headers,
      76             :     bool? syncLocal,
      77             :     OnDataError<List<T>>? onError,
      78             :   }) {
      79           2 :     return remoteAdapter.findAll(
      80             :       remote: remote,
      81             :       params: params,
      82             :       headers: headers,
      83             :       syncLocal: syncLocal,
      84             :       onError: onError,
      85             :     );
      86             :   }
      87             : 
      88             :   /// Returns model of type [T] by [id].
      89             :   ///
      90             :   /// If [_RemoteAdapter.shouldLoadRemoteOne] (function of [remote]) is `true`,
      91             :   /// it will initiate an HTTP call.
      92             :   /// Otherwise returns model of type [T] and [id] in local storage.
      93             :   ///
      94             :   /// Arguments [params] and [headers] will be merged with
      95             :   /// [_RemoteAdapter.defaultParams] and [_RemoteAdapter.defaultHeaders], respectively.
      96             :   ///
      97             :   /// See also: [_RemoteAdapter.urlForFindOne], [_RemoteAdapter.methodForFindOne].
      98           1 :   Future<T?> findOne(
      99             :     final dynamic id, {
     100             :     bool? remote,
     101             :     Map<String, dynamic>? params,
     102             :     Map<String, String>? headers,
     103             :     OnDataError<T>? onError,
     104             :   }) {
     105           2 :     return remoteAdapter.findOne(
     106             :       id,
     107             :       remote: remote,
     108             :       params: params,
     109             :       headers: headers,
     110             :       onError: onError,
     111             :     );
     112             :   }
     113             : 
     114             :   /// Saves [model] of type [T].
     115             :   ///
     116             :   /// If [remote] is `true`, it will initiate an HTTP call.
     117             :   ///
     118             :   /// Always persists to local storage.
     119             :   ///
     120             :   /// Arguments [params] and [headers] will be merged with
     121             :   /// [_RemoteAdapter.defaultParams] and [_RemoteAdapter.defaultHeaders], respectively.
     122             :   ///
     123             :   /// See also: [_RemoteAdapter.urlForSave], [_RemoteAdapter.methodForSave].
     124           1 :   Future<T> save(
     125             :     T model, {
     126             :     bool? remote,
     127             :     Map<String, dynamic>? params,
     128             :     Map<String, String>? headers,
     129             :     OnData<T>? onSuccess,
     130             :     OnDataError<T>? onError,
     131             :   }) {
     132           2 :     return remoteAdapter.save(
     133             :       model,
     134             :       remote: remote,
     135             :       params: params,
     136             :       headers: headers,
     137             :       onSuccess: onSuccess,
     138             :       onError: onError,
     139             :     );
     140             :   }
     141             : 
     142             :   /// Deletes [model] of type [T].
     143             :   ///
     144             :   /// If [remote] is `true`, it will initiate an HTTP call.
     145             :   ///
     146             :   /// Always deletes from local storage.
     147             :   ///
     148             :   /// Arguments [params] and [headers] will be merged with
     149             :   /// [_RemoteAdapter.defaultParams] and [_RemoteAdapter.defaultHeaders], respectively.
     150             :   ///
     151             :   /// See also: [_RemoteAdapter.urlForDelete], [_RemoteAdapter.methodForDelete].
     152           1 :   Future<void> delete(
     153             :     dynamic model, {
     154             :     bool? remote,
     155             :     Map<String, dynamic>? params,
     156             :     Map<String, String>? headers,
     157             :     OnData<void>? onSuccess,
     158             :     OnDataError<void>? onError,
     159             :   }) {
     160           2 :     return remoteAdapter.delete(
     161             :       model,
     162             :       remote: remote,
     163             :       params: params,
     164             :       headers: headers,
     165             :       onSuccess: onSuccess,
     166             :       onError: onError,
     167             :     );
     168             :   }
     169             : 
     170             :   /// Deletes all models of type [T] in local storage.
     171             :   ///
     172             :   ///
     173             :   ///
     174             :   /// If you need to clear all models, use the
     175             :   /// `repositoryProviders` map exposed on your `main.data.dart`.
     176           3 :   Future<void> clear() => remoteAdapter.clear();
     177             : 
     178             :   // offline
     179             : 
     180             :   /// Gets a list of all pending [OfflineOperation]s for this type.
     181           1 :   Set<OfflineOperation<T>> get offlineOperations =>
     182           2 :       remoteAdapter.offlineOperations;
     183             : 
     184             :   // watchers
     185             : 
     186             :   /// Watches changes on all models of type [T] in local storage.
     187             :   ///
     188             :   /// When called, will in turn call [findAll] with [remote], [params],
     189             :   /// [headers], [syncLocal].
     190           1 :   DataStateNotifier<List<T>> watchAllNotifier({
     191             :     bool? remote,
     192             :     Map<String, dynamic>? params,
     193             :     Map<String, String>? headers,
     194             :     bool? syncLocal,
     195             :   }) {
     196           2 :     return remoteAdapter.watchAllNotifier(
     197             :       remote: remote,
     198             :       params: params,
     199             :       headers: headers,
     200             :       syncLocal: syncLocal,
     201             :     );
     202             :   }
     203             : 
     204             :   /// Watches a provider wrapping [watchAllNotifier]
     205             :   /// which allows the watcher to be notified of changes
     206             :   /// on any model of this [type].
     207             :   ///
     208             :   /// Example: Watch all models of type `books` on a Riverpod hook-enabled app.
     209             :   ///
     210             :   /// ```
     211             :   /// ref.books.watchAll();
     212             :   /// ```
     213           0 :   DataState<List<T>> watchAll({
     214             :     bool? remote,
     215             :     Map<String, dynamic>? params,
     216             :     Map<String, String>? headers,
     217             :     bool? syncLocal,
     218             :   }) {
     219           0 :     return remoteAdapter.watchAll(
     220             :       remote: remote,
     221             :       params: params,
     222             :       headers: headers,
     223             :       syncLocal: syncLocal,
     224             :     );
     225             :   }
     226             : 
     227             :   /// Returns a [DataState] notifier with changes on model of
     228             :   /// type [T] by [id] in local storage.
     229             :   ///
     230             :   /// Optionally reacts to selected relationships of this model via [alsoWatch].
     231             :   ///
     232             :   /// Will invoke [findAll] with [remote], [params], [headers].
     233           1 :   DataStateNotifier<T?> watchOneNotifier(
     234             :     dynamic id, {
     235             :     bool? remote,
     236             :     Map<String, dynamic>? params,
     237             :     Map<String, String>? headers,
     238             :     AlsoWatch<T>? alsoWatch,
     239             :   }) {
     240           2 :     return remoteAdapter.watchOneNotifier(
     241             :       id,
     242             :       remote: remote,
     243             :       params: params,
     244             :       headers: headers,
     245             :       alsoWatch: alsoWatch,
     246             :     );
     247             :   }
     248             : 
     249             :   /// Watches a provider wrapping [watchOneNotifier]
     250             :   /// which allows the watcher to be notified of changes
     251             :   /// on a specific model of this [type], optionally reacting
     252             :   /// to selected relationships of this model via [alsoWatch].
     253             :   ///
     254             :   /// Example: Watch model of type `books` and `id=1` along
     255             :   /// with its `author` relationship on a Riverpod hook-enabled app.
     256             :   ///
     257             :   /// ```
     258             :   /// ref.books.watchOne(1, alsoWatch: (book) => [book.author]);
     259             :   /// ```
     260           0 :   DataState<T?> watchOne(
     261             :     dynamic id, {
     262             :     bool? remote,
     263             :     Map<String, dynamic>? params,
     264             :     Map<String, String>? headers,
     265             :     AlsoWatch<T>? alsoWatch,
     266             :   }) {
     267           0 :     return remoteAdapter.watchOne(
     268             :       id,
     269             :       remote: remote,
     270             :       params: params,
     271             :       headers: headers,
     272             :       alsoWatch: alsoWatch,
     273             :     );
     274             :   }
     275             : }
     276             : 
     277             : /// Annotation on a [DataModel] model to request a [Repository] be generated for it.
     278             : ///
     279             : /// Takes a list of [adapters] to be mixed into this [Repository].
     280             : /// Public methods of these [adapters] mixins will be made available in the repository
     281             : /// via extensions.
     282             : ///
     283             : /// A classic example is:
     284             : ///
     285             : /// ```
     286             : /// @JsonSerializable()
     287             : /// @DataRepository([JSONAPIAdapter])
     288             : /// class Todo with DataModel<Todo> {
     289             : ///   @override
     290             : ///   final int id;
     291             : ///   final String title;
     292             : ///   final bool completed;
     293             : ///
     294             : ///   Todo({this.id, this.title, this.completed = false});
     295             : /// }
     296             : ///```
     297             : class DataRepository {
     298             :   final List<Type> adapters;
     299             :   final bool remote;
     300           6 :   const DataRepository(this.adapters, {this.remote = true});
     301             : }

Generated by: LCOV version 1.15