Skip to content

Commit a2a418b

Browse files
authored
feat: Add AGENTS.md (#6815)
1 parent e85df40 commit a2a418b

1 file changed

Lines changed: 172 additions & 0 deletions

File tree

AGENTS.md

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# Project Info
2+
3+
## Setup
4+
5+
```bash
6+
git submodule update --init --recursive
7+
dart pub global activate -spath packages/aft
8+
aft bootstrap
9+
```
10+
11+
## Linting
12+
13+
Changes MUST pass:
14+
```
15+
flutter analyze
16+
```
17+
18+
### Auto format:
19+
```
20+
dart pub get # crucial to run this!
21+
dart fix --apply .
22+
dart format .
23+
```
24+
25+
## Project Coding Conventions & Patterns Summary
26+
27+
### Project Overview
28+
- **Language**: Dart (Flutter + pure Dart)
29+
- **Architecture**: Monorepo with ~25+ packages under `packages/`
30+
- **Tooling**: Custom `aft` (Amplify Flutter Tool) for bootstrapping, formatting, analysis, testing
31+
- Root `pubspec.yaml` - Flutter/Dart monorepo configuration with multiple packages
32+
33+
---
34+
35+
### 1. File & Directory Naming
36+
- **snake_case** for all Dart files: `auth_plugin_impl.dart`, `state_machine.dart`, `amplify_exception.dart`
37+
- **snake_case** for directories: `amplify_core`, `aws_common`, `amplify_auth_cognito_dart`
38+
- Package names follow pattern: `amplify_<category>` for Flutter, `amplify_<category>_dart` for pure Dart
39+
- Generated files use `.g.dart` suffix (json_serializable)
40+
- Platform-conditional files use suffixes: `globals.flutter.dart`, `globals.dart.dart`, `initial_parameters_stub.dart` / `initial_parameters_html.dart`
41+
42+
### 2. License Header (Required on ALL files)
43+
```dart
44+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
45+
// SPDX-License-Identifier: Apache-2.0
46+
```
47+
Enforced via `tool/license.sh` and CI checks.
48+
49+
### 3. Code Style & Lint Rules
50+
- Every `analysis_options.yaml` MUST include a shared lint profile from `packages/amplify_lints/`:
51+
- **Library packages**: `include: package:amplify_lints/library.yaml`
52+
- **Example/app packages**: `include: package:amplify_lints/app.yaml`
53+
- The profiles handle all lint rules, strict mode settings, and enforced conventions. Packages may add local overrides (e.g., excluding `.g.dart` files) but must not replace the base include.
54+
55+
### 4. Documentation Patterns
56+
- **Dartdoc template/macro system** used extensively:
57+
```dart
58+
/// {@template amplify_core.amplify_exception}
59+
/// Description here.
60+
/// {@endtemplate}
61+
```
62+
Then referenced elsewhere:
63+
```dart
64+
/// {@macro amplify_core.amplify_exception}
65+
```
66+
- **Category tags** for dartdoc categorization: `/// {@category Auth}`
67+
- All public APIs have doc comments (enforced by `public_member_api_docs`)
68+
- Code examples in docs use `<?code-excerpt>` syntax for verified code excerpts
69+
70+
### 5. Architecture Patterns
71+
72+
#### 5a. Category/Plugin Architecture
73+
- **Categories**: Abstract interfaces (`AuthCategory`, `StorageCategory`, etc.) define the public API
74+
- **Plugins**: Concrete implementations (`AmplifyAuthCognitoDart`) implement category interfaces
75+
- **Plugin Key pattern**: Static `pluginKey` constant for type-safe plugin retrieval:
76+
```dart
77+
static const AuthPluginKey<AmplifyAuthCognitoDart> pluginKey = _AmplifyAuthCognitoDartPluginKey();
78+
```
79+
80+
#### 5b. State Machine Pattern (Core architectural pattern)
81+
- Extensive use of typed state machines for complex flows (auth, sign-in, sign-out, etc.)
82+
- Hierarchy: `StateMachineManager``StateMachine``StateMachineEvent` / `StateMachineState`
83+
- States are `sealed` classes with named constructors for each variant:
84+
```dart
85+
sealed class SignInState extends AuthState<SignInStateType> {
86+
const factory SignInState.notStarted() = SignInNotStarted;
87+
const factory SignInState.success(AuthUser user) = SignInSuccess;
88+
const factory SignInState.failure({...}) = SignInFailure;
89+
}
90+
```
91+
- State types expressed as enums: `SignInStateType { notStarted, initiating, challenge, success, failure }`
92+
- `SuccessState` and `ErrorState` mixins for terminal states
93+
- `EventCompleter<E, S>` for async event tracking with `accepted`/`completed` futures
94+
- Events have `checkPrecondition()` method for guard conditions
95+
96+
#### 5c. Dependency Injection
97+
- `DependencyManager` (service locator pattern) with `addBuilder()`, `addInstance()`, `get()`, `getOrCreate()`
98+
- `Token<T>` for type-safe dependency keys
99+
- `_ScopedDependencyManager` for hierarchical scope
100+
101+
#### 5d. Dart/Flutter Split
102+
- Pure Dart packages (`_dart` suffix) for cross-platform logic
103+
- Flutter packages wrap Dart packages for platform integration
104+
- Conditional imports for web vs. VM: `if (dart.library.js_interop)`
105+
106+
### 6. Type System Patterns
107+
108+
#### 6a. Mixins as Core Building Blocks
109+
- `AWSEquatable<T>` — Value equality via `props` list (like Equatable package)
110+
- `AWSDebuggable` — Safe `toString()` via `runtimeTypeName` (prevents runtime reflection)
111+
- `AWSSerializable<T>``toJson()` contract
112+
- `AmplifyLoggerMixin` — Logging integration
113+
- Classes commonly compose multiple mixins:
114+
```dart
115+
class AmplifyOutputs with AWSEquatable<AmplifyOutputs>, AWSSerializable, AWSDebuggable { ... }
116+
```
117+
118+
#### 6b. Sealed Classes & Pattern Matching
119+
- Heavy use of Dart 3 sealed classes for states and results:
120+
```dart
121+
sealed class AWSResult<V, E extends Exception> { ... }
122+
final class AWSSuccessResult<V, E> extends AWSResult<V, E> { ... }
123+
final class AWSErrorResult<V, E> extends AWSResult<V, E> { ... }
124+
```
125+
- `final class` for concrete implementations (prevent extension)
126+
- `base class` / `base mixin` for state machine types (controlled hierarchy)
127+
- Dart 3 pattern matching (`switch` expressions, `case` patterns) used throughout
128+
129+
#### 6c. Immutability
130+
- `@immutable` annotation on value types
131+
- `const` constructors used wherever possible
132+
- `prefer_final_locals` enforced by lints
133+
134+
### 7. Error Handling
135+
- `AmplifyException` (recoverable) vs `AmplifyError` (non-recoverable) distinction
136+
- Exceptions include `message`, `recoverySuggestion`, `underlyingException`
137+
- Category-specific exception hierarchies via `part` files
138+
- `PreconditionException` for state machine guard failures
139+
- `only_throw_errors` lint: only throw `Exception`/`Error` subclasses
140+
141+
### 8. Serialization
142+
- `json_serializable` + `json_annotation` for JSON serialization
143+
- Shared serialization options via constants:
144+
- `zAmplifySerializable` — Standard Amplify types (`includeIfNull: false`, `explicitToJson: true`)
145+
- `zAwsSerializable` — AWS types (`fieldRename: FieldRename.pascal`)
146+
- `zAmplifyOutputsSerializable` — Amplify Outputs (`fieldRename: FieldRename.snake`)
147+
- Generated code in `.g.dart` files, excluded from analysis
148+
149+
### 9. Naming Conventions
150+
- **Constants**: `lowerCamelCase` with `z` prefix for internal/library-wide constants: `zAmplifySerializable`, `zIsFlutter`, `zDefaultLogLevel`, `zAssertsEnabled`
151+
- **Enums**: `PascalCase` type, `lowerCamelCase` values
152+
- Use visibility annotations (`@protected`, `@visibleForTesting`, `@internal`) from `package:meta`
153+
- **Factory constructors**: Named after source — `fromJson`, `fromMap`
154+
155+
### 10. Testing Patterns
156+
- Tests use `package:test` (not `flutter_test`) for pure Dart
157+
- Standard `group`/`test` structure
158+
- `@TestOn('vm')` or `@TestOn('browser')` for platform-specific tests
159+
- `MockAWSHttpClient` for HTTP mocking
160+
- `@visibleForTesting` setters/properties for test hooks
161+
- `zAssertsEnabled` guard for test-only code paths
162+
163+
### 11. Library Declarations
164+
- Modern `library;` syntax (unnamed libraries) in Dart 3
165+
- `part`/`part of` used for tightly-coupled files (e.g., state machine states/events grouped via parts)
166+
- Barrel files use explicit `export` with `show`/`hide` for API control
167+
168+
### 12. Monorepo Management
169+
- Root `pubspec.yaml` defines shared dependency versions
170+
- `aft bootstrap` creates `pubspec_overrides.yaml` for local development
171+
- Components are grouped for coordinated versioning (e.g., all `Amplify Flutter` packages version together)
172+
- Semantic versioning followed; new enum cases = minor version bump

0 commit comments

Comments
 (0)