cfsa-antigravity 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/bin/cli.mjs +324 -0
- package/package.json +34 -0
- package/template/.agent/instructions/commands.md +48 -0
- package/template/.agent/instructions/patterns.md +61 -0
- package/template/.agent/instructions/structure.md +29 -0
- package/template/.agent/instructions/tech-stack.md +43 -0
- package/template/.agent/instructions/workflow.md +41 -0
- package/template/.agent/kit-sync.md +15 -0
- package/template/.agent/rules/boundary-not-placeholder.md +146 -0
- package/template/.agent/rules/completion-checklist.md +48 -0
- package/template/.agent/rules/decision-classification.md +103 -0
- package/template/.agent/rules/extensibility.md +47 -0
- package/template/.agent/rules/question-vs-command.md +81 -0
- package/template/.agent/rules/security-first.md +43 -0
- package/template/.agent/rules/specificity-standards.md +54 -0
- package/template/.agent/rules/tdd-contract-first.md +57 -0
- package/template/.agent/rules/vertical-slices.md +42 -0
- package/template/.agent/skill-library/MANIFEST.md +480 -0
- package/template/.agent/skill-library/README.md +38 -0
- package/template/.agent/skill-library/meta/brand-guidelines/SKILL.md +73 -0
- package/template/.agent/skill-library/meta/claude-code/README.md +9 -0
- package/template/.agent/skill-library/meta/claude-code/agent-development/SKILL.md +415 -0
- package/template/.agent/skill-library/meta/claude-code/hook-development/SKILL.md +712 -0
- package/template/.agent/skill-library/meta/claude-code/plugin-structure/SKILL.md +476 -0
- package/template/.agent/skill-library/meta/git-advanced/SKILL.md +972 -0
- package/template/.agent/skill-library/meta/mcp-builder/SKILL.md +236 -0
- package/template/.agent/skill-library/meta/product-marketing-context/SKILL.md +241 -0
- package/template/.agent/skill-library/meta/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skill-library/meta/tmux-processes/SKILL.md +210 -0
- package/template/.agent/skill-library/meta/using-tmux-for-interactive-commands/SKILL.md +178 -0
- package/template/.agent/skill-library/stack/3d/threejs-pro/SKILL.md +300 -0
- package/template/.agent/skill-library/stack/ai/ai-sdk/SKILL.md +77 -0
- package/template/.agent/skill-library/stack/ai/langchain/SKILL.md +530 -0
- package/template/.agent/skill-library/stack/ai/ollama/SKILL.md +321 -0
- package/template/.agent/skill-library/stack/ai/openai-sdk/SKILL.md +549 -0
- package/template/.agent/skill-library/stack/analytics/google-analytics/SKILL.md +153 -0
- package/template/.agent/skill-library/stack/api/graphql/SKILL.md +1061 -0
- package/template/.agent/skill-library/stack/api/trpc/SKILL.md +576 -0
- package/template/.agent/skill-library/stack/auth/authjs/SKILL.md +569 -0
- package/template/.agent/skill-library/stack/auth/clerk/SKILL.md +590 -0
- package/template/.agent/skill-library/stack/auth/firebase-auth/SKILL.md +734 -0
- package/template/.agent/skill-library/stack/cms/payload-cms/SKILL.md +573 -0
- package/template/.agent/skill-library/stack/cms/shopify/SKILL.md +1193 -0
- package/template/.agent/skill-library/stack/cms/wordpress/SKILL.md +1104 -0
- package/template/.agent/skill-library/stack/css/sass-scss/SKILL.md +1121 -0
- package/template/.agent/skill-library/stack/css/tailwind-css-patterns/SKILL.md +863 -0
- package/template/.agent/skill-library/stack/css/tailwind-design-system/SKILL.md +490 -0
- package/template/.agent/skill-library/stack/css/vanilla-css/SKILL.md +1078 -0
- package/template/.agent/skill-library/stack/databases/clickhouse/SKILL.md +311 -0
- package/template/.agent/skill-library/stack/databases/influxdb/SKILL.md +280 -0
- package/template/.agent/skill-library/stack/databases/lancedb/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/databases/mongodb/SKILL.md +1169 -0
- package/template/.agent/skill-library/stack/databases/neo4j/SKILL.md +839 -0
- package/template/.agent/skill-library/stack/databases/pgvector/SKILL.md +241 -0
- package/template/.agent/skill-library/stack/databases/pinecone/SKILL.md +212 -0
- package/template/.agent/skill-library/stack/databases/postgresql/SKILL.md +658 -0
- package/template/.agent/skill-library/stack/databases/qdrant/SKILL.md +312 -0
- package/template/.agent/skill-library/stack/databases/redis/SKILL.md +1079 -0
- package/template/.agent/skill-library/stack/databases/spacetimedb/SKILL.md +532 -0
- package/template/.agent/skill-library/stack/databases/sqlite/SKILL.md +1132 -0
- package/template/.agent/skill-library/stack/databases/supabase/SKILL.md +640 -0
- package/template/.agent/skill-library/stack/databases/surrealdb-expert/SKILL.md +945 -0
- package/template/.agent/skill-library/stack/databases/timescaledb/SKILL.md +745 -0
- package/template/.agent/skill-library/stack/databases/weaviate/SKILL.md +218 -0
- package/template/.agent/skill-library/stack/devops/github-actions/SKILL.md +554 -0
- package/template/.agent/skill-library/stack/devops/kubernetes/SKILL.md +950 -0
- package/template/.agent/skill-library/stack/devops/nginx/SKILL.md +841 -0
- package/template/.agent/skill-library/stack/devops/terraform/SKILL.md +860 -0
- package/template/.agent/skill-library/stack/email/resend/SKILL.md +391 -0
- package/template/.agent/skill-library/stack/engines/godot/SKILL.md +488 -0
- package/template/.agent/skill-library/stack/extensions/chrome-extension/SKILL.md +375 -0
- package/template/.agent/skill-library/stack/extensions/vscode-extension/SKILL.md +453 -0
- package/template/.agent/skill-library/stack/frameworks/astro-framework/SKILL.md +162 -0
- package/template/.agent/skill-library/stack/frameworks/electron/SKILL.md +1286 -0
- package/template/.agent/skill-library/stack/frameworks/fastapi/SKILL.md +650 -0
- package/template/.agent/skill-library/stack/frameworks/hono/SKILL.md +90 -0
- package/template/.agent/skill-library/stack/frameworks/nestjs/SKILL.md +878 -0
- package/template/.agent/skill-library/stack/frameworks/nextjs/SKILL.md +635 -0
- package/template/.agent/skill-library/stack/frameworks/nuxt/SKILL.md +564 -0
- package/template/.agent/skill-library/stack/frameworks/sveltekit/SKILL.md +614 -0
- package/template/.agent/skill-library/stack/frameworks/tauri/SKILL.md +920 -0
- package/template/.agent/skill-library/stack/gamedev/godot/SKILL.md +1032 -0
- package/template/.agent/skill-library/stack/gamedev/unity/SKILL.md +1175 -0
- package/template/.agent/skill-library/stack/hosting/aws/SKILL.md +467 -0
- package/template/.agent/skill-library/stack/hosting/cloudflare/SKILL.md +201 -0
- package/template/.agent/skill-library/stack/hosting/docker-expert/SKILL.md +409 -0
- package/template/.agent/skill-library/stack/hosting/vercel/SKILL.md +484 -0
- package/template/.agent/skill-library/stack/languages/bash-scripting/SKILL.md +773 -0
- package/template/.agent/skill-library/stack/languages/c-cpp/SKILL.md +712 -0
- package/template/.agent/skill-library/stack/languages/gdscript/SKILL.md +789 -0
- package/template/.agent/skill-library/stack/languages/go/SKILL.md +664 -0
- package/template/.agent/skill-library/stack/languages/java/SKILL.md +778 -0
- package/template/.agent/skill-library/stack/languages/kotlin/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/languages/python/SKILL.md +678 -0
- package/template/.agent/skill-library/stack/languages/rust/SKILL.md +673 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/SKILL.md +141 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/advanced-generics.md +90 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/branded-types.md +57 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/builder-pattern.md +71 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/common-pitfalls.md +135 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/conditional-types.md +27 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/decorators.md +98 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/discriminated-unions.md +62 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/mapped-types.md +53 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/performance-best-practices.md +104 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/template-literal-types.md +49 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/testing-types.md +112 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-guards.md +70 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-inference.md +101 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/utility-types.md +98 -0
- package/template/.agent/skill-library/stack/languages/vanilla-javascript/SKILL.md +803 -0
- package/template/.agent/skill-library/stack/messaging/kafka/SKILL.md +235 -0
- package/template/.agent/skill-library/stack/mobile/expo-react-native/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/mobile/flutter/SKILL.md +316 -0
- package/template/.agent/skill-library/stack/mobile/react-native/SKILL.md +337 -0
- package/template/.agent/skill-library/stack/monitoring/posthog/SKILL.md +396 -0
- package/template/.agent/skill-library/stack/monitoring/sentry/SKILL.md +509 -0
- package/template/.agent/skill-library/stack/observability/datadog/SKILL.md +179 -0
- package/template/.agent/skill-library/stack/observability/distributed-tracing/SKILL.md +140 -0
- package/template/.agent/skill-library/stack/observability/logging-best-practices/SKILL.md +168 -0
- package/template/.agent/skill-library/stack/observability/opentelemetry/SKILL.md +164 -0
- package/template/.agent/skill-library/stack/observability/prometheus-grafana/SKILL.md +246 -0
- package/template/.agent/skill-library/stack/observability/python-observability/SKILL.md +158 -0
- package/template/.agent/skill-library/stack/orm/drizzle-orm/SKILL.md +613 -0
- package/template/.agent/skill-library/stack/orm/prisma/SKILL.md +744 -0
- package/template/.agent/skill-library/stack/payments/lemonsqueezy/SKILL.md +393 -0
- package/template/.agent/skill-library/stack/payments/stripe-integration/SKILL.md +457 -0
- package/template/.agent/skill-library/stack/queue/bullmq/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/queue/inngest/SKILL.md +438 -0
- package/template/.agent/skill-library/stack/realtime/socketio/SKILL.md +595 -0
- package/template/.agent/skill-library/stack/search/elasticsearch/SKILL.md +248 -0
- package/template/.agent/skill-library/stack/search/meilisearch/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/security/crypto-patterns/SKILL.md +437 -0
- package/template/.agent/skill-library/stack/security/csp-cors-headers/SKILL.md +588 -0
- package/template/.agent/skill-library/stack/security/dependency-auditing/SKILL.md +560 -0
- package/template/.agent/skill-library/stack/security/input-sanitization/SKILL.md +430 -0
- package/template/.agent/skill-library/stack/security/owasp-web-security/SKILL.md +421 -0
- package/template/.agent/skill-library/stack/state/tanstack-query/SKILL.md +637 -0
- package/template/.agent/skill-library/stack/state/zustand/SKILL.md +483 -0
- package/template/.agent/skill-library/stack/storage/aws-s3/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/testing/playwright/SKILL.md +641 -0
- package/template/.agent/skill-library/stack/testing/storybook/SKILL.md +923 -0
- package/template/.agent/skill-library/stack/testing/testing-library/SKILL.md +872 -0
- package/template/.agent/skill-library/stack/testing/vitest/SKILL.md +714 -0
- package/template/.agent/skill-library/stack/ui/react-best-practices/SKILL.md +877 -0
- package/template/.agent/skill-library/stack/ui/react-composition-patterns/SKILL.md +1107 -0
- package/template/.agent/skill-library/stack/ui/react-flow/SKILL.md +425 -0
- package/template/.agent/skill-library/stack/ui/shadcn-ui/SKILL.md +703 -0
- package/template/.agent/skill-library/surface/api/api-caching/SKILL.md +458 -0
- package/template/.agent/skill-library/surface/api/api-documentation-openapi/SKILL.md +697 -0
- package/template/.agent/skill-library/surface/api/api-error-handling/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/api-security-checklist/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/api-versioning/SKILL.md +420 -0
- package/template/.agent/skill-library/surface/api/email-best-practices/SKILL.md +59 -0
- package/template/.agent/skill-library/surface/api/rate-limiting-abuse-protection/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/webhook-design/SKILL.md +752 -0
- package/template/.agent/skill-library/surface/cli/cli-configuration-management/SKILL.md +445 -0
- package/template/.agent/skill-library/surface/cli/cli-error-diagnostics/SKILL.md +515 -0
- package/template/.agent/skill-library/surface/cli/cli-shell-integration/SKILL.md +479 -0
- package/template/.agent/skill-library/surface/cli/cli-ux-design/SKILL.md +477 -0
- package/template/.agent/skill-library/surface/desktop/desktop-app-distribution/SKILL.md +416 -0
- package/template/.agent/skill-library/surface/desktop/desktop-security-sandboxing/SKILL.md +407 -0
- package/template/.agent/skill-library/surface/desktop/desktop-ux-conventions/SKILL.md +361 -0
- package/template/.agent/skill-library/surface/desktop/native-os-integration/SKILL.md +563 -0
- package/template/.agent/skill-library/surface/extension/browser-extension-patterns/SKILL.md +482 -0
- package/template/.agent/skill-library/surface/extension/plugin-architecture-design/SKILL.md +632 -0
- package/template/.agent/skill-library/surface/extension/vscode-extension-development/SKILL.md +728 -0
- package/template/.agent/skill-library/surface/mobile/app-store-submission/SKILL.md +304 -0
- package/template/.agent/skill-library/surface/mobile/mobile-offline-sync/SKILL.md +443 -0
- package/template/.agent/skill-library/surface/mobile/mobile-responsive-patterns/SKILL.md +432 -0
- package/template/.agent/skill-library/surface/mobile/push-notifications/SKILL.md +495 -0
- package/template/.agent/skill-library/surface/web/accessibility-compliance/SKILL.md +827 -0
- package/template/.agent/skill-library/surface/web/ai-seo/SKILL.md +398 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/content-patterns.md +285 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/platform-ranking-factors.md +152 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/SKILL.md +309 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/event-library.md +260 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/ga4-implementation.md +300 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/gtm-implementation.md +390 -0
- package/template/.agent/skill-library/surface/web/authentication-ui-flows/SKILL.md +530 -0
- package/template/.agent/skill-library/surface/web/dark-mode-theming/SKILL.md +516 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/SKILL.md +105 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/charts.csv +26 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/colors.csv +97 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/landing.csv +31 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/styles.csv +59 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/typography.csv +58 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/ux-guidelines.csv +100 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/core.py +258 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/design_system.py +1067 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/search.py +106 -0
- package/template/.agent/skill-library/surface/web/form-handling-validation/SKILL.md +675 -0
- package/template/.agent/skill-library/surface/web/frontend-design/SKILL.md +1393 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/cppn-hero.tsx +299 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/wave-hero.tsx +875 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/SKILL.md +111 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/scripts/ux_audit.py +739 -0
- package/template/.agent/skill-library/surface/web/i18n-localization/SKILL.md +154 -0
- package/template/.agent/skill-library/surface/web/offline-first-pwa/SKILL.md +657 -0
- package/template/.agent/skill-library/surface/web/page-cro/SKILL.md +182 -0
- package/template/.agent/skill-library/surface/web/page-cro/references/experiments.md +248 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/SKILL.md +238 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/references/playbooks.md +308 -0
- package/template/.agent/skill-library/surface/web/schema-markup/SKILL.md +179 -0
- package/template/.agent/skill-library/surface/web/schema-markup/references/schema-examples.md +398 -0
- package/template/.agent/skill-library/surface/web/seo-audit/SKILL.md +394 -0
- package/template/.agent/skill-library/surface/web/seo-audit/references/ai-writing-detection.md +200 -0
- package/template/.agent/skill-library/surface/web/web-performance-optimization/SKILL.md +646 -0
- package/template/.agent/skill-library/surface/web/web-scraping/SKILL.md +58 -0
- package/template/.agent/skills/accessibility/SKILL.md +522 -0
- package/template/.agent/skills/accessibility/references/WCAG.md +162 -0
- package/template/.agent/skills/adversarial-review/SKILL.md +90 -0
- package/template/.agent/skills/antigravity-workflows/SKILL.md +81 -0
- package/template/.agent/skills/antigravity-workflows/resources/implementation-playbook.md +36 -0
- package/template/.agent/skills/api-design-principles/SKILL.md +37 -0
- package/template/.agent/skills/api-design-principles/assets/api-design-checklist.md +155 -0
- package/template/.agent/skills/api-design-principles/assets/rest-api-template.py +182 -0
- package/template/.agent/skills/api-design-principles/references/graphql-schema-design.md +583 -0
- package/template/.agent/skills/api-design-principles/references/rest-best-practices.md +408 -0
- package/template/.agent/skills/api-design-principles/resources/implementation-playbook.md +513 -0
- package/template/.agent/skills/api-versioning/SKILL.md +420 -0
- package/template/.agent/skills/architecture-mapping/SKILL.md +219 -0
- package/template/.agent/skills/bootstrap-agents/SKILL.md +259 -0
- package/template/.agent/skills/brainstorming/SKILL.md +236 -0
- package/template/.agent/skills/brand-guidelines/SKILL.md +44 -0
- package/template/.agent/skills/clean-code/SKILL.md +94 -0
- package/template/.agent/skills/code-review-pro/SKILL.md +152 -0
- package/template/.agent/skills/concise-planning/SKILL.md +68 -0
- package/template/.agent/skills/cross-layer-consistency/SKILL.md +117 -0
- package/template/.agent/skills/database-schema-design/SKILL.md +429 -0
- package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
- package/template/.agent/skills/design-anti-cliche/SKILL.md +159 -0
- package/template/.agent/skills/design-direction/SKILL.md +45 -0
- package/template/.agent/skills/error-handling-patterns/SKILL.md +721 -0
- package/template/.agent/skills/find-skills/SKILL.md +145 -0
- package/template/.agent/skills/git-advanced/SKILL.md +972 -0
- package/template/.agent/skills/git-workflow/SKILL.md +420 -0
- package/template/.agent/skills/idea-extraction/SKILL.md +271 -0
- package/template/.agent/skills/logging-best-practices/SKILL.md +851 -0
- package/template/.agent/skills/migration-management/SKILL.md +384 -0
- package/template/.agent/skills/minimalist-surgical-development/SKILL.md +69 -0
- package/template/.agent/skills/parallel-agents/SKILL.md +165 -0
- package/template/.agent/skills/parallel-debugging/SKILL.md +135 -0
- package/template/.agent/skills/parallel-feature-development/SKILL.md +166 -0
- package/template/.agent/skills/performance-budgeting/SKILL.md +144 -0
- package/template/.agent/skills/pipeline-rubrics/SKILL.md +51 -0
- package/template/.agent/skills/pipeline-rubrics/references/architecture-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +21 -0
- package/template/.agent/skills/pipeline-rubrics/references/fe-rubric.md +20 -0
- package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/scoring.md +28 -0
- package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +11 -0
- package/template/.agent/skills/prd-templates/SKILL.md +88 -0
- package/template/.agent/skills/prd-templates/references/architecture-design-template.md +88 -0
- package/template/.agent/skills/prd-templates/references/be-spec-template.md +101 -0
- package/template/.agent/skills/prd-templates/references/data-placement-template.md +74 -0
- package/template/.agent/skills/prd-templates/references/decomposition-templates.md +211 -0
- package/template/.agent/skills/prd-templates/references/design-system-decisions.md +198 -0
- package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +124 -0
- package/template/.agent/skills/prd-templates/references/fe-classification-procedures.md +47 -0
- package/template/.agent/skills/prd-templates/references/fe-spec-template.md +84 -0
- package/template/.agent/skills/prd-templates/references/infrastructure-report-template.md +71 -0
- package/template/.agent/skills/prd-templates/references/operational-templates.md +116 -0
- package/template/.agent/skills/prd-templates/references/placeholder-guard-template.md +21 -0
- package/template/.agent/skills/prd-templates/references/surface-model.md +61 -0
- package/template/.agent/skills/prd-templates/references/vision-template.md +66 -0
- package/template/.agent/skills/prompt-engineer/README.md +659 -0
- package/template/.agent/skills/prompt-engineer/SKILL.md +249 -0
- package/template/.agent/skills/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skills/resolve-ambiguity/SKILL.md +278 -0
- package/template/.agent/skills/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skills/security-scanning-security-hardening/SKILL.md +231 -0
- package/template/.agent/skills/session-continuity/SKILL.md +730 -0
- package/template/.agent/skills/session-continuity/protocols/01-session-resumption.md +38 -0
- package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +85 -0
- package/template/.agent/skills/session-continuity/protocols/03-progress-update.md +70 -0
- package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +60 -0
- package/template/.agent/skills/session-continuity/protocols/05-session-close.md +37 -0
- package/template/.agent/skills/session-continuity/protocols/06-decision-analysis.md +84 -0
- package/template/.agent/skills/session-continuity/protocols/07-spec-pipeline-generation.md +48 -0
- package/template/.agent/skills/session-continuity/protocols/08-spec-pipeline-update.md +43 -0
- package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +122 -0
- package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +104 -0
- package/template/.agent/skills/session-continuity/protocols/ambiguity-gates.md +48 -0
- package/template/.agent/skills/skill-creator/LICENSE.txt +202 -0
- package/template/.agent/skills/skill-creator/README.md +270 -0
- package/template/.agent/skills/skill-creator/SKILL.md +590 -0
- package/template/.agent/skills/skill-creator/references/output-patterns.md +82 -0
- package/template/.agent/skills/skill-creator/references/workflows.md +28 -0
- package/template/.agent/skills/skill-creator/scripts/init_skill.py +303 -0
- package/template/.agent/skills/skill-creator/scripts/package_skill.py +110 -0
- package/template/.agent/skills/skill-creator/scripts/quick_validate.py +95 -0
- package/template/.agent/skills/spec-writing/SKILL.md +110 -0
- package/template/.agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/template/.agent/skills/systematic-debugging/SKILL.md +297 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/template/.agent/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/template/.agent/skills/systematic-debugging/find-polluter.sh +63 -0
- package/template/.agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/template/.agent/skills/systematic-debugging/test-academic.md +14 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/template/.agent/skills/tdd-workflow/SKILL.md +409 -0
- package/template/.agent/skills/tech-stack-catalog/SKILL.md +49 -0
- package/template/.agent/skills/tech-stack-catalog/references/constraint-questions.md +21 -0
- package/template/.agent/skills/tech-stack-catalog/references/dev-tooling-decisions.md +37 -0
- package/template/.agent/skills/tech-stack-catalog/references/surface-decision-tables.md +69 -0
- package/template/.agent/skills/technical-writer/SKILL.md +242 -0
- package/template/.agent/skills/testing-strategist/SKILL.md +932 -0
- package/template/.agent/skills/verification-before-completion/SKILL.md +145 -0
- package/template/.agent/skills/workflow-automation/SKILL.md +73 -0
- package/template/.agent/workflows/audit-ambiguity-execute.md +165 -0
- package/template/.agent/workflows/audit-ambiguity-rubrics.md +83 -0
- package/template/.agent/workflows/audit-ambiguity.md +64 -0
- package/template/.agent/workflows/bootstrap-agents-fill.md +201 -0
- package/template/.agent/workflows/bootstrap-agents-provision.md +197 -0
- package/template/.agent/workflows/bootstrap-agents.md +66 -0
- package/template/.agent/workflows/create-prd-architecture.md +119 -0
- package/template/.agent/workflows/create-prd-compile.md +138 -0
- package/template/.agent/workflows/create-prd-design-system.md +135 -0
- package/template/.agent/workflows/create-prd-security.md +113 -0
- package/template/.agent/workflows/create-prd-stack.md +91 -0
- package/template/.agent/workflows/create-prd.md +168 -0
- package/template/.agent/workflows/decompose-architecture-structure.md +82 -0
- package/template/.agent/workflows/decompose-architecture-validate.md +119 -0
- package/template/.agent/workflows/decompose-architecture.md +111 -0
- package/template/.agent/workflows/evolve-contract.md +98 -0
- package/template/.agent/workflows/evolve-feature-cascade.md +140 -0
- package/template/.agent/workflows/evolve-feature-classify.md +116 -0
- package/template/.agent/workflows/evolve-feature.md +56 -0
- package/template/.agent/workflows/ideate-discover.md +144 -0
- package/template/.agent/workflows/ideate-extract.md +129 -0
- package/template/.agent/workflows/ideate-validate.md +117 -0
- package/template/.agent/workflows/ideate.md +113 -0
- package/template/.agent/workflows/implement-slice-setup.md +113 -0
- package/template/.agent/workflows/implement-slice-tdd.md +198 -0
- package/template/.agent/workflows/implement-slice.md +50 -0
- package/template/.agent/workflows/plan-phase.md +202 -0
- package/template/.agent/workflows/propagate-decision-apply.md +135 -0
- package/template/.agent/workflows/propagate-decision-scan.md +147 -0
- package/template/.agent/workflows/propagate-decision.md +56 -0
- package/template/.agent/workflows/remediate-pipeline-assess.md +138 -0
- package/template/.agent/workflows/remediate-pipeline-execute.md +135 -0
- package/template/.agent/workflows/remediate-pipeline.md +55 -0
- package/template/.agent/workflows/resolve-ambiguity.md +82 -0
- package/template/.agent/workflows/sync-kit.md +209 -0
- package/template/.agent/workflows/update-architecture-map.md +74 -0
- package/template/.agent/workflows/validate-phase.md +219 -0
- package/template/.agent/workflows/verify-infrastructure.md +207 -0
- package/template/.agent/workflows/write-architecture-spec-deepen.md +139 -0
- package/template/.agent/workflows/write-architecture-spec-design.md +202 -0
- package/template/.agent/workflows/write-architecture-spec.md +63 -0
- package/template/.agent/workflows/write-be-spec-classify.md +165 -0
- package/template/.agent/workflows/write-be-spec-write.md +98 -0
- package/template/.agent/workflows/write-be-spec.md +76 -0
- package/template/.agent/workflows/write-fe-spec-classify.md +170 -0
- package/template/.agent/workflows/write-fe-spec-write.md +94 -0
- package/template/.agent/workflows/write-fe-spec.md +71 -0
- package/template/AGENTS.md +176 -0
- package/template/GEMINI.md +177 -0
- package/template/docs/README.md +187 -0
- package/template/docs/audits/.gitkeep +0 -0
- package/template/docs/audits/README.md +10 -0
- package/template/docs/plans/.gitkeep +0 -0
- package/template/docs/plans/README.md +21 -0
- package/template/docs/plans/be/.gitkeep +0 -0
- package/template/docs/plans/be/README.md +11 -0
- package/template/docs/plans/fe/.gitkeep +0 -0
- package/template/docs/plans/fe/README.md +11 -0
- package/template/docs/plans/ia/.gitkeep +0 -0
- package/template/docs/plans/ia/README.md +17 -0
- package/template/docs/plans/ia/deep-dives/.gitkeep +0 -0
- package/template/docs/plans/ia/deep-dives/README.md +5 -0
- package/template/docs/plans/phases/.gitkeep +0 -0
- package/template/docs/plans/phases/README.md +11 -0
|
@@ -0,0 +1,665 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kotlin
|
|
3
|
+
description: Kotlin development patterns for concise, safe, and expressive code. Covers null safety, data/sealed classes, coroutines, extension functions, scope functions, Flow, delegation, DSL builders, testing, and multiplatform patterns.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Kotlin Development Patterns
|
|
8
|
+
|
|
9
|
+
Expert guidance for writing idiomatic, production-grade Kotlin code. Covers null safety, data modeling with data and sealed classes, structured concurrency with coroutines, extension functions, scope functions, Kotlin Flow, DSL builders, testing, and multiplatform development.
|
|
10
|
+
|
|
11
|
+
## When to Use This Skill
|
|
12
|
+
|
|
13
|
+
- Building Android applications with modern architecture
|
|
14
|
+
- Writing backend services with Ktor or Spring Boot
|
|
15
|
+
- Creating multiplatform libraries (JVM, JS, Native)
|
|
16
|
+
- Migrating Java codebases to Kotlin
|
|
17
|
+
- Implementing reactive streams with Kotlin Flow
|
|
18
|
+
- Building type-safe DSLs for configuration or testing
|
|
19
|
+
|
|
20
|
+
## Core Concepts
|
|
21
|
+
|
|
22
|
+
### 1. Null Safety
|
|
23
|
+
|
|
24
|
+
Kotlin's type system distinguishes nullable and non-nullable types at compile time.
|
|
25
|
+
|
|
26
|
+
```kotlin
|
|
27
|
+
// Non-nullable -- cannot be null
|
|
28
|
+
val name: String = "Alice"
|
|
29
|
+
|
|
30
|
+
// Nullable -- can be null
|
|
31
|
+
val email: String? = findEmail(userId)
|
|
32
|
+
|
|
33
|
+
// Safe call operator
|
|
34
|
+
val length: Int? = email?.length
|
|
35
|
+
|
|
36
|
+
// Elvis operator -- provide default for null
|
|
37
|
+
val displayName: String = email ?: "unknown"
|
|
38
|
+
|
|
39
|
+
// Safe call chain
|
|
40
|
+
val city: String? = user?.address?.city
|
|
41
|
+
|
|
42
|
+
// Not-null assertion (avoid in production code)
|
|
43
|
+
val forcedLength: Int = email!!.length // Throws NPE if null
|
|
44
|
+
|
|
45
|
+
// Smart casting after null check
|
|
46
|
+
fun process(value: String?) {
|
|
47
|
+
if (value != null) {
|
|
48
|
+
// value is automatically cast to String (non-nullable) here
|
|
49
|
+
println(value.length)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// let for nullable transformations
|
|
54
|
+
val upperEmail: String? = email?.let { it.uppercase() }
|
|
55
|
+
|
|
56
|
+
// require/check for preconditions
|
|
57
|
+
fun setAge(age: Int) {
|
|
58
|
+
require(age in 0..150) { "Age must be between 0 and 150, got $age" }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fun processOrder(order: Order) {
|
|
62
|
+
check(order.status == Status.PENDING) { "Order must be pending, was ${order.status}" }
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Null safety rules:**
|
|
67
|
+
|
|
68
|
+
| Rule | Explanation |
|
|
69
|
+
|------|-------------|
|
|
70
|
+
| Prefer non-nullable types | Make nullability explicit and intentional |
|
|
71
|
+
| Never use `!!` in production | It defeats the purpose of null safety |
|
|
72
|
+
| Use `?.let {}` for nullable chains | Cleaner than nested if-null checks |
|
|
73
|
+
| Use Elvis `?:` for defaults | Concise and readable |
|
|
74
|
+
| Use `requireNotNull()` at boundaries | Fail fast with clear messages |
|
|
75
|
+
|
|
76
|
+
### 2. Data Classes and Sealed Classes
|
|
77
|
+
|
|
78
|
+
```kotlin
|
|
79
|
+
// Data class -- immutable value object with generated equals/hashCode/toString/copy
|
|
80
|
+
data class User(
|
|
81
|
+
val id: String,
|
|
82
|
+
val name: String,
|
|
83
|
+
val email: String,
|
|
84
|
+
val age: Int
|
|
85
|
+
) {
|
|
86
|
+
init {
|
|
87
|
+
require(name.isNotBlank()) { "Name must not be blank" }
|
|
88
|
+
require(age in 13..150) { "Age must be between 13 and 150" }
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// copy() for creating modified copies
|
|
93
|
+
val updated = user.copy(name = "Bob")
|
|
94
|
+
|
|
95
|
+
// Destructuring
|
|
96
|
+
val (id, name, email, age) = user
|
|
97
|
+
|
|
98
|
+
// Sealed class -- restricted hierarchy for exhaustive when
|
|
99
|
+
sealed class Result<out T> {
|
|
100
|
+
data class Success<T>(val data: T) : Result<T>()
|
|
101
|
+
data class Error(val message: String, val cause: Throwable? = null) : Result<Nothing>()
|
|
102
|
+
data object Loading : Result<Nothing>()
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Exhaustive when -- compiler ensures all cases handled
|
|
106
|
+
fun <T> handleResult(result: Result<T>): String = when (result) {
|
|
107
|
+
is Result.Success -> "Data: ${result.data}"
|
|
108
|
+
is Result.Error -> "Error: ${result.message}"
|
|
109
|
+
is Result.Loading -> "Loading..."
|
|
110
|
+
// No else needed -- compiler knows all cases
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Sealed interface (Kotlin 1.5+) -- allows multiple inheritance
|
|
114
|
+
sealed interface UiState {
|
|
115
|
+
data object Idle : UiState
|
|
116
|
+
data object Loading : UiState
|
|
117
|
+
data class Content(val items: List<Item>) : UiState
|
|
118
|
+
data class Error(val message: String) : UiState
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Value class (Kotlin 1.5+) -- zero-overhead wrapper
|
|
122
|
+
@JvmInline
|
|
123
|
+
value class UserId(val value: String) {
|
|
124
|
+
init {
|
|
125
|
+
require(value.isNotBlank()) { "UserId must not be blank" }
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Prevents mixing up String parameters
|
|
130
|
+
fun findUser(id: UserId): User? = TODO()
|
|
131
|
+
// findUser(UserId("abc")) -- explicit, type-safe
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### 3. Coroutines and Structured Concurrency
|
|
135
|
+
|
|
136
|
+
```kotlin
|
|
137
|
+
import kotlinx.coroutines.*
|
|
138
|
+
|
|
139
|
+
// Suspend function -- can be paused and resumed
|
|
140
|
+
suspend fun fetchUser(id: String): User {
|
|
141
|
+
return httpClient.get("https://api.example.com/users/$id")
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Launching coroutines with structured concurrency
|
|
145
|
+
fun main() = runBlocking {
|
|
146
|
+
// launch -- fire and forget (returns Job)
|
|
147
|
+
val job = launch {
|
|
148
|
+
delay(1000)
|
|
149
|
+
println("World")
|
|
150
|
+
}
|
|
151
|
+
println("Hello")
|
|
152
|
+
job.join()
|
|
153
|
+
|
|
154
|
+
// async -- returns a value (returns Deferred<T>)
|
|
155
|
+
val deferred = async {
|
|
156
|
+
fetchUser("123")
|
|
157
|
+
}
|
|
158
|
+
val user = deferred.await()
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// coroutineScope -- structured concurrency boundary
|
|
162
|
+
suspend fun fetchUserWithOrders(userId: String): UserWithOrders =
|
|
163
|
+
coroutineScope {
|
|
164
|
+
val userDeferred = async { fetchUser(userId) }
|
|
165
|
+
val ordersDeferred = async { fetchOrders(userId) }
|
|
166
|
+
|
|
167
|
+
UserWithOrders(
|
|
168
|
+
user = userDeferred.await(),
|
|
169
|
+
orders = ordersDeferred.await()
|
|
170
|
+
)
|
|
171
|
+
// If either fails, both are cancelled
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// supervisorScope -- children failures do not cancel siblings
|
|
175
|
+
suspend fun fetchAll(ids: List<String>): List<User?> =
|
|
176
|
+
supervisorScope {
|
|
177
|
+
ids.map { id ->
|
|
178
|
+
async {
|
|
179
|
+
try {
|
|
180
|
+
fetchUser(id)
|
|
181
|
+
} catch (e: Exception) {
|
|
182
|
+
null // Individual failure does not cancel others
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}.awaitAll()
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Exception handling
|
|
189
|
+
suspend fun safeOperation() {
|
|
190
|
+
val handler = CoroutineExceptionHandler { _, exception ->
|
|
191
|
+
println("Caught: $exception")
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Default + handler)
|
|
195
|
+
scope.launch {
|
|
196
|
+
throw RuntimeException("Something went wrong")
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// withTimeout
|
|
201
|
+
suspend fun fetchWithTimeout(id: String): User =
|
|
202
|
+
withTimeout(5000) {
|
|
203
|
+
fetchUser(id)
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// Dispatchers
|
|
207
|
+
// Dispatchers.Default -- CPU-bound work
|
|
208
|
+
// Dispatchers.IO -- I/O-bound work (network, disk)
|
|
209
|
+
// Dispatchers.Main -- UI thread (Android)
|
|
210
|
+
// Dispatchers.Unconfined -- advanced, rarely needed
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### 4. Extension Functions
|
|
214
|
+
|
|
215
|
+
```kotlin
|
|
216
|
+
// Add methods to existing types without inheritance
|
|
217
|
+
fun String.isValidEmail(): Boolean =
|
|
218
|
+
contains("@") && contains(".") && length > 5
|
|
219
|
+
|
|
220
|
+
// Usage
|
|
221
|
+
"alice@example.com".isValidEmail() // true
|
|
222
|
+
|
|
223
|
+
// Extension property
|
|
224
|
+
val String.wordCount: Int
|
|
225
|
+
get() = split("\\s+".toRegex()).size
|
|
226
|
+
|
|
227
|
+
"hello world".wordCount // 2
|
|
228
|
+
|
|
229
|
+
// Extension functions on nullable types
|
|
230
|
+
fun String?.orEmpty(): String = this ?: ""
|
|
231
|
+
|
|
232
|
+
// Generic extension functions
|
|
233
|
+
fun <T> List<T>.secondOrNull(): T? = if (size >= 2) this[1] else null
|
|
234
|
+
|
|
235
|
+
// Extension functions for fluent APIs
|
|
236
|
+
fun StringBuilder.appendLine(line: String): StringBuilder =
|
|
237
|
+
append(line).append('\n')
|
|
238
|
+
|
|
239
|
+
// Scope-limiting extensions
|
|
240
|
+
fun <T : AutoCloseable, R> T.useAndReturn(block: (T) -> R): R =
|
|
241
|
+
use { block(it) }
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### 5. Scope Functions: let, run, with, apply, also
|
|
245
|
+
|
|
246
|
+
```kotlin
|
|
247
|
+
// let -- transform nullable, chain operations
|
|
248
|
+
// Context object: it | Returns: lambda result
|
|
249
|
+
val email = user?.email?.let { normalizeEmail(it) }
|
|
250
|
+
|
|
251
|
+
val numbers = mutableListOf(1, 2, 3)
|
|
252
|
+
val doubled = numbers.map { it * 2 }.let { println(it); it }
|
|
253
|
+
|
|
254
|
+
// run -- execute block with receiver, compute result
|
|
255
|
+
// Context object: this | Returns: lambda result
|
|
256
|
+
val greeting = user.run {
|
|
257
|
+
"Hello, $name! You are $age years old."
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Null-safe run
|
|
261
|
+
val length = nullableString?.run { length } ?: 0
|
|
262
|
+
|
|
263
|
+
// with -- call multiple methods on same object (non-extension)
|
|
264
|
+
// Context object: this | Returns: lambda result
|
|
265
|
+
val description = with(user) {
|
|
266
|
+
"Name: $name, Email: $email, Age: $age"
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// apply -- configure an object, return the object itself
|
|
270
|
+
// Context object: this | Returns: context object
|
|
271
|
+
val user = User().apply {
|
|
272
|
+
name = "Alice"
|
|
273
|
+
email = "alice@example.com"
|
|
274
|
+
age = 30
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// also -- side effects, return the object unchanged
|
|
278
|
+
// Context object: it | Returns: context object
|
|
279
|
+
val user = createUser()
|
|
280
|
+
.also { log.info("Created user: ${it.id}") }
|
|
281
|
+
.also { analytics.trackUserCreation(it) }
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Scope function decision matrix:**
|
|
285
|
+
|
|
286
|
+
| Function | Object ref | Return value | Use case |
|
|
287
|
+
|----------|-----------|-------------|----------|
|
|
288
|
+
| `let` | `it` | Lambda result | Null check + transform |
|
|
289
|
+
| `run` | `this` | Lambda result | Object config + compute result |
|
|
290
|
+
| `with` | `this` | Lambda result | Grouping calls on an object |
|
|
291
|
+
| `apply` | `this` | Object itself | Object configuration |
|
|
292
|
+
| `also` | `it` | Object itself | Side effects (logging, validation) |
|
|
293
|
+
|
|
294
|
+
### 6. Kotlin Flow
|
|
295
|
+
|
|
296
|
+
```kotlin
|
|
297
|
+
import kotlinx.coroutines.flow.*
|
|
298
|
+
|
|
299
|
+
// Creating flows
|
|
300
|
+
fun numbersFlow(): Flow<Int> = flow {
|
|
301
|
+
for (i in 1..10) {
|
|
302
|
+
delay(100)
|
|
303
|
+
emit(i)
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Flow operators (similar to sequences but async)
|
|
308
|
+
val evenSquares = numbersFlow()
|
|
309
|
+
.filter { it % 2 == 0 }
|
|
310
|
+
.map { it * it }
|
|
311
|
+
.take(3)
|
|
312
|
+
|
|
313
|
+
// Collecting flows
|
|
314
|
+
suspend fun main() {
|
|
315
|
+
evenSquares.collect { value ->
|
|
316
|
+
println(value)
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
// StateFlow -- observable state holder
|
|
321
|
+
class UserViewModel {
|
|
322
|
+
private val _state = MutableStateFlow<UiState>(UiState.Idle)
|
|
323
|
+
val state: StateFlow<UiState> = _state.asStateFlow()
|
|
324
|
+
|
|
325
|
+
fun loadUsers() {
|
|
326
|
+
_state.value = UiState.Loading
|
|
327
|
+
viewModelScope.launch {
|
|
328
|
+
try {
|
|
329
|
+
val users = repository.getUsers()
|
|
330
|
+
_state.value = UiState.Content(users)
|
|
331
|
+
} catch (e: Exception) {
|
|
332
|
+
_state.value = UiState.Error(e.message ?: "Unknown error")
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// SharedFlow -- event broadcasting
|
|
339
|
+
class EventBus {
|
|
340
|
+
private val _events = MutableSharedFlow<Event>(replay = 0)
|
|
341
|
+
val events: SharedFlow<Event> = _events.asSharedFlow()
|
|
342
|
+
|
|
343
|
+
suspend fun emit(event: Event) {
|
|
344
|
+
_events.emit(event)
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
// Flow operators
|
|
349
|
+
val transformed = sourceFlow
|
|
350
|
+
.debounce(300) // Wait for pause in emissions
|
|
351
|
+
.distinctUntilChanged() // Skip consecutive duplicates
|
|
352
|
+
.flatMapLatest { query -> // Cancel previous inner flow
|
|
353
|
+
searchRepository.search(query)
|
|
354
|
+
}
|
|
355
|
+
.catch { e -> // Handle upstream errors
|
|
356
|
+
emit(emptyList())
|
|
357
|
+
}
|
|
358
|
+
.onEach { results -> // Side effect
|
|
359
|
+
analytics.trackSearch(results.size)
|
|
360
|
+
}
|
|
361
|
+
.flowOn(Dispatchers.IO) // Switch upstream dispatcher
|
|
362
|
+
|
|
363
|
+
// Combining flows
|
|
364
|
+
val combined = combine(flow1, flow2, flow3) { a, b, c ->
|
|
365
|
+
Triple(a, b, c)
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### 7. Companion Objects and Delegation
|
|
370
|
+
|
|
371
|
+
```kotlin
|
|
372
|
+
// Companion object -- static-like members
|
|
373
|
+
class User private constructor(
|
|
374
|
+
val name: String,
|
|
375
|
+
val email: String
|
|
376
|
+
) {
|
|
377
|
+
companion object {
|
|
378
|
+
fun create(name: String, email: String): User {
|
|
379
|
+
require(name.isNotBlank())
|
|
380
|
+
return User(name, email.lowercase())
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// Can implement interfaces
|
|
384
|
+
// companion object : Factory<User> { ... }
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Property delegation
|
|
389
|
+
class PreferencesManager(private val prefs: SharedPreferences) {
|
|
390
|
+
var theme: String by prefs.string(default = "system")
|
|
391
|
+
var fontSize: Int by prefs.int(default = 14)
|
|
392
|
+
var isDarkMode: Boolean by prefs.boolean(default = false)
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Built-in delegates
|
|
396
|
+
val lazyValue: String by lazy {
|
|
397
|
+
println("Computing...")
|
|
398
|
+
"Hello"
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
var observed: String by Delegates.observable("initial") { _, old, new ->
|
|
402
|
+
println("Changed from $old to $new")
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Custom delegate
|
|
406
|
+
class LoggingDelegate<T>(private var value: T) {
|
|
407
|
+
operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
|
408
|
+
println("Reading ${property.name}: $value")
|
|
409
|
+
return value
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: T) {
|
|
413
|
+
println("Writing ${property.name}: $value -> $newValue")
|
|
414
|
+
value = newValue
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
var debuggable: String by LoggingDelegate("initial")
|
|
419
|
+
|
|
420
|
+
// Class delegation
|
|
421
|
+
interface Repository {
|
|
422
|
+
fun findAll(): List<Item>
|
|
423
|
+
fun findById(id: String): Item?
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
class CachingRepository(
|
|
427
|
+
private val delegate: Repository
|
|
428
|
+
) : Repository by delegate {
|
|
429
|
+
// Override only what you need -- everything else delegates automatically
|
|
430
|
+
private val cache = mutableMapOf<String, Item>()
|
|
431
|
+
|
|
432
|
+
override fun findById(id: String): Item? =
|
|
433
|
+
cache.getOrPut(id) { delegate.findById(id) ?: return null }
|
|
434
|
+
}
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### 8. DSL Builders
|
|
438
|
+
|
|
439
|
+
```kotlin
|
|
440
|
+
// Type-safe builder using receiver lambdas
|
|
441
|
+
class HtmlBuilder {
|
|
442
|
+
private val elements = mutableListOf<String>()
|
|
443
|
+
|
|
444
|
+
fun head(block: HeadBuilder.() -> Unit) {
|
|
445
|
+
val builder = HeadBuilder().apply(block)
|
|
446
|
+
elements.add("<head>${builder.build()}</head>")
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
fun body(block: BodyBuilder.() -> Unit) {
|
|
450
|
+
val builder = BodyBuilder().apply(block)
|
|
451
|
+
elements.add("<body>${builder.build()}</body>")
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
fun build(): String = "<html>${elements.joinToString("")}</html>"
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
class BodyBuilder {
|
|
458
|
+
private val elements = mutableListOf<String>()
|
|
459
|
+
|
|
460
|
+
fun h1(text: String) { elements.add("<h1>$text</h1>") }
|
|
461
|
+
fun p(text: String) { elements.add("<p>$text</p>") }
|
|
462
|
+
fun div(block: BodyBuilder.() -> Unit) {
|
|
463
|
+
val inner = BodyBuilder().apply(block)
|
|
464
|
+
elements.add("<div>${inner.build()}</div>")
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
fun build(): String = elements.joinToString("")
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
fun html(block: HtmlBuilder.() -> Unit): String =
|
|
471
|
+
HtmlBuilder().apply(block).build()
|
|
472
|
+
|
|
473
|
+
// Usage
|
|
474
|
+
val page = html {
|
|
475
|
+
body {
|
|
476
|
+
h1("Welcome")
|
|
477
|
+
div {
|
|
478
|
+
p("Hello, world!")
|
|
479
|
+
p("This is a DSL.")
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
// Route DSL example (Ktor-style)
|
|
485
|
+
fun Application.configureRouting() {
|
|
486
|
+
routing {
|
|
487
|
+
route("/api") {
|
|
488
|
+
get("/users") {
|
|
489
|
+
val users = userService.findAll()
|
|
490
|
+
call.respond(users)
|
|
491
|
+
}
|
|
492
|
+
post("/users") {
|
|
493
|
+
val request = call.receive<CreateUserRequest>()
|
|
494
|
+
val created = userService.create(request)
|
|
495
|
+
call.respond(HttpStatusCode.Created, created)
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
### 9. Testing with Kotest and JUnit 5
|
|
503
|
+
|
|
504
|
+
```kotlin
|
|
505
|
+
// JUnit 5 style (works with Spring, familiar to Java devs)
|
|
506
|
+
class UserServiceTest {
|
|
507
|
+
|
|
508
|
+
private val repository = mockk<UserRepository>()
|
|
509
|
+
private val service = UserService(repository)
|
|
510
|
+
|
|
511
|
+
@Test
|
|
512
|
+
fun `findById returns user when exists`() {
|
|
513
|
+
val user = User("1", "Alice", "alice@example.com")
|
|
514
|
+
every { repository.findById("1") } returns user
|
|
515
|
+
|
|
516
|
+
val result = service.findById("1")
|
|
517
|
+
|
|
518
|
+
assertThat(result).isNotNull()
|
|
519
|
+
assertThat(result?.name).isEqualTo("Alice")
|
|
520
|
+
verify { repository.findById("1") }
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
@Test
|
|
524
|
+
fun `create throws on duplicate email`() {
|
|
525
|
+
every { repository.existsByEmail("alice@example.com") } returns true
|
|
526
|
+
|
|
527
|
+
assertThrows<IllegalArgumentException> {
|
|
528
|
+
service.create(CreateUserRequest("Alice", "alice@example.com", 30))
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// Kotest style (BDD, property-based, more Kotlin-native)
|
|
534
|
+
class UserSpec : FunSpec({
|
|
535
|
+
|
|
536
|
+
val repository = mockk<UserRepository>()
|
|
537
|
+
val service = UserService(repository)
|
|
538
|
+
|
|
539
|
+
test("findById returns user when exists") {
|
|
540
|
+
val user = User("1", "Alice", "alice@example.com")
|
|
541
|
+
every { repository.findById("1") } returns user
|
|
542
|
+
|
|
543
|
+
service.findById("1") shouldNotBe null
|
|
544
|
+
service.findById("1")?.name shouldBe "Alice"
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
test("findById returns null when not exists") {
|
|
548
|
+
every { repository.findById("999") } returns null
|
|
549
|
+
|
|
550
|
+
service.findById("999") shouldBe null
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
context("create") {
|
|
554
|
+
test("succeeds with valid input") {
|
|
555
|
+
every { repository.existsByEmail(any()) } returns false
|
|
556
|
+
every { repository.save(any()) } answers { firstArg() }
|
|
557
|
+
|
|
558
|
+
val result = service.create(CreateUserRequest("Bob", "bob@example.com", 25))
|
|
559
|
+
result.name shouldBe "Bob"
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
test("fails on duplicate email") {
|
|
563
|
+
every { repository.existsByEmail("alice@example.com") } returns true
|
|
564
|
+
|
|
565
|
+
shouldThrow<IllegalArgumentException> {
|
|
566
|
+
service.create(CreateUserRequest("Alice", "alice@example.com", 30))
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
})
|
|
571
|
+
|
|
572
|
+
// Coroutine testing
|
|
573
|
+
class CoroutineTest {
|
|
574
|
+
@Test
|
|
575
|
+
fun `concurrent fetch completes`() = runTest {
|
|
576
|
+
val result = fetchUserWithOrders("123")
|
|
577
|
+
assertThat(result.user).isNotNull()
|
|
578
|
+
assertThat(result.orders).isNotEmpty()
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### 10. Multiplatform Patterns
|
|
584
|
+
|
|
585
|
+
```kotlin
|
|
586
|
+
// Common module -- shared across all platforms
|
|
587
|
+
// commonMain/kotlin/com/example/
|
|
588
|
+
expect fun platformName(): String
|
|
589
|
+
|
|
590
|
+
class Greeting {
|
|
591
|
+
fun greet(): String = "Hello from ${platformName()}"
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// JVM implementation
|
|
595
|
+
// jvmMain/kotlin/com/example/
|
|
596
|
+
actual fun platformName(): String = "JVM"
|
|
597
|
+
|
|
598
|
+
// JS implementation
|
|
599
|
+
// jsMain/kotlin/com/example/
|
|
600
|
+
actual fun platformName(): String = "JavaScript"
|
|
601
|
+
|
|
602
|
+
// Native implementation
|
|
603
|
+
// nativeMain/kotlin/com/example/
|
|
604
|
+
actual fun platformName(): String = "Native"
|
|
605
|
+
|
|
606
|
+
// Shared data models work everywhere
|
|
607
|
+
data class User(val id: String, val name: String, val email: String)
|
|
608
|
+
|
|
609
|
+
// Use expect/actual for platform-specific implementations
|
|
610
|
+
expect class HttpClient() {
|
|
611
|
+
suspend fun get(url: String): String
|
|
612
|
+
}
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
## Anti-Patterns
|
|
616
|
+
|
|
617
|
+
| Anti-Pattern | Why It Is Bad | Do This Instead |
|
|
618
|
+
|-------------|--------------|----------------|
|
|
619
|
+
| `!!` (not-null assertion) | Defeats null safety, crashes at runtime | Use safe calls, Elvis, or `requireNotNull` |
|
|
620
|
+
| `var` everywhere | Mutable state is error-prone | Prefer `val` (immutable) |
|
|
621
|
+
| Java-style getters/setters | Verbose, un-Kotlin | Use properties with custom get/set |
|
|
622
|
+
| `companion object` for utility functions | Unnecessary wrapper | Use top-level functions |
|
|
623
|
+
| `GlobalScope.launch` | Unstructured, leaks coroutines | Use structured scope (viewModelScope, etc.) |
|
|
624
|
+
| Catching `Exception` without rethrowing `CancellationException` | Breaks coroutine cancellation | Always rethrow `CancellationException` |
|
|
625
|
+
| `runBlocking` in production code | Blocks the thread | Use `suspend` functions and proper scopes |
|
|
626
|
+
| Ignoring Flow backpressure | Memory issues | Use `conflate()`, `buffer()`, or `collectLatest` |
|
|
627
|
+
|
|
628
|
+
## Project Structure
|
|
629
|
+
|
|
630
|
+
```
|
|
631
|
+
src/
|
|
632
|
+
main/kotlin/com/example/
|
|
633
|
+
Application.kt
|
|
634
|
+
config/
|
|
635
|
+
controller/
|
|
636
|
+
service/
|
|
637
|
+
repository/
|
|
638
|
+
model/
|
|
639
|
+
test/kotlin/com/example/
|
|
640
|
+
service/
|
|
641
|
+
repository/
|
|
642
|
+
build.gradle.kts
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
## Common Commands
|
|
646
|
+
|
|
647
|
+
```bash
|
|
648
|
+
# Gradle (Kotlin projects use Gradle almost exclusively)
|
|
649
|
+
./gradlew build # Build and test
|
|
650
|
+
./gradlew test # Run tests only
|
|
651
|
+
./gradlew run # Run application
|
|
652
|
+
./gradlew ktlintCheck # Lint check
|
|
653
|
+
./gradlew ktlintFormat # Auto-format
|
|
654
|
+
./gradlew detekt # Static analysis
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
## Resources
|
|
658
|
+
|
|
659
|
+
- **Kotlin Docs**: https://kotlinlang.org/docs/home.html
|
|
660
|
+
- **Kotlin Coroutines Guide**: https://kotlinlang.org/docs/coroutines-guide.html
|
|
661
|
+
- **Kotlin Flow Guide**: https://kotlinlang.org/docs/flow.html
|
|
662
|
+
- **Ktor Documentation**: https://ktor.io/docs/welcome.html
|
|
663
|
+
- **Kotest**: https://kotest.io/
|
|
664
|
+
- **MockK**: https://mockk.io/
|
|
665
|
+
- **Kotlin Multiplatform**: https://kotlinlang.org/docs/multiplatform.html
|