diff --git a/.gitignore b/.gitignore index c4b9f885..f894cace 100644 --- a/.gitignore +++ b/.gitignore @@ -12,7 +12,6 @@ devtools_options.yaml .fvmrc .fvm/ -AGENTS.md # Environment files ios/Flutter/Dart-Defines.xcconfig diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..b935535f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,188 @@ +# flutter_cache_manager agent instructions + +Technical reference for AI agents and contributors developing in this repository. + +Process and conduct live in their own files: contribution workflow in +[CONTRIBUTING.md](CONTRIBUTING.md), the [Contributor Covenant Code of +Conduct](CODE_OF_CONDUCT.md) (report unacceptable behavior to +[hello@baseflow.com](mailto:hello@baseflow.com)). + +## Scope and stack + +- This repo is the **Flutter Cache Manager** monorepo maintained by [Baseflow](https://baseflow.com). +- It contains two Dart packages (not a federated plugin). Work inside the **specific package** you are changing; there is no Melos or root pub workspace, and neither should be added unless the team decides to. +- Run Flutter and Dart commands with the same tooling CI uses (`flutter`, `dart`). If you pin SDK versions locally with [fvm](https://fvm.app), prefix commands with `fvm` (this checkout typically uses `fvm`). + +### Prerequisites + +- Basic Dart and Flutter knowledge +- A working Flutter SDK installation (stable channel, matching CI — currently Flutter **3.44.4** in workflows) +- Comfort with filesystem / HTTP caching concepts helps, but is not required to start +- For running or building the example on iOS/macOS, access to a Mac is required +- Android example builds require JDK 17 + +### Reference documentation + +This package is primarily a **Dart/Flutter library** (file download + disk cache), not a federated platform plugin. Prefer official Flutter/Dart docs and this repo's existing code for hands-on work: + +- [Using packages](https://docs.flutter.dev/packages-and-plugins/using-packages) +- [Developing packages & plugins](https://docs.flutter.dev/packages-and-plugins/developing-packages) +- [Effective Dart](https://dart.dev/effective-dart) +- [pub versioning philosophy](https://dart.dev/tools/pub/versioning) + +## Packages in this repo + +| Package | Role | +|---------|------| +| `flutter_cache_manager` | Core cache manager: download, store, and serve files with configurable TTL / capacity | +| `flutter_cache_manager_firebase` | Optional `FileService` / cache manager integration for `firebase_storage` (`gs://` → HTTPS) | + +There is no Melos workspace. Each package has its own `pubspec.yaml`, tests, and CI workflow. + +## Architecture overview + +``` +App → CacheManager / DefaultCacheManager / custom Config + → CacheStore (mem cache + CacheInfoRepository) + → WebHelper + FileService (HTTP or custom, e.g. Firebase) + → FileSystem (IO or memory on web) +``` + +Platform defaults for `CacheInfoRepository` (see `lib/src/config/_config_io.dart`): + +- **Android / iOS / macOS** → `CacheObjectProvider` (sqflite) +- **Windows / Linux** → `JsonCacheInfoRepository` +- **Web** → non-storing provider + +Custom `Config` can override `repo`, `fileSystem`, and `fileService`. Prefer extending or composing these abstractions rather than forking `CacheManager` internals. + +**Persistence**: treat durability seriously — especially `JsonCacheInfoRepository` (full-file rewrite). Prefer serialized writes and atomic replace (temp + rename) over long debounce windows that can lose data on process kill. Do not reintroduce long debounce delays for JSON persistence without an explicit durability strategy (flush on close is not enough for force-stop). + +## Authoritative project structure + +- Root overview: `README.md` (symlink to `flutter_cache_manager/README.md`) +- Contribution workflow: `CONTRIBUTING.md` +- App-facing API: `flutter_cache_manager/lib/flutter_cache_manager.dart` +- Core manager: `flutter_cache_manager/lib/src/cache_manager.dart` +- Default / image managers: `flutter_cache_manager/lib/src/cache_managers/` +- Config (IO / web / unsupported): `flutter_cache_manager/lib/src/config/` +- In-memory + DB orchestration: `flutter_cache_manager/lib/src/cache_store.dart` +- Download / HTTP: `flutter_cache_manager/lib/src/web/` +- Cache metadata storage: `flutter_cache_manager/lib/src/storage/cache_info_repositories/` + - `CacheObjectProvider` — sqflite (default on Android / iOS / macOS) + - `JsonCacheInfoRepository` — JSON file (default on Windows / Linux) + - `NonStoringObjectProvider` — web / no persistence +- File system abstraction: `flutter_cache_manager/lib/src/storage/file_system/` +- Firebase package: `flutter_cache_manager_firebase/lib/` +- Example app: `flutter_cache_manager/example/` +- CI: + - `.github/workflows/build.yaml` — `flutter_cache_manager` + - `.github/workflows/build-firebase.yaml` — `flutter_cache_manager_firebase` + +## Where to make changes + +- **Public API / docs for app developers** → `flutter_cache_manager/lib/` exports and `README.md` +- **Download / HTTP behavior** → `lib/src/web/` +- **Persistence / metadata** → `lib/src/storage/cache_info_repositories/` +- **Cache eviction / mem cache** → `lib/src/cache_store.dart` +- **Firebase integration** → `flutter_cache_manager_firebase/` only +- **Never** put Firebase-specific logic in `flutter_cache_manager`, or platform-specific logic in the core package when it belongs in config hooks or the Firebase package + +Keep changes minimal in scope — one concern per change; match existing naming, error-handling (`FlutterError.reportError` where used), and testing patterns. + +## Development setup + +Per [CONTRIBUTING.md](CONTRIBUTING.md) and Baseflow's open-source forking workflow: + +1. Fork `https://github.com/Baseflow/flutter_cache_manager` on GitHub. +2. Clone your fork: `git clone git@github.com:/flutter_cache_manager.git` +3. Add upstream (the official repo you fetch from, not your fork): + +```bash +git remote add upstream git@github.com:Baseflow/flutter_cache_manager.git +``` + +4. Branch from latest `develop`: + +```bash +git fetch upstream +git checkout upstream/develop -b +``` + +Expected remotes after setup: + +``` +origin git@github.com:/flutter_cache_manager.git # your fork (push here) +upstream git@github.com:Baseflow/flutter_cache_manager.git # official repo (fetch here) +``` + +## Commands + +Run from the package you are editing (prefix with `fvm` when using FVM locally): + +```bash +cd flutter_cache_manager # or flutter_cache_manager_firebase +fvm flutter pub get +fvm dart format . +fvm flutter analyze +fvm flutter test +``` + +CI equivalents (no `fvm` on GitHub Actions): + +```bash +dart format --set-exit-if-changed . +flutter analyze +flutter test --coverage +``` + +Run the example app: + +```bash +cd flutter_cache_manager/example +fvm flutter run +``` + +Before finishing work, run the same checks CI runs for that package (format, analyze, test; example builds are covered in `build.yaml` for the main package). + +## Testing expectations + +| Package | Tests | +|---------|-------| +| `flutter_cache_manager` | Dart unit tests under `test/` (manager, store, web helper, repositories, image helpers) | +| `flutter_cache_manager_firebase` | Minimal Dart tests — verify via analyze/format and integration judgment | + +Prefer `MemoryFileSystem` / mocks over real disk or network in unit tests. When changing `JsonCacheInfoRepository`, cover persistence without relying on timers, and keep temp-file / failure paths in mind. + +## Platform notes + +- **Mobile / macOS**: default metadata store is sqflite (`CacheObjectProvider`). +- **Windows / Linux**: default metadata store is JSON (`JsonCacheInfoRepository`); writes should remain durable (write-through / short-lived queues, atomic replace). +- **Web**: limited / non-persisting storage via conditional imports (`_config_web.dart`, memory file system). +- **Firebase package**: depends on published `flutter_cache_manager`; local path overrides are only for integration experiments — do not assume Melos linking. + +## Pull request workflow + +This repo uses the **forking workflow**: contributors work on their own fork and open PRs to the main repository. Maintainers review and merge — do not push directly to `Baseflow/flutter_cache_manager`. + +1. Apply changes on a branch based on `upstream/develop`. +2. Verify locally (from the changed package): + - `dart format .` (or `fvm dart format .`) + - `flutter analyze` + - `flutter test` +3. Push to your fork: `git push origin ` +4. Open a PR against `Baseflow/flutter_cache_manager` and fill out the full [PR template](.github/PULL_REQUEST_TEMPLATE.md). + +Keep public API changes additive and non-breaking where possible; breaking changes need a clear major-version plan and README/CHANGELOG callouts. + +### PR checklist + +- [ ] Project builds for the changed package(s) +- [ ] This PR only changes one package (or documents why an exception is needed) +- [ ] `CHANGELOG.md` updated under `## [Unreleased]` in the changed package, following the [Flutter changelog style](https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changelog-style) — no version heading until maintainers cut a release +- [ ] Public API documented with `///` doc comments where applicable +- [ ] Rebased onto `develop` +- [ ] New tests added where applicable; all tests pass +- [ ] `dart format .` and `flutter analyze` pass with no errors, no warnings left unfixed +- [ ] Relevant README / docs updated for user-facing changes +- [ ] Full [PR template](.github/PULL_REQUEST_TEMPLATE.md) filled in diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..5b26f0ec --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,41 @@ +@AGENTS.md + +## Claude Code + +Everything tool-neutral lives in `AGENTS.md` (imported above). Keep it that way: only add +things here that are specific to Claude Code, and put any new project rule in `AGENTS.md` +so other agents and human contributors pick it up too. + +### Tooling in this checkout + +- Always drive Flutter/Dart through FVM: `fvm flutter ...` / `fvm dart ...`. A bare + `flutter` may resolve to a different SDK than CI (`.fvmrc` pins the `stable` channel). +- `flutter run` for `flutter_cache_manager/example/` is long-running — ask before starting + it and don't leave it running in the background. + +### Working style + +- Prefer the file tools (Read / Edit / Grep / Glob) over `cat`/`sed`/`grep` in Bash for + reading and editing repo files. +- Use the `Explore` subagent for wide searches across both packages; the tree is small + enough that targeted `Grep` is usually faster for anything narrower. +- Run `/code-review` on the diff before handing work over, and `/security-review` when a + change touches download/HTTP (`lib/src/web/`) or on-disk persistence + (`lib/src/storage/`). + +### Commits and PRs + +- Follow the forking + PR workflow in `AGENTS.md`; don't push to + `Baseflow/flutter_cache_manager` branches directly unless the maintainer asks for it in + that session. +- End commit messages with: + + ``` + Co-Authored-By: Claude + ``` + +- End PR descriptions with: + + ``` + 🤖 Generated with [Claude Code](https://claude.com/claude-code) + ``` diff --git a/flutter_cache_manager/CHANGELOG.md b/flutter_cache_manager/CHANGELOG.md index 97c1a155..195d5f6b 100644 --- a/flutter_cache_manager/CHANGELOG.md +++ b/flutter_cache_manager/CHANGELOG.md @@ -5,6 +5,8 @@ * Updates example Android project to AGP 9.0.1 / Gradle 9.1 / Kotlin 2.3.20 * Migrates example Android app to built-in Kotlin * Pins example `path_provider_android` to 2.2.22 to avoid transitive `jni` / `jni_flutter` AGP 9 issues +* Adds a root `CLAUDE.md` that imports `AGENTS.md` and holds Claude Code-specific contributor notes +* Publishes `AGENTS.md` (previously git-ignored) and trims it to technical content: architecture, directory map, fork workflow, commands, testing, and PR checklist ## [3.4.2]