@aicgen/aicgen 1.0.0-beta.2 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agent/rules/api-design.md +649 -0
- package/.agent/rules/architecture.md +2507 -0
- package/.agent/rules/best-practices.md +622 -0
- package/.agent/rules/code-style.md +308 -0
- package/.agent/rules/design-patterns.md +577 -0
- package/.agent/rules/devops.md +230 -0
- package/.agent/rules/error-handling.md +417 -0
- package/.agent/rules/instructions.md +28 -0
- package/.agent/rules/language.md +786 -0
- package/.agent/rules/performance.md +710 -0
- package/.agent/rules/security.md +587 -0
- package/.agent/rules/testing.md +572 -0
- package/.agent/workflows/add-documentation.md +10 -0
- package/.agent/workflows/generate-integration-tests.md +10 -0
- package/.agent/workflows/generate-unit-tests.md +11 -0
- package/.agent/workflows/performance-audit.md +11 -0
- package/.agent/workflows/refactor-extract-module.md +12 -0
- package/.agent/workflows/security-audit.md +12 -0
- package/.gemini/instructions.md +4843 -0
- package/AGENTS.md +9 -11
- package/bun.lock +755 -4
- package/claude.md +2 -2
- package/config.example.yml +129 -0
- package/config.yml +38 -0
- package/data/guideline-mappings.yml +128 -0
- package/data/language/dart/async.md +289 -0
- package/data/language/dart/basics.md +280 -0
- package/data/language/dart/error-handling.md +355 -0
- package/data/language/dart/index.md +10 -0
- package/data/language/dart/testing.md +352 -0
- package/data/language/swift/basics.md +477 -0
- package/data/language/swift/concurrency.md +654 -0
- package/data/language/swift/error-handling.md +679 -0
- package/data/language/swift/swiftui-mvvm.md +795 -0
- package/data/language/swift/testing.md +708 -0
- package/data/version.json +10 -8
- package/dist/index.js +50295 -29101
- package/jest.config.js +46 -0
- package/package.json +13 -2
package/claude.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# my-project - Development Guidelines
|
|
2
2
|
|
|
3
3
|
**Role:** You are an expert software engineer specialized in typescript.
|
|
4
4
|
**User's Goal:** Build high-quality, maintainable software following strict project guidelines.
|
|
@@ -8,13 +8,13 @@
|
|
|
8
8
|
This project follows structured coding guidelines organized by category:
|
|
9
9
|
|
|
10
10
|
- **Language**: @.claude/guidelines/language.md
|
|
11
|
-
- **Architecture**: @.claude/guidelines/architecture.md
|
|
12
11
|
- **Testing**: @.claude/guidelines/testing.md
|
|
13
12
|
- **Security**: @.claude/guidelines/security.md
|
|
14
13
|
- **Performance**: @.claude/guidelines/performance.md
|
|
15
14
|
- **API Design**: @.claude/guidelines/api-design.md
|
|
16
15
|
- **Code Style**: @.claude/guidelines/code-style.md
|
|
17
16
|
- **Error Handling**: @.claude/guidelines/error-handling.md
|
|
17
|
+
- **Architecture**: @.claude/guidelines/architecture.md
|
|
18
18
|
- **DevOps**: @.claude/guidelines/devops.md
|
|
19
19
|
- **Best Practices**: @.claude/guidelines/best-practices.md
|
|
20
20
|
- **Design Patterns**: @.claude/guidelines/design-patterns.md
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Example AICGEN Configuration File
|
|
2
|
+
#
|
|
3
|
+
# LOCATION: This file should be placed at:
|
|
4
|
+
# - Windows: C:\Users\YourUsername\.aicgen\config.yml
|
|
5
|
+
# - Linux/Mac: ~/.aicgen/config.yml
|
|
6
|
+
#
|
|
7
|
+
# INSTALLATION:
|
|
8
|
+
# Windows:
|
|
9
|
+
# mkdir C:\Users\%USERNAME%\.aicgen
|
|
10
|
+
# copy config.example.yml C:\Users\%USERNAME%\.aicgen\config.yml
|
|
11
|
+
#
|
|
12
|
+
# Linux/Mac:
|
|
13
|
+
# mkdir -p ~/.aicgen
|
|
14
|
+
# cp config.example.yml ~/.aicgen/config.yml
|
|
15
|
+
#
|
|
16
|
+
# Configuration priority: Environment Variables > User Config > Defaults
|
|
17
|
+
|
|
18
|
+
# GitHub repository configuration
|
|
19
|
+
github:
|
|
20
|
+
owner: aicgen
|
|
21
|
+
repo: aicgen-data
|
|
22
|
+
|
|
23
|
+
# AI Provider Configuration
|
|
24
|
+
# Customize models, timeouts, and behavior for different AI providers
|
|
25
|
+
ai:
|
|
26
|
+
# Google Gemini Configuration
|
|
27
|
+
gemini:
|
|
28
|
+
# Model: Use latest Gemini 2.0 or 2.5 models
|
|
29
|
+
# See: https://ai.google.dev/gemini-api/docs/models
|
|
30
|
+
model: gemini-2.0-flash-exp
|
|
31
|
+
# Available models:
|
|
32
|
+
# - gemini-2.5-flash (latest, recommended)
|
|
33
|
+
# - gemini-2.5-pro (most capable, slower)
|
|
34
|
+
# - gemini-2.0-flash-exp (experimental, fast)
|
|
35
|
+
|
|
36
|
+
# Request timeout in milliseconds
|
|
37
|
+
timeout: 30000
|
|
38
|
+
|
|
39
|
+
# Maximum retry attempts for failed requests
|
|
40
|
+
maxRetries: 3
|
|
41
|
+
|
|
42
|
+
# Maximum output tokens
|
|
43
|
+
maxTokens: 8192
|
|
44
|
+
|
|
45
|
+
# Anthropic Claude Configuration
|
|
46
|
+
claude:
|
|
47
|
+
# Model: Use Claude 3.5 Sonnet or Opus
|
|
48
|
+
# See: https://docs.anthropic.com/en/docs/about-claude/models
|
|
49
|
+
model: claude-3-5-sonnet-20241022
|
|
50
|
+
# Available models:
|
|
51
|
+
# - claude-3-5-sonnet-20241022 (best balance, recommended)
|
|
52
|
+
# - claude-3-opus-20240229 (most capable, expensive)
|
|
53
|
+
# - claude-3-haiku-20240307 (fastest, cheapest)
|
|
54
|
+
|
|
55
|
+
# Request timeout in milliseconds
|
|
56
|
+
timeout: 30000
|
|
57
|
+
|
|
58
|
+
# Maximum retry attempts
|
|
59
|
+
maxRetries: 3
|
|
60
|
+
|
|
61
|
+
# Maximum output tokens
|
|
62
|
+
maxTokens: 8096
|
|
63
|
+
|
|
64
|
+
# Temperature (0-1): Lower = more focused, Higher = more creative
|
|
65
|
+
temperature: 0.7
|
|
66
|
+
|
|
67
|
+
# OpenAI Configuration
|
|
68
|
+
openai:
|
|
69
|
+
# Model: Use GPT-4o or GPT-4 Turbo
|
|
70
|
+
# See: https://platform.openai.com/docs/models
|
|
71
|
+
model: gpt-4o
|
|
72
|
+
# Available models:
|
|
73
|
+
# - gpt-4o (latest, recommended)
|
|
74
|
+
# - gpt-4-turbo (high capability)
|
|
75
|
+
# - gpt-4 (most capable, expensive)
|
|
76
|
+
# - gpt-3.5-turbo (fast, cheaper)
|
|
77
|
+
|
|
78
|
+
# Request timeout in milliseconds
|
|
79
|
+
timeout: 30000
|
|
80
|
+
|
|
81
|
+
# Maximum retry attempts
|
|
82
|
+
maxRetries: 3
|
|
83
|
+
|
|
84
|
+
# Maximum output tokens
|
|
85
|
+
maxTokens: 4096
|
|
86
|
+
|
|
87
|
+
# Temperature (0-2): Lower = more focused, Higher = more creative
|
|
88
|
+
temperature: 0.7
|
|
89
|
+
|
|
90
|
+
# Sub-Agent Configuration
|
|
91
|
+
# These are specialized agents for code review tasks
|
|
92
|
+
subAgents:
|
|
93
|
+
# Guideline Checker - Verifies code follows project guidelines
|
|
94
|
+
guidelineChecker:
|
|
95
|
+
model: claude-opus-4-5
|
|
96
|
+
# Use lower temperature for strict guideline checking
|
|
97
|
+
temperature: 0.3
|
|
98
|
+
|
|
99
|
+
# Architecture Reviewer - Reviews architectural decisions
|
|
100
|
+
architectureReviewer:
|
|
101
|
+
model: claude-sonnet-4-5
|
|
102
|
+
# Balanced temperature for architecture review
|
|
103
|
+
temperature: 0.5
|
|
104
|
+
|
|
105
|
+
# Security Auditor - Identifies security vulnerabilities
|
|
106
|
+
securityAuditor:
|
|
107
|
+
model: claude-opus-4-5
|
|
108
|
+
# Lower temperature for thorough security analysis
|
|
109
|
+
temperature: 0.3
|
|
110
|
+
|
|
111
|
+
# Alternative: Use environment variables instead
|
|
112
|
+
# Export these in your shell profile (.bashrc, .zshrc, etc.):
|
|
113
|
+
#
|
|
114
|
+
# # Gemini
|
|
115
|
+
# export AICGEN_GEMINI_MODEL=gemini-2.5-pro
|
|
116
|
+
# export AICGEN_GEMINI_TIMEOUT=60000
|
|
117
|
+
# export AICGEN_GEMINI_MAX_RETRIES=5
|
|
118
|
+
#
|
|
119
|
+
# # Claude
|
|
120
|
+
# export AICGEN_CLAUDE_MODEL=claude-3-opus-20240229
|
|
121
|
+
# export AICGEN_CLAUDE_TEMPERATURE=0.5
|
|
122
|
+
#
|
|
123
|
+
# # OpenAI
|
|
124
|
+
# export AICGEN_OPENAI_MODEL=gpt-4-turbo
|
|
125
|
+
# export AICGEN_OPENAI_TEMPERATURE=0.8
|
|
126
|
+
#
|
|
127
|
+
# # Sub-Agents
|
|
128
|
+
# export AICGEN_SUBAGENT_GUIDELINE_MODEL=claude-opus-4-5
|
|
129
|
+
# export AICGEN_SUBAGENT_GUIDELINE_TEMP=0.2
|
package/config.yml
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
github:
|
|
2
|
+
owner: aicgen
|
|
3
|
+
repo: aicgen-data
|
|
4
|
+
|
|
5
|
+
# AI Provider Configuration
|
|
6
|
+
ai:
|
|
7
|
+
gemini:
|
|
8
|
+
model: gemini-2.0-flash-exp
|
|
9
|
+
timeout: 30000
|
|
10
|
+
maxRetries: 3
|
|
11
|
+
maxTokens: 8192
|
|
12
|
+
|
|
13
|
+
claude:
|
|
14
|
+
model: claude-3-5-sonnet-20241022
|
|
15
|
+
timeout: 30000
|
|
16
|
+
maxRetries: 3
|
|
17
|
+
maxTokens: 8096
|
|
18
|
+
temperature: 0.7
|
|
19
|
+
|
|
20
|
+
openai:
|
|
21
|
+
model: gpt-4o
|
|
22
|
+
timeout: 30000
|
|
23
|
+
maxRetries: 3
|
|
24
|
+
maxTokens: 4096
|
|
25
|
+
temperature: 0.7
|
|
26
|
+
|
|
27
|
+
subAgents:
|
|
28
|
+
guidelineChecker:
|
|
29
|
+
model: claude-opus-4-5
|
|
30
|
+
temperature: 0.3
|
|
31
|
+
|
|
32
|
+
architectureReviewer:
|
|
33
|
+
model: claude-sonnet-4-5
|
|
34
|
+
temperature: 0.5
|
|
35
|
+
|
|
36
|
+
securityAuditor:
|
|
37
|
+
model: claude-opus-4-5
|
|
38
|
+
temperature: 0.3
|
|
@@ -332,6 +332,134 @@ javascript-testing:
|
|
|
332
332
|
- testing
|
|
333
333
|
- jest
|
|
334
334
|
category: Language
|
|
335
|
+
dart-basics:
|
|
336
|
+
path: language/dart/basics.md
|
|
337
|
+
languages:
|
|
338
|
+
- dart
|
|
339
|
+
levels:
|
|
340
|
+
- basic
|
|
341
|
+
- standard
|
|
342
|
+
- expert
|
|
343
|
+
- full
|
|
344
|
+
tags:
|
|
345
|
+
- dart
|
|
346
|
+
- fundamentals
|
|
347
|
+
- null-safety
|
|
348
|
+
category: Language
|
|
349
|
+
dart-async:
|
|
350
|
+
path: language/dart/async.md
|
|
351
|
+
languages:
|
|
352
|
+
- dart
|
|
353
|
+
levels:
|
|
354
|
+
- basic
|
|
355
|
+
- standard
|
|
356
|
+
- expert
|
|
357
|
+
- full
|
|
358
|
+
tags:
|
|
359
|
+
- dart
|
|
360
|
+
- async
|
|
361
|
+
- futures
|
|
362
|
+
- streams
|
|
363
|
+
category: Language
|
|
364
|
+
dart-error-handling:
|
|
365
|
+
path: language/dart/error-handling.md
|
|
366
|
+
languages:
|
|
367
|
+
- dart
|
|
368
|
+
levels:
|
|
369
|
+
- standard
|
|
370
|
+
- expert
|
|
371
|
+
- full
|
|
372
|
+
tags:
|
|
373
|
+
- dart
|
|
374
|
+
- errors
|
|
375
|
+
- exceptions
|
|
376
|
+
category: Language
|
|
377
|
+
dart-testing:
|
|
378
|
+
path: language/dart/testing.md
|
|
379
|
+
languages:
|
|
380
|
+
- dart
|
|
381
|
+
levels:
|
|
382
|
+
- standard
|
|
383
|
+
- expert
|
|
384
|
+
- full
|
|
385
|
+
tags:
|
|
386
|
+
- dart
|
|
387
|
+
- testing
|
|
388
|
+
- flutter
|
|
389
|
+
category: Language
|
|
390
|
+
swift-basics:
|
|
391
|
+
path: language/swift/basics.md
|
|
392
|
+
languages:
|
|
393
|
+
- swift
|
|
394
|
+
levels:
|
|
395
|
+
- basic
|
|
396
|
+
- standard
|
|
397
|
+
- expert
|
|
398
|
+
- full
|
|
399
|
+
tags:
|
|
400
|
+
- swift
|
|
401
|
+
- fundamentals
|
|
402
|
+
- optionals
|
|
403
|
+
- value-types
|
|
404
|
+
category: Language
|
|
405
|
+
swift-concurrency:
|
|
406
|
+
path: language/swift/concurrency.md
|
|
407
|
+
languages:
|
|
408
|
+
- swift
|
|
409
|
+
levels:
|
|
410
|
+
- standard
|
|
411
|
+
- expert
|
|
412
|
+
- full
|
|
413
|
+
tags:
|
|
414
|
+
- swift
|
|
415
|
+
- async
|
|
416
|
+
- actors
|
|
417
|
+
- structured-concurrency
|
|
418
|
+
- task
|
|
419
|
+
category: Language
|
|
420
|
+
swift-swiftui-mvvm:
|
|
421
|
+
path: language/swift/swiftui-mvvm.md
|
|
422
|
+
languages:
|
|
423
|
+
- swift
|
|
424
|
+
levels:
|
|
425
|
+
- standard
|
|
426
|
+
- expert
|
|
427
|
+
- full
|
|
428
|
+
tags:
|
|
429
|
+
- swift
|
|
430
|
+
- swiftui
|
|
431
|
+
- mvvm
|
|
432
|
+
- state-management
|
|
433
|
+
- combine
|
|
434
|
+
category: Language
|
|
435
|
+
swift-testing:
|
|
436
|
+
path: language/swift/testing.md
|
|
437
|
+
languages:
|
|
438
|
+
- swift
|
|
439
|
+
levels:
|
|
440
|
+
- standard
|
|
441
|
+
- expert
|
|
442
|
+
- full
|
|
443
|
+
tags:
|
|
444
|
+
- swift
|
|
445
|
+
- testing
|
|
446
|
+
- xctest
|
|
447
|
+
- swift-testing
|
|
448
|
+
category: Language
|
|
449
|
+
swift-error-handling:
|
|
450
|
+
path: language/swift/error-handling.md
|
|
451
|
+
languages:
|
|
452
|
+
- swift
|
|
453
|
+
levels:
|
|
454
|
+
- standard
|
|
455
|
+
- expert
|
|
456
|
+
- full
|
|
457
|
+
tags:
|
|
458
|
+
- swift
|
|
459
|
+
- errors
|
|
460
|
+
- throws
|
|
461
|
+
- result
|
|
462
|
+
category: Language
|
|
335
463
|
microservices-boundaries:
|
|
336
464
|
path: architecture/microservices/boundaries.md
|
|
337
465
|
architectures:
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# Async Programming in Dart
|
|
2
|
+
|
|
3
|
+
## Futures and async/await
|
|
4
|
+
|
|
5
|
+
```dart
|
|
6
|
+
// ✅ Async function returns Future
|
|
7
|
+
Future<User> fetchUser(String id) async {
|
|
8
|
+
final response = await http.get('/api/users/$id');
|
|
9
|
+
return User.fromJson(response.data);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// ✅ Handle errors with try-catch
|
|
13
|
+
Future<User> fetchUserSafely(String id) async {
|
|
14
|
+
try {
|
|
15
|
+
final response = await http.get('/api/users/$id');
|
|
16
|
+
return User.fromJson(response.data);
|
|
17
|
+
} catch (e) {
|
|
18
|
+
print('Failed to fetch user: $e');
|
|
19
|
+
rethrow;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// ❌ Don't forget await
|
|
24
|
+
Future<void> badExample() async {
|
|
25
|
+
final user = fetchUser('123'); // Missing await!
|
|
26
|
+
print(user); // Prints: Instance of 'Future<User>'
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ✅ Correct
|
|
30
|
+
Future<void> goodExample() async {
|
|
31
|
+
final user = await fetchUser('123');
|
|
32
|
+
print(user.name); // Prints: Alice
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Parallel Execution
|
|
37
|
+
|
|
38
|
+
```dart
|
|
39
|
+
// ❌ Sequential - slow
|
|
40
|
+
Future<void> sequential() async {
|
|
41
|
+
final user = await fetchUser('1'); // 100ms
|
|
42
|
+
final posts = await fetchPosts('1'); // 150ms
|
|
43
|
+
final comments = await fetchComments('1'); // 120ms
|
|
44
|
+
// Total: 370ms
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// ✅ Parallel - fast
|
|
48
|
+
Future<void> parallel() async {
|
|
49
|
+
final results = await Future.wait([
|
|
50
|
+
fetchUser('1'),
|
|
51
|
+
fetchPosts('1'),
|
|
52
|
+
fetchComments('1'),
|
|
53
|
+
]);
|
|
54
|
+
// Total: 150ms (longest operation)
|
|
55
|
+
|
|
56
|
+
final user = results[0] as User;
|
|
57
|
+
final posts = results[1] as List<Post>;
|
|
58
|
+
final comments = results[2] as List<Comment>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ✅ With better typing using records (Dart 3.0+)
|
|
62
|
+
Future<(User, List<Post>, List<Comment>)> fetchUserData(String id) async {
|
|
63
|
+
final (user, posts, comments) = await (
|
|
64
|
+
fetchUser(id),
|
|
65
|
+
fetchPosts(id),
|
|
66
|
+
fetchComments(id),
|
|
67
|
+
).wait;
|
|
68
|
+
|
|
69
|
+
return (user, posts, comments);
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Future Methods
|
|
74
|
+
|
|
75
|
+
```dart
|
|
76
|
+
// timeout - fail if takes too long
|
|
77
|
+
Future<User> fetchWithTimeout(String id) async {
|
|
78
|
+
return fetchUser(id).timeout(
|
|
79
|
+
const Duration(seconds: 5),
|
|
80
|
+
onTimeout: () => throw TimeoutException('Request timed out'),
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// catchError - handle errors without try-catch
|
|
85
|
+
final user = await fetchUser('123').catchError((error) {
|
|
86
|
+
print('Error: $error');
|
|
87
|
+
return User.guest(); // Fallback value
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// then - chain operations (prefer async/await)
|
|
91
|
+
fetchUser('123')
|
|
92
|
+
.then((user) => user.name)
|
|
93
|
+
.then((name) => print(name));
|
|
94
|
+
|
|
95
|
+
// whenComplete - always runs (like finally)
|
|
96
|
+
await fetchUser('123').whenComplete(() {
|
|
97
|
+
print('Request completed');
|
|
98
|
+
});
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Streams
|
|
102
|
+
|
|
103
|
+
```dart
|
|
104
|
+
// Create stream
|
|
105
|
+
Stream<int> countStream(int max) async* {
|
|
106
|
+
for (int i = 1; i <= max; i++) {
|
|
107
|
+
await Future.delayed(const Duration(seconds: 1));
|
|
108
|
+
yield i;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ✅ Listen to stream
|
|
113
|
+
final subscription = countStream(5).listen(
|
|
114
|
+
(count) {
|
|
115
|
+
print('Count: $count');
|
|
116
|
+
},
|
|
117
|
+
onError: (error) {
|
|
118
|
+
print('Error: $error');
|
|
119
|
+
},
|
|
120
|
+
onDone: () {
|
|
121
|
+
print('Stream completed');
|
|
122
|
+
},
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
// Cancel subscription
|
|
126
|
+
await subscription.cancel();
|
|
127
|
+
|
|
128
|
+
// ✅ Async for loop
|
|
129
|
+
Future<void> processStream() async {
|
|
130
|
+
await for (final count in countStream(5)) {
|
|
131
|
+
print('Count: $count');
|
|
132
|
+
}
|
|
133
|
+
print('Done');
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Stream Transformations
|
|
138
|
+
|
|
139
|
+
```dart
|
|
140
|
+
// Transform stream data
|
|
141
|
+
Stream<String> getUserNames() {
|
|
142
|
+
return fetchUsersStream()
|
|
143
|
+
.map((user) => user.name)
|
|
144
|
+
.where((name) => name.isNotEmpty);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Async map
|
|
148
|
+
Stream<User> enrichUsers(Stream<String> userIds) {
|
|
149
|
+
return userIds.asyncMap((id) async {
|
|
150
|
+
return await fetchUser(id);
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Combine streams
|
|
155
|
+
final combined = StreamGroup.merge([stream1, stream2, stream3]);
|
|
156
|
+
|
|
157
|
+
// Buffer events
|
|
158
|
+
final buffered = stream.transform(
|
|
159
|
+
StreamTransformer.fromHandlers(
|
|
160
|
+
handleData: (data, sink) {
|
|
161
|
+
sink.add(data);
|
|
162
|
+
},
|
|
163
|
+
),
|
|
164
|
+
);
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## StreamController
|
|
168
|
+
|
|
169
|
+
```dart
|
|
170
|
+
class ChatService {
|
|
171
|
+
final _messagesController = StreamController<Message>.broadcast();
|
|
172
|
+
|
|
173
|
+
Stream<Message> get messages => _messagesController.stream;
|
|
174
|
+
|
|
175
|
+
void sendMessage(Message message) {
|
|
176
|
+
_messagesController.add(message);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
void dispose() {
|
|
180
|
+
_messagesController.close();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Usage
|
|
185
|
+
final chat = ChatService();
|
|
186
|
+
|
|
187
|
+
final subscription = chat.messages.listen((message) {
|
|
188
|
+
print('New message: ${message.text}');
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
chat.sendMessage(Message(text: 'Hello'));
|
|
192
|
+
|
|
193
|
+
// Clean up
|
|
194
|
+
await subscription.cancel();
|
|
195
|
+
chat.dispose();
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Isolates (Heavy Computation)
|
|
199
|
+
|
|
200
|
+
```dart
|
|
201
|
+
// Run expensive computation in isolate
|
|
202
|
+
Future<int> calculateInIsolate(int n) async {
|
|
203
|
+
return await Isolate.run(() {
|
|
204
|
+
int result = 0;
|
|
205
|
+
for (int i = 0; i < n; i++) {
|
|
206
|
+
result += i;
|
|
207
|
+
}
|
|
208
|
+
return result;
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// ✅ For CPU-intensive tasks
|
|
213
|
+
Future<Image> processImage(File imageFile) async {
|
|
214
|
+
final bytes = await imageFile.readAsBytes();
|
|
215
|
+
|
|
216
|
+
// Run in isolate to avoid blocking UI
|
|
217
|
+
final processed = await Isolate.run(() {
|
|
218
|
+
return applyFilters(bytes);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
return Image.memory(processed);
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Completer
|
|
226
|
+
|
|
227
|
+
```dart
|
|
228
|
+
// Create Future manually
|
|
229
|
+
class DatabaseConnection {
|
|
230
|
+
final Completer<void> _readyCompleter = Completer();
|
|
231
|
+
|
|
232
|
+
Future<void> get ready => _readyCompleter.future;
|
|
233
|
+
|
|
234
|
+
void connect() async {
|
|
235
|
+
try {
|
|
236
|
+
await _performConnection();
|
|
237
|
+
_readyCompleter.complete();
|
|
238
|
+
} catch (e) {
|
|
239
|
+
_readyCompleter.completeError(e);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Usage
|
|
245
|
+
final db = DatabaseConnection();
|
|
246
|
+
db.connect();
|
|
247
|
+
await db.ready; // Wait until connected
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## Error Handling
|
|
251
|
+
|
|
252
|
+
```dart
|
|
253
|
+
// ✅ Use try-catch with async/await
|
|
254
|
+
Future<void> safeOperation() async {
|
|
255
|
+
try {
|
|
256
|
+
await riskyOperation();
|
|
257
|
+
} on NetworkException catch (e) {
|
|
258
|
+
print('Network error: ${e.message}');
|
|
259
|
+
} on TimeoutException {
|
|
260
|
+
print('Operation timed out');
|
|
261
|
+
} catch (e, stackTrace) {
|
|
262
|
+
print('Unexpected error: $e');
|
|
263
|
+
print('Stack trace: $stackTrace');
|
|
264
|
+
rethrow;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// ✅ Handle stream errors
|
|
269
|
+
stream.listen(
|
|
270
|
+
(data) => process(data),
|
|
271
|
+
onError: (error) {
|
|
272
|
+
if (error is NetworkException) {
|
|
273
|
+
reconnect();
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
);
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Best Practices
|
|
280
|
+
|
|
281
|
+
- Always use `async`/`await` for readability
|
|
282
|
+
- Run independent operations in parallel with `Future.wait`
|
|
283
|
+
- Set timeouts for network operations
|
|
284
|
+
- Cancel subscriptions when done
|
|
285
|
+
- Use isolates for CPU-intensive work
|
|
286
|
+
- Handle errors explicitly
|
|
287
|
+
- Close StreamControllers when finished
|
|
288
|
+
- Use `async*` and `yield` for generating stream data
|
|
289
|
+
- Prefer `await for` over `listen` for sequential processing
|