-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
eng(supabase): add abstract packages (#402)
- Loading branch information
Showing
18 changed files
with
644 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
!example/**/*.g.dart |
5 changes: 5 additions & 0 deletions
5
packages/brick_offline_first_with_supabase_abstract/CHANGELOG.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## Unreleased | ||
|
||
### 0.0.1 | ||
|
||
Initial |
21 changes: 21 additions & 0 deletions
21
packages/brick_offline_first_with_supabase_abstract/LICENSE
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) Green Bits, Inc. and its affiliates. | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
147 changes: 147 additions & 0 deletions
147
packages/brick_offline_first_with_supabase_abstract/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
![brick_offline_first_with_rest workflow](https://github.com/GetDutchie/brick/actions/workflows/brick_offline_first_with_rest.yaml/badge.svg) | ||
|
||
`OfflineFirstWithRestRepository` streamlines the REST integration with an `OfflineFirstRepository`. A serial queue is included to track REST requests in a separate SQLite database, only removing requests when a response is returned from the host (i.e. the device has lost internet connectivity). See `OfflineFirstWithRest#reattemptForStatusCodes`. | ||
|
||
The `OfflineFirstWithRest` domain uses all the same configurations and annotations as `OfflineFirst`. | ||
|
||
## Models | ||
|
||
### ConnectOfflineFirstWithRest | ||
|
||
`@ConnectOfflineFirstWithRest` decorates the model that can be serialized by one or more providers. Offline First does not have configuration at the class level and only extends configuration held by its providers: | ||
|
||
```dart | ||
@ConnectOfflineFirstWithRest( | ||
restConfig: RestSerializable(), | ||
sqliteConfig: SqliteSerializable(), | ||
) | ||
class MyModel extends OfflineFirstModel {} | ||
``` | ||
|
||
## Generating Models from a REST Endpoint | ||
|
||
A utility class is provided to make model generation from a JSON API a snap. Given an endpoint, the converter will infer the type of a field and scaffold a class. For example, the following would be saved to the `lib` directory of your project and run `$ dart lib/converter_script.dart`: | ||
|
||
```dart | ||
// lib/converter_script.dart | ||
import 'package:brick_offline_first/rest_to_offline_first_converter.dart'; | ||
const BASE = "http://0.0.0.0:3000"; | ||
const endpoint = "$BASE/users"; | ||
final converter = RestToOfflineFirstConverter(endpoint: endpoint); | ||
void main() { | ||
converter.saveToFile(); | ||
} | ||
// => dart lib/converter_script.dart | ||
``` | ||
|
||
After the model is generated, double check for `List<dynamic>` and `null` types. While the converter is smart, it's not smarter than you. | ||
|
||
## Testing | ||
|
||
Responses can be stubbed to and from an `OfflineFirstWithRest` repository. For convenience, file data can be used to stub JSON responses from an API: | ||
|
||
```dart | ||
// test/models/api/user.json | ||
{ | ||
"user": { "name" : "Thomas" } | ||
} | ||
// test/models/user_test.dart | ||
import 'package:brick_sqlite/testing.dart'; | ||
import 'package:my_app/brick/repository.dart'; | ||
void main() { | ||
group("MySqliteProvider", () { | ||
late MyRepository repository; | ||
setUpAll(() async { | ||
repository = MyRepository( | ||
restProvider: RestProvider( | ||
client: StubOfflineFirstWithRest.fromFiles('http://0.0.0.0:3000', { | ||
'users': 'api/user.json' | ||
}).client, | ||
) | ||
); | ||
await repository.initialize() | ||
}); | ||
}); | ||
} | ||
``` | ||
|
||
By default, the same response is returned for both `upsert` and `get` methods, with the only variation being in status code. However, responses can be configured for different methods: | ||
|
||
```dart | ||
StubOfflineFirstWithRest( | ||
baseEndpoint: 'http://0.0.0.0:3000', | ||
responses: [ | ||
StubOfflineFirstRestResponse.fromFile('users', 'api/user.json', StubHttpMethod.get), | ||
StubOfflineFirstRestResponse.fromFile('users', 'api/user-post.json', StubHttpMethod.post), | ||
], | ||
) | ||
``` | ||
|
||
### Stubbing Without Files | ||
|
||
While storing the responses in a file can be convenient and reduce code clutter, responses can be defined inline: | ||
|
||
```dart | ||
StubOfflineFirstWithRest( | ||
baseEndpoint: 'http://0.0.0.0:3000', | ||
responses: [ | ||
StubOfflineFirstRestResponse('users', '{"name":"Bob"'), | ||
StubOfflineFirstRestResponse('users', '{"name":"Alice"'), | ||
], | ||
) | ||
``` | ||
|
||
### Handling Endpoint Variations | ||
|
||
Variants in the endpoint must be explicitly declared. For example, `/user`, `/users`, `/users?by_first_name=Guy` are all different. When instantiating, specify any expected variants: | ||
|
||
```dart | ||
StubOfflineFirstRestResponse<User>( | ||
endpoints: ["user", "users", "users?by_first_name=Guy"] | ||
) | ||
``` | ||
|
||
### Stubbing Multiple Models | ||
|
||
Rarely will only one model need to be stubbed. All classes in an app can be stubbed efficiently using `StubOfflineFirstWithRest`: | ||
|
||
```dart | ||
setUpAll() async { | ||
final config = { | ||
User: ['user', 'users'], | ||
// Even individual member endpoints must be declared for association fetching | ||
// REST endpoints are manually configured, so the content may vary | ||
Hat: ['hat/1', 'hat/2', 'hats'], | ||
} | ||
final responses = config.entries.map((modelConfig) { | ||
return modelConfig.value.map((endpoint) { | ||
return StubOfflineFirstRestResponse.fromFile( | ||
'api/${modelConfig.key.toString().toLowerCase()}.json', | ||
endpoint: endpoint, | ||
); | ||
}); | ||
}).expand((e) => e); | ||
final client = StubOfflineFirstWithRest( | ||
baseEndpoint: 'http://0.0.0.0:3000', | ||
responses: responses, | ||
).client; | ||
} | ||
``` | ||
|
||
### FAQ | ||
|
||
#### Why can't I declare a model argument? | ||
|
||
Due to [an open analyzer bug](https://github.com/dart-lang/sdk/issues/38309), a custom model cannot be passed to the repository as a type argument. | ||
|
||
## Unsupported Field Types | ||
|
||
* Any unsupported field types from `RestProvider`, or `SqliteProvider` | ||
* Future iterables of future models (i.e. `Future<List<Future<Model>>>`. |
1 change: 1 addition & 0 deletions
1
packages/brick_offline_first_with_supabase_abstract/analysis_options.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
include: ../../analysis_options.yaml |
1 change: 1 addition & 0 deletions
1
..._offline_first_with_supabase_abstract/lib/brick_offline_first_with_supabase_abstract.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export 'package:brick_offline_first_with_supabase_abstract/src/connect_offline_first_with_supabase.dart'; |
36 changes: 36 additions & 0 deletions
36
...ick_offline_first_with_supabase_abstract/lib/src/connect_offline_first_with_supabase.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import 'package:brick_sqlite/brick_sqlite.dart'; | ||
import 'package:brick_supabase_abstract/brick_supabase_abstract.dart'; | ||
|
||
/// An annotation used to specify a class to generate code for. | ||
/// | ||
/// Clones the annotated class to two files for processing by their respective builders | ||
class ConnectOfflineFirstWithSupabase { | ||
/// Creates a new [ConnectOfflineFirstWithSupabase] instance. | ||
const ConnectOfflineFirstWithSupabase({ | ||
this.sqliteConfig, | ||
this.supabaseConfig, | ||
}); | ||
|
||
/// Configuration for the [SqliteSerializable] annotation | ||
final SqliteSerializable? sqliteConfig; | ||
|
||
/// Configuration for the [SupabaseSerializable] annotation | ||
final SupabaseSerializable? supabaseConfig; | ||
|
||
/// An instance of [ConnectOfflineFirstWithSupabase] with all fields set to their default | ||
/// values. | ||
static const defaults = ConnectOfflineFirstWithSupabase( | ||
sqliteConfig: SqliteSerializable.defaults, | ||
supabaseConfig: SupabaseSerializable.defaults, | ||
); | ||
|
||
/// Returns a new [ConnectOfflineFirstWithSupabase] instance with fields equal to the | ||
/// corresponding values in `this`, if not `null`. | ||
/// | ||
/// Otherwise, the returned value has the default value as defined in | ||
/// [defaults]. | ||
ConnectOfflineFirstWithSupabase withDefaults() => ConnectOfflineFirstWithSupabase( | ||
sqliteConfig: sqliteConfig ?? defaults.sqliteConfig, | ||
supabaseConfig: supabaseConfig ?? defaults.supabaseConfig, | ||
); | ||
} |
19 changes: 19 additions & 0 deletions
19
packages/brick_offline_first_with_supabase_abstract/pubspec.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
name: brick_offline_first_with_supabase_abstract | ||
description: A Brick domain that routes data fetching through local providers | ||
before a Supabase provider. | ||
homepage: https://github.com/GetDutchie/brick/tree/main/packages/brick_offline_first_with_supabase_abstract | ||
issue_tracker: https://github.com/GetDutchie/brick/issues | ||
repository: https://github.com/GetDutchie/brick | ||
|
||
version: 0.0.1 | ||
|
||
environment: | ||
sdk: ">=2.18.0 <4.0.0" | ||
|
||
dependencies: | ||
brick_supabase_abstract: ">=0.0.1 <1.0.0" | ||
brick_sqlite: ">=3.0.0 <4.0.0" | ||
|
||
dev_dependencies: | ||
lints: ^2.0.1 | ||
test: ^1.16.5 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
## Unreleased | ||
|
||
### 0.0.1 | ||
|
||
Initial |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
The MIT License (MIT) | ||
|
||
Copyright (c) Green Bits, Inc. and its affiliates. | ||
|
||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without supabaseriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
Oops, something went wrong.