maxsim-flutter 1.0.0
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/CHANGELOG.md +42 -0
- package/LICENSE +21 -0
- package/README.md +445 -0
- package/claude-plugin/.claude-plugin/plugin.json +46 -0
- package/claude-plugin/agents/flutter-setup-agent.md +54 -0
- package/claude-plugin/commands/flutter-add.md +32 -0
- package/claude-plugin/commands/flutter-create.md +28 -0
- package/claude-plugin/commands/flutter-migrate.md +28 -0
- package/claude-plugin/skills/flutter-scaffolding/SKILL.md +109 -0
- package/dist/claude-setup/agent-writer.d.ts +21 -0
- package/dist/claude-setup/agent-writer.d.ts.map +1 -0
- package/dist/claude-setup/agent-writer.js +365 -0
- package/dist/claude-setup/agent-writer.js.map +1 -0
- package/dist/claude-setup/claude-md-generator.d.ts +7 -0
- package/dist/claude-setup/claude-md-generator.d.ts.map +1 -0
- package/dist/claude-setup/claude-md-generator.js +428 -0
- package/dist/claude-setup/claude-md-generator.js.map +1 -0
- package/dist/claude-setup/commands-writer.d.ts +7 -0
- package/dist/claude-setup/commands-writer.d.ts.map +1 -0
- package/dist/claude-setup/commands-writer.js +303 -0
- package/dist/claude-setup/commands-writer.js.map +1 -0
- package/dist/claude-setup/hooks-writer.d.ts +3 -0
- package/dist/claude-setup/hooks-writer.d.ts.map +1 -0
- package/dist/claude-setup/hooks-writer.js +34 -0
- package/dist/claude-setup/hooks-writer.js.map +1 -0
- package/dist/claude-setup/index.d.ts +10 -0
- package/dist/claude-setup/index.d.ts.map +1 -0
- package/dist/claude-setup/index.js +9 -0
- package/dist/claude-setup/index.js.map +1 -0
- package/dist/claude-setup/mcp-config-writer.d.ts +3 -0
- package/dist/claude-setup/mcp-config-writer.d.ts.map +1 -0
- package/dist/claude-setup/mcp-config-writer.js +42 -0
- package/dist/claude-setup/mcp-config-writer.js.map +1 -0
- package/dist/claude-setup/plugin-assembler.d.ts +2 -0
- package/dist/claude-setup/plugin-assembler.d.ts.map +1 -0
- package/dist/claude-setup/plugin-assembler.js +3 -0
- package/dist/claude-setup/plugin-assembler.js.map +1 -0
- package/dist/claude-setup/prd-generator.d.ts +10 -0
- package/dist/claude-setup/prd-generator.d.ts.map +1 -0
- package/dist/claude-setup/prd-generator.js +295 -0
- package/dist/claude-setup/prd-generator.js.map +1 -0
- package/dist/claude-setup/setup-orchestrator.d.ts +11 -0
- package/dist/claude-setup/setup-orchestrator.d.ts.map +1 -0
- package/dist/claude-setup/setup-orchestrator.js +46 -0
- package/dist/claude-setup/setup-orchestrator.js.map +1 -0
- package/dist/claude-setup/skill-writer.d.ts +3 -0
- package/dist/claude-setup/skill-writer.d.ts.map +1 -0
- package/dist/claude-setup/skill-writer.js +256 -0
- package/dist/claude-setup/skill-writer.js.map +1 -0
- package/dist/cli/commands/add.d.ts +16 -0
- package/dist/cli/commands/add.d.ts.map +1 -0
- package/dist/cli/commands/add.js +414 -0
- package/dist/cli/commands/add.js.map +1 -0
- package/dist/cli/commands/create.d.ts +3 -0
- package/dist/cli/commands/create.d.ts.map +1 -0
- package/dist/cli/commands/create.js +161 -0
- package/dist/cli/commands/create.js.map +1 -0
- package/dist/cli/commands/list.d.ts +12 -0
- package/dist/cli/commands/list.d.ts.map +1 -0
- package/dist/cli/commands/list.js +148 -0
- package/dist/cli/commands/list.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +3 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +332 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +34 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ui/prompts.d.ts +9 -0
- package/dist/cli/ui/prompts.d.ts.map +1 -0
- package/dist/cli/ui/prompts.js +74 -0
- package/dist/cli/ui/prompts.js.map +1 -0
- package/dist/cli/ui/spinner.d.ts +2 -0
- package/dist/cli/ui/spinner.d.ts.map +1 -0
- package/dist/cli/ui/spinner.js +5 -0
- package/dist/cli/ui/spinner.js.map +1 -0
- package/dist/cli/version-check.d.ts +7 -0
- package/dist/cli/version-check.d.ts.map +1 -0
- package/dist/cli/version-check.js +92 -0
- package/dist/cli/version-check.js.map +1 -0
- package/dist/core/config/defaults.d.ts +3 -0
- package/dist/core/config/defaults.d.ts.map +1 -0
- package/dist/core/config/defaults.js +21 -0
- package/dist/core/config/defaults.js.map +1 -0
- package/dist/core/config/loader.d.ts +4 -0
- package/dist/core/config/loader.d.ts.map +1 -0
- package/dist/core/config/loader.js +38 -0
- package/dist/core/config/loader.js.map +1 -0
- package/dist/core/config/schema.d.ts +406 -0
- package/dist/core/config/schema.d.ts.map +1 -0
- package/dist/core/config/schema.js +119 -0
- package/dist/core/config/schema.js.map +1 -0
- package/dist/core/context.d.ts +57 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +99 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/detector.d.ts +28 -0
- package/dist/core/detector.d.ts.map +1 -0
- package/dist/core/detector.js +200 -0
- package/dist/core/detector.js.map +1 -0
- package/dist/core/validator.d.ts +7 -0
- package/dist/core/validator.d.ts.map +1 -0
- package/dist/core/validator.js +35 -0
- package/dist/core/validator.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/modules/composer.d.ts +50 -0
- package/dist/modules/composer.d.ts.map +1 -0
- package/dist/modules/composer.js +122 -0
- package/dist/modules/composer.js.map +1 -0
- package/dist/modules/definitions/analytics/module.d.ts +7 -0
- package/dist/modules/definitions/analytics/module.d.ts.map +1 -0
- package/dist/modules/definitions/analytics/module.js +28 -0
- package/dist/modules/definitions/analytics/module.js.map +1 -0
- package/dist/modules/definitions/api/module.d.ts +7 -0
- package/dist/modules/definitions/api/module.d.ts.map +1 -0
- package/dist/modules/definitions/api/module.js +41 -0
- package/dist/modules/definitions/api/module.js.map +1 -0
- package/dist/modules/definitions/auth/module.d.ts +7 -0
- package/dist/modules/definitions/auth/module.d.ts.map +1 -0
- package/dist/modules/definitions/auth/module.js +53 -0
- package/dist/modules/definitions/auth/module.js.map +1 -0
- package/dist/modules/definitions/cicd/module.d.ts +7 -0
- package/dist/modules/definitions/cicd/module.d.ts.map +1 -0
- package/dist/modules/definitions/cicd/module.js +34 -0
- package/dist/modules/definitions/cicd/module.js.map +1 -0
- package/dist/modules/definitions/core/module.d.ts +7 -0
- package/dist/modules/definitions/core/module.d.ts.map +1 -0
- package/dist/modules/definitions/core/module.js +31 -0
- package/dist/modules/definitions/core/module.js.map +1 -0
- package/dist/modules/definitions/database/module.d.ts +8 -0
- package/dist/modules/definitions/database/module.d.ts.map +1 -0
- package/dist/modules/definitions/database/module.js +47 -0
- package/dist/modules/definitions/database/module.js.map +1 -0
- package/dist/modules/definitions/deep-linking/module.d.ts +7 -0
- package/dist/modules/definitions/deep-linking/module.d.ts.map +1 -0
- package/dist/modules/definitions/deep-linking/module.js +48 -0
- package/dist/modules/definitions/deep-linking/module.js.map +1 -0
- package/dist/modules/definitions/i18n/module.d.ts +7 -0
- package/dist/modules/definitions/i18n/module.d.ts.map +1 -0
- package/dist/modules/definitions/i18n/module.js +37 -0
- package/dist/modules/definitions/i18n/module.js.map +1 -0
- package/dist/modules/definitions/push/module.d.ts +7 -0
- package/dist/modules/definitions/push/module.d.ts.map +1 -0
- package/dist/modules/definitions/push/module.js +40 -0
- package/dist/modules/definitions/push/module.js.map +1 -0
- package/dist/modules/definitions/theme/module.d.ts +7 -0
- package/dist/modules/definitions/theme/module.d.ts.map +1 -0
- package/dist/modules/definitions/theme/module.js +42 -0
- package/dist/modules/definitions/theme/module.js.map +1 -0
- package/dist/modules/registry.d.ts +50 -0
- package/dist/modules/registry.d.ts.map +1 -0
- package/dist/modules/registry.js +104 -0
- package/dist/modules/registry.js.map +1 -0
- package/dist/modules/resolver.d.ts +42 -0
- package/dist/modules/resolver.d.ts.map +1 -0
- package/dist/modules/resolver.js +140 -0
- package/dist/modules/resolver.js.map +1 -0
- package/dist/ralph/prd-generator.d.ts +2 -0
- package/dist/ralph/prd-generator.d.ts.map +1 -0
- package/dist/ralph/prd-generator.js +3 -0
- package/dist/ralph/prd-generator.js.map +1 -0
- package/dist/ralph/ralph-converter.d.ts +2 -0
- package/dist/ralph/ralph-converter.d.ts.map +1 -0
- package/dist/ralph/ralph-converter.js +3 -0
- package/dist/ralph/ralph-converter.js.map +1 -0
- package/dist/ralph/story-sizer.d.ts +2 -0
- package/dist/ralph/story-sizer.d.ts.map +1 -0
- package/dist/ralph/story-sizer.js +3 -0
- package/dist/ralph/story-sizer.js.map +1 -0
- package/dist/scaffold/engine.d.ts +40 -0
- package/dist/scaffold/engine.d.ts.map +1 -0
- package/dist/scaffold/engine.js +233 -0
- package/dist/scaffold/engine.js.map +1 -0
- package/dist/scaffold/file-writer.d.ts +22 -0
- package/dist/scaffold/file-writer.d.ts.map +1 -0
- package/dist/scaffold/file-writer.js +68 -0
- package/dist/scaffold/file-writer.js.map +1 -0
- package/dist/scaffold/post-processors/build-runner.d.ts +2 -0
- package/dist/scaffold/post-processors/build-runner.d.ts.map +1 -0
- package/dist/scaffold/post-processors/build-runner.js +5 -0
- package/dist/scaffold/post-processors/build-runner.js.map +1 -0
- package/dist/scaffold/post-processors/dart-format.d.ts +2 -0
- package/dist/scaffold/post-processors/dart-format.d.ts.map +1 -0
- package/dist/scaffold/post-processors/dart-format.js +5 -0
- package/dist/scaffold/post-processors/dart-format.js.map +1 -0
- package/dist/scaffold/post-processors/flutter-pub-get.d.ts +2 -0
- package/dist/scaffold/post-processors/flutter-pub-get.d.ts.map +1 -0
- package/dist/scaffold/post-processors/flutter-pub-get.js +5 -0
- package/dist/scaffold/post-processors/flutter-pub-get.js.map +1 -0
- package/dist/scaffold/renderer.d.ts +20 -0
- package/dist/scaffold/renderer.d.ts.map +1 -0
- package/dist/scaffold/renderer.js +75 -0
- package/dist/scaffold/renderer.js.map +1 -0
- package/dist/scaffold/template-helpers.d.ts +25 -0
- package/dist/scaffold/template-helpers.d.ts.map +1 -0
- package/dist/scaffold/template-helpers.js +115 -0
- package/dist/scaffold/template-helpers.js.map +1 -0
- package/dist/types/config.d.ts +4 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +2 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/module.d.ts +85 -0
- package/dist/types/module.d.ts.map +1 -0
- package/dist/types/module.js +2 -0
- package/dist/types/module.js.map +1 -0
- package/dist/types/project.d.ts +13 -0
- package/dist/types/project.d.ts.map +1 -0
- package/dist/types/project.js +2 -0
- package/dist/types/project.js.map +1 -0
- package/package.json +80 -0
- package/templates/core/analysis_options.yaml.hbs +21 -0
- package/templates/core/lib/app.dart.hbs +20 -0
- package/templates/core/lib/core/providers/app_providers.dart.hbs +3 -0
- package/templates/core/lib/core/router/app_router.dart.hbs +19 -0
- package/templates/core/lib/core/theme/app_theme.dart.hbs +15 -0
- package/templates/core/lib/features/home/data/models/.gitkeep +0 -0
- package/templates/core/lib/features/home/data/repositories/.gitkeep +0 -0
- package/templates/core/lib/features/home/domain/entities/.gitkeep +0 -0
- package/templates/core/lib/features/home/domain/repositories/.gitkeep +0 -0
- package/templates/core/lib/features/home/presentation/pages/home_page.dart.hbs +18 -0
- package/templates/core/lib/features/home/presentation/widgets/.gitkeep +0 -0
- package/templates/core/lib/main.dart.hbs +11 -0
- package/templates/core/pubspec.yaml.hbs +30 -0
- package/templates/core/test/widget_test.dart.hbs +16 -0
- package/templates/modules/analytics/lib/features/analytics/data/observers/analytics_route_observer.dart.hbs +53 -0
- package/templates/modules/analytics/lib/features/analytics/data/services/firebase_analytics_service.dart.hbs +39 -0
- package/templates/modules/analytics/lib/features/analytics/domain/services/analytics_service.dart.hbs +25 -0
- package/templates/modules/analytics/lib/features/analytics/presentation/providers/analytics_provider.dart.hbs +17 -0
- package/templates/modules/analytics/pubspec.partial.yaml +2 -0
- package/templates/modules/api/lib/features/api/data/datasources/api_client.dart.hbs +171 -0
- package/templates/modules/api/lib/features/api/data/interceptors/auth_interceptor.dart.hbs +25 -0
- package/templates/modules/api/lib/features/api/data/interceptors/retry_interceptor.dart.hbs +42 -0
- package/templates/modules/api/lib/features/api/data/repositories/api_repository_impl.dart.hbs +21 -0
- package/templates/modules/api/lib/features/api/domain/exceptions/api_exception.dart.hbs +31 -0
- package/templates/modules/api/lib/features/api/domain/repositories/api_repository.dart.hbs +8 -0
- package/templates/modules/api/lib/features/api/presentation/providers/api_provider.dart.hbs +17 -0
- package/templates/modules/api/pubspec.partial.yaml +7 -0
- package/templates/modules/auth/lib/features/auth/data/datasources/auth_remote_datasource.dart.hbs +181 -0
- package/templates/modules/auth/lib/features/auth/data/models/auth_user_model.dart.hbs +27 -0
- package/templates/modules/auth/lib/features/auth/data/repositories/auth_repository_impl.dart.hbs +49 -0
- package/templates/modules/auth/lib/features/auth/domain/entities/user_entity.dart.hbs +18 -0
- package/templates/modules/auth/lib/features/auth/domain/repositories/auth_repository.dart.hbs +22 -0
- package/templates/modules/auth/lib/features/auth/domain/usecases/register_usecase.dart.hbs +20 -0
- package/templates/modules/auth/lib/features/auth/domain/usecases/sign_in_usecase.dart.hbs +15 -0
- package/templates/modules/auth/lib/features/auth/domain/usecases/sign_out_usecase.dart.hbs +11 -0
- package/templates/modules/auth/lib/features/auth/presentation/pages/login_page.dart.hbs +118 -0
- package/templates/modules/auth/lib/features/auth/presentation/pages/register_page.dart.hbs +131 -0
- package/templates/modules/auth/lib/features/auth/presentation/providers/auth_provider.dart.hbs +31 -0
- package/templates/modules/auth/pubspec.partial.yaml +13 -0
- package/templates/modules/cicd/.github/workflows/ci.yml.hbs +45 -0
- package/templates/modules/cicd/.gitlab-ci.yml.hbs +53 -0
- package/templates/modules/cicd/bitbucket-pipelines.yml.hbs +39 -0
- package/templates/modules/cicd/pubspec.partial.yaml +1 -0
- package/templates/modules/database/lib/features/database/data/datasources/database_datasource.dart.hbs +115 -0
- package/templates/modules/database/lib/features/database/data/repositories/database_repository_impl.dart.hbs +73 -0
- package/templates/modules/database/lib/features/database/domain/repositories/database_repository.dart.hbs +10 -0
- package/templates/modules/database/lib/features/database/presentation/providers/database_provider.dart.hbs +43 -0
- package/templates/modules/database/pubspec.partial.yaml +27 -0
- package/templates/modules/deep-linking/lib/features/deep_linking/data/datasources/deep_link_datasource.dart.hbs +18 -0
- package/templates/modules/deep-linking/lib/features/deep_linking/data/repositories/deep_link_repository_impl.dart.hbs +14 -0
- package/templates/modules/deep-linking/lib/features/deep_linking/domain/repositories/deep_link_repository.dart.hbs +7 -0
- package/templates/modules/deep-linking/lib/features/deep_linking/presentation/providers/deep_link_provider.dart.hbs +57 -0
- package/templates/modules/deep-linking/pubspec.partial.yaml +2 -0
- package/templates/modules/i18n/l10n.yaml.hbs +5 -0
- package/templates/modules/i18n/lib/core/l10n/l10n_config.dart.hbs +29 -0
- package/templates/modules/i18n/lib/core/l10n/l10n_provider.dart.hbs +20 -0
- package/templates/modules/i18n/lib/l10n/app_de.arb.hbs +27 -0
- package/templates/modules/i18n/lib/l10n/app_en.arb.hbs +27 -0
- package/templates/modules/i18n/pubspec.partial.yaml +7 -0
- package/templates/modules/push/lib/features/push/data/datasources/push_datasource.dart.hbs +124 -0
- package/templates/modules/push/lib/features/push/data/repositories/push_repository_impl.dart.hbs +28 -0
- package/templates/modules/push/lib/features/push/domain/repositories/push_repository.dart.hbs +31 -0
- package/templates/modules/push/lib/features/push/presentation/providers/push_provider.dart.hbs +34 -0
- package/templates/modules/push/pubspec.partial.yaml +8 -0
- package/templates/modules/theme/lib/core/theme/app_theme.dart.hbs +74 -0
- package/templates/modules/theme/lib/core/theme/theme_provider.dart.hbs +46 -0
- package/templates/modules/theme/pubspec.partial.yaml +2 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates a prd.json for the scaffolded Flutter project.
|
|
3
|
+
* Stories are organized into three phases:
|
|
4
|
+
* Phase 1 - Core app setup and basic navigation
|
|
5
|
+
* Phase 2 - Module-specific features (conditional on enabled modules)
|
|
6
|
+
* Phase 3 - Integration and end-to-end testing
|
|
7
|
+
*/
|
|
8
|
+
export function generatePrd(context) {
|
|
9
|
+
const rawStories = [
|
|
10
|
+
...generatePhase1Stories(context),
|
|
11
|
+
...generatePhase2Stories(context),
|
|
12
|
+
...generatePhase3Stories(context),
|
|
13
|
+
];
|
|
14
|
+
// Assign sequential IDs
|
|
15
|
+
const numbered = rawStories.map((story, index) => ({
|
|
16
|
+
...story,
|
|
17
|
+
id: `S-${String(index + 1).padStart(3, '0')}`,
|
|
18
|
+
}));
|
|
19
|
+
const prd = {
|
|
20
|
+
version: '1.0.0',
|
|
21
|
+
project: context.projectName,
|
|
22
|
+
stories: numbered,
|
|
23
|
+
};
|
|
24
|
+
return JSON.stringify(prd, null, 2) + '\n';
|
|
25
|
+
}
|
|
26
|
+
function generatePhase1Stories(context) {
|
|
27
|
+
return [
|
|
28
|
+
{
|
|
29
|
+
phase: 1,
|
|
30
|
+
priority: 'P0',
|
|
31
|
+
title: 'Setup Clean Architecture project structure',
|
|
32
|
+
description: `Verify and finalize the scaffolded project structure for ${context.projectName}. Ensure all directories follow Clean Architecture conventions with domain, data, and presentation layers per feature. Configure analysis_options.yaml with appropriate lint rules.`,
|
|
33
|
+
acceptanceCriteria: [
|
|
34
|
+
'`lib/features/` directory exists with at minimum a `home` feature',
|
|
35
|
+
'Each feature contains `domain/`, `data/`, and `presentation/` subdirectories',
|
|
36
|
+
'`lib/core/` contains router, theme, and providers directories',
|
|
37
|
+
'`flutter analyze` reports zero errors',
|
|
38
|
+
'`dart format --set-exit-if-changed .` passes',
|
|
39
|
+
],
|
|
40
|
+
passes: false,
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
phase: 1,
|
|
44
|
+
priority: 'P0',
|
|
45
|
+
title: 'Configure go_router with type-safe routes',
|
|
46
|
+
description: 'Set up go_router in `lib/core/router/app_router.dart` using TypedGoRoute annotations. Define initial route to HomeRoute. Register the router as a Riverpod provider. Run build_runner to generate route code.',
|
|
47
|
+
acceptanceCriteria: [
|
|
48
|
+
'`lib/core/router/app_router.dart` exists with GoRouter configuration',
|
|
49
|
+
'Router is exposed as a Riverpod provider (`routerProvider`)',
|
|
50
|
+
'`HomeRoute` is defined with `@TypedGoRoute(path: \'/\')`',
|
|
51
|
+
'`lib/core/router/app_router.g.dart` is generated by build_runner',
|
|
52
|
+
'`flutter analyze` reports zero errors',
|
|
53
|
+
],
|
|
54
|
+
passes: false,
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
phase: 1,
|
|
58
|
+
priority: 'P0',
|
|
59
|
+
title: 'Configure Riverpod ProviderScope and global providers',
|
|
60
|
+
description: 'Ensure `main.dart` wraps the app in `ProviderScope`. Set up `lib/core/providers/app_providers.dart` as a barrel export for all core providers. Verify the app boots without errors.',
|
|
61
|
+
acceptanceCriteria: [
|
|
62
|
+
'`main.dart` wraps `runApp` with `ProviderScope`',
|
|
63
|
+
'`lib/core/providers/app_providers.dart` exports core providers',
|
|
64
|
+
'App compiles and runs without errors',
|
|
65
|
+
'`flutter analyze` reports zero errors',
|
|
66
|
+
],
|
|
67
|
+
passes: false,
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
phase: 1,
|
|
71
|
+
priority: 'P1',
|
|
72
|
+
title: `Implement ${context.projectName} home screen`,
|
|
73
|
+
description: `Build the initial home screen at \`lib/features/home/presentation/pages/home_page.dart\`. The page should use ConsumerWidget and display the project name. Wire it up to the \`/\` route in app_router.`,
|
|
74
|
+
acceptanceCriteria: [
|
|
75
|
+
'`home_page.dart` exists and extends `ConsumerWidget`',
|
|
76
|
+
'Home page displays the app name or a welcome message',
|
|
77
|
+
'Route `/` navigates to the home page',
|
|
78
|
+
'Widget test in `test/features/home/` passes',
|
|
79
|
+
'`flutter test` passes all tests',
|
|
80
|
+
],
|
|
81
|
+
passes: false,
|
|
82
|
+
},
|
|
83
|
+
];
|
|
84
|
+
}
|
|
85
|
+
function generatePhase2Stories(context) {
|
|
86
|
+
const stories = [];
|
|
87
|
+
if (context.modules.auth) {
|
|
88
|
+
const provider = context.modules.auth.provider;
|
|
89
|
+
const providerLabel = provider === 'firebase' ? 'Firebase Auth' : provider === 'supabase' ? 'Supabase Auth' : 'custom auth';
|
|
90
|
+
stories.push({
|
|
91
|
+
phase: 2,
|
|
92
|
+
priority: 'P0',
|
|
93
|
+
title: `Implement authentication with ${providerLabel}`,
|
|
94
|
+
description: `Build the auth feature in \`lib/features/auth/\` following Clean Architecture. Domain layer: \`AuthRepository\` interface and \`User\` entity. Data layer: \`${capitalize(provider)}AuthDataSource\` and \`AuthRepositoryImpl\`. Presentation layer: \`authRepositoryProvider\`, login page, register page. Add auth guard to go_router redirect.`,
|
|
95
|
+
acceptanceCriteria: [
|
|
96
|
+
'`lib/features/auth/domain/repositories/auth_repository.dart` defines `AuthRepository` interface',
|
|
97
|
+
'`lib/features/auth/domain/entities/user.dart` defines `User` entity with freezed',
|
|
98
|
+
'Auth repository implementation connects to ' + providerLabel,
|
|
99
|
+
'`/login` and `/register` routes exist and render auth pages',
|
|
100
|
+
'Auth guard in go_router redirects unauthenticated users to `/login`',
|
|
101
|
+
'Unit tests for auth use cases pass',
|
|
102
|
+
'`flutter analyze` reports zero errors',
|
|
103
|
+
],
|
|
104
|
+
passes: false,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
if (context.modules.api) {
|
|
108
|
+
const baseUrl = context.modules.api.baseUrl ?? 'API_BASE_URL env variable';
|
|
109
|
+
stories.push({
|
|
110
|
+
phase: 2,
|
|
111
|
+
priority: 'P1',
|
|
112
|
+
title: 'Implement API client with Dio and interceptors',
|
|
113
|
+
description: `Configure a Dio HTTP client in \`lib/features/api/\`. Base URL: ${baseUrl}. Add interceptors for auth token injection, retry on transient failures, and request logging. Expose via \`dioClientProvider\`. Define \`ApiException\` for typed error handling.`,
|
|
114
|
+
acceptanceCriteria: [
|
|
115
|
+
'`dioClientProvider` is a Riverpod Provider returning a configured `Dio` instance',
|
|
116
|
+
'Auth interceptor injects Bearer token from auth state (if auth module is enabled)',
|
|
117
|
+
'Retry interceptor handles 5xx errors with exponential backoff',
|
|
118
|
+
'`ApiException` maps HTTP status codes to typed errors',
|
|
119
|
+
'Unit tests for interceptors pass',
|
|
120
|
+
'`flutter analyze` reports zero errors',
|
|
121
|
+
],
|
|
122
|
+
passes: false,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
if (context.modules.database) {
|
|
126
|
+
const engine = context.modules.database.engine;
|
|
127
|
+
const engineLabel = engine === 'drift' ? 'Drift (SQLite)' : engine === 'hive' ? 'Hive' : 'Isar';
|
|
128
|
+
stories.push({
|
|
129
|
+
phase: 2,
|
|
130
|
+
priority: 'P1',
|
|
131
|
+
title: `Configure local database with ${engineLabel}`,
|
|
132
|
+
description: `Set up ${engineLabel} in \`lib/features/database/\`. Define initial schema/collections. Expose database via \`databaseProvider\`. Add initialization in main.dart before runApp. Run build_runner to generate database code.`,
|
|
133
|
+
acceptanceCriteria: [
|
|
134
|
+
`${engineLabel} is initialized before the app starts`,
|
|
135
|
+
'`databaseProvider` exposes the database instance via Riverpod',
|
|
136
|
+
engine === 'drift' ? '`AppDatabase` class with at least one table defined' : `${engineLabel} adapter/collection defined`,
|
|
137
|
+
'build_runner generates code without conflicts',
|
|
138
|
+
'Unit test verifies database can be opened and written to',
|
|
139
|
+
'`flutter analyze` reports zero errors',
|
|
140
|
+
],
|
|
141
|
+
passes: false,
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
if (context.modules.i18n) {
|
|
145
|
+
const { defaultLocale, supportedLocales } = context.modules.i18n;
|
|
146
|
+
stories.push({
|
|
147
|
+
phase: 2,
|
|
148
|
+
priority: 'P1',
|
|
149
|
+
title: 'Implement internationalization with flutter_localizations',
|
|
150
|
+
description: `Set up i18n in \`lib/core/l10n/\`. Create ARB files for: ${supportedLocales.join(', ')} (default: ${defaultLocale}). Run \`flutter gen-l10n\` to generate \`AppLocalizations\`. Update MaterialApp to include localization delegates.`,
|
|
151
|
+
acceptanceCriteria: [
|
|
152
|
+
`ARB files exist for all supported locales: ${supportedLocales.join(', ')}`,
|
|
153
|
+
'`AppLocalizations` is generated and available via `AppLocalizations.of(context)!`',
|
|
154
|
+
'MaterialApp includes `AppLocalizations.delegate` and `supportedLocales`',
|
|
155
|
+
'At minimum, app title and home screen greeting are localized',
|
|
156
|
+
'`flutter analyze` reports zero errors',
|
|
157
|
+
],
|
|
158
|
+
passes: false,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
if (context.modules.theme) {
|
|
162
|
+
const { seedColor, darkMode } = context.modules.theme;
|
|
163
|
+
const seedNote = seedColor ? `seed color ${seedColor}` : 'default purple seed color';
|
|
164
|
+
stories.push({
|
|
165
|
+
phase: 2,
|
|
166
|
+
priority: 'P1',
|
|
167
|
+
title: 'Implement Material 3 theme system',
|
|
168
|
+
description: `Build the theme in \`lib/core/theme/app_theme.dart\` using Material 3 ColorScheme.fromSeed with ${seedNote}. ${darkMode ? 'Support both light and dark themes via `appThemeModeProvider`.' : 'Light theme only.'} Apply Google Fonts (Inter) as the default text theme.`,
|
|
169
|
+
acceptanceCriteria: [
|
|
170
|
+
'`AppTheme.light()` returns a `ThemeData` with Material 3 enabled',
|
|
171
|
+
darkMode ? '`AppTheme.dark()` returns a dark `ThemeData`' : 'Light theme applied consistently',
|
|
172
|
+
darkMode ? '`appThemeModeProvider` toggles between light and dark modes' : 'Theme applied to MaterialApp',
|
|
173
|
+
'Google Fonts Inter is applied as the text theme',
|
|
174
|
+
'`flutter analyze` reports zero errors',
|
|
175
|
+
],
|
|
176
|
+
passes: false,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
if (context.modules.push) {
|
|
180
|
+
const provider = context.modules.push.provider;
|
|
181
|
+
const providerLabel = provider === 'firebase' ? 'Firebase Cloud Messaging' : 'OneSignal';
|
|
182
|
+
stories.push({
|
|
183
|
+
phase: 2,
|
|
184
|
+
priority: 'P2',
|
|
185
|
+
title: `Implement push notifications with ${providerLabel}`,
|
|
186
|
+
description: `Configure ${providerLabel} in \`lib/features/push/\`. Request notification permissions at app startup. Handle foreground, background, and terminated state notifications. Expose push token via \`pushTokenProvider\`.`,
|
|
187
|
+
acceptanceCriteria: [
|
|
188
|
+
`${providerLabel} is initialized before the app starts`,
|
|
189
|
+
'Notification permission is requested on first launch',
|
|
190
|
+
'Foreground notification handler displays an in-app notification',
|
|
191
|
+
'Background/terminated notification tap navigates to correct screen',
|
|
192
|
+
'`pushTokenProvider` returns the device token as a Future<String?>',
|
|
193
|
+
'`flutter analyze` reports zero errors',
|
|
194
|
+
],
|
|
195
|
+
passes: false,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
if (context.modules.analytics) {
|
|
199
|
+
stories.push({
|
|
200
|
+
phase: 2,
|
|
201
|
+
priority: 'P2',
|
|
202
|
+
title: 'Implement analytics event tracking',
|
|
203
|
+
description: 'Create `AnalyticsService` abstraction in `lib/features/analytics/`. Implement a GoRouter observer that tracks screen views automatically. Provide `analyticsServiceProvider` for logging custom events. Log app open event on startup.',
|
|
204
|
+
acceptanceCriteria: [
|
|
205
|
+
'`AnalyticsService` interface defines `logEvent(name, params)` and `logScreen(name)`',
|
|
206
|
+
'GoRouter observer automatically tracks screen navigation',
|
|
207
|
+
'`analyticsServiceProvider` exposes the `AnalyticsService`',
|
|
208
|
+
'App open event is logged on startup',
|
|
209
|
+
'Unit tests mock `AnalyticsService` and verify event calls',
|
|
210
|
+
'`flutter analyze` reports zero errors',
|
|
211
|
+
],
|
|
212
|
+
passes: false,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
if (context.modules.cicd) {
|
|
216
|
+
const providerLabel = context.modules.cicd.provider;
|
|
217
|
+
stories.push({
|
|
218
|
+
phase: 2,
|
|
219
|
+
priority: 'P2',
|
|
220
|
+
title: `Configure ${capitalize(providerLabel)} CI/CD pipeline`,
|
|
221
|
+
description: `Set up CI/CD pipeline for ${capitalize(providerLabel)}. Pipeline should run on every push: (1) flutter analyze, (2) flutter test, (3) flutter build. Cache Flutter SDK and pub dependencies for speed.`,
|
|
222
|
+
acceptanceCriteria: [
|
|
223
|
+
providerLabel === 'github' ? '`.github/workflows/ci.yml` exists and is valid YAML' : providerLabel === 'gitlab' ? '`.gitlab-ci.yml` exists and is valid YAML' : '`bitbucket-pipelines.yml` exists and is valid YAML',
|
|
224
|
+
'Pipeline includes analyze, test, and build stages/jobs',
|
|
225
|
+
'Flutter pub cache is configured for fast runs',
|
|
226
|
+
'Pipeline triggers on push to main and pull requests',
|
|
227
|
+
'`flutter analyze` reports zero errors in CI config files',
|
|
228
|
+
],
|
|
229
|
+
passes: false,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
if (context.modules.deepLinking) {
|
|
233
|
+
const { scheme, host } = context.modules.deepLinking;
|
|
234
|
+
const linkExample = scheme && host ? `${scheme}://${host}` : 'app://example.com';
|
|
235
|
+
stories.push({
|
|
236
|
+
phase: 2,
|
|
237
|
+
priority: 'P2',
|
|
238
|
+
title: 'Implement deep linking with app_links',
|
|
239
|
+
description: `Configure deep links using \`app_links\` package. Handle Universal Links (iOS) and App Links (Android). Integrate with go_router for automatic route resolution. Example link: \`${linkExample}\`.`,
|
|
240
|
+
acceptanceCriteria: [
|
|
241
|
+
'`app_links` is initialized at app startup',
|
|
242
|
+
'Incoming deep links are forwarded to go_router for navigation',
|
|
243
|
+
scheme ? `Custom scheme \`${scheme}://\` is handled` : 'Deep link scheme is configured in platform files',
|
|
244
|
+
host ? `Host \`${host}\` is configured for Universal/App Links` : 'Host is configured in platform-specific files',
|
|
245
|
+
'Widget test verifies deep link navigation',
|
|
246
|
+
'`flutter analyze` reports zero errors',
|
|
247
|
+
],
|
|
248
|
+
passes: false,
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
return stories;
|
|
252
|
+
}
|
|
253
|
+
function generatePhase3Stories(context) {
|
|
254
|
+
const enabledModules = [];
|
|
255
|
+
if (context.modules.auth)
|
|
256
|
+
enabledModules.push('auth');
|
|
257
|
+
if (context.modules.api)
|
|
258
|
+
enabledModules.push('api');
|
|
259
|
+
if (context.modules.database)
|
|
260
|
+
enabledModules.push('database');
|
|
261
|
+
return [
|
|
262
|
+
{
|
|
263
|
+
phase: 3,
|
|
264
|
+
priority: 'P1',
|
|
265
|
+
title: 'Write integration tests for core user flows',
|
|
266
|
+
description: `Write integration tests covering the main user journeys in ${context.projectName}. ${enabledModules.length > 0 ? `Test flows involving: ${enabledModules.join(', ')}.` : 'Test home screen navigation and basic app flows.'} Use \`integration_test\` package with \`flutter_test\`.`,
|
|
267
|
+
acceptanceCriteria: [
|
|
268
|
+
'`integration_test/` directory exists with at least one integration test file',
|
|
269
|
+
'Tests cover the happy path for core user journeys',
|
|
270
|
+
'Tests use `WidgetTester` for UI interactions',
|
|
271
|
+
'`flutter test integration_test/` passes all tests',
|
|
272
|
+
'Test coverage report shows >70% coverage for presentation layer',
|
|
273
|
+
],
|
|
274
|
+
passes: false,
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
phase: 3,
|
|
278
|
+
priority: 'P2',
|
|
279
|
+
title: 'Final quality audit and documentation',
|
|
280
|
+
description: `Perform a final quality pass on all code in ${context.projectName}. Fix any remaining analyzer warnings. Ensure all public APIs have dartdoc comments. Verify README.md documents how to run the app and run tests.`,
|
|
281
|
+
acceptanceCriteria: [
|
|
282
|
+
'`flutter analyze` reports zero errors AND zero warnings',
|
|
283
|
+
'`flutter test` passes all tests',
|
|
284
|
+
'`dart format --set-exit-if-changed .` passes',
|
|
285
|
+
'README.md includes setup instructions and how to run the app',
|
|
286
|
+
'All public provider declarations have dartdoc comments',
|
|
287
|
+
],
|
|
288
|
+
passes: false,
|
|
289
|
+
},
|
|
290
|
+
];
|
|
291
|
+
}
|
|
292
|
+
function capitalize(str) {
|
|
293
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=prd-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prd-generator.js","sourceRoot":"","sources":["../../src/claude-setup/prd-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ProjectContext } from '../core/context.js';
|
|
2
|
+
export interface ClaudeSetupResult {
|
|
3
|
+
filesWritten: string[];
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Runs the full Claude setup for a scaffolded Flutter project.
|
|
7
|
+
* Generates CLAUDE.md, agent definitions, skills, hooks, MCP config,
|
|
8
|
+
* slash commands, and prd.json.
|
|
9
|
+
*/
|
|
10
|
+
export declare function runClaudeSetup(context: ProjectContext, outputPath: string): Promise<ClaudeSetupResult>;
|
|
11
|
+
//# sourceMappingURL=setup-orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-orchestrator.d.ts","sourceRoot":"","sources":["../../src/claude-setup/setup-orchestrator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AASzD,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC,CA+C5B"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { writeFile, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { generateClaudeMd } from './claude-md-generator.js';
|
|
4
|
+
import { writeAgents } from './agent-writer.js';
|
|
5
|
+
import { writeSkills } from './skill-writer.js';
|
|
6
|
+
import { writeHooks } from './hooks-writer.js';
|
|
7
|
+
import { writeMcpConfig } from './mcp-config-writer.js';
|
|
8
|
+
import { writeCommands } from './commands-writer.js';
|
|
9
|
+
import { generatePrd } from './prd-generator.js';
|
|
10
|
+
/**
|
|
11
|
+
* Runs the full Claude setup for a scaffolded Flutter project.
|
|
12
|
+
* Generates CLAUDE.md, agent definitions, skills, hooks, MCP config,
|
|
13
|
+
* slash commands, and prd.json.
|
|
14
|
+
*/
|
|
15
|
+
export async function runClaudeSetup(context, outputPath) {
|
|
16
|
+
const filesWritten = [];
|
|
17
|
+
// Ensure .claude directory exists
|
|
18
|
+
await mkdir(join(outputPath, '.claude'), { recursive: true });
|
|
19
|
+
// 1. Generate and write CLAUDE.md
|
|
20
|
+
const claudeMdContent = generateClaudeMd(context);
|
|
21
|
+
const claudeMdPath = join(outputPath, 'CLAUDE.md');
|
|
22
|
+
await writeFile(claudeMdPath, claudeMdContent, 'utf-8');
|
|
23
|
+
filesWritten.push(claudeMdPath);
|
|
24
|
+
// 2. Write agent definition files (.claude/agents/)
|
|
25
|
+
const agentFiles = await writeAgents(context, outputPath);
|
|
26
|
+
filesWritten.push(...agentFiles);
|
|
27
|
+
// 3. Write skill files (.claude/skills/)
|
|
28
|
+
await writeSkills(context, outputPath);
|
|
29
|
+
filesWritten.push(join(outputPath, '.claude', 'skills', 'flutter-patterns.md'), join(outputPath, '.claude', 'skills', 'go-router-patterns.md'), join(outputPath, '.claude', 'skills', 'module-conventions.md'), join(outputPath, '.claude', 'skills', 'prd.md'));
|
|
30
|
+
// 4. Write hooks config (.claude/settings.local.json)
|
|
31
|
+
await writeHooks(context, outputPath);
|
|
32
|
+
filesWritten.push(join(outputPath, '.claude', 'settings.local.json'));
|
|
33
|
+
// 5. Write MCP server config (.mcp.json)
|
|
34
|
+
await writeMcpConfig(context, outputPath);
|
|
35
|
+
filesWritten.push(join(outputPath, '.mcp.json'));
|
|
36
|
+
// 6. Write slash commands (.claude/commands/)
|
|
37
|
+
await writeCommands(context, outputPath);
|
|
38
|
+
filesWritten.push(join(outputPath, '.claude', 'commands', 'add-feature.md'), join(outputPath, '.claude', 'commands', 'analyze.md'));
|
|
39
|
+
// 7. Generate and write prd.json
|
|
40
|
+
const prdContent = generatePrd(context);
|
|
41
|
+
const prdPath = join(outputPath, 'prd.json');
|
|
42
|
+
await writeFile(prdPath, prdContent, 'utf-8');
|
|
43
|
+
filesWritten.push(prdPath);
|
|
44
|
+
return { filesWritten };
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=setup-orchestrator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup-orchestrator.js","sourceRoot":"","sources":["../../src/claude-setup/setup-orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAC5D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAMjD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,OAAuB,EACvB,UAAkB;IAElB,MAAM,YAAY,GAAa,EAAE,CAAC;IAElC,kCAAkC;IAClC,MAAM,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9D,kCAAkC;IAClC,MAAM,eAAe,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;IAClD,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;IACnD,MAAM,SAAS,CAAC,YAAY,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;IACxD,YAAY,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAEhC,oDAAoD;IACpD,MAAM,UAAU,GAAG,MAAM,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC1D,YAAY,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,CAAC;IAEjC,yCAAyC;IACzC,MAAM,WAAW,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACvC,YAAY,CAAC,IAAI,CACf,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,qBAAqB,CAAC,EAC5D,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,uBAAuB,CAAC,EAC9D,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,uBAAuB,CAAC,EAC9D,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAChD,CAAC;IAEF,sDAAsD;IACtD,MAAM,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACtC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,qBAAqB,CAAC,CAAC,CAAC;IAEtE,yCAAyC;IACzC,MAAM,cAAc,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAC1C,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;IAEjD,8CAA8C;IAC9C,MAAM,aAAa,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACzC,YAAY,CAAC,IAAI,CACf,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,gBAAgB,CAAC,EACzD,IAAI,CAAC,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,CAAC,CACtD,CAAC;IAEF,iCAAiC;IACjC,MAAM,UAAU,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IAC7C,MAAM,SAAS,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IAC9C,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAE3B,OAAO,EAAE,YAAY,EAAE,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-writer.d.ts","sourceRoot":"","sources":["../../src/claude-setup/skill-writer.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEzD,wBAAsB,WAAW,CAAC,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAU5F"}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export async function writeSkills(context, outputPath) {
|
|
4
|
+
const skillsDir = path.join(outputPath, '.claude', 'skills');
|
|
5
|
+
await fs.ensureDir(skillsDir);
|
|
6
|
+
await Promise.all([
|
|
7
|
+
fs.writeFile(path.join(skillsDir, 'flutter-patterns.md'), generateFlutterPatterns()),
|
|
8
|
+
fs.writeFile(path.join(skillsDir, 'go-router-patterns.md'), generateGoRouterPatterns(context)),
|
|
9
|
+
fs.writeFile(path.join(skillsDir, 'module-conventions.md'), generateModuleConventions()),
|
|
10
|
+
fs.writeFile(path.join(skillsDir, 'prd.md'), generatePrdGuide()),
|
|
11
|
+
]);
|
|
12
|
+
}
|
|
13
|
+
function generateFlutterPatterns() {
|
|
14
|
+
return [
|
|
15
|
+
'# Flutter / Riverpod Patterns',
|
|
16
|
+
'',
|
|
17
|
+
'## Provider Naming Conventions',
|
|
18
|
+
'',
|
|
19
|
+
'- Providers are top-level `final` variables with a `Provider` suffix',
|
|
20
|
+
'- Repository providers: `authRepositoryProvider`, `userRepositoryProvider`',
|
|
21
|
+
'- State providers: `userNotifierProvider`, `authStateProvider`',
|
|
22
|
+
'- Computed providers: `isLoggedInProvider`, `currentUserProvider`',
|
|
23
|
+
'',
|
|
24
|
+
'## Provider Types',
|
|
25
|
+
'',
|
|
26
|
+
'| Type | Use Case |',
|
|
27
|
+
'|------|----------|',
|
|
28
|
+
'| `Provider` | Computed values, repository instances, services |',
|
|
29
|
+
'| `NotifierProvider` | Synchronous mutable state (Riverpod 2.0+) |',
|
|
30
|
+
'| `AsyncNotifierProvider` | Async mutable state (Riverpod 2.0+) |',
|
|
31
|
+
'| `FutureProvider` | One-shot async data (auto-disposes, caches) |',
|
|
32
|
+
'| `StreamProvider` | Real-time streams (Firestore, WebSocket) |',
|
|
33
|
+
'| `StateProvider` | Simple primitive state (bool, int, String) |',
|
|
34
|
+
'',
|
|
35
|
+
'## ref.watch vs ref.read',
|
|
36
|
+
'',
|
|
37
|
+
'- **`ref.watch()`**: Use inside `build()` methods and provider bodies. Re-builds when value changes.',
|
|
38
|
+
'- **`ref.read()`**: Use inside callbacks, event handlers. Does NOT trigger rebuilds.',
|
|
39
|
+
'- **`ref.listen()`**: Side effects in response to state changes (snackbars, navigation).',
|
|
40
|
+
'',
|
|
41
|
+
'## AsyncNotifier (preferred for Riverpod 2.0+)',
|
|
42
|
+
'',
|
|
43
|
+
'```dart',
|
|
44
|
+
'final userProvider = AsyncNotifierProvider<UserNotifier, User?>(() {',
|
|
45
|
+
' return UserNotifier();',
|
|
46
|
+
'});',
|
|
47
|
+
'',
|
|
48
|
+
'class UserNotifier extends AsyncNotifier<User?> {',
|
|
49
|
+
' @override',
|
|
50
|
+
' Future<User?> build() async {',
|
|
51
|
+
' return ref.watch(authRepositoryProvider).getCurrentUser();',
|
|
52
|
+
' }',
|
|
53
|
+
'',
|
|
54
|
+
' Future<void> refresh() async {',
|
|
55
|
+
' state = const AsyncLoading();',
|
|
56
|
+
' state = await AsyncValue.guard(() =>',
|
|
57
|
+
' ref.read(authRepositoryProvider).getCurrentUser()',
|
|
58
|
+
' );',
|
|
59
|
+
' }',
|
|
60
|
+
'}',
|
|
61
|
+
'```',
|
|
62
|
+
'',
|
|
63
|
+
'## Provider Composition',
|
|
64
|
+
'',
|
|
65
|
+
'```dart',
|
|
66
|
+
'final httpClientProvider = Provider<Dio>((ref) => Dio());',
|
|
67
|
+
'',
|
|
68
|
+
'final authDataSourceProvider = Provider<AuthRemoteDataSource>((ref) {',
|
|
69
|
+
' return AuthRemoteDataSourceImpl(ref.watch(httpClientProvider));',
|
|
70
|
+
'});',
|
|
71
|
+
'',
|
|
72
|
+
'final authRepositoryProvider = Provider<AuthRepository>((ref) {',
|
|
73
|
+
' return AuthRepositoryImpl(ref.watch(authDataSourceProvider));',
|
|
74
|
+
'});',
|
|
75
|
+
'```',
|
|
76
|
+
'',
|
|
77
|
+
'## State Management Best Practices',
|
|
78
|
+
'',
|
|
79
|
+
'1. **Immutable state**: Use `freezed` for state classes to avoid mutation bugs',
|
|
80
|
+
'2. **Single source of truth**: One provider owns each piece of state',
|
|
81
|
+
'3. **Invalidation**: Use `ref.invalidate(provider)` to force a refresh',
|
|
82
|
+
'4. **Family providers**: Use `.family` modifier for parameterized providers',
|
|
83
|
+
'5. **Auto-dispose**: Use `.autoDispose` to clean up providers when not in use',
|
|
84
|
+
].join('\n');
|
|
85
|
+
}
|
|
86
|
+
function generateGoRouterPatterns(context) {
|
|
87
|
+
const deepLinkingNote = context.modules.deepLinking
|
|
88
|
+
? [
|
|
89
|
+
'',
|
|
90
|
+
'## Deep Linking Integration',
|
|
91
|
+
'',
|
|
92
|
+
'This project has deep linking enabled. Routes are handled via `app_links`.',
|
|
93
|
+
].join('\n')
|
|
94
|
+
: '';
|
|
95
|
+
const authGuardNote = context.modules.auth
|
|
96
|
+
? [
|
|
97
|
+
'',
|
|
98
|
+
'## Auth Guards',
|
|
99
|
+
'',
|
|
100
|
+
'```dart',
|
|
101
|
+
'GoRouter(',
|
|
102
|
+
' redirect: (context, state) {',
|
|
103
|
+
' final isLoggedIn = ref.read(isLoggedInProvider);',
|
|
104
|
+
' final isAuthRoute = state.matchedLocation.startsWith(\'/auth\');',
|
|
105
|
+
' if (!isLoggedIn && !isAuthRoute) return \'/auth/login\';',
|
|
106
|
+
' if (isLoggedIn && isAuthRoute) return \'/\';',
|
|
107
|
+
' return null;',
|
|
108
|
+
' },',
|
|
109
|
+
')',
|
|
110
|
+
'```',
|
|
111
|
+
].join('\n')
|
|
112
|
+
: '';
|
|
113
|
+
return [
|
|
114
|
+
'# go_router Patterns',
|
|
115
|
+
'',
|
|
116
|
+
'## Route Definition',
|
|
117
|
+
'',
|
|
118
|
+
'Routes are defined in `lib/core/router/app_router.dart` using TypedGoRoute for type-safe navigation.',
|
|
119
|
+
'',
|
|
120
|
+
'```dart',
|
|
121
|
+
'part \'app_router.g.dart\';',
|
|
122
|
+
'',
|
|
123
|
+
'@TypedGoRoute<HomeRoute>(path: \'/\', routes: [',
|
|
124
|
+
' TypedGoRoute<ProfileRoute>(path: \'profile\'),',
|
|
125
|
+
'])',
|
|
126
|
+
'@immutable',
|
|
127
|
+
'class HomeRoute extends GoRouteData {',
|
|
128
|
+
' const HomeRoute();',
|
|
129
|
+
'',
|
|
130
|
+
' @override',
|
|
131
|
+
' Widget build(BuildContext context, GoRouterState state) => const HomePage();',
|
|
132
|
+
'}',
|
|
133
|
+
'```',
|
|
134
|
+
'',
|
|
135
|
+
'## Navigation',
|
|
136
|
+
'',
|
|
137
|
+
'```dart',
|
|
138
|
+
'// Type-safe (preferred)',
|
|
139
|
+
'const HomeRoute().go(context);',
|
|
140
|
+
'ProfileRoute(userId: \'123\').push(context);',
|
|
141
|
+
'```',
|
|
142
|
+
authGuardNote,
|
|
143
|
+
deepLinkingNote,
|
|
144
|
+
'',
|
|
145
|
+
'## Adding a New Route',
|
|
146
|
+
'',
|
|
147
|
+
'1. Create a route class with `@TypedGoRoute` annotation',
|
|
148
|
+
'2. Implement the `build()` method returning the page widget',
|
|
149
|
+
'3. Run `dart run build_runner build --delete-conflicting-outputs`',
|
|
150
|
+
'4. Update the parent route\'s `routes` list if it\'s a child route',
|
|
151
|
+
].join('\n');
|
|
152
|
+
}
|
|
153
|
+
function generateModuleConventions() {
|
|
154
|
+
return [
|
|
155
|
+
'# Module Conventions (Clean Architecture)',
|
|
156
|
+
'',
|
|
157
|
+
'## Directory Structure Per Feature',
|
|
158
|
+
'',
|
|
159
|
+
'```',
|
|
160
|
+
'lib/features/<feature-name>/',
|
|
161
|
+
'├── domain/',
|
|
162
|
+
'│ ├── entities/ # Pure Dart models (use freezed)',
|
|
163
|
+
'│ ├── repositories/ # Abstract repository interfaces',
|
|
164
|
+
'│ └── usecases/ # Single-responsibility business operations',
|
|
165
|
+
'├── data/',
|
|
166
|
+
'│ ├── datasources/ # Remote (API) and local (DB) data sources',
|
|
167
|
+
'│ ├── models/ # Data transfer objects with serialization',
|
|
168
|
+
'│ └── repositories/ # Repository implementations',
|
|
169
|
+
'└── presentation/',
|
|
170
|
+
' ├── pages/ # Full-screen UI (route targets)',
|
|
171
|
+
' ├── widgets/ # Reusable UI components',
|
|
172
|
+
' └── providers/ # Riverpod providers and state notifiers',
|
|
173
|
+
'```',
|
|
174
|
+
'',
|
|
175
|
+
'## Layer Dependency Rules',
|
|
176
|
+
'',
|
|
177
|
+
'```',
|
|
178
|
+
'Domain ← Data ← Presentation',
|
|
179
|
+
'```',
|
|
180
|
+
'',
|
|
181
|
+
'- **Domain**: No dependencies on other layers or external packages',
|
|
182
|
+
'- **Data**: Depends on Domain only (implements repository interfaces)',
|
|
183
|
+
'- **Presentation**: Depends on Domain only (accesses Data via providers)',
|
|
184
|
+
'',
|
|
185
|
+
'## Cross-Feature Communication',
|
|
186
|
+
'',
|
|
187
|
+
'Features should NOT import from each other directly. Use:',
|
|
188
|
+
'',
|
|
189
|
+
'- **Providers**: Share state through Riverpod providers in `lib/core/providers/`',
|
|
190
|
+
'- **Entities**: Share domain entities through `lib/core/domain/`',
|
|
191
|
+
'- **Events**: Use streams or callbacks for loose coupling',
|
|
192
|
+
'',
|
|
193
|
+
'## Adding a New Feature',
|
|
194
|
+
'',
|
|
195
|
+
'1. Create feature directory following the structure above',
|
|
196
|
+
'2. Start with Domain layer: entities, repository interfaces, use cases',
|
|
197
|
+
'3. Add Data layer: models, data sources, repository implementation',
|
|
198
|
+
'4. Add Presentation layer: providers, pages, widgets',
|
|
199
|
+
'5. Register routes in `lib/core/router/app_router.dart`',
|
|
200
|
+
'6. Run code generation: `dart run build_runner build`',
|
|
201
|
+
'7. Write tests in `test/features/<name>/`',
|
|
202
|
+
].join('\n');
|
|
203
|
+
}
|
|
204
|
+
function generatePrdGuide() {
|
|
205
|
+
return [
|
|
206
|
+
'# Working with prd.json',
|
|
207
|
+
'',
|
|
208
|
+
'## Story Structure',
|
|
209
|
+
'',
|
|
210
|
+
'```json',
|
|
211
|
+
'{',
|
|
212
|
+
' "id": "S-001",',
|
|
213
|
+
' "phase": 1,',
|
|
214
|
+
' "priority": "P0",',
|
|
215
|
+
' "title": "Short imperative title",',
|
|
216
|
+
' "description": "Detailed description of what needs to be built",',
|
|
217
|
+
' "acceptanceCriteria": [',
|
|
218
|
+
' "Criterion 1 that must be true for the story to be complete",',
|
|
219
|
+
' "Criterion 2"',
|
|
220
|
+
' ],',
|
|
221
|
+
' "passes": false',
|
|
222
|
+
'}',
|
|
223
|
+
'```',
|
|
224
|
+
'',
|
|
225
|
+
'## Fields',
|
|
226
|
+
'',
|
|
227
|
+
'| Field | Type | Description |',
|
|
228
|
+
'|-------|------|-------------|',
|
|
229
|
+
'| `id` | string | Unique story identifier (e.g., "S-001") |',
|
|
230
|
+
'| `phase` | number | Implementation phase (1=core, 2=features, 3=polish, 4=advanced) |',
|
|
231
|
+
'| `priority` | string | P0 (critical), P1 (high), P2 (medium), P3 (low) |',
|
|
232
|
+
'| `title` | string | Short description of what to implement |',
|
|
233
|
+
'| `description` | string | Full requirements and context |',
|
|
234
|
+
'| `acceptanceCriteria` | string[] | Measurable conditions that must be true when done |',
|
|
235
|
+
'| `passes` | boolean | `true` when story is complete and quality gates pass |',
|
|
236
|
+
'',
|
|
237
|
+
'## Workflow for Implementing a Story',
|
|
238
|
+
'',
|
|
239
|
+
'1. **Read the story**: Understand the description and acceptance criteria',
|
|
240
|
+
'2. **Plan**: Identify which files need to be created or modified',
|
|
241
|
+
'3. **Implement**: Follow Clean Architecture layers (domain → data → presentation)',
|
|
242
|
+
'4. **Test**: Write unit/integration tests covering the acceptance criteria',
|
|
243
|
+
'5. **Quality gates**: Run `flutter analyze && flutter test`',
|
|
244
|
+
'6. **Mark complete**: Set `"passes": true` in `prd.json`',
|
|
245
|
+
'7. **Commit**: `git commit -m "feat: [S-001] - Story title"`',
|
|
246
|
+
'',
|
|
247
|
+
'## Marking a Story Complete',
|
|
248
|
+
'',
|
|
249
|
+
'Only mark `passes: true` when:',
|
|
250
|
+
'- All acceptance criteria are demonstrably met',
|
|
251
|
+
'- `flutter analyze` returns zero errors or warnings',
|
|
252
|
+
'- `flutter test` passes all tests',
|
|
253
|
+
'- Code follows Clean Architecture layer rules',
|
|
254
|
+
].join('\n');
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=skill-writer.js.map
|