agy-superpowers 5.0.7 → 5.0.9
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/package.json +1 -1
- package/template/agent/rules/superpowers.md +54 -0
- package/template/agent/skills/api-design/SKILL.md +193 -0
- package/template/agent/skills/app-store-optimizer/SKILL.md +127 -0
- package/template/agent/skills/auth-and-identity/SKILL.md +167 -0
- package/template/agent/skills/backend-developer/SKILL.md +148 -0
- package/template/agent/skills/community-manager/SKILL.md +115 -0
- package/template/agent/skills/content-marketer/SKILL.md +111 -0
- package/template/agent/skills/conversion-optimizer/SKILL.md +142 -0
- package/template/agent/skills/copywriter/SKILL.md +114 -0
- package/template/agent/skills/cto-architect/SKILL.md +133 -0
- package/template/agent/skills/customer-success-manager/SKILL.md +126 -0
- package/template/agent/skills/data-analyst/SKILL.md +147 -0
- package/template/agent/skills/devops-engineer/SKILL.md +117 -0
- package/template/agent/skills/email-infrastructure/SKILL.md +164 -0
- package/template/agent/skills/frontend-developer/SKILL.md +172 -0
- package/template/agent/skills/frontend-developer/references/react-nextjs.md +343 -0
- package/template/agent/skills/frontend-developer/references/react-rules/_sections.md +46 -0
- package/template/agent/skills/frontend-developer/references/react-rules/_template.md +28 -0
- package/template/agent/skills/frontend-developer/references/react-rules/advanced-event-handler-refs.md +55 -0
- package/template/agent/skills/frontend-developer/references/react-rules/advanced-init-once.md +42 -0
- package/template/agent/skills/frontend-developer/references/react-rules/advanced-use-latest.md +39 -0
- package/template/agent/skills/frontend-developer/references/react-rules/async-api-routes.md +38 -0
- package/template/agent/skills/frontend-developer/references/react-rules/async-defer-await.md +80 -0
- package/template/agent/skills/frontend-developer/references/react-rules/async-dependencies.md +51 -0
- package/template/agent/skills/frontend-developer/references/react-rules/async-parallel.md +28 -0
- package/template/agent/skills/frontend-developer/references/react-rules/async-suspense-boundaries.md +99 -0
- package/template/agent/skills/frontend-developer/references/react-rules/bundle-barrel-imports.md +59 -0
- package/template/agent/skills/frontend-developer/references/react-rules/bundle-conditional.md +31 -0
- package/template/agent/skills/frontend-developer/references/react-rules/bundle-defer-third-party.md +49 -0
- package/template/agent/skills/frontend-developer/references/react-rules/bundle-dynamic-imports.md +35 -0
- package/template/agent/skills/frontend-developer/references/react-rules/bundle-preload.md +50 -0
- package/template/agent/skills/frontend-developer/references/react-rules/client-event-listeners.md +74 -0
- package/template/agent/skills/frontend-developer/references/react-rules/client-localstorage-schema.md +71 -0
- package/template/agent/skills/frontend-developer/references/react-rules/client-passive-event-listeners.md +48 -0
- package/template/agent/skills/frontend-developer/references/react-rules/client-swr-dedup.md +56 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-batch-dom-css.md +107 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-cache-function-results.md +80 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-cache-property-access.md +28 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-cache-storage.md +70 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-combine-iterations.md +32 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-early-exit.md +50 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-flatmap-filter.md +60 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-hoist-regexp.md +45 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-index-maps.md +37 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-length-check-first.md +49 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-min-max-loop.md +82 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-set-map-lookups.md +24 -0
- package/template/agent/skills/frontend-developer/references/react-rules/js-tosorted-immutable.md +57 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-activity.md +26 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-animate-svg-wrapper.md +47 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-conditional-render.md +40 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-content-visibility.md +38 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-hoist-jsx.md +46 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-hydration-no-flicker.md +82 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-hydration-suppress-warning.md +30 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-resource-hints.md +85 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-script-defer-async.md +68 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-svg-precision.md +28 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rendering-usetransition-loading.md +75 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-defer-reads.md +39 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-dependencies.md +45 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-derived-state-no-effect.md +40 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-derived-state.md +29 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-functional-setstate.md +74 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-lazy-state-init.md +58 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-memo-with-default-value.md +38 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-memo.md +44 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-move-effect-to-event.md +45 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-no-inline-components.md +82 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-simple-expression-in-memo.md +35 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-split-combined-hooks.md +64 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-transitions.md +40 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-use-deferred-value.md +59 -0
- package/template/agent/skills/frontend-developer/references/react-rules/rerender-use-ref-transient-values.md +73 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-after-nonblocking.md +73 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-auth-actions.md +96 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-cache-lru.md +41 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-cache-react.md +76 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-dedup-props.md +65 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-hoist-static-io.md +142 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-parallel-fetching.md +83 -0
- package/template/agent/skills/frontend-developer/references/react-rules/server-serialization.md +38 -0
- package/template/agent/skills/frontend-developer/references/svelte-sveltekit.md +220 -0
- package/template/agent/skills/frontend-developer/references/vanilla.md +275 -0
- package/template/agent/skills/frontend-developer/references/vue-nuxt.md +289 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/_index.md +154 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/animation-class-based-technique.md +254 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/animation-state-driven-technique.md +291 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-async.md +97 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-data-flow.md +307 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-fallthrough-attrs.md +174 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-keep-alive.md +137 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-slots.md +216 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-suspense.md +228 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-teleport.md +108 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-transition-group.md +128 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/component-transition.md +125 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/composables.md +290 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/directives.md +162 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/perf-avoid-component-abstraction-in-lists.md +159 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/perf-v-once-v-memo-directives.md +182 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/perf-virtualize-large-lists.md +187 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/plugins.md +166 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/reactivity.md +344 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/render-functions.md +201 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/sfc.md +310 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/state-management.md +135 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/best-practices/updated-hook-performance.md +187 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/_index.md +23 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-beforeenter-no-param-trigger.md +167 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-beforerouteenter-no-this.md +176 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-guard-async-await-pattern.md +227 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-navigation-guard-infinite-loop.md +187 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-navigation-guard-next-deprecated.md +150 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-param-change-no-lifecycle.md +181 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-simple-routing-cleanup.md +209 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/router/router-use-vue-router-for-production.md +183 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/_index.md +29 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/async-component-testing.md +163 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/teleport-testing-complexity.md +158 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-async-await-flushpromises.md +175 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-browser-vs-node-runners.md +208 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-component-blackbox-approach.md +144 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-composables-helper-wrapper.md +238 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-e2e-playwright-recommended.md +242 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-no-snapshot-only.md +197 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-pinia-store-setup.md +228 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-suspense-async-components.md +229 -0
- package/template/agent/skills/frontend-developer/references/vue-rules/testing/testing-vitest-recommended-for-vue.md +204 -0
- package/template/agent/skills/game-design/SKILL.md +194 -0
- package/template/agent/skills/game-developer/SKILL.md +175 -0
- package/template/agent/skills/growth-hacker/SKILL.md +122 -0
- package/template/agent/skills/i18n-localization/SKILL.md +126 -0
- package/template/agent/skills/influencer-marketer/SKILL.md +141 -0
- package/template/agent/skills/mobile-developer/SKILL.md +194 -0
- package/template/agent/skills/mobile-developer/references/android-native.md +396 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-accessibility.md +36 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-architecture.md +52 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-coroutines.md +139 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-data-layer.md +51 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-emulator-skill.md +108 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-gradle-logic.md +126 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-retrofit.md +142 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-testing.md +102 -0
- package/template/agent/skills/mobile-developer/references/android-rules/android-viewmodel.md +43 -0
- package/template/agent/skills/mobile-developer/references/android-rules/coil-compose.md +74 -0
- package/template/agent/skills/mobile-developer/references/android-rules/compose-navigation.md +422 -0
- package/template/agent/skills/mobile-developer/references/android-rules/compose-performance-audit.md +199 -0
- package/template/agent/skills/mobile-developer/references/android-rules/compose-ui.md +49 -0
- package/template/agent/skills/mobile-developer/references/android-rules/gradle-build-performance.md +346 -0
- package/template/agent/skills/mobile-developer/references/android-rules/kotlin-concurrency-expert.md +169 -0
- package/template/agent/skills/mobile-developer/references/android-rules/rxjava-to-coroutines-migration.md +101 -0
- package/template/agent/skills/mobile-developer/references/android-rules/xml-to-compose-migration.md +338 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-best-practices.md +52 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-checks-migration.md +134 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-cli-app-best-practices.md +123 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-doc-validation.md +45 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-matcher-best-practices.md +106 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-modern-features.md +241 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-package-maintenance.md +75 -0
- package/template/agent/skills/mobile-developer/references/flutter-rules/dart-test-fundamentals.md +124 -0
- package/template/agent/skills/mobile-developer/references/flutter.md +291 -0
- package/template/agent/skills/mobile-developer/references/ios-native.md +358 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/accessibility-patterns.md +215 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/animation-advanced.md +403 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/animation-basics.md +284 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/animation-transitions.md +326 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/charts-accessibility.md +135 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/charts.md +602 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/image-optimization.md +203 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/latest-apis.md +464 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/layout-best-practices.md +266 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/liquid-glass.md +416 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/list-patterns.md +394 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/macos-scenes.md +318 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/macos-views.md +357 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/macos-window-styling.md +303 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/performance-patterns.md +403 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/scroll-patterns.md +293 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/sheet-navigation-patterns.md +363 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/state-management.md +417 -0
- package/template/agent/skills/mobile-developer/references/ios-rules/view-structure.md +389 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/_sections.md +86 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/_template.md +28 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/animation-derived-value.md +53 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/animation-gesture-detector-press.md +95 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/animation-gpu-properties.md +65 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/design-system-compound-components.md +66 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/fonts-config-plugin.md +71 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/imports-design-system-folder.md +68 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/js-hoist-intl.md +61 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-callbacks.md +44 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-function-references.md +132 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-images.md +53 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-inline-objects.md +97 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-item-expensive.md +94 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-item-memo.md +82 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-item-types.md +104 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/list-performance-virtualize.md +67 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/monorepo-native-deps-in-app.md +46 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/monorepo-single-dependency-versions.md +63 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/navigation-native-navigators.md +188 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/react-compiler-destructure-functions.md +50 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/react-compiler-reanimated-shared-values.md +48 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/react-state-dispatcher.md +91 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/react-state-fallback.md +56 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/react-state-minimize.md +65 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/rendering-no-falsy-and.md +74 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/rendering-text-in-text-component.md +36 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/scroll-position-no-state.md +82 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/state-ground-truth.md +80 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-expo-image.md +66 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-image-gallery.md +104 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-measure-views.md +78 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-menus.md +174 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-native-modals.md +77 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-pressable.md +61 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-safe-area-scroll.md +65 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-scrollview-content-inset.md +45 -0
- package/template/agent/skills/mobile-developer/references/react-native-rules/ui-styling.md +87 -0
- package/template/agent/skills/mobile-developer/references/react-native.md +345 -0
- package/template/agent/skills/monetization-strategist/SKILL.md +119 -0
- package/template/agent/skills/paid-acquisition-specialist/SKILL.md +119 -0
- package/template/agent/skills/product-manager/SKILL.md +105 -0
- package/template/agent/skills/real-time-features/SKILL.md +194 -0
- package/template/agent/skills/retention-specialist/SKILL.md +123 -0
- package/template/agent/skills/saas-architect/SKILL.md +139 -0
- package/template/agent/skills/security-engineer/SKILL.md +133 -0
- package/template/agent/skills/seo-specialist/SKILL.md +130 -0
- package/template/agent/skills/subscription-billing/SKILL.md +179 -0
- package/template/agent/skills/ux-designer/SKILL.md +128 -0
package/template/agent/skills/mobile-developer/references/android-rules/xml-to-compose-migration.md
ADDED
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: xml-to-compose-migration
|
|
3
|
+
description: Convert Android XML layouts to Jetpack Compose. Use when asked to migrate Views to Compose, convert XML to Composables, or modernize UI from View system to Compose.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# XML to Compose Migration
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
Systematically convert Android XML layouts to idiomatic Jetpack Compose, preserving functionality while embracing Compose patterns. This skill covers layout mapping, state migration, and incremental adoption strategies.
|
|
11
|
+
|
|
12
|
+
## Workflow
|
|
13
|
+
|
|
14
|
+
### 1. Analyze the XML Layout
|
|
15
|
+
|
|
16
|
+
- Identify the root layout type (`ConstraintLayout`, `LinearLayout`, `FrameLayout`, etc.).
|
|
17
|
+
- List all View widgets and their key attributes.
|
|
18
|
+
- Map data binding expressions (`@{}`) or view binding references.
|
|
19
|
+
- Identify custom views that need special handling.
|
|
20
|
+
- Note any `include`, `merge`, or `ViewStub` usage.
|
|
21
|
+
|
|
22
|
+
### 2. Plan the Migration
|
|
23
|
+
|
|
24
|
+
- Decide: **Full rewrite** or **incremental migration** (using `ComposeView`/`AndroidView`).
|
|
25
|
+
- Identify state sources (ViewModel, LiveData, savedInstanceState).
|
|
26
|
+
- List reusable components to extract as separate Composables.
|
|
27
|
+
- Plan navigation integration if using Navigation component.
|
|
28
|
+
|
|
29
|
+
### 3. Convert Layouts
|
|
30
|
+
|
|
31
|
+
Apply the layout mapping table below to convert each View to its Compose equivalent.
|
|
32
|
+
|
|
33
|
+
### 4. Migrate State
|
|
34
|
+
|
|
35
|
+
- Convert `LiveData` observation to `StateFlow` collection or `observeAsState()`.
|
|
36
|
+
- Replace `findViewById` / ViewBinding with Compose state.
|
|
37
|
+
- Convert click listeners to lambda parameters.
|
|
38
|
+
|
|
39
|
+
### 5. Test and Verify
|
|
40
|
+
|
|
41
|
+
- Compare visual output between XML and Compose versions.
|
|
42
|
+
- Test accessibility (content descriptions, touch targets).
|
|
43
|
+
- Verify state preservation across configuration changes.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Layout Mapping Reference
|
|
48
|
+
|
|
49
|
+
### Container Layouts
|
|
50
|
+
|
|
51
|
+
| XML Layout | Compose Equivalent | Notes |
|
|
52
|
+
|------------|-------------------|-------|
|
|
53
|
+
| `LinearLayout (vertical)` | `Column` | Use `Arrangement` and `Alignment` |
|
|
54
|
+
| `LinearLayout (horizontal)` | `Row` | Use `Arrangement` and `Alignment` |
|
|
55
|
+
| `FrameLayout` | `Box` | Children stack on top of each other |
|
|
56
|
+
| `ConstraintLayout` | `ConstraintLayout` (Compose) | Use `createRefs()` and `constrainAs` |
|
|
57
|
+
| `RelativeLayout` | `Box` or `ConstraintLayout` | Prefer Box for simple overlap |
|
|
58
|
+
| `ScrollView` | `Column` + `Modifier.verticalScroll()` | Or use `LazyColumn` for lists |
|
|
59
|
+
| `HorizontalScrollView` | `Row` + `Modifier.horizontalScroll()` | Or use `LazyRow` for lists |
|
|
60
|
+
| `RecyclerView` | `LazyColumn` / `LazyRow` / `LazyGrid` | Most common migration |
|
|
61
|
+
| `ViewPager2` | `HorizontalPager` | From accompanist or Compose Foundation |
|
|
62
|
+
| `CoordinatorLayout` | Custom + `Scaffold` | Use `TopAppBar` with scroll behavior |
|
|
63
|
+
| `NestedScrollView` | `Column` + `Modifier.verticalScroll()` | Prefer Lazy variants |
|
|
64
|
+
|
|
65
|
+
### Common Widgets
|
|
66
|
+
|
|
67
|
+
| XML Widget | Compose Equivalent | Notes |
|
|
68
|
+
|------------|-------------------|-------|
|
|
69
|
+
| `TextView` | `Text` | Use `style` → `TextStyle` |
|
|
70
|
+
| `EditText` | `TextField` / `OutlinedTextField` | Requires state hoisting |
|
|
71
|
+
| `Button` | `Button` | Use `onClick` lambda |
|
|
72
|
+
| `ImageView` | `Image` | Use `painterResource()` or Coil |
|
|
73
|
+
| `ImageButton` | `IconButton` | Use `Icon` inside |
|
|
74
|
+
| `CheckBox` | `Checkbox` | Requires `checked` + `onCheckedChange` |
|
|
75
|
+
| `RadioButton` | `RadioButton` | Use with `Row` for groups |
|
|
76
|
+
| `Switch` | `Switch` | Requires state hoisting |
|
|
77
|
+
| `ProgressBar (circular)` | `CircularProgressIndicator` | |
|
|
78
|
+
| `ProgressBar (horizontal)` | `LinearProgressIndicator` | |
|
|
79
|
+
| `SeekBar` | `Slider` | Requires state hoisting |
|
|
80
|
+
| `Spinner` | `DropdownMenu` + `ExposedDropdownMenuBox` | More complex pattern |
|
|
81
|
+
| `CardView` | `Card` | From Material 3 |
|
|
82
|
+
| `Toolbar` | `TopAppBar` | Use inside `Scaffold` |
|
|
83
|
+
| `BottomNavigationView` | `NavigationBar` | Material 3 |
|
|
84
|
+
| `FloatingActionButton` | `FloatingActionButton` | Use inside `Scaffold` |
|
|
85
|
+
| `Divider` | `HorizontalDivider` / `VerticalDivider` | |
|
|
86
|
+
| `Space` | `Spacer` | Use `Modifier.size()` |
|
|
87
|
+
|
|
88
|
+
### Attribute Mapping
|
|
89
|
+
|
|
90
|
+
| XML Attribute | Compose Modifier/Property |
|
|
91
|
+
|---------------|--------------------------|
|
|
92
|
+
| `android:layout_width="match_parent"` | `Modifier.fillMaxWidth()` |
|
|
93
|
+
| `android:layout_height="match_parent"` | `Modifier.fillMaxHeight()` |
|
|
94
|
+
| `android:layout_width="wrap_content"` | `Modifier.wrapContentWidth()` (usually implicit) |
|
|
95
|
+
| `android:layout_weight` | `Modifier.weight(1f)` |
|
|
96
|
+
| `android:padding` | `Modifier.padding()` |
|
|
97
|
+
| `android:layout_margin` | `Modifier.padding()` on parent, or use `Arrangement.spacedBy()` |
|
|
98
|
+
| `android:background` | `Modifier.background()` |
|
|
99
|
+
| `android:visibility="gone"` | Conditional composition (don't emit) |
|
|
100
|
+
| `android:visibility="invisible"` | `Modifier.alpha(0f)` (keeps space) |
|
|
101
|
+
| `android:clickable` | `Modifier.clickable { }` |
|
|
102
|
+
| `android:contentDescription` | `Modifier.semantics { contentDescription = "" }` |
|
|
103
|
+
| `android:elevation` | `Modifier.shadow()` or component's `elevation` param |
|
|
104
|
+
| `android:alpha` | `Modifier.alpha()` |
|
|
105
|
+
| `android:rotation` | `Modifier.rotate()` |
|
|
106
|
+
| `android:scaleX/Y` | `Modifier.scale()` |
|
|
107
|
+
| `android:gravity` | `Alignment` parameter or `Arrangement` |
|
|
108
|
+
| `android:layout_gravity` | `Modifier.align()` |
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Common Patterns
|
|
113
|
+
|
|
114
|
+
### LinearLayout with Weights
|
|
115
|
+
|
|
116
|
+
```xml
|
|
117
|
+
<!-- XML -->
|
|
118
|
+
<LinearLayout android:orientation="horizontal">
|
|
119
|
+
<View android:layout_weight="1" />
|
|
120
|
+
<View android:layout_weight="2" />
|
|
121
|
+
</LinearLayout>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
```kotlin
|
|
125
|
+
// Compose
|
|
126
|
+
Row(modifier = Modifier.fillMaxWidth()) {
|
|
127
|
+
Box(modifier = Modifier.weight(1f))
|
|
128
|
+
Box(modifier = Modifier.weight(2f))
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### RecyclerView to LazyColumn
|
|
133
|
+
|
|
134
|
+
```xml
|
|
135
|
+
<!-- XML -->
|
|
136
|
+
<androidx.recyclerview.widget.RecyclerView
|
|
137
|
+
android:id="@+id/recyclerView"
|
|
138
|
+
android:layout_width="match_parent"
|
|
139
|
+
android:layout_height="match_parent" />
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
```kotlin
|
|
143
|
+
// Compose
|
|
144
|
+
LazyColumn(modifier = Modifier.fillMaxSize()) {
|
|
145
|
+
items(items, key = { it.id }) { item ->
|
|
146
|
+
ItemRow(item = item, onClick = { onItemClick(item) })
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### EditText with Two-Way Binding
|
|
152
|
+
|
|
153
|
+
```xml
|
|
154
|
+
<!-- XML with Data Binding -->
|
|
155
|
+
<EditText
|
|
156
|
+
android:text="@={viewModel.username}"
|
|
157
|
+
android:hint="@string/username_hint" />
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
```kotlin
|
|
161
|
+
// Compose
|
|
162
|
+
val username by viewModel.username.collectAsState()
|
|
163
|
+
|
|
164
|
+
OutlinedTextField(
|
|
165
|
+
value = username,
|
|
166
|
+
onValueChange = { viewModel.updateUsername(it) },
|
|
167
|
+
label = { Text(stringResource(R.string.username_hint)) },
|
|
168
|
+
modifier = Modifier.fillMaxWidth()
|
|
169
|
+
)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### ConstraintLayout Migration
|
|
173
|
+
|
|
174
|
+
```xml
|
|
175
|
+
<!-- XML -->
|
|
176
|
+
<androidx.constraintlayout.widget.ConstraintLayout>
|
|
177
|
+
<TextView
|
|
178
|
+
android:id="@+id/title"
|
|
179
|
+
app:layout_constraintTop_toTopOf="parent"
|
|
180
|
+
app:layout_constraintStart_toStartOf="parent" />
|
|
181
|
+
<TextView
|
|
182
|
+
android:id="@+id/subtitle"
|
|
183
|
+
app:layout_constraintTop_toBottomOf="@id/title"
|
|
184
|
+
app:layout_constraintStart_toStartOf="@id/title" />
|
|
185
|
+
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
```kotlin
|
|
189
|
+
// Compose
|
|
190
|
+
ConstraintLayout(modifier = Modifier.fillMaxWidth()) {
|
|
191
|
+
val (title, subtitle) = createRefs()
|
|
192
|
+
|
|
193
|
+
Text(
|
|
194
|
+
text = "Title",
|
|
195
|
+
modifier = Modifier.constrainAs(title) {
|
|
196
|
+
top.linkTo(parent.top)
|
|
197
|
+
start.linkTo(parent.start)
|
|
198
|
+
}
|
|
199
|
+
)
|
|
200
|
+
Text(
|
|
201
|
+
text = "Subtitle",
|
|
202
|
+
modifier = Modifier.constrainAs(subtitle) {
|
|
203
|
+
top.linkTo(title.bottom)
|
|
204
|
+
start.linkTo(title.start)
|
|
205
|
+
}
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### Include / Merge → Extract Composable
|
|
211
|
+
|
|
212
|
+
```xml
|
|
213
|
+
<!-- XML: layout_header.xml -->
|
|
214
|
+
<merge>
|
|
215
|
+
<ImageView android:id="@+id/avatar" />
|
|
216
|
+
<TextView android:id="@+id/name" />
|
|
217
|
+
</merge>
|
|
218
|
+
|
|
219
|
+
<!-- Usage -->
|
|
220
|
+
<include layout="@layout/layout_header" />
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
```kotlin
|
|
224
|
+
// Compose: Extract as a reusable Composable
|
|
225
|
+
@Composable
|
|
226
|
+
fun HeaderSection(
|
|
227
|
+
avatarUrl: String,
|
|
228
|
+
name: String,
|
|
229
|
+
modifier: Modifier = Modifier
|
|
230
|
+
) {
|
|
231
|
+
Row(modifier = modifier) {
|
|
232
|
+
AsyncImage(model = avatarUrl, contentDescription = null)
|
|
233
|
+
Text(text = name)
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// Usage
|
|
238
|
+
HeaderSection(avatarUrl = user.avatar, name = user.name)
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
---
|
|
242
|
+
|
|
243
|
+
## Incremental Migration (Interop)
|
|
244
|
+
|
|
245
|
+
### Embedding Compose in XML
|
|
246
|
+
|
|
247
|
+
```xml
|
|
248
|
+
<!-- In your XML layout -->
|
|
249
|
+
<androidx.compose.ui.platform.ComposeView
|
|
250
|
+
android:id="@+id/compose_view"
|
|
251
|
+
android:layout_width="match_parent"
|
|
252
|
+
android:layout_height="wrap_content" />
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
```kotlin
|
|
256
|
+
// In Fragment/Activity
|
|
257
|
+
binding.composeView.setContent {
|
|
258
|
+
MaterialTheme {
|
|
259
|
+
MyComposable()
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Embedding XML Views in Compose
|
|
265
|
+
|
|
266
|
+
```kotlin
|
|
267
|
+
// Use AndroidView for Views that don't have Compose equivalents
|
|
268
|
+
@Composable
|
|
269
|
+
fun MapViewComposable(modifier: Modifier = Modifier) {
|
|
270
|
+
AndroidView(
|
|
271
|
+
factory = { context ->
|
|
272
|
+
MapView(context).apply {
|
|
273
|
+
// Initialize the view
|
|
274
|
+
}
|
|
275
|
+
},
|
|
276
|
+
update = { mapView ->
|
|
277
|
+
// Update the view when state changes
|
|
278
|
+
},
|
|
279
|
+
modifier = modifier
|
|
280
|
+
)
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## State Migration
|
|
287
|
+
|
|
288
|
+
### LiveData to Compose
|
|
289
|
+
|
|
290
|
+
```kotlin
|
|
291
|
+
// Before: Observing in Fragment
|
|
292
|
+
viewModel.uiState.observe(viewLifecycleOwner) { state ->
|
|
293
|
+
binding.title.text = state.title
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// After: Collecting in Compose
|
|
297
|
+
@Composable
|
|
298
|
+
fun MyScreen(viewModel: MyViewModel = hiltViewModel()) {
|
|
299
|
+
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
|
|
300
|
+
|
|
301
|
+
Text(text = uiState.title)
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Click Listeners
|
|
306
|
+
|
|
307
|
+
```kotlin
|
|
308
|
+
// Before: XML + setOnClickListener
|
|
309
|
+
binding.submitButton.setOnClickListener {
|
|
310
|
+
viewModel.submit()
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// After: Lambda in Compose
|
|
314
|
+
Button(onClick = { viewModel.submit() }) {
|
|
315
|
+
Text("Submit")
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## Checklist
|
|
322
|
+
|
|
323
|
+
- [ ] All layouts converted (no `include` or `merge` left)
|
|
324
|
+
- [ ] State hoisted properly (no internal mutable state for user input)
|
|
325
|
+
- [ ] Click handlers converted to lambdas
|
|
326
|
+
- [ ] RecyclerView adapters removed (using LazyColumn/LazyRow)
|
|
327
|
+
- [ ] ViewBinding/DataBinding removed
|
|
328
|
+
- [ ] Navigation integrated (NavHost or interop)
|
|
329
|
+
- [ ] Theming applied (MaterialTheme)
|
|
330
|
+
- [ ] Accessibility preserved (content descriptions, touch targets)
|
|
331
|
+
- [ ] Preview annotations added for development
|
|
332
|
+
- [ ] Old XML files deleted
|
|
333
|
+
|
|
334
|
+
## References
|
|
335
|
+
|
|
336
|
+
- [Interoperability APIs](https://developer.android.com/develop/ui/compose/migrate/interoperability-apis)
|
|
337
|
+
- [Migration Strategy](https://developer.android.com/develop/ui/compose/migrate/strategy)
|
|
338
|
+
- [Compose and Views side by side](https://developer.android.com/develop/ui/compose/migrate)
|
package/template/agent/skills/mobile-developer/references/flutter-rules/dart-best-practices.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dart-best-practices
|
|
3
|
+
description: |-
|
|
4
|
+
General best practices for Dart development.
|
|
5
|
+
Covers code style, effective Dart, and language features.
|
|
6
|
+
license: Apache-2.0
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Dart Best Practices
|
|
10
|
+
|
|
11
|
+
## 1. When to use this skill
|
|
12
|
+
Use this skill when:
|
|
13
|
+
- Writing or reviewing Dart code.
|
|
14
|
+
- Looking for guidance on idiomatic Dart usage.
|
|
15
|
+
|
|
16
|
+
## 2. Best Practices
|
|
17
|
+
|
|
18
|
+
### Multi-line Strings
|
|
19
|
+
Prefer using multi-line strings (`'''`) over concatenating strings with `+` and
|
|
20
|
+
`\n`, especially for large blocks of text like SQL queries, HTML, or
|
|
21
|
+
PEM-encoded keys. This improves readability and avoids
|
|
22
|
+
`lines_longer_than_80_chars` lint errors by allowing natural line breaks.
|
|
23
|
+
|
|
24
|
+
**Avoid:**
|
|
25
|
+
```dart
|
|
26
|
+
final pem = '-----BEGIN RSA PRIVATE KEY-----\n' +
|
|
27
|
+
base64Encode(fullBytes) +
|
|
28
|
+
'\n-----END RSA PRIVATE KEY-----';
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Prefer:**
|
|
32
|
+
```dart
|
|
33
|
+
final pem = '''
|
|
34
|
+
-----BEGIN RSA PRIVATE KEY-----
|
|
35
|
+
${base64Encode(fullBytes)}
|
|
36
|
+
-----END RSA PRIVATE KEY-----''';
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Line Length
|
|
40
|
+
Avoid lines longer than 80 characters, even in Markdown files and comments.
|
|
41
|
+
This ensures code is readable in split-screen views and on smaller screens
|
|
42
|
+
without horizontal scrolling.
|
|
43
|
+
|
|
44
|
+
**Prefer:**
|
|
45
|
+
Target 80 characters for wrapping text. Exceptions are allowed for long URLs
|
|
46
|
+
or identifiers that cannot be broken.
|
|
47
|
+
|
|
48
|
+
## Related Skills
|
|
49
|
+
|
|
50
|
+
- **[`dart-modern-features`](../dart-modern-features/SKILL.md)**: For idiomatic
|
|
51
|
+
usage of modern Dart features like Pattern Matching (useful for deep JSON
|
|
52
|
+
extraction), Records, and Switch Expressions.
|
package/template/agent/skills/mobile-developer/references/flutter-rules/dart-checks-migration.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dart-checks-migration
|
|
3
|
+
description: |-
|
|
4
|
+
Replace the usage of `expect` and similar functions from `package:matcher`
|
|
5
|
+
to `package:checks` equivalents.
|
|
6
|
+
license: Apache-2.0
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Dart Checks Migration
|
|
10
|
+
|
|
11
|
+
## When to use this skill
|
|
12
|
+
Use this skill when:
|
|
13
|
+
- Migrating existing test files from `package:matcher` to `package:checks`.
|
|
14
|
+
- A user specifically asks for "modern checks" or similar.
|
|
15
|
+
|
|
16
|
+
## The Workflow
|
|
17
|
+
|
|
18
|
+
1. **Analysis**:
|
|
19
|
+
- Use `grep` to identify files using `expect` or `package:matcher`.
|
|
20
|
+
- Review custom matchers; these may require manual migration.
|
|
21
|
+
2. **Tools & Dependencies**:
|
|
22
|
+
- Ensure `dev_dependencies` includes `checks`.
|
|
23
|
+
- Run `dart pub add --dev checks` if missing.
|
|
24
|
+
3. **Discovery**:
|
|
25
|
+
- Use the **Strategies for Discovery** below to find candidates.
|
|
26
|
+
4. **Replacement**:
|
|
27
|
+
- Add `import 'package:checks/checks.dart';`.
|
|
28
|
+
- Apply the **Common Patterns** below.
|
|
29
|
+
- **Final Step**: Replace `import 'package:test/test.dart';` with
|
|
30
|
+
`import 'package:test/scaffolding.dart';` ONLY after all `expect` calls
|
|
31
|
+
are replaced. This ensures incremental progress.
|
|
32
|
+
5. **Verification**:
|
|
33
|
+
- Ensure the code analyzes cleanly.
|
|
34
|
+
- Ensure tests pass.
|
|
35
|
+
|
|
36
|
+
## Common Patterns
|
|
37
|
+
|
|
38
|
+
| Legacy `expect` | Modern `check` |
|
|
39
|
+
| :--- | :--- |
|
|
40
|
+
| `expect(a, equals(b))` | `check(a).equals(b)` |
|
|
41
|
+
| `expect(a, isTrue)` | `check(a).isTrue()` |
|
|
42
|
+
| `expect(a, isFalse)` | `check(a).isFalse()` |
|
|
43
|
+
| `expect(a, isNull)` | `check(a).isNull()` |
|
|
44
|
+
| `expect(a, isNotNull)` | `check(a).isNotNull()` |
|
|
45
|
+
| `expect(() => fn(), throwsA<T>())` | `check(() => fn()).throws<T>()` |
|
|
46
|
+
| `expect(list, hasLength(n))` | `check(list).length.equals(n)` |
|
|
47
|
+
| `expect(a, closeTo(b, delta))` | `check(a).isA<num>().isCloseTo(b, delta)` |
|
|
48
|
+
| `expect(a, greaterThan(b))` | `check(a).isGreaterThan(b)` |
|
|
49
|
+
| `expect(a, lessThan(b))` | `check(a).isLessThan(b)` |
|
|
50
|
+
| `expect(list, isEmpty)` | `check(list).isEmpty()` |
|
|
51
|
+
| `expect(list, isNotEmpty)` | `check(list).isNotEmpty()` |
|
|
52
|
+
| `expect(list, contains(item))` | `check(list).contains(item)` |
|
|
53
|
+
| `expect(map, equals(otherMap))` | `check(map).deepEquals(otherMap)` |
|
|
54
|
+
| `expect(list, equals(otherList))` | `check(list).deepEquals(otherList)` |
|
|
55
|
+
| `expect(future, completes)` | `await check(future).completes()` |
|
|
56
|
+
| `expect(stream, emitsInOrder(...))` | `await check(stream).withQueue.inOrder(...)` |
|
|
57
|
+
|
|
58
|
+
### Async & Futures (CRITICAL)
|
|
59
|
+
|
|
60
|
+
- **Checking async functions:**
|
|
61
|
+
`check(() => asyncFunc()).throws<T>()` causes **FALSE POSITIVES** because the
|
|
62
|
+
closure returns a `Future`, which is a value, so it "completes normally"
|
|
63
|
+
(as a Future).
|
|
64
|
+
**Correct Usage:**
|
|
65
|
+
```dart
|
|
66
|
+
await check(asyncFunc()).throws<T>();
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
- **Chaining on void returns:**
|
|
70
|
+
Many async check methods (like `throws`) return `Future<void>`. You cannot
|
|
71
|
+
chain directly on them. Use cascades or callbacks.
|
|
72
|
+
**Wrong:**
|
|
73
|
+
```dart
|
|
74
|
+
await check(future).throws<Error>().has((e) => e.message, 'message').equals('foo');
|
|
75
|
+
```
|
|
76
|
+
**Correct:**
|
|
77
|
+
```dart
|
|
78
|
+
await check(future).throws<Error>((it) => it.has((e) => e.message, 'message').equals('foo'));
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Complex Examples
|
|
82
|
+
|
|
83
|
+
*Deep Verification with `isA` and `having`:*
|
|
84
|
+
|
|
85
|
+
**Legacy:**
|
|
86
|
+
```dart
|
|
87
|
+
expect(() => foo(), throwsA(isA<ArgumentError>()
|
|
88
|
+
.having((e) => e.message, 'message', contains('MSG'))));
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Modern:**
|
|
92
|
+
```dart
|
|
93
|
+
check(() => foo())
|
|
94
|
+
.throws<ArgumentError>()
|
|
95
|
+
.has((e) => e.message, 'message')
|
|
96
|
+
.contains('MSG');
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
*Property Extraction:*
|
|
100
|
+
|
|
101
|
+
**Legacy:**
|
|
102
|
+
```dart
|
|
103
|
+
expect(obj.prop, equals(value)); // When checking multiple props
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Modern:**
|
|
107
|
+
```dart
|
|
108
|
+
check(obj)
|
|
109
|
+
..has((e) => e.prop, 'prop').equals(value)
|
|
110
|
+
..has((e) => e.other, 'other').equals(otherValue);
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
*One-line Cascades:*
|
|
114
|
+
Since checks often return `void`, use cascades for multiple assertions on the
|
|
115
|
+
same subject.
|
|
116
|
+
```dart
|
|
117
|
+
check(it)..isGreaterThan(10)..isLessThan(20);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Constraints
|
|
121
|
+
|
|
122
|
+
- **Scope**: Only modify files in `test/` (and `pubspec.yaml`).
|
|
123
|
+
- **Correctness**: One failing test is unacceptable. If a test fails after
|
|
124
|
+
migration and you cannot fix it immediately, REVERT that specific change.
|
|
125
|
+
- **Type Safety**: `package:checks` is stricter about types than `matcher`.
|
|
126
|
+
You may need to add explicit `as T` casts or `isA<T>()` checks in the chain.
|
|
127
|
+
|
|
128
|
+
## Related Skills
|
|
129
|
+
|
|
130
|
+
- **[`dart-test-fundamentals`](../dart-test-fundamentals/SKILL.md)**: Core
|
|
131
|
+
concepts for structuring tests, lifecycles, and configuration.
|
|
132
|
+
- **[`dart-matcher-best-practices`](../dart-matcher-best-practices/SKILL.md)**:
|
|
133
|
+
Best practices for the traditional `package:matcher` that is being migrated
|
|
134
|
+
away from.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dart-cli-app-best-practices
|
|
3
|
+
description: |-
|
|
4
|
+
Best practices for creating high-quality, executable Dart CLI applications.
|
|
5
|
+
Covers entrypoint structure, exit code handling, and recommended packages.
|
|
6
|
+
license: Apache-2.0
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Dart CLI Application Best Practices
|
|
10
|
+
|
|
11
|
+
## 1. When to use this skill
|
|
12
|
+
Use this skill when:
|
|
13
|
+
- Creating a new Dart CLI application.
|
|
14
|
+
- Refactoring an existing CLI entrypoint (`bin/`).
|
|
15
|
+
- Reviewing CLI code for quality and standards.
|
|
16
|
+
- Setting up executable scripts for Linux/Mac.
|
|
17
|
+
|
|
18
|
+
## 2. Best Practices
|
|
19
|
+
|
|
20
|
+
### Entrypoint Structure (`bin/`)
|
|
21
|
+
Keep the contents of your entrypoint file (e.g., `bin/my_app.dart`) minimal.
|
|
22
|
+
This improves testability by decoupling logic from the process runner.
|
|
23
|
+
|
|
24
|
+
**DO:**
|
|
25
|
+
```dart
|
|
26
|
+
// bin/my_app.dart
|
|
27
|
+
import 'package:my_app/src/entry_point.dart';
|
|
28
|
+
|
|
29
|
+
Future<void> main(List<String> arguments) async {
|
|
30
|
+
await runApp(arguments);
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**DON'T:**
|
|
35
|
+
- Put complex logic directly in `bin/my_app.dart`.
|
|
36
|
+
- Define classes or heavy functions in the entrypoint.
|
|
37
|
+
|
|
38
|
+
### Executable Scripts
|
|
39
|
+
For CLI tools intended to be run directly on Linux and Mac, add a shebang and
|
|
40
|
+
ensure the file is executable.
|
|
41
|
+
|
|
42
|
+
**DO:**
|
|
43
|
+
1. Add `#!/usr/bin/env dart` to the first line.
|
|
44
|
+
2. Run `chmod +x bin/my_script.dart` to make it executable.
|
|
45
|
+
|
|
46
|
+
```dart
|
|
47
|
+
#!/usr/bin/env dart
|
|
48
|
+
|
|
49
|
+
void main() => print('Ready to run!');
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Process Termination (`exitCode`)
|
|
53
|
+
Properly handle process termination to allow for debugging and correct status
|
|
54
|
+
reporting.
|
|
55
|
+
|
|
56
|
+
**DO:**
|
|
57
|
+
- Use the `exitCode` setter to report failure.
|
|
58
|
+
- Allow `main` to complete naturally.
|
|
59
|
+
- Use standard exit codes (sysexits) for clarity (e.g., `64` for bad usage,
|
|
60
|
+
`78` for configuration errors).
|
|
61
|
+
- See `package:io` `ExitCode` class or FreeBSD sysexits man page.
|
|
62
|
+
|
|
63
|
+
```dart
|
|
64
|
+
import 'dart:io';
|
|
65
|
+
|
|
66
|
+
void main() {
|
|
67
|
+
if (someFailure) {
|
|
68
|
+
exitCode = 64; // DO!
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**AVOID:**
|
|
75
|
+
- Calling `exit(code)` directly, as it terminates the VM immediately,
|
|
76
|
+
preventing "pause on exit" debugging and `finally` blocks from running.
|
|
77
|
+
|
|
78
|
+
### Exception Handling
|
|
79
|
+
Uncaught exceptions automatically set a non-zero exit code, but you should
|
|
80
|
+
handle expected errors gracefully.
|
|
81
|
+
|
|
82
|
+
**Example:**
|
|
83
|
+
```dart
|
|
84
|
+
Future<void> main(List<String> arguments) async {
|
|
85
|
+
try {
|
|
86
|
+
await runApp(arguments);
|
|
87
|
+
} catch (e, stack) {
|
|
88
|
+
print('App crashed!');
|
|
89
|
+
print(e);
|
|
90
|
+
print(stack);
|
|
91
|
+
exitCode = 1; // Explicitly fail
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 3. Recommended Packages
|
|
97
|
+
|
|
98
|
+
Use these community-standard packages owned by the [Dart team](https://dart.dev)
|
|
99
|
+
to solve common CLI problems:
|
|
100
|
+
|
|
101
|
+
| Category | Recommended Package | Usage |
|
|
102
|
+
| :--- | :--- | :--- |
|
|
103
|
+
| **Stack Traces** | [`package:stack_trace`](https://pub.dev/packages/stack_trace) | detailed, cleaner stack traces |
|
|
104
|
+
| **Arg Parsing** | [`package:args`](https://pub.dev/packages/args) | standard flag/option parsing |
|
|
105
|
+
| **Testing** | [`package:test_process`](https://pub.dev/packages/test_process) | integration testing for CLI apps |
|
|
106
|
+
| **Testing** | [`package:test_descriptor`](https://pub.dev/packages/test_descriptor) | file system fixtures for tests |
|
|
107
|
+
| **Networking** | [`package:http`](https://pub.dev/packages/http) | standard HTTP client (remember user-agent!) |
|
|
108
|
+
| **ANSI Output** | [`package:io`](https://pub.dev/packages/io) | handling ANSI colors and styles |
|
|
109
|
+
|
|
110
|
+
## 4. Interesting community packages
|
|
111
|
+
|
|
112
|
+
| Category | Recommended Package | Usage |
|
|
113
|
+
| :--- | :--- | :--- |
|
|
114
|
+
| **Configuration** | [`package:json_serializable`](https://pub.dev/packages/json_serializable) | strongly typed config objects |
|
|
115
|
+
| **CLI Generation** | [`package:build_cli`](https://pub.dev/packages/build_cli) | generate arg parsers from classes |
|
|
116
|
+
| **Version Info** | [`package:build_version`](https://pub.dev/packages/build_version) | automatic version injection |
|
|
117
|
+
| **Configuration** | [`package:checked_yaml`](https://pub.dev/packages/checked_yaml) | precise YAML parsing with line numbers |
|
|
118
|
+
|
|
119
|
+
## 5. Conventions
|
|
120
|
+
|
|
121
|
+
- **File Caching**: Write cached files to `.dart_tool/[pkg_name]/`.
|
|
122
|
+
- **User-Agent**: Always set a User-Agent header in HTTP requests, including
|
|
123
|
+
version info.
|
package/template/agent/skills/mobile-developer/references/flutter-rules/dart-doc-validation.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dart-doc-validation
|
|
3
|
+
description: |-
|
|
4
|
+
Best practices for validating Dart documentation comments.
|
|
5
|
+
Covers using `dart doc` to catch unresolved references and macros.
|
|
6
|
+
license: Apache-2.0
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Dart Doc Validation
|
|
10
|
+
|
|
11
|
+
## 1. When to use this skill
|
|
12
|
+
|
|
13
|
+
Use this skill when:
|
|
14
|
+
- Writing or updating documentation comments (`///`) in Dart code.
|
|
15
|
+
- Checking for broken documentation links, references, or macros.
|
|
16
|
+
- Preparing a package for publishing to pub.dev.
|
|
17
|
+
|
|
18
|
+
## 2. Best Practices
|
|
19
|
+
|
|
20
|
+
### Validating Documentation Locally
|
|
21
|
+
|
|
22
|
+
Use the `dart doc` command with a temporary output directory to validate
|
|
23
|
+
documentation comments without polluting the local project workspace.
|
|
24
|
+
|
|
25
|
+
This command parses all documentation comments and reports warnings such as:
|
|
26
|
+
- `warning: unresolved doc reference`
|
|
27
|
+
- `warning: undefined macro`
|
|
28
|
+
|
|
29
|
+
**Command to run:**
|
|
30
|
+
```bash
|
|
31
|
+
dart doc -o $(mktemp -d)
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
This ensures that the generated HTML files are stored in a temporary location
|
|
35
|
+
and don't clutter the package directory, while still surfacing all validation
|
|
36
|
+
warnings in the terminal output.
|
|
37
|
+
|
|
38
|
+
### Fixing Common Warnings
|
|
39
|
+
|
|
40
|
+
- **Unresolved doc reference**: Ensure that any identifier wrapped in square
|
|
41
|
+
brackets (`[Identifier]`) correctly points to an existing class, method,
|
|
42
|
+
property, or parameter in the current scope or imported libraries.
|
|
43
|
+
- **Undefined macro**: If using `{@macro macro_name}`, ensure that the
|
|
44
|
+
template `{@template macro_name}` is defined in the same file or a file
|
|
45
|
+
that is imported and visible to the documentation generator.
|