
kiss-repository
by WAMF
A repository interface following the KISS (Keep It Simple, Stupid) principle.
SKILL.md
name: kiss-repository description: Guide for implementing and using kiss_repository - a lightweight Dart repository pattern for data access with CRUD, streaming, and batch operations allowed-tools: Read, Grep, Glob
kiss_repository Usage Guide
A lightweight, generic repository pattern implementation for Dart following the KISS principle.
Core Concepts
Repository
The abstract base class defining all data operations. Generic type T is your domain model.
IdentifiedObject
Wraps an object with its unique string ID:
final item = IdentifiedObject('user-123', User(name: 'Alice'));
// item.id == 'user-123'
// item.object == User(name: 'Alice')
Query System
Extend Query for domain-specific filters. Implement QueryBuilder<T> to translate queries to your implementation.
Available Implementations
- InMemoryRepository: Testing and temporary storage
- JsonFileRepository: File-based JSON persistence
CRUD Operations
Reading Data
// Get single item by ID (throws RepositoryException.notFound if missing)
final user = await repository.get('user-123');
// Query multiple items
final users = await repository.query(query: ActiveUsersQuery());
// Get all items
final allUsers = await repository.query();
Creating Data
// Add with explicit ID
await repository.add(IdentifiedObject('user-123', user));
// Add with auto-generated ID
await repository.addAutoIdentified(
user,
updateObjectWithId: (user, id) => user.copyWith(id: id),
);
Updating Data
// Update with transformer function
final updated = await repository.update('user-123', (current) =>
current.copyWith(name: 'New Name')
);
Deleting Data
await repository.delete('user-123');
Batch Operations
// Add multiple items atomically
await repository.addAll([
IdentifiedObject('id1', item1),
IdentifiedObject('id2', item2),
]);
// Update multiple items
await repository.updateAll([
IdentifiedObject('id1', updatedItem1),
IdentifiedObject('id2', updatedItem2),
]);
// Delete multiple items
await repository.deleteAll(['id1', 'id2', 'id3']);
Streaming (Real-time Updates)
// Stream single item changes
repository.stream('user-123').listen((user) {
print('User updated: ${user.name}');
});
// Stream query results
repository.streamQuery(query: ActiveUsersQuery()).listen((users) {
print('Active users: ${users.length}');
});
Streams emit immediately with current data (BehaviorSubject-like behavior).
Query Implementation
Define Custom Query
class UsersByRoleQuery extends Query {
const UsersByRoleQuery(this.role);
final String role;
}
Implement QueryBuilder
class UserQueryBuilder implements QueryBuilder<InMemoryFilterQuery<User>> {
@override
InMemoryFilterQuery<User> build(Query query) {
if (query is UsersByRoleQuery) {
return InMemoryFilterQuery<User>((user) => user.role == query.role);
}
return InMemoryFilterQuery<User>((user) => true);
}
}
Error Handling
try {
final user = await repository.get('non-existent');
} on RepositoryException catch (e) {
switch (e.code) {
case RepositoryErrorCode.notFound:
// Item doesn't exist
case RepositoryErrorCode.alreadyExists:
// ID already in use (on add)
case RepositoryErrorCode.unknown:
// Other error
}
}
Creating a Repository
InMemoryRepository
final repository = InMemoryRepository<User>(
queryBuilder: UserQueryBuilder(),
path: 'users',
initialItems: [
IdentifiedObject('user-1', User(name: 'Alice')),
],
);
JsonFileRepository
final repository = JsonFileRepository<User>(
queryBuilder: UserQueryBuilder(),
path: 'users',
file: File('users.json'),
fromJson: User.fromJson,
toJson: (user) => user.toJson(),
);
Resource Management
Always dispose repositories when done:
repository.dispose();
This cleans up all internal streams and resources.
Best Practices
- Generate IDs outside the repository or use
addAutoIdentified - Use
InMemoryRepositoryfor unit tests - Use
JsonFileRepositoryfor integration tests - Always call
dispose()when done - Handle
RepositoryExceptionfor error cases - Use streaming for real-time UI updates
- Use batch operations for multiple items of same type
Score
Total Score
Based on repository quality metrics
SKILL.mdファイルが含まれている
ライセンスが設定されている
100文字以上の説明がある
GitHub Stars 100以上
3ヶ月以内に更新がある
10回以上フォークされている
オープンIssueが50未満
プログラミング言語が設定されている
1つ以上のタグが設定されている
Reviews
Reviews coming soon