mirror of
https://github.com/zapstore/zapstore.git
synced 2026-10-05 12:38:24 +00:00
Architecture improvements
This commit is contained in:
@@ -53,18 +53,9 @@ If a guideline seems wrong or incomplete, report it as a Spec Issue.
|
||||
| `test/**` | Shared | Yes |
|
||||
| `CONTEXT.md` | Human | No |
|
||||
|
||||
## Key Dependencies
|
||||
|
||||
- **models** / **purplebase**: Nostr SDK (local-first storage, relay sync, domain models).
|
||||
See package README in pub cache. Basic usage patterns in `spec/guidelines/ARCHITECTURE.md`.
|
||||
- **amber_signer**: NIP-55 Android signer integration.
|
||||
- **background_downloader**: Download management with pause/resume.
|
||||
|
||||
## Working Rules
|
||||
|
||||
- Prefer small, localized changes. Avoid unrelated refactors.
|
||||
- After dependency changes, run: `fvm flutter pub get`
|
||||
- Fix any analyze/lint errors introduced by your changes.
|
||||
- Do not use polling or artificial `Future.delayed`; await Futures/Streams correctly.
|
||||
- Keep `lib/widgets/common` generic and reusable.
|
||||
- Assume Android as default target unless instructed otherwise.
|
||||
|
||||
@@ -1,35 +1,98 @@
|
||||
# Zapstore — Architecture
|
||||
|
||||
## Core Principle
|
||||
|
||||
Architecture exists to prevent accidental coupling and hidden ownership.
|
||||
Each package has clear responsibilities and must not exceed them.
|
||||
Each layer has clear responsibilities and must not exceed them.
|
||||
|
||||
## Package Responsibilities
|
||||
## Layers
|
||||
|
||||
### zapstore (this Flutter app)
|
||||
|
||||
- Flutter UI and application orchestration
|
||||
- Navigation, presentation, and user interaction
|
||||
- Coordinates use cases across dependencies
|
||||
- Must not contain domain rules or persistence logic
|
||||
|
||||
### Dart dependencies
|
||||
|
||||
#### models
|
||||
|
||||
### models
|
||||
- Domain models for Nostr events, kinds, zaps, releases, and NWC
|
||||
- Parsing, validation, signing, encryption, and verification
|
||||
- Pure domain logic only
|
||||
- Must not depend on storage, networking, isolates, or UI
|
||||
|
||||
### purplebase
|
||||
#### purplebase
|
||||
|
||||
- Local-first storage and indexing (SQLite)
|
||||
- Relay synchronization and subscription lifecycle management
|
||||
- Background work and isolate execution
|
||||
- Must not depend on UI or presentation logic
|
||||
|
||||
### zapstore
|
||||
- Flutter UI and application orchestration
|
||||
- Navigation, presentation, and user interaction
|
||||
- Coordinates use cases across packages
|
||||
- Must not contain domain rules or persistence logic
|
||||
|
||||
## Dependency Rules
|
||||
|
||||
- zapstore → purplebase → models
|
||||
- Reverse dependencies are forbidden
|
||||
- UI widgets must not manage relay connections, storage, or background jobs
|
||||
|
||||
## Ownership & Orchestration
|
||||
|
||||
- Relay pools and subscriptions are owned by purplebase
|
||||
- Background work lifecycle is explicit and cancellable
|
||||
- zapstore orchestrates flows but does not own low-level resources
|
||||
|
||||
## Common Patterns
|
||||
|
||||
### Widget watching data
|
||||
|
||||
```dart
|
||||
// Watch a query provider — reactive, auto-disposes
|
||||
final state = ref.watch(
|
||||
query<Profile>(
|
||||
authors: {pubkey},
|
||||
source: const LocalAndRemoteSource(relays: {'social'}),
|
||||
),
|
||||
);
|
||||
|
||||
return switch (state) {
|
||||
StorageLoading() => CircularProgressIndicator(),
|
||||
StorageError(:final exception) => Text('Error: $exception'),
|
||||
StorageData(:final models) => ProfileWidget(models.first),
|
||||
};
|
||||
|
||||
// Nested queries with `and` — loads relationships
|
||||
final appState = ref.watch(
|
||||
query<App>(
|
||||
tags: {'#d': {identifier}},
|
||||
and: (app) => {
|
||||
app.latestRelease.query(
|
||||
source: const LocalAndRemoteSource(relays: 'AppCatalog', stream: false),
|
||||
and: (release) => {release.latestMetadata.query()},
|
||||
),
|
||||
},
|
||||
source: const LocalAndRemoteSource(relays: 'AppCatalog'),
|
||||
subscriptionPrefix: 'app-detail',
|
||||
),
|
||||
);
|
||||
```
|
||||
|
||||
### Imperative queries (notifiers/services)
|
||||
|
||||
```dart
|
||||
// One-shot query via storage extension
|
||||
final apps = await ref.storage.query(
|
||||
RequestFilter<App>(authors: {pubkey}, limit: 20).toRequest(),
|
||||
);
|
||||
```
|
||||
|
||||
### Saving and publishing (from callbacks)
|
||||
|
||||
```dart
|
||||
onPressed: () async {
|
||||
await ref.storage.save({signedModel});
|
||||
await ref.storage.publish({signedModel});
|
||||
}
|
||||
```
|
||||
|
||||
For detailed API, see models/purplebase READMEs in pub cache.
|
||||
|
||||
Reference in New Issue
Block a user