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,613 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: drizzle-orm
|
|
3
|
+
description: "Comprehensive Drizzle ORM guide covering schema definition, query building, relational queries, migrations, type inference, raw SQL, transactions, and Zod integration. Use when building type-safe database layers with Drizzle, designing schemas, writing queries, or managing migrations."
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Drizzle ORM
|
|
8
|
+
|
|
9
|
+
## 1. Schema Definition
|
|
10
|
+
|
|
11
|
+
### Tables and Columns (PostgreSQL)
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
// src/db/schema/users.ts
|
|
15
|
+
import { pgTable, uuid, text, boolean, timestamp, integer, numeric, jsonb, pgEnum } from 'drizzle-orm/pg-core';
|
|
16
|
+
|
|
17
|
+
// Enum type
|
|
18
|
+
export const roleEnum = pgEnum('role', ['user', 'admin', 'moderator']);
|
|
19
|
+
|
|
20
|
+
export const users = pgTable('users', {
|
|
21
|
+
id: uuid('id').defaultRandom().primaryKey(),
|
|
22
|
+
email: text('email').notNull().unique(),
|
|
23
|
+
name: text('name').notNull(),
|
|
24
|
+
role: roleEnum('role').notNull().default('user'),
|
|
25
|
+
active: boolean('active').notNull().default(true),
|
|
26
|
+
metadata: jsonb('metadata').$type<{ preferences: Record<string, unknown> }>().default({}),
|
|
27
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
28
|
+
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export const posts = pgTable('posts', {
|
|
32
|
+
id: uuid('id').defaultRandom().primaryKey(),
|
|
33
|
+
title: text('title').notNull(),
|
|
34
|
+
content: text('content').notNull(),
|
|
35
|
+
published: boolean('published').notNull().default(false),
|
|
36
|
+
authorId: uuid('author_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
|
|
37
|
+
viewCount: integer('view_count').notNull().default(0),
|
|
38
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export const comments = pgTable('comments', {
|
|
42
|
+
id: uuid('id').defaultRandom().primaryKey(),
|
|
43
|
+
content: text('content').notNull(),
|
|
44
|
+
postId: uuid('post_id').notNull().references(() => posts.id, { onDelete: 'cascade' }),
|
|
45
|
+
authorId: uuid('author_id').notNull().references(() => users.id, { onDelete: 'cascade' }),
|
|
46
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
47
|
+
});
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Indexes and Constraints
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { pgTable, text, uuid, timestamp, index, uniqueIndex } from 'drizzle-orm/pg-core';
|
|
54
|
+
|
|
55
|
+
export const products = pgTable('products', {
|
|
56
|
+
id: uuid('id').defaultRandom().primaryKey(),
|
|
57
|
+
sku: text('sku').notNull(),
|
|
58
|
+
name: text('name').notNull(),
|
|
59
|
+
categoryId: uuid('category_id').notNull(),
|
|
60
|
+
price: numeric('price', { precision: 12, scale: 2 }).notNull(),
|
|
61
|
+
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
62
|
+
}, (table) => [
|
|
63
|
+
uniqueIndex('products_sku_idx').on(table.sku),
|
|
64
|
+
index('products_category_idx').on(table.categoryId),
|
|
65
|
+
index('products_created_idx').on(table.createdAt.desc()),
|
|
66
|
+
]);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Relations
|
|
70
|
+
|
|
71
|
+
Relations are separate from foreign keys. They define how Drizzle's relational query API joins tables.
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
// src/db/schema/relations.ts
|
|
75
|
+
import { relations } from 'drizzle-orm';
|
|
76
|
+
import { users, posts, comments } from './tables';
|
|
77
|
+
|
|
78
|
+
export const usersRelations = relations(users, ({ many }) => ({
|
|
79
|
+
posts: many(posts),
|
|
80
|
+
comments: many(comments),
|
|
81
|
+
}));
|
|
82
|
+
|
|
83
|
+
export const postsRelations = relations(posts, ({ one, many }) => ({
|
|
84
|
+
author: one(users, { fields: [posts.authorId], references: [users.id] }),
|
|
85
|
+
comments: many(comments),
|
|
86
|
+
}));
|
|
87
|
+
|
|
88
|
+
export const commentsRelations = relations(comments, ({ one }) => ({
|
|
89
|
+
post: one(posts, { fields: [comments.postId], references: [posts.id] }),
|
|
90
|
+
author: one(users, { fields: [comments.authorId], references: [users.id] }),
|
|
91
|
+
}));
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## 2. Database Connection
|
|
97
|
+
|
|
98
|
+
### PostgreSQL with node-postgres
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
// src/db/index.ts
|
|
102
|
+
import { drizzle } from 'drizzle-orm/node-postgres';
|
|
103
|
+
import { Pool } from 'pg';
|
|
104
|
+
import * as schema from './schema';
|
|
105
|
+
|
|
106
|
+
const pool = new Pool({
|
|
107
|
+
connectionString: process.env.DATABASE_URL,
|
|
108
|
+
max: 20,
|
|
109
|
+
idleTimeoutMillis: 30000,
|
|
110
|
+
connectionTimeoutMillis: 2000,
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
export const db = drizzle(pool, { schema });
|
|
114
|
+
|
|
115
|
+
// For serverless (Neon, Supabase, etc.)
|
|
116
|
+
import { drizzle } from 'drizzle-orm/neon-http';
|
|
117
|
+
import { neon } from '@neondatabase/serverless';
|
|
118
|
+
|
|
119
|
+
const sql = neon(process.env.DATABASE_URL!);
|
|
120
|
+
export const db = drizzle(sql, { schema });
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
### SQLite with better-sqlite3
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
127
|
+
import Database from 'better-sqlite3';
|
|
128
|
+
import * as schema from './schema';
|
|
129
|
+
|
|
130
|
+
const sqlite = new Database('app.db');
|
|
131
|
+
export const db = drizzle(sqlite, { schema });
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Turso (LibSQL)
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
import { drizzle } from 'drizzle-orm/libsql';
|
|
138
|
+
import { createClient } from '@libsql/client';
|
|
139
|
+
import * as schema from './schema';
|
|
140
|
+
|
|
141
|
+
const client = createClient({
|
|
142
|
+
url: process.env.TURSO_DATABASE_URL!,
|
|
143
|
+
authToken: process.env.TURSO_AUTH_TOKEN,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
export const db = drizzle(client, { schema });
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 3. Query Builder
|
|
152
|
+
|
|
153
|
+
### Select
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
import { eq, ne, gt, gte, lt, lte, like, ilike, inArray, and, or, desc, asc, count, sum, sql } from 'drizzle-orm';
|
|
157
|
+
|
|
158
|
+
// Basic select
|
|
159
|
+
const allUsers = await db.select().from(users);
|
|
160
|
+
|
|
161
|
+
// Select specific columns
|
|
162
|
+
const userEmails = await db.select({ id: users.id, email: users.email }).from(users);
|
|
163
|
+
|
|
164
|
+
// Where clause
|
|
165
|
+
const activeAdmins = await db
|
|
166
|
+
.select()
|
|
167
|
+
.from(users)
|
|
168
|
+
.where(and(eq(users.active, true), eq(users.role, 'admin')));
|
|
169
|
+
|
|
170
|
+
// OR conditions
|
|
171
|
+
const results = await db
|
|
172
|
+
.select()
|
|
173
|
+
.from(users)
|
|
174
|
+
.where(or(eq(users.role, 'admin'), eq(users.role, 'moderator')));
|
|
175
|
+
|
|
176
|
+
// Pattern matching
|
|
177
|
+
const matched = await db.select().from(users).where(ilike(users.email, '%@example.com'));
|
|
178
|
+
|
|
179
|
+
// IN clause
|
|
180
|
+
const specific = await db.select().from(users).where(inArray(users.id, [id1, id2, id3]));
|
|
181
|
+
|
|
182
|
+
// Ordering, limit, offset
|
|
183
|
+
const paginated = await db
|
|
184
|
+
.select()
|
|
185
|
+
.from(users)
|
|
186
|
+
.orderBy(desc(users.createdAt))
|
|
187
|
+
.limit(20)
|
|
188
|
+
.offset(40);
|
|
189
|
+
|
|
190
|
+
// Aggregates
|
|
191
|
+
const stats = await db
|
|
192
|
+
.select({
|
|
193
|
+
role: users.role,
|
|
194
|
+
count: count(),
|
|
195
|
+
})
|
|
196
|
+
.from(users)
|
|
197
|
+
.groupBy(users.role);
|
|
198
|
+
|
|
199
|
+
// Joins
|
|
200
|
+
const postsWithAuthors = await db
|
|
201
|
+
.select({
|
|
202
|
+
postTitle: posts.title,
|
|
203
|
+
authorName: users.name,
|
|
204
|
+
authorEmail: users.email,
|
|
205
|
+
})
|
|
206
|
+
.from(posts)
|
|
207
|
+
.innerJoin(users, eq(posts.authorId, users.id))
|
|
208
|
+
.where(eq(posts.published, true));
|
|
209
|
+
|
|
210
|
+
// Left join
|
|
211
|
+
const usersWithPosts = await db
|
|
212
|
+
.select({
|
|
213
|
+
userName: users.name,
|
|
214
|
+
postCount: count(posts.id),
|
|
215
|
+
})
|
|
216
|
+
.from(users)
|
|
217
|
+
.leftJoin(posts, eq(users.id, posts.authorId))
|
|
218
|
+
.groupBy(users.name);
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Insert
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
// Single insert
|
|
225
|
+
const [newUser] = await db
|
|
226
|
+
.insert(users)
|
|
227
|
+
.values({ email: 'alice@example.com', name: 'Alice' })
|
|
228
|
+
.returning();
|
|
229
|
+
|
|
230
|
+
// Bulk insert
|
|
231
|
+
await db.insert(users).values([
|
|
232
|
+
{ email: 'bob@example.com', name: 'Bob' },
|
|
233
|
+
{ email: 'carol@example.com', name: 'Carol' },
|
|
234
|
+
]);
|
|
235
|
+
|
|
236
|
+
// Upsert (insert or update on conflict)
|
|
237
|
+
await db
|
|
238
|
+
.insert(users)
|
|
239
|
+
.values({ email: 'alice@example.com', name: 'Alice Updated' })
|
|
240
|
+
.onConflictDoUpdate({
|
|
241
|
+
target: users.email,
|
|
242
|
+
set: { name: 'Alice Updated', updatedAt: new Date() },
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Insert or ignore on conflict
|
|
246
|
+
await db
|
|
247
|
+
.insert(users)
|
|
248
|
+
.values({ email: 'alice@example.com', name: 'Alice' })
|
|
249
|
+
.onConflictDoNothing({ target: users.email });
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
### Update
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
// Update with returning
|
|
256
|
+
const [updated] = await db
|
|
257
|
+
.update(users)
|
|
258
|
+
.set({ active: false, updatedAt: new Date() })
|
|
259
|
+
.where(eq(users.id, userId))
|
|
260
|
+
.returning();
|
|
261
|
+
|
|
262
|
+
// Increment a value
|
|
263
|
+
await db
|
|
264
|
+
.update(posts)
|
|
265
|
+
.set({ viewCount: sql`${posts.viewCount} + 1` })
|
|
266
|
+
.where(eq(posts.id, postId));
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Delete
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
// Delete with returning
|
|
273
|
+
const [deleted] = await db
|
|
274
|
+
.delete(users)
|
|
275
|
+
.where(eq(users.id, userId))
|
|
276
|
+
.returning();
|
|
277
|
+
|
|
278
|
+
// Bulk delete
|
|
279
|
+
await db.delete(posts).where(and(eq(posts.published, false), lt(posts.createdAt, cutoffDate)));
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
---
|
|
283
|
+
|
|
284
|
+
## 4. Relational Queries
|
|
285
|
+
|
|
286
|
+
The relational query API uses the `relations` definitions for type-safe eager loading.
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
// Find many with relations
|
|
290
|
+
const usersWithPosts = await db.query.users.findMany({
|
|
291
|
+
with: {
|
|
292
|
+
posts: {
|
|
293
|
+
where: eq(posts.published, true),
|
|
294
|
+
orderBy: [desc(posts.createdAt)],
|
|
295
|
+
limit: 5,
|
|
296
|
+
with: {
|
|
297
|
+
comments: {
|
|
298
|
+
limit: 3,
|
|
299
|
+
with: {
|
|
300
|
+
author: { columns: { id: true, name: true } },
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
},
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
where: eq(users.active, true),
|
|
307
|
+
limit: 20,
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
// Find first (returns single object or undefined)
|
|
311
|
+
const user = await db.query.users.findFirst({
|
|
312
|
+
where: eq(users.email, 'alice@example.com'),
|
|
313
|
+
with: { posts: true },
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
// Select specific columns
|
|
317
|
+
const userNames = await db.query.users.findMany({
|
|
318
|
+
columns: { id: true, name: true, email: true },
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
// Computed/extra fields
|
|
322
|
+
const postsWithExtra = await db.query.posts.findMany({
|
|
323
|
+
extras: {
|
|
324
|
+
titleLength: sql<number>`length(${posts.title})`.as('title_length'),
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## 5. Raw SQL
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
import { sql } from 'drizzle-orm';
|
|
335
|
+
|
|
336
|
+
// Tagged template (parameterized -- safe from injection)
|
|
337
|
+
const result = await db.execute(sql`
|
|
338
|
+
SELECT u.name, count(p.id) as post_count
|
|
339
|
+
FROM ${users} u
|
|
340
|
+
LEFT JOIN ${posts} p ON p.author_id = u.id
|
|
341
|
+
WHERE u.active = ${true}
|
|
342
|
+
GROUP BY u.name
|
|
343
|
+
HAVING count(p.id) > ${5}
|
|
344
|
+
ORDER BY post_count DESC
|
|
345
|
+
`);
|
|
346
|
+
|
|
347
|
+
// sql.raw() for trusted strings only (NOT user input)
|
|
348
|
+
const orderDir = 'DESC';
|
|
349
|
+
const sorted = await db.execute(sql`SELECT * FROM ${users} ORDER BY created_at ${sql.raw(orderDir)}`);
|
|
350
|
+
|
|
351
|
+
// Type the result
|
|
352
|
+
const typedResult = await db.execute<{ name: string; post_count: number }>(sql`
|
|
353
|
+
SELECT name, count(*) as post_count FROM ${users} GROUP BY name
|
|
354
|
+
`);
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
---
|
|
358
|
+
|
|
359
|
+
## 6. Transactions
|
|
360
|
+
|
|
361
|
+
```typescript
|
|
362
|
+
// Basic transaction
|
|
363
|
+
const result = await db.transaction(async (tx) => {
|
|
364
|
+
const [order] = await tx.insert(orders).values({ userId, total: 0 }).returning();
|
|
365
|
+
|
|
366
|
+
const itemRows = items.map((item) => ({
|
|
367
|
+
orderId: order.id,
|
|
368
|
+
productId: item.productId,
|
|
369
|
+
quantity: item.quantity,
|
|
370
|
+
unitPrice: item.unitPrice,
|
|
371
|
+
}));
|
|
372
|
+
await tx.insert(orderItems).values(itemRows);
|
|
373
|
+
|
|
374
|
+
const total = items.reduce((sum, i) => sum + i.quantity * i.unitPrice, 0);
|
|
375
|
+
const [updated] = await tx.update(orders).set({ total }).where(eq(orders.id, order.id)).returning();
|
|
376
|
+
|
|
377
|
+
return updated;
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
// Nested savepoints
|
|
381
|
+
await db.transaction(async (tx) => {
|
|
382
|
+
await tx.insert(users).values({ email: 'a@b.com', name: 'A' });
|
|
383
|
+
|
|
384
|
+
try {
|
|
385
|
+
await tx.transaction(async (tx2) => {
|
|
386
|
+
await tx2.insert(users).values({ email: 'a@b.com', name: 'Duplicate' }); // fails
|
|
387
|
+
});
|
|
388
|
+
} catch {
|
|
389
|
+
// Savepoint rolled back, outer transaction continues
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
await tx.insert(users).values({ email: 'c@d.com', name: 'C' }); // still works
|
|
393
|
+
});
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## 7. Prepared Statements
|
|
399
|
+
|
|
400
|
+
```typescript
|
|
401
|
+
// Prepare once, execute many times
|
|
402
|
+
const getUserByEmail = db
|
|
403
|
+
.select()
|
|
404
|
+
.from(users)
|
|
405
|
+
.where(eq(users.email, sql.placeholder('email')))
|
|
406
|
+
.prepare('get_user_by_email');
|
|
407
|
+
|
|
408
|
+
const user = await getUserByEmail.execute({ email: 'alice@example.com' });
|
|
409
|
+
|
|
410
|
+
// With multiple placeholders
|
|
411
|
+
const getPostsByAuthor = db
|
|
412
|
+
.select()
|
|
413
|
+
.from(posts)
|
|
414
|
+
.where(and(eq(posts.authorId, sql.placeholder('authorId')), eq(posts.published, sql.placeholder('published'))))
|
|
415
|
+
.orderBy(desc(posts.createdAt))
|
|
416
|
+
.limit(sql.placeholder('limit'))
|
|
417
|
+
.prepare('get_posts_by_author');
|
|
418
|
+
|
|
419
|
+
const results = await getPostsByAuthor.execute({ authorId: userId, published: true, limit: 10 });
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## 8. Migrations (drizzle-kit)
|
|
425
|
+
|
|
426
|
+
### Configuration
|
|
427
|
+
|
|
428
|
+
```typescript
|
|
429
|
+
// drizzle.config.ts
|
|
430
|
+
import { defineConfig } from 'drizzle-kit';
|
|
431
|
+
|
|
432
|
+
export default defineConfig({
|
|
433
|
+
schema: './src/db/schema/index.ts',
|
|
434
|
+
out: './drizzle/migrations',
|
|
435
|
+
dialect: 'postgresql',
|
|
436
|
+
dbCredentials: {
|
|
437
|
+
url: process.env.DATABASE_URL!,
|
|
438
|
+
},
|
|
439
|
+
verbose: true,
|
|
440
|
+
strict: true,
|
|
441
|
+
});
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
### Commands
|
|
445
|
+
|
|
446
|
+
```bash
|
|
447
|
+
# Generate migration from schema changes
|
|
448
|
+
pnpm drizzle-kit generate
|
|
449
|
+
|
|
450
|
+
# Apply migrations
|
|
451
|
+
pnpm drizzle-kit migrate
|
|
452
|
+
|
|
453
|
+
# Push schema directly (development only -- no migration files)
|
|
454
|
+
pnpm drizzle-kit push
|
|
455
|
+
|
|
456
|
+
# Introspect existing database and generate schema
|
|
457
|
+
pnpm drizzle-kit introspect
|
|
458
|
+
|
|
459
|
+
# Open Drizzle Studio (database browser)
|
|
460
|
+
pnpm drizzle-kit studio
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### Programmatic Migration
|
|
464
|
+
|
|
465
|
+
```typescript
|
|
466
|
+
import { migrate } from 'drizzle-orm/node-postgres/migrator';
|
|
467
|
+
import { db } from './db';
|
|
468
|
+
|
|
469
|
+
async function runMigrations() {
|
|
470
|
+
await migrate(db, { migrationsFolder: './drizzle/migrations' });
|
|
471
|
+
console.log('Migrations complete');
|
|
472
|
+
}
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
## 9. Type Inference
|
|
478
|
+
|
|
479
|
+
```typescript
|
|
480
|
+
import { type InferSelectModel, type InferInsertModel } from 'drizzle-orm';
|
|
481
|
+
|
|
482
|
+
// Infer types from schema
|
|
483
|
+
type User = InferSelectModel<typeof users>;
|
|
484
|
+
// { id: string; email: string; name: string; role: 'user' | 'admin' | 'moderator'; active: boolean; ... }
|
|
485
|
+
|
|
486
|
+
type NewUser = InferInsertModel<typeof users>;
|
|
487
|
+
// { id?: string; email: string; name: string; role?: 'user' | 'admin' | 'moderator'; active?: boolean; ... }
|
|
488
|
+
|
|
489
|
+
// Use in function signatures
|
|
490
|
+
async function createUser(data: NewUser): Promise<User> {
|
|
491
|
+
const [user] = await db.insert(users).values(data).returning();
|
|
492
|
+
return user;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Partial select types using $inferSelect
|
|
496
|
+
type UserPreview = Pick<typeof users.$inferSelect, 'id' | 'name' | 'email'>;
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
---
|
|
500
|
+
|
|
501
|
+
## 10. Drizzle + Zod Integration
|
|
502
|
+
|
|
503
|
+
```typescript
|
|
504
|
+
import { createInsertSchema, createSelectSchema } from 'drizzle-zod';
|
|
505
|
+
import { z } from 'zod';
|
|
506
|
+
|
|
507
|
+
// Auto-generate Zod schemas from Drizzle tables
|
|
508
|
+
const insertUserSchema = createInsertSchema(users, {
|
|
509
|
+
// Override/refine auto-generated validators
|
|
510
|
+
email: z.string().email('Invalid email format'),
|
|
511
|
+
name: z.string().min(1, 'Name is required').max(100),
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
const selectUserSchema = createSelectSchema(users);
|
|
515
|
+
|
|
516
|
+
// Use for API validation
|
|
517
|
+
type CreateUserInput = z.infer<typeof insertUserSchema>;
|
|
518
|
+
|
|
519
|
+
export async function handleCreateUser(body: unknown) {
|
|
520
|
+
const parsed = insertUserSchema.safeParse(body);
|
|
521
|
+
if (!parsed.success) {
|
|
522
|
+
return { error: parsed.error.flatten().fieldErrors };
|
|
523
|
+
}
|
|
524
|
+
const [user] = await db.insert(users).values(parsed.data).returning();
|
|
525
|
+
return { user };
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
// Omit server-only fields for API responses
|
|
529
|
+
const userResponseSchema = selectUserSchema.omit({ metadata: true });
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
---
|
|
533
|
+
|
|
534
|
+
## 11. Performance Patterns
|
|
535
|
+
|
|
536
|
+
### Preventing N+1
|
|
537
|
+
|
|
538
|
+
```typescript
|
|
539
|
+
// BAD: N+1 queries
|
|
540
|
+
const allUsers = await db.select().from(users);
|
|
541
|
+
for (const user of allUsers) {
|
|
542
|
+
const userPosts = await db.select().from(posts).where(eq(posts.authorId, user.id));
|
|
543
|
+
// ...
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
// GOOD: Relational query (single query with joins)
|
|
547
|
+
const usersWithPosts = await db.query.users.findMany({
|
|
548
|
+
with: { posts: true },
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
// GOOD: Manual join when you need aggregates
|
|
552
|
+
const usersWithCounts = await db
|
|
553
|
+
.select({
|
|
554
|
+
id: users.id,
|
|
555
|
+
name: users.name,
|
|
556
|
+
postCount: count(posts.id),
|
|
557
|
+
})
|
|
558
|
+
.from(users)
|
|
559
|
+
.leftJoin(posts, eq(users.id, posts.authorId))
|
|
560
|
+
.groupBy(users.id, users.name);
|
|
561
|
+
```
|
|
562
|
+
|
|
563
|
+
### Select Only What You Need
|
|
564
|
+
|
|
565
|
+
```typescript
|
|
566
|
+
// BAD: select all columns when you only need two
|
|
567
|
+
const allData = await db.select().from(users);
|
|
568
|
+
|
|
569
|
+
// GOOD: select specific columns
|
|
570
|
+
const needed = await db.select({ id: users.id, email: users.email }).from(users);
|
|
571
|
+
|
|
572
|
+
// GOOD: with relational queries
|
|
573
|
+
const partial = await db.query.users.findMany({
|
|
574
|
+
columns: { id: true, email: true },
|
|
575
|
+
});
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
|
|
580
|
+
## 12. Common Anti-Patterns
|
|
581
|
+
|
|
582
|
+
| Anti-Pattern | Why It's Wrong | Fix |
|
|
583
|
+
|-------------|---------------|-----|
|
|
584
|
+
| No `returning()` on insert/update | Requires a separate SELECT query | Always chain `.returning()` when you need the result |
|
|
585
|
+
| Using `db.execute(sql\`...\`)` for everything | Loses type safety, harder to maintain | Use the query builder; reserve raw SQL for complex queries |
|
|
586
|
+
| Defining relations but not using `db.query` | Relations only work with the relational API | Use `db.query.tableName.findMany({ with: ... })` |
|
|
587
|
+
| Forgetting `onDelete` on foreign keys | Orphaned rows when parent is deleted | Specify `onDelete: 'cascade'` or `'set null'` |
|
|
588
|
+
| Not exporting schema from a barrel file | `drizzle-kit` cannot find schemas | Export all tables and relations from `schema/index.ts` |
|
|
589
|
+
| Mutating inside `db.select()` | Select should be read-only | Use `db.insert/update/delete` for mutations |
|
|
590
|
+
| Not using transactions for multi-table writes | Partial writes on failure | Wrap related writes in `db.transaction()` |
|
|
591
|
+
|
|
592
|
+
---
|
|
593
|
+
|
|
594
|
+
## 13. Critical Reminders
|
|
595
|
+
|
|
596
|
+
### ALWAYS
|
|
597
|
+
|
|
598
|
+
- Define `relations` separately from foreign keys (both are needed)
|
|
599
|
+
- Use `returning()` after insert/update/delete when you need the result
|
|
600
|
+
- Export all schema files from a single barrel (`schema/index.ts`)
|
|
601
|
+
- Use `drizzle-kit generate` for migration files (not `push` in production)
|
|
602
|
+
- Use parameterized queries via the query builder or `sql` template tag
|
|
603
|
+
- Wrap multi-step writes in `db.transaction()`
|
|
604
|
+
- Infer types with `InferSelectModel` / `InferInsertModel` rather than defining manually
|
|
605
|
+
- Use `drizzle-zod` to generate Zod schemas from your Drizzle tables
|
|
606
|
+
|
|
607
|
+
### NEVER
|
|
608
|
+
|
|
609
|
+
- Use `db.execute(sql.raw(userInput))` -- this enables SQL injection
|
|
610
|
+
- Skip migration files in production (always use `generate` + `migrate`)
|
|
611
|
+
- Define relations without corresponding foreign key constraints
|
|
612
|
+
- Use `push` in production (it can drop columns/tables)
|
|
613
|
+
- Ignore the `strict: true` config in drizzle-kit (catches dangerous migrations)
|