ui-syncup 0.3.13 → 0.4.0-beta.2
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/.agents/skills/ai-spec-workflow/SKILL.md +58 -0
- package/.agents/skills/ai-spec-workflow/references/AI_SPECIFICATION_WORKFLOW.md +1434 -0
- package/.agents/skills/ai-spec-workflow/references/templates/design-template.md +729 -0
- package/.agents/skills/ai-spec-workflow/references/templates/requirements-template.md +179 -0
- package/.agents/skills/ai-spec-workflow/references/templates/tasks-template.md +501 -0
- package/.agents/skills/animation-designer/SKILL.md +688 -0
- package/.agents/skills/animation-designer/manifest.yaml +44 -0
- package/.agents/skills/brainstorming/SKILL.md +54 -0
- package/.agents/skills/contract-driven-ui/SKILL.md +270 -0
- package/.agents/skills/dispatching-parallel-agents/SKILL.md +180 -0
- package/.agents/skills/executing-plans/SKILL.md +76 -0
- package/.agents/skills/executing-specs/SKILL.md +53 -0
- package/.agents/skills/finishing-a-development-branch/SKILL.md +200 -0
- package/.agents/skills/github-workflow-automation/SKILL.md +846 -0
- package/.agents/skills/react-best-practices/AGENTS.md +2249 -0
- package/.agents/skills/react-best-practices/README.md +123 -0
- package/.agents/skills/react-best-practices/SKILL.md +121 -0
- package/.agents/skills/react-best-practices/metadata.json +15 -0
- package/.agents/skills/react-best-practices/rules/_sections.md +46 -0
- package/.agents/skills/react-best-practices/rules/_template.md +28 -0
- package/.agents/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/.agents/skills/react-best-practices/rules/advanced-use-latest.md +49 -0
- package/.agents/skills/react-best-practices/rules/async-api-routes.md +38 -0
- package/.agents/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/.agents/skills/react-best-practices/rules/async-dependencies.md +36 -0
- package/.agents/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/.agents/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/.agents/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/.agents/skills/react-best-practices/rules/bundle-conditional.md +31 -0
- package/.agents/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/.agents/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/.agents/skills/react-best-practices/rules/bundle-preload.md +50 -0
- package/.agents/skills/react-best-practices/rules/client-event-listeners.md +74 -0
- package/.agents/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/.agents/skills/react-best-practices/rules/js-batch-dom-css.md +82 -0
- package/.agents/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/.agents/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/.agents/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/.agents/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/.agents/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/.agents/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/.agents/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/.agents/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/.agents/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/.agents/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/.agents/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/.agents/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/.agents/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/.agents/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/.agents/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/.agents/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/.agents/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/.agents/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/.agents/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/.agents/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/.agents/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/.agents/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/.agents/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/.agents/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/.agents/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/.agents/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/.agents/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/.agents/skills/react-best-practices/rules/server-cache-react.md +26 -0
- package/.agents/skills/react-best-practices/rules/server-parallel-fetching.md +79 -0
- package/.agents/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/.agents/skills/react-ui-patterns/SKILL.md +289 -0
- package/.agents/skills/receiving-code-review/SKILL.md +213 -0
- package/.agents/skills/requesting-code-review/SKILL.md +105 -0
- package/.agents/skills/requesting-code-review/code-reviewer.md +146 -0
- package/.agents/skills/reviewing-code/SKILL.md +28 -0
- package/.agents/skills/shadcn/SKILL.md +240 -0
- package/.agents/skills/shadcn/agents/openai.yml +5 -0
- package/.agents/skills/shadcn/assets/shadcn-small.png +0 -0
- package/.agents/skills/shadcn/assets/shadcn.png +0 -0
- package/.agents/skills/shadcn/cli.md +255 -0
- package/.agents/skills/shadcn/customization.md +202 -0
- package/.agents/skills/shadcn/evals/evals.json +47 -0
- package/.agents/skills/shadcn/mcp.md +94 -0
- package/.agents/skills/shadcn/rules/base-vs-radix.md +306 -0
- package/.agents/skills/shadcn/rules/composition.md +195 -0
- package/.agents/skills/shadcn/rules/forms.md +192 -0
- package/.agents/skills/shadcn/rules/icons.md +101 -0
- package/.agents/skills/shadcn/rules/styling.md +162 -0
- package/.agents/skills/steering-creation/SKILL.md +221 -0
- package/.agents/skills/steering-creation/references/STEERING_CREATION_INSTRUCTION.md +850 -0
- package/.agents/skills/subagent-driven-development/SKILL.md +240 -0
- package/.agents/skills/subagent-driven-development/code-quality-reviewer-prompt.md +20 -0
- package/.agents/skills/subagent-driven-development/implementer-prompt.md +78 -0
- package/.agents/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/.agents/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/.agents/skills/systematic-debugging/SKILL.md +296 -0
- package/.agents/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/.agents/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/.agents/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/.agents/skills/systematic-debugging/find-polluter.sh +63 -0
- package/.agents/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/.agents/skills/systematic-debugging/test-academic.md +14 -0
- package/.agents/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/.agents/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/.agents/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/.agents/skills/test-driven-development/SKILL.md +371 -0
- package/.agents/skills/test-driven-development/testing-anti-patterns.md +299 -0
- package/.agents/skills/using-git-worktrees/SKILL.md +217 -0
- package/.agents/skills/using-superpowers/SKILL.md +87 -0
- package/.agents/skills/verification-before-completion/SKILL.md +139 -0
- package/.agents/skills/web-design-guidelines/SKILL.md +36 -0
- package/.agents/skills/writing-plans/SKILL.md +116 -0
- package/.agents/skills/writing-skills/SKILL.md +655 -0
- package/.agents/skills/writing-skills/anthropic-best-practices.md +1150 -0
- package/.agents/skills/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/.agents/skills/writing-skills/graphviz-conventions.dot +172 -0
- package/.agents/skills/writing-skills/persuasion-principles.md +187 -0
- package/.agents/skills/writing-skills/render-graphs.js +168 -0
- package/.agents/skills/writing-skills/testing-skills-with-subagents.md +384 -0
- package/.ai/steering/product.md +51 -0
- package/.ai/steering/structure.md +275 -0
- package/.ai/steering/tech.md +188 -0
- package/.claude/agents/database-architect.md +96 -0
- package/.claude/agents/deployment-pipeline-architect.md +122 -0
- package/.claude/agents/nextjs-expert.md +69 -0
- package/.claude/agents/ui-design-expert.md +106 -0
- package/.claudeignore +69 -0
- package/.dockerignore +8 -0
- package/.env.development +86 -0
- package/.env.example +171 -0
- package/.env.production +139 -0
- package/.env.test +58 -0
- package/.gitattributes +2 -0
- package/.github/ISSUE_TEMPLATE/bug_report.yml +33 -0
- package/.github/ISSUE_TEMPLATE/feature_request.yml +20 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +23 -0
- package/.github/workflows/ci.yml +64 -0
- package/.github/workflows/release.yml +174 -0
- package/.nvmrc +1 -0
- package/.releaserc.json +18 -0
- package/.vercelignore +73 -0
- package/AGENTS.md +544 -0
- package/CHANGELOG.md +69 -0
- package/CODE_OF_CONDUCT.md +21 -0
- package/CONTRIBUTING.md +32 -0
- package/Dockerfile +84 -0
- package/LICENSE +21 -0
- package/README.md +328 -59
- package/SECURITY.md +16 -0
- package/bun.lock +3853 -0
- package/cli/README.md +94 -0
- package/cli/bun.lock +306 -0
- package/cli/index.ts +96 -0
- package/cli/package-lock.json +2157 -0
- package/cli/package.json +30 -0
- package/cli/src/commands/backup.ts +78 -0
- package/cli/src/commands/doctor.ts +82 -0
- package/cli/src/commands/init.ts +234 -0
- package/cli/src/commands/logs.ts +26 -0
- package/cli/src/commands/open.ts +23 -0
- package/cli/src/commands/remove.ts +44 -0
- package/cli/src/commands/restart.ts +21 -0
- package/cli/src/commands/restore.ts +90 -0
- package/cli/src/commands/start.ts +26 -0
- package/cli/src/commands/status.ts +25 -0
- package/cli/src/commands/stop.ts +20 -0
- package/cli/src/commands/upgrade.ts +28 -0
- package/cli/src/lib/docker.ts +40 -0
- package/cli/src/lib/env.ts +42 -0
- package/cli/src/lib/ui.ts +43 -0
- package/cli/tsconfig.json +13 -0
- package/cli/tsup.config.ts +12 -0
- package/components.json +24 -0
- package/docker/README.md +430 -0
- package/docker/compose.dev-minio.yml +30 -0
- package/docker/compose.dev.yml +39 -0
- package/docker/compose.local.yml +84 -0
- package/docker/compose.yml +153 -0
- package/docs/VERSIONING.md +101 -0
- package/docs/database/DRIZZLE_COMMANDS_EXPLAINED.md +1779 -0
- package/docs/database/DRIZZLE_ZOD_POSTGRESQL_INSTRUCTION.md +646 -0
- package/docs/database/MIGRATION_BEST_PRACTICES.md +601 -0
- package/docs/database/MIGRATION_ROLLBACK.md +1080 -0
- package/docs/database/MIGRATION_SYSTEM.md +165 -0
- package/docs/database/MIGRATION_TROUBLESHOOTING.md +881 -0
- package/docs/development/ENVIRONMENT_CONFIG.md +896 -0
- package/docs/development/LOCAL_DEVELOPMENT.md +456 -0
- package/docs/development/REMOTE_DATABASE_SETUP.md +786 -0
- package/docs/development/STORAGE_SETUP.md +207 -0
- package/docs/development/SUPABASE_LOCAL_SETUP.md +178 -0
- package/docs/development/TESTING.md +714 -0
- package/docs/feature-architectures/LOADING_ARCHITECTURE.md +343 -0
- package/docs/feature-architectures/NOTIFICATION_ARCHITECTURE.md +858 -0
- package/docs/feature-architectures/RATE_LIMIT_RESET.md +147 -0
- package/docs/feature-architectures/RBAC.md +1132 -0
- package/docs/feature-architectures/RESOURCE_LIMITS.md +69 -0
- package/docs/feature-architectures/SECURITY.md +284 -0
- package/docs/feature-architectures/WORKSPACES.md +278 -0
- package/docs/plans/admin-setup-wizard-routing-plan.md +623 -0
- package/drizzle/0000_purple_wilson_fisk.sql +360 -0
- package/drizzle/0001_drop_instance_public_url.sql +1 -0
- package/drizzle/meta/0000_snapshot.json +3118 -0
- package/drizzle/meta/_journal.json +20 -0
- package/drizzle.config.ts +13 -0
- package/eslint.config.mjs +44 -0
- package/install.sh +180 -0
- package/next.config.ts +91 -0
- package/package.json +128 -22
- package/playwright.config.ts +70 -0
- package/postcss.config.mjs +7 -0
- package/public/file.svg +1 -0
- package/public/globe.svg +1 -0
- package/public/logo.svg +11 -0
- package/public/next.svg +1 -0
- package/public/playground/CPM-101/as-is-image.jpg +0 -0
- package/public/playground/CPM-101/to-be-image.jpg +0 -0
- package/public/playground/TEST-1/LinkedIn-skeleton-screen.png +0 -0
- package/public/playground/TEST-1/https___dev-to-uploads.s3.amazonaws.com_uploads_articles_vuahe90ka1mkx9aepmea.webp +0 -0
- package/public/playground/TEST-1/linkedin_skeletonscreen.jpg +0 -0
- package/public/vercel.svg +1 -0
- package/public/window.svg +1 -0
- package/scripts/__tests__/migrate.integration.test.ts +642 -0
- package/scripts/__tests__/migrate.property.test.ts +1714 -0
- package/scripts/__tests__/migrate.test.ts +536 -0
- package/scripts/admin-reset-password.ts +114 -0
- package/scripts/check-email-queue.ts +99 -0
- package/scripts/check-sessions.ts +50 -0
- package/scripts/db-pull-data.sh +73 -0
- package/scripts/force-verify-email.sh +13 -0
- package/scripts/migrate.ts +693 -0
- package/scripts/process-email-queue.ts +26 -0
- package/scripts/reset-db.ts +47 -0
- package/scripts/reset-rate-limit.sh +26 -0
- package/scripts/reset-remote-db.sql +31 -0
- package/scripts/retry-failed-emails.ts +67 -0
- package/scripts/seed.ts +605 -0
- package/scripts/setup-monitoring.sh +440 -0
- package/scripts/sync-migration-tracking.ts +113 -0
- package/scripts/test-ci-error-handling.sh +237 -0
- package/scripts/test-ci-workflow.sh +200 -0
- package/scripts/test-migration.sh +151 -0
- package/scripts/validate-env.ts +25 -0
- package/scripts/validate-migration-system.ts +566 -0
- package/scripts/verify-ci-status-reporting.sh +206 -0
- package/scripts/verify-user-email.sql +22 -0
- package/scripts/verify-vercel-integration.ts +292 -0
- package/seed_data.md +54 -0
- package/src/app/(protected)/(team)/(routes)/[projectSlug]/error.tsx +89 -0
- package/src/app/(protected)/(team)/(routes)/[projectSlug]/loading.tsx +101 -0
- package/src/app/(protected)/(team)/(routes)/[projectSlug]/page.tsx +91 -0
- package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/README.md +192 -0
- package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/error.tsx +58 -0
- package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/loading.tsx +14 -0
- package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/not-found.tsx +47 -0
- package/src/app/(protected)/(team)/(routes)/issue/[issueKey]/page.tsx +91 -0
- package/src/app/(protected)/(team)/projects/page.tsx +16 -0
- package/src/app/(protected)/(team)/team/settings/(section)/instance/page.tsx +52 -0
- package/src/app/(protected)/(team)/team/settings/(section)/integrations/loading.tsx +5 -0
- package/src/app/(protected)/(team)/team/settings/(section)/integrations/page.tsx +23 -0
- package/src/app/(protected)/(team)/team/settings/(section)/members/loading.tsx +5 -0
- package/src/app/(protected)/(team)/team/settings/(section)/members/page.tsx +35 -0
- package/src/app/(protected)/(team)/team/settings/layout.tsx +72 -0
- package/src/app/(protected)/(team)/team/settings/loading.tsx +5 -0
- package/src/app/(protected)/(team)/team/settings/page.tsx +71 -0
- package/src/app/(protected)/dev/auth/README.md +151 -0
- package/src/app/(protected)/dev/auth/page.tsx +590 -0
- package/src/app/(protected)/layout.test.tsx +209 -0
- package/src/app/(protected)/layout.tsx +28 -0
- package/src/app/(protected)/onboarding/page.tsx +27 -0
- package/src/app/(protected)/settings/integrations/page.tsx +23 -0
- package/src/app/(protected)/settings/layout.tsx +26 -0
- package/src/app/(protected)/settings/notifications/page.tsx +26 -0
- package/src/app/(protected)/settings/other/page.tsx +23 -0
- package/src/app/(protected)/settings/page.tsx +23 -0
- package/src/app/(protected)/settings/preferences/page.tsx +23 -0
- package/src/app/(protected)/settings/security/page.tsx +37 -0
- package/src/app/(public)/forgot-password/page.tsx +20 -0
- package/src/app/(public)/invite/project/[token]/error.tsx +50 -0
- package/src/app/(public)/invite/project/[token]/loading.tsx +39 -0
- package/src/app/(public)/invite/project/[token]/page.tsx +156 -0
- package/src/app/(public)/layout.tsx +9 -0
- package/src/app/(public)/privacy-policy/page.tsx +12 -0
- package/src/app/(public)/reset-password/page.tsx +37 -0
- package/src/app/(public)/setup/__tests__/page.test.tsx +30 -0
- package/src/app/(public)/setup/page.tsx +17 -0
- package/src/app/(public)/share/issue/[token]/page.tsx +51 -0
- package/src/app/(public)/sign-in/page.tsx +55 -0
- package/src/app/(public)/sign-up/page.tsx +23 -0
- package/src/app/(public)/verify-email/page.tsx +22 -0
- package/src/app/(public)/verify-email-confirm/page.tsx +40 -0
- package/src/app/api/auth/[...all]/route.ts +6 -0
- package/src/app/api/auth/delete-account/route.ts +134 -0
- package/src/app/api/auth/dev/force-verify/route.ts +180 -0
- package/src/app/api/auth/dev/reset-rate-limit/route.ts +144 -0
- package/src/app/api/auth/dev/sessions/route.ts +172 -0
- package/src/app/api/auth/forgot-password/__tests__/forgot-password.property.test.ts +397 -0
- package/src/app/api/auth/forgot-password/route.ts +277 -0
- package/src/app/api/auth/logout/route.ts +115 -0
- package/src/app/api/auth/me/route.ts +123 -0
- package/src/app/api/auth/providers/__tests__/route.test.ts +236 -0
- package/src/app/api/auth/providers/route.ts +119 -0
- package/src/app/api/auth/resend-verification/route.ts +262 -0
- package/src/app/api/auth/reset-password/__tests__/reset-password.property.test.ts +493 -0
- package/src/app/api/auth/reset-password/__tests__/route.test.ts +284 -0
- package/src/app/api/auth/reset-password/route.ts +251 -0
- package/src/app/api/auth/verify-email/route.ts +232 -0
- package/src/app/api/example-cors/route.ts +61 -0
- package/src/app/api/health/route.ts +14 -0
- package/src/app/api/invite/project/[token]/__tests__/accept-invitation.integration.test.ts +348 -0
- package/src/app/api/invite/project/[token]/decline/route.ts +99 -0
- package/src/app/api/invite/project/[token]/route.ts +269 -0
- package/src/app/api/issues/[issueId]/activities/route.ts +213 -0
- package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/[annotationId]/comments/[commentId]/route.ts +486 -0
- package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/[annotationId]/comments/route.ts +283 -0
- package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/[annotationId]/read/route.ts +242 -0
- package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/[annotationId]/route.ts +534 -0
- package/src/app/api/issues/[issueId]/attachments/[attachmentId]/annotations/route.ts +514 -0
- package/src/app/api/issues/[issueId]/attachments/[attachmentId]/route.ts +161 -0
- package/src/app/api/issues/[issueId]/attachments/route.ts +376 -0
- package/src/app/api/issues/[issueId]/route.ts +516 -0
- package/src/app/api/notifications/[id]/read/route.ts +131 -0
- package/src/app/api/notifications/__tests__/notifications.integration.test.ts +350 -0
- package/src/app/api/notifications/read-all/route.ts +72 -0
- package/src/app/api/notifications/route.ts +148 -0
- package/src/app/api/notifications/unread-count/route.ts +77 -0
- package/src/app/api/projects/[id]/activities/route.ts +174 -0
- package/src/app/api/projects/[id]/invitations/[invitationId]/resend/route.ts +99 -0
- package/src/app/api/projects/[id]/invitations/[invitationId]/route.ts +96 -0
- package/src/app/api/projects/[id]/invitations/route.ts +254 -0
- package/src/app/api/projects/[id]/issues/route.ts +452 -0
- package/src/app/api/projects/[id]/join/route.ts +207 -0
- package/src/app/api/projects/[id]/members/[memberId]/route.ts +364 -0
- package/src/app/api/projects/[id]/members/me/route.ts +121 -0
- package/src/app/api/projects/[id]/members/route.ts +129 -0
- package/src/app/api/projects/[id]/route.ts +476 -0
- package/src/app/api/projects/route.ts +394 -0
- package/src/app/api/setup/admin/route.ts +255 -0
- package/src/app/api/setup/complete/__tests__/route.test.ts +60 -0
- package/src/app/api/setup/complete/route.ts +244 -0
- package/src/app/api/setup/config/route.ts +195 -0
- package/src/app/api/setup/export/route.ts +111 -0
- package/src/app/api/setup/health/route.ts +74 -0
- package/src/app/api/setup/import/route.ts +154 -0
- package/src/app/api/setup/status/route.ts +82 -0
- package/src/app/api/setup/workspace/route.ts +252 -0
- package/src/app/api/teams/[teamId]/export/route.ts +115 -0
- package/src/app/api/teams/[teamId]/invitations/[invitationId]/resend/route.ts +132 -0
- package/src/app/api/teams/[teamId]/invitations/[invitationId]/route.ts +117 -0
- package/src/app/api/teams/[teamId]/invitations/route.ts +363 -0
- package/src/app/api/teams/[teamId]/members/[userId]/route.ts +335 -0
- package/src/app/api/teams/[teamId]/members/route.ts +184 -0
- package/src/app/api/teams/[teamId]/members/search/route.ts +202 -0
- package/src/app/api/teams/[teamId]/route.ts +423 -0
- package/src/app/api/teams/[teamId]/switch/route.ts +140 -0
- package/src/app/api/teams/[teamId]/transfer-ownership/route.ts +212 -0
- package/src/app/api/teams/invitations/[token]/accept/route.ts +140 -0
- package/src/app/api/teams/invitations/by-id/[id]/accept/route.ts +98 -0
- package/src/app/api/teams/invitations/by-id/[id]/decline/route.ts +90 -0
- package/src/app/api/teams/route.ts +278 -0
- package/src/app/api/uploads/media/route.ts +118 -0
- package/src/app/api/uploads/presigned/route.ts +49 -0
- package/src/app/api/user/linked-accounts/route.ts +35 -0
- package/src/app/email-preview/page.tsx +11 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/global-error.tsx +21 -0
- package/src/app/layout.tsx +50 -0
- package/src/app/page.tsx +5 -0
- package/src/components/icons/atlassian-icon.tsx +22 -0
- package/src/components/icons/index.ts +1 -0
- package/src/components/layout/SIDEBAR_LAYOUT_BEST_PRACTICES.md +240 -0
- package/src/components/layout/app-shell-header-store.tsx +20 -0
- package/src/components/layout/app-shell-skeleton.tsx +89 -0
- package/src/components/layout/app-shell-wrapper.tsx +32 -0
- package/src/components/layout/app-shell.test.tsx +155 -0
- package/src/components/layout/app-shell.tsx +100 -0
- package/src/components/shared/headers/app-header-configurator.tsx +42 -0
- package/src/components/shared/headers/app-header.tsx +103 -0
- package/src/components/shared/headers/header-user-menu.tsx +247 -0
- package/src/components/shared/headers/index.ts +44 -0
- package/src/components/shared/headers/page-header.tsx +25 -0
- package/src/components/shared/notifications/__tests__/notification-bell.test.tsx +159 -0
- package/src/components/shared/notifications/__tests__/notification-dropdown.test.tsx +296 -0
- package/src/components/shared/notifications/__tests__/notification-item.test.tsx +328 -0
- package/src/components/shared/notifications/index.ts +45 -0
- package/src/components/shared/notifications/notification-actions.tsx +295 -0
- package/src/components/shared/notifications/notification-bell-button.tsx +77 -0
- package/src/components/shared/notifications/notification-dropdown.tsx +160 -0
- package/src/components/shared/notifications/notification-group-item.tsx +268 -0
- package/src/components/shared/notifications/notification-item.tsx +193 -0
- package/src/components/shared/notifications/notification-load-more.tsx +50 -0
- package/src/components/shared/notifications/notification-panel.tsx +49 -0
- package/src/components/shared/notifications/utils.tsx +127 -0
- package/src/components/shared/permission-guard/index.ts +1 -0
- package/src/components/shared/permission-guard/permission-tooltip.tsx +45 -0
- package/src/components/shared/relative-time.tsx +53 -0
- package/src/components/shared/section-container.tsx +32 -0
- package/src/components/shared/service-status-banner.tsx +121 -0
- package/src/components/shared/settings-sidebar/index.ts +2 -0
- package/src/components/shared/settings-sidebar/team-setting-aside.tsx +97 -0
- package/src/components/shared/settings-sidebar/user-settings-aside.tsx +66 -0
- package/src/components/shared/sidebar/app-sidebar.tsx +146 -0
- package/src/components/shared/sidebar/index.ts +36 -0
- package/src/components/shared/sidebar/sidebar-main.tsx +81 -0
- package/src/components/shared/sidebar/sidebar-project.tsx +61 -0
- package/src/components/shared/sidebar/sidebar-team-avatar.tsx +126 -0
- package/src/components/shared/sidebar/sidebar-team-switcher.tsx +185 -0
- package/src/components/shared/sidebar/type.ts +97 -0
- package/src/components/ui/alert-dialog.tsx +157 -0
- package/src/components/ui/alert.tsx +66 -0
- package/src/components/ui/avatar-upload.tsx +147 -0
- package/src/components/ui/avatar.tsx +53 -0
- package/src/components/ui/badge.tsx +46 -0
- package/src/components/ui/breadcrumb.tsx +109 -0
- package/src/components/ui/button.tsx +60 -0
- package/src/components/ui/card.tsx +92 -0
- package/src/components/ui/checkbox.tsx +32 -0
- package/src/components/ui/collapsible.tsx +33 -0
- package/src/components/ui/command.tsx +184 -0
- package/src/components/ui/dialog.tsx +143 -0
- package/src/components/ui/dropdown-menu.tsx +257 -0
- package/src/components/ui/empty.tsx +104 -0
- package/src/components/ui/field.tsx +244 -0
- package/src/components/ui/image-cropper-dialog.tsx +167 -0
- package/src/components/ui/input.tsx +21 -0
- package/src/components/ui/label.tsx +24 -0
- package/src/components/ui/optimized-image.tsx +220 -0
- package/src/components/ui/pagination.tsx +127 -0
- package/src/components/ui/popover.tsx +48 -0
- package/src/components/ui/progress.tsx +31 -0
- package/src/components/ui/radio-group.tsx +45 -0
- package/src/components/ui/scroll-area.tsx +58 -0
- package/src/components/ui/select.tsx +187 -0
- package/src/components/ui/separator.tsx +28 -0
- package/src/components/ui/sheet.tsx +139 -0
- package/src/components/ui/sidebar.tsx +733 -0
- package/src/components/ui/skeleton.tsx +13 -0
- package/src/components/ui/sonner.tsx +40 -0
- package/src/components/ui/spinner.tsx +16 -0
- package/src/components/ui/switch.tsx +31 -0
- package/src/components/ui/table.tsx +116 -0
- package/src/components/ui/tabs.tsx +66 -0
- package/src/components/ui/textarea.tsx +23 -0
- package/src/components/ui/tooltip.tsx +61 -0
- package/src/config/__tests__/workspace.property.test.ts +40 -0
- package/src/config/auth.ts +62 -0
- package/src/config/integrations.ts +126 -0
- package/src/config/quotas.ts +20 -0
- package/src/config/roles.ts +463 -0
- package/src/config/settings-nav.ts +39 -0
- package/src/config/team-settings-nav.ts +37 -0
- package/src/config/user-settings-nav.ts +42 -0
- package/src/config/version.ts +1 -0
- package/src/config/workspace.ts +64 -0
- package/src/features/annotations/README.md +283 -0
- package/src/features/annotations/api/annotations-api.ts +194 -0
- package/src/features/annotations/api/comments-api.ts +147 -0
- package/src/features/annotations/api/index.ts +71 -0
- package/src/features/annotations/api/save-annotation.ts +150 -0
- package/src/features/annotations/api/schemas.ts +142 -0
- package/src/features/annotations/components/annotated-attachment-view.tsx +576 -0
- package/src/features/annotations/components/annotation-action-sheet.tsx +140 -0
- package/src/features/annotations/components/annotation-annotations-panel.tsx +213 -0
- package/src/features/annotations/components/annotation-box.tsx +539 -0
- package/src/features/annotations/components/annotation-canvas.tsx +534 -0
- package/src/features/annotations/components/annotation-comment-input.tsx +145 -0
- package/src/features/annotations/components/annotation-context-menu.tsx +164 -0
- package/src/features/annotations/components/annotation-drawer.tsx +231 -0
- package/src/features/annotations/components/annotation-layer.tsx +271 -0
- package/src/features/annotations/components/annotation-pin.tsx +318 -0
- package/src/features/annotations/components/annotation-popover.tsx +562 -0
- package/src/features/annotations/components/annotation-thread-panel.tsx +485 -0
- package/src/features/annotations/components/annotation-thread-preview.tsx +195 -0
- package/src/features/annotations/components/annotation-toolbar.tsx +244 -0
- package/src/features/annotations/components/keyboard-shortcuts-modal.tsx +79 -0
- package/src/features/annotations/docs/ANNOTATIONS_ARCHITECTURE.md +67 -0
- package/src/features/annotations/docs/ANNOTATION_SAVE_ARCHITECTURE.md +422 -0
- package/src/features/annotations/docs/ANNOTATION_SAVE_FEATURE.md +408 -0
- package/src/features/annotations/docs/BOX_ANNOTATION_GUIDE.md +542 -0
- package/src/features/annotations/docs/NEXTSTEP.md +28 -0
- package/src/features/annotations/docs/STALE_CLOSURE_FIX.md +344 -0
- package/src/features/annotations/docs/UNDO_REDO_QUICK_START.md +545 -0
- package/src/features/annotations/docs/local_first_canvas_autosave_architecture.md +674 -0
- package/src/features/annotations/examples/complete-example.tsx +266 -0
- package/src/features/annotations/examples/save-annotation-example.tsx +309 -0
- package/src/features/annotations/hooks/__tests__/use-annotation-permissions.property.test.tsx +493 -0
- package/src/features/annotations/hooks/index.ts +36 -0
- package/src/features/annotations/hooks/use-annotation-batch-save.ts +109 -0
- package/src/features/annotations/hooks/use-annotation-comments.ts +353 -0
- package/src/features/annotations/hooks/use-annotation-drafts.ts +137 -0
- package/src/features/annotations/hooks/use-annotation-edit-state.ts +99 -0
- package/src/features/annotations/hooks/use-annotation-history-tracker.ts +159 -0
- package/src/features/annotations/hooks/use-annotation-integration.ts +916 -0
- package/src/features/annotations/hooks/use-annotation-permissions.ts +210 -0
- package/src/features/annotations/hooks/use-annotation-popover.ts +175 -0
- package/src/features/annotations/hooks/use-annotation-save.ts +208 -0
- package/src/features/annotations/hooks/use-annotation-tools.ts +237 -0
- package/src/features/annotations/hooks/use-annotations-with-history.ts +332 -0
- package/src/features/annotations/hooks/use-auto-save.ts +94 -0
- package/src/features/annotations/index.ts +111 -0
- package/src/features/annotations/types/annotation.ts +201 -0
- package/src/features/annotations/types/index.ts +28 -0
- package/src/features/annotations/utils/history-manager.ts +73 -0
- package/src/features/annotations/utils/index.ts +2 -0
- package/src/features/annotations/utils/map-attachments-to-threads.ts +28 -0
- package/src/features/annotations/utils/position-comment-input.ts +136 -0
- package/src/features/annotations/utils/re-sequence-labels.ts +92 -0
- package/src/features/annotations/utils/validate-annotation-label.ts +120 -0
- package/src/features/auth/api/types.ts +101 -0
- package/src/features/auth/components/__tests__/role-gate.test.tsx +448 -0
- package/src/features/auth/components/__tests__/social-login-buttons.test.tsx +313 -0
- package/src/features/auth/components/auth-card.tsx +36 -0
- package/src/features/auth/components/forgot-password-form.tsx +115 -0
- package/src/features/auth/components/index.ts +14 -0
- package/src/features/auth/components/invite-code-input.tsx +155 -0
- package/src/features/auth/components/invited-user-form.tsx +309 -0
- package/src/features/auth/components/onboarding-form.tsx +195 -0
- package/src/features/auth/components/password-strength-indicator.tsx +113 -0
- package/src/features/auth/components/reset-password-form.tsx +138 -0
- package/src/features/auth/components/role-gate.tsx +124 -0
- package/src/features/auth/components/self-registration-choice.tsx +153 -0
- package/src/features/auth/components/sign-in-form.tsx +159 -0
- package/src/features/auth/components/sign-up-form.tsx +158 -0
- package/src/features/auth/components/social-login-buttons.tsx +219 -0
- package/src/features/auth/hooks/__tests__/use-onboarding.test.tsx +109 -0
- package/src/features/auth/hooks/__tests__/use-session.test.tsx +160 -0
- package/src/features/auth/hooks/index.ts +15 -0
- package/src/features/auth/hooks/use-accept-invitation.ts +194 -0
- package/src/features/auth/hooks/use-delete-account.ts +86 -0
- package/src/features/auth/hooks/use-force-verify.ts +89 -0
- package/src/features/auth/hooks/use-forgot-password.ts +144 -0
- package/src/features/auth/hooks/use-link-account.ts +78 -0
- package/src/features/auth/hooks/use-linked-accounts.ts +88 -0
- package/src/features/auth/hooks/use-onboarding.ts +159 -0
- package/src/features/auth/hooks/use-resend-verification.ts +139 -0
- package/src/features/auth/hooks/use-reset-password.ts +151 -0
- package/src/features/auth/hooks/use-reset-rate-limit.ts +56 -0
- package/src/features/auth/hooks/use-self-registration.ts +202 -0
- package/src/features/auth/hooks/use-session.ts +81 -0
- package/src/features/auth/hooks/use-sessions.ts +59 -0
- package/src/features/auth/hooks/use-sign-in.ts +234 -0
- package/src/features/auth/hooks/use-sign-out.ts +88 -0
- package/src/features/auth/hooks/use-sign-up.ts +194 -0
- package/src/features/auth/hooks/use-unlink-account.ts +100 -0
- package/src/features/auth/hooks/use-verify-email-token.ts +125 -0
- package/src/features/auth/index.ts +75 -0
- package/src/features/auth/screens/forgot-password-screen.tsx +33 -0
- package/src/features/auth/screens/index.ts +7 -0
- package/src/features/auth/screens/onboarding-screen.tsx +49 -0
- package/src/features/auth/screens/reset-password-screen.tsx +33 -0
- package/src/features/auth/screens/sign-in-screen.tsx +61 -0
- package/src/features/auth/screens/sign-up-screen.tsx +37 -0
- package/src/features/auth/screens/verify-email-confirm-screen.tsx +286 -0
- package/src/features/auth/screens/verify-email-screen.tsx +146 -0
- package/src/features/auth/types/index.ts +14 -0
- package/src/features/auth/utils/__tests__/validators.test.ts +331 -0
- package/src/features/auth/utils/password-strength.ts +129 -0
- package/src/features/auth/utils/validators.ts +124 -0
- package/src/features/email-preview/actions/render-email.ts +21 -0
- package/src/features/email-preview/screens/email-preview-screen.tsx +81 -0
- package/src/features/folder-scaffold-template/index.ts +0 -0
- package/src/features/instance-settings/components/index.ts +6 -0
- package/src/features/instance-settings/components/instance-settings-form.tsx +180 -0
- package/src/features/instance-settings/components/instance-status-display.tsx +158 -0
- package/src/features/instance-settings/index.ts +7 -0
- package/src/features/instance-settings/screens/index.ts +5 -0
- package/src/features/instance-settings/screens/instance-settings-screen.tsx +59 -0
- package/src/features/issues/README.md +330 -0
- package/src/features/issues/api/create-issue.ts +19 -0
- package/src/features/issues/api/delete-issue.ts +27 -0
- package/src/features/issues/api/get-issue-activities.ts +58 -0
- package/src/features/issues/api/get-issue-details.ts +25 -0
- package/src/features/issues/api/get-project-issues-server.ts +44 -0
- package/src/features/issues/api/get-project-issues.ts +21 -0
- package/src/features/issues/api/index.ts +44 -0
- package/src/features/issues/api/update-issue.ts +31 -0
- package/src/features/issues/api/upload-attachment.ts +81 -0
- package/src/features/issues/components/activity-timeline.tsx +440 -0
- package/src/features/issues/components/canvas-state-indicator.tsx +90 -0
- package/src/features/issues/components/centered-canvas-view.tsx +739 -0
- package/src/features/issues/components/image-selector.tsx +123 -0
- package/src/features/issues/components/image-upload-zone.tsx +262 -0
- package/src/features/issues/components/infinite-canvas-background.tsx +163 -0
- package/src/features/issues/components/inline-editable-select.tsx +173 -0
- package/src/features/issues/components/inline-editable-text.tsx +225 -0
- package/src/features/issues/components/inline-editable-textarea.tsx +219 -0
- package/src/features/issues/components/inline-editable-user-select.tsx +202 -0
- package/src/features/issues/components/issue-deletion-dialog.tsx +142 -0
- package/src/features/issues/components/issue-details-panel.tsx +101 -0
- package/src/features/issues/components/issues-create-dialog.tsx +578 -0
- package/src/features/issues/components/issues-list-filter.tsx +312 -0
- package/src/features/issues/components/issues-list.tsx +151 -0
- package/src/features/issues/components/issues-priority-badge.tsx +77 -0
- package/src/features/issues/components/issues-status-badge.tsx +100 -0
- package/src/features/issues/components/metadata-section.tsx +389 -0
- package/src/features/issues/components/optimized-attachment-view.tsx +528 -0
- package/src/features/issues/components/optimized-image.tsx +257 -0
- package/src/features/issues/components/panel-header.tsx +186 -0
- package/src/features/issues/components/preload.ts +31 -0
- package/src/features/issues/components/priority-selector.tsx +101 -0
- package/src/features/issues/components/responsive-issue-layout-skeleton.tsx +139 -0
- package/src/features/issues/components/responsive-issue-layout.tsx +617 -0
- package/src/features/issues/components/status-selector.tsx +320 -0
- package/src/features/issues/components/type-selector.tsx +102 -0
- package/src/features/issues/components/upload-progress-overlay.tsx +35 -0
- package/src/features/issues/components/uploaded-image-preview.tsx +173 -0
- package/src/features/issues/components/workflow-control.tsx +318 -0
- package/src/features/issues/components/zoom-controls.tsx +150 -0
- package/src/features/issues/config/index.ts +47 -0
- package/src/features/issues/config/options.ts +323 -0
- package/src/features/issues/config/workflow.ts +102 -0
- package/src/features/issues/docs/ARCHITECTURE_DIAGRAM.md +321 -0
- package/src/features/issues/docs/BACKEND_ARCHITECTURE.md +194 -0
- package/src/features/issues/docs/IMAGE_COMPONENTS_ARCHITECTURE.md +363 -0
- package/src/features/issues/docs/IMAGE_COMPONENTS_IMPORTS.md +412 -0
- package/src/features/issues/docs/IMPLEMENTATION_CHECKLIST.md +210 -0
- package/src/features/issues/docs/ROUTE_SETUP_COMPLETE.md +242 -0
- package/src/features/issues/hooks/index.ts +78 -0
- package/src/features/issues/hooks/use-canvas-transform.ts +255 -0
- package/src/features/issues/hooks/use-create-issue.ts +28 -0
- package/src/features/issues/hooks/use-elastic-scroll.ts +296 -0
- package/src/features/issues/hooks/use-issue-activities.ts +71 -0
- package/src/features/issues/hooks/use-issue-delete.ts +84 -0
- package/src/features/issues/hooks/use-issue-details.ts +70 -0
- package/src/features/issues/hooks/use-issue-filters.ts +50 -0
- package/src/features/issues/hooks/use-issue-update.ts +93 -0
- package/src/features/issues/hooks/use-keyboard-shortcuts.ts +104 -0
- package/src/features/issues/hooks/use-optimized-image.ts +228 -0
- package/src/features/issues/hooks/use-project-issues.ts +14 -0
- package/src/features/issues/index.ts +65 -0
- package/src/features/issues/screens/issue-details-screen.tsx +207 -0
- package/src/features/issues/screens/issue-details-skeletons.tsx +295 -0
- package/src/features/issues/screens/issue-share-screen.tsx +56 -0
- package/src/features/issues/types/index.ts +48 -0
- package/src/features/issues/types/issue.ts +291 -0
- package/src/features/issues/utils/filter-issues.ts +141 -0
- package/src/features/issues/utils/index.ts +14 -0
- package/src/features/legal/index.ts +1 -0
- package/src/features/legal/screens/privacy-policy-screen.tsx +307 -0
- package/src/features/notifications/api/get-notifications.ts +58 -0
- package/src/features/notifications/api/get-unread-count.ts +37 -0
- package/src/features/notifications/api/index.ts +35 -0
- package/src/features/notifications/api/mark-all-as-read.ts +37 -0
- package/src/features/notifications/api/mark-as-read.ts +41 -0
- package/src/features/notifications/api/types.ts +109 -0
- package/src/features/notifications/hooks/__tests__/use-notification-subscription.test.ts +206 -0
- package/src/features/notifications/hooks/index.ts +28 -0
- package/src/features/notifications/hooks/use-mark-all-as-read.ts +106 -0
- package/src/features/notifications/hooks/use-mark-as-read.ts +106 -0
- package/src/features/notifications/hooks/use-notification-subscription.ts +244 -0
- package/src/features/notifications/hooks/use-notification-toast.ts +161 -0
- package/src/features/notifications/hooks/use-notifications.ts +80 -0
- package/src/features/notifications/hooks/use-unread-count.ts +60 -0
- package/src/features/notifications/index.ts +48 -0
- package/src/features/notifications/utils/group-notifications.ts +152 -0
- package/src/features/notifications/utils/index.ts +9 -0
- package/src/features/projects/api/create-invitation.ts +45 -0
- package/src/features/projects/api/create-project.ts +64 -0
- package/src/features/projects/api/delete-project.ts +50 -0
- package/src/features/projects/api/get-project-activities.ts +43 -0
- package/src/features/projects/api/get-project-members.ts +53 -0
- package/src/features/projects/api/get-project.ts +49 -0
- package/src/features/projects/api/get-projects.ts +61 -0
- package/src/features/projects/api/index.ts +27 -0
- package/src/features/projects/api/join-project.ts +52 -0
- package/src/features/projects/api/leave-project.ts +51 -0
- package/src/features/projects/api/list-invitations.ts +36 -0
- package/src/features/projects/api/remove-member.ts +60 -0
- package/src/features/projects/api/resend-invitation.ts +36 -0
- package/src/features/projects/api/revoke-invitation.ts +36 -0
- package/src/features/projects/api/types.ts +286 -0
- package/src/features/projects/api/update-member-role.ts +70 -0
- package/src/features/projects/api/update-project.ts +69 -0
- package/src/features/projects/components/__tests__/project-detail-activity-feed.test.tsx +106 -0
- package/src/features/projects/components/__tests__/project-invitation-dialog.test.tsx +211 -0
- package/src/features/projects/components/__tests__/project-member-manager-dialog.test.tsx +254 -0
- package/src/features/projects/components/index.ts +21 -0
- package/src/features/projects/components/project-actions.tsx +248 -0
- package/src/features/projects/components/project-create-dialog.tsx +410 -0
- package/src/features/projects/components/project-detail-activity-feed.tsx +206 -0
- package/src/features/projects/components/project-detail-header.tsx +103 -0
- package/src/features/projects/components/project-detail-overview.tsx +128 -0
- package/src/features/projects/components/project-icon-selector.test.tsx +49 -0
- package/src/features/projects/components/project-icon-selector.tsx +76 -0
- package/src/features/projects/components/project-invitation-dialog.tsx +368 -0
- package/src/features/projects/components/project-issues.tsx +128 -0
- package/src/features/projects/components/project-leave-button.tsx +69 -0
- package/src/features/projects/components/project-list-card.tsx +246 -0
- package/src/features/projects/components/project-list-filters.tsx +320 -0
- package/src/features/projects/components/project-member-manager-dialog.tsx +419 -0
- package/src/features/projects/components/project-settings-dialog.tsx +204 -0
- package/src/features/projects/components/project-stats.tsx +46 -0
- package/src/features/projects/components/project-title-section.tsx +78 -0
- package/src/features/projects/config/icons.ts +91 -0
- package/src/features/projects/hooks/index.ts +28 -0
- package/src/features/projects/hooks/use-create-invitation.ts +83 -0
- package/src/features/projects/hooks/use-create-project.ts +77 -0
- package/src/features/projects/hooks/use-delete-project.ts +84 -0
- package/src/features/projects/hooks/use-join-project.ts +43 -0
- package/src/features/projects/hooks/use-leave-project.ts +84 -0
- package/src/features/projects/hooks/use-project-activities.ts +39 -0
- package/src/features/projects/hooks/use-project-filters.ts +86 -0
- package/src/features/projects/hooks/use-project-invitations.ts +66 -0
- package/src/features/projects/hooks/use-project-members.ts +57 -0
- package/src/features/projects/hooks/use-project.ts +67 -0
- package/src/features/projects/hooks/use-projects.ts +49 -0
- package/src/features/projects/hooks/use-recent-projects.ts +58 -0
- package/src/features/projects/hooks/use-remove-member.ts +89 -0
- package/src/features/projects/hooks/use-resend-invitation.ts +68 -0
- package/src/features/projects/hooks/use-revoke-invitation.ts +71 -0
- package/src/features/projects/hooks/use-team-member-suggestions.ts +133 -0
- package/src/features/projects/hooks/use-update-member-role.ts +92 -0
- package/src/features/projects/hooks/use-update-project.ts +88 -0
- package/src/features/projects/index.ts +91 -0
- package/src/features/projects/screens/index.ts +3 -0
- package/src/features/projects/screens/invitation-acceptance-screen.tsx +320 -0
- package/src/features/projects/screens/project-detail-screen-wrapper.tsx +47 -0
- package/src/features/projects/screens/project-detail-screen.tsx +661 -0
- package/src/features/projects/screens/projects-list-screen.tsx +161 -0
- package/src/features/projects/types/index.ts +59 -0
- package/src/features/projects/utils/format-helpers.ts +16 -0
- package/src/features/projects/utils/index.ts +2 -0
- package/src/features/projects/utils/role-helpers.ts +25 -0
- package/src/features/setup/api/complete-setup.ts +21 -0
- package/src/features/setup/api/create-admin.ts +21 -0
- package/src/features/setup/api/create-first-workspace.ts +21 -0
- package/src/features/setup/api/get-instance-status.ts +12 -0
- package/src/features/setup/api/get-service-health.ts +12 -0
- package/src/features/setup/api/index.ts +44 -0
- package/src/features/setup/api/save-instance-config.ts +21 -0
- package/src/features/setup/api/types.ts +122 -0
- package/src/features/setup/components/__tests__/setup-wizard-ui.test.tsx +362 -0
- package/src/features/setup/components/admin-account-step.tsx +205 -0
- package/src/features/setup/components/first-workspace-step.tsx +120 -0
- package/src/features/setup/components/index.ts +9 -0
- package/src/features/setup/components/instance-config-step.tsx +107 -0
- package/src/features/setup/components/mail-config-step.tsx +205 -0
- package/src/features/setup/components/sample-data-step.tsx +131 -0
- package/src/features/setup/components/service-health-step.tsx +180 -0
- package/src/features/setup/components/service-status-badge.tsx +50 -0
- package/src/features/setup/components/setup-progress.tsx +103 -0
- package/src/features/setup/components/setup-wizard.tsx +169 -0
- package/src/features/setup/hooks/index.ts +12 -0
- package/src/features/setup/hooks/use-complete-setup.ts +23 -0
- package/src/features/setup/hooks/use-create-admin.ts +25 -0
- package/src/features/setup/hooks/use-create-first-workspace.ts +24 -0
- package/src/features/setup/hooks/use-instance-status.ts +21 -0
- package/src/features/setup/hooks/use-save-instance-config.ts +23 -0
- package/src/features/setup/hooks/use-service-health.ts +21 -0
- package/src/features/setup/hooks/use-setup-wizard.ts +152 -0
- package/src/features/setup/hooks/use-workspace-mode.ts +19 -0
- package/src/features/setup/index.ts +30 -0
- package/src/features/setup/screens/index.ts +1 -0
- package/src/features/setup/screens/setup-screen.tsx +40 -0
- package/src/features/setup/types/index.ts +69 -0
- package/src/features/setup/utils/index.ts +78 -0
- package/src/features/team-settings/components/index.ts +39 -0
- package/src/features/team-settings/components/loading-states.tsx +296 -0
- package/src/features/team-settings/components/permission-guard.tsx +23 -0
- package/src/features/team-settings/components/settings-card.tsx +22 -0
- package/src/features/team-settings/components/settings-context-provider.tsx +51 -0
- package/src/features/team-settings/components/settings-error-boundary.tsx +366 -0
- package/src/features/team-settings/components/settings-navigation.tsx +87 -0
- package/src/features/team-settings/components/settings-section.tsx +23 -0
- package/src/features/team-settings/components/team-danger-zone.tsx +275 -0
- package/src/features/team-settings/components/team-information-form.tsx +116 -0
- package/src/features/team-settings/components/team-invitations-list.tsx +463 -0
- package/src/features/team-settings/components/team-members-list.tsx +342 -0
- package/src/features/team-settings/components/team-permission-guard.tsx +56 -0
- package/src/features/team-settings/components/team-setting-integrations.tsx +27 -0
- package/src/features/team-settings/components/team-setting-member.tsx +28 -0
- package/src/features/team-settings/components/team-settings-general.tsx +131 -0
- package/src/features/team-settings/components/transfer-ownership-modal.tsx +164 -0
- package/src/features/team-settings/components/unauthorized-access.tsx +52 -0
- package/src/features/team-settings/hooks/__tests__/use-team-settings.test.tsx +139 -0
- package/src/features/team-settings/hooks/index.ts +1 -0
- package/src/features/team-settings/hooks/use-team-settings.ts +148 -0
- package/src/features/team-settings/hooks/use-transfer-ownership.ts +45 -0
- package/src/features/team-settings/index.ts +25 -0
- package/src/features/team-settings/screens/index.ts +1 -0
- package/src/features/team-settings/screens/team-settings-screen.tsx +33 -0
- package/src/features/team-settings/types/index.ts +78 -0
- package/src/features/team-settings/utils/index.ts +6 -0
- package/src/features/team-settings/utils/mock-data.ts +40 -0
- package/src/features/teams/api/cancel-invitation.ts +25 -0
- package/src/features/teams/api/create-invitation.ts +28 -0
- package/src/features/teams/api/create-team.ts +14 -0
- package/src/features/teams/api/delete-team.ts +19 -0
- package/src/features/teams/api/get-invitations.ts +25 -0
- package/src/features/teams/api/get-team-members.ts +25 -0
- package/src/features/teams/api/get-team.ts +13 -0
- package/src/features/teams/api/get-teams.ts +19 -0
- package/src/features/teams/api/index.ts +49 -0
- package/src/features/teams/api/leave-team.ts +22 -0
- package/src/features/teams/api/remove-member.ts +25 -0
- package/src/features/teams/api/resend-invitation.ts +26 -0
- package/src/features/teams/api/switch-team.ts +13 -0
- package/src/features/teams/api/types.ts +122 -0
- package/src/features/teams/api/update-member-roles.ts +28 -0
- package/src/features/teams/api/update-team.ts +17 -0
- package/src/features/teams/components/create-team-dialog.tsx +105 -0
- package/src/features/teams/hooks/__tests__/cache-invalidation.property.test.tsx +268 -0
- package/src/features/teams/hooks/index.ts +35 -0
- package/src/features/teams/hooks/use-can-manage-members.ts +21 -0
- package/src/features/teams/hooks/use-can-manage-team.ts +21 -0
- package/src/features/teams/hooks/use-cancel-invitation.ts +52 -0
- package/src/features/teams/hooks/use-create-invitation.ts +59 -0
- package/src/features/teams/hooks/use-create-team.ts +38 -0
- package/src/features/teams/hooks/use-delete-team.ts +43 -0
- package/src/features/teams/hooks/use-invitations.ts +31 -0
- package/src/features/teams/hooks/use-leave-team.ts +43 -0
- package/src/features/teams/hooks/use-remove-member.ts +58 -0
- package/src/features/teams/hooks/use-resend-invitation.ts +52 -0
- package/src/features/teams/hooks/use-switch-team.ts +41 -0
- package/src/features/teams/hooks/use-team-members.ts +31 -0
- package/src/features/teams/hooks/use-team-permissions.ts +102 -0
- package/src/features/teams/hooks/use-team.ts +30 -0
- package/src/features/teams/hooks/use-teams.ts +26 -0
- package/src/features/teams/hooks/use-update-member-roles.ts +64 -0
- package/src/features/teams/hooks/use-update-team.ts +47 -0
- package/src/features/teams/index.ts +111 -0
- package/src/features/user-settings/actions/set-password.ts +63 -0
- package/src/features/user-settings/api/index.ts +16 -0
- package/src/features/user-settings/components/__tests__/security-settings.test.tsx +125 -0
- package/src/features/user-settings/components/delete-account-dialog.tsx +185 -0
- package/src/features/user-settings/components/index.ts +13 -0
- package/src/features/user-settings/components/integrations-list.tsx +152 -0
- package/src/features/user-settings/components/notification-preferences.tsx +112 -0
- package/src/features/user-settings/components/other-settings.tsx +126 -0
- package/src/features/user-settings/components/password-section.tsx +297 -0
- package/src/features/user-settings/components/security-settings.tsx +184 -0
- package/src/features/user-settings/components/user-preferences.tsx +146 -0
- package/src/features/user-settings/hooks/index.ts +8 -0
- package/src/features/user-settings/hooks/use-notification-preferences.ts +65 -0
- package/src/features/user-settings/hooks/use-user-preferences.ts +52 -0
- package/src/features/user-settings/index.ts +22 -0
- package/src/features/user-settings/screens/index.ts +11 -0
- package/src/features/user-settings/screens/integrations-screen.tsx +24 -0
- package/src/features/user-settings/screens/notifications-screen.tsx +29 -0
- package/src/features/user-settings/screens/other-settings-screen.tsx +24 -0
- package/src/features/user-settings/screens/setting-preferences-screen.tsx +24 -0
- package/src/features/user-settings/screens/user-settings-screen.tsx +23 -0
- package/src/features/user-settings/types/index.ts +42 -0
- package/src/features/user-settings/utils/index.ts +8 -0
- package/src/hooks/use-long-press.ts +196 -0
- package/src/hooks/use-media-upload.ts +95 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/hooks/use-team.ts +32 -0
- package/src/instrumentation.ts +14 -0
- package/src/lib/__tests__/auth-config.test.ts +166 -0
- package/src/lib/__tests__/config.test.ts +42 -0
- package/src/lib/__tests__/db.test.ts +101 -0
- package/src/lib/__tests__/env.property.test.ts +197 -0
- package/src/lib/__tests__/env.test.ts +177 -0
- package/src/lib/__tests__/health-check.test.ts +87 -0
- package/src/lib/__tests__/oauth-errors.test.ts +184 -0
- package/src/lib/__tests__/oauth-redirect.test.ts +224 -0
- package/src/lib/__tests__/oauth-scopes.test.ts +268 -0
- package/src/lib/__tests__/storage.test.ts +58 -0
- package/src/lib/__tests__/url-validator.test.ts +232 -0
- package/src/lib/api-client.ts +93 -0
- package/src/lib/auth-client.ts +5 -0
- package/src/lib/auth-config.ts +146 -0
- package/src/lib/auth.ts +209 -0
- package/src/lib/config.ts +228 -0
- package/src/lib/cors.ts +96 -0
- package/src/lib/date.ts +16 -0
- package/src/lib/db.ts +88 -0
- package/src/lib/env.ts +489 -0
- package/src/lib/feedback.ts +29 -0
- package/src/lib/health-check.ts +229 -0
- package/src/lib/logger.ts +204 -0
- package/src/lib/oauth-errors.ts +138 -0
- package/src/lib/performance.ts +367 -0
- package/src/lib/query-server.ts +35 -0
- package/src/lib/query.tsx +43 -0
- package/src/lib/resend.ts +36 -0
- package/src/lib/security-headers.ts +165 -0
- package/src/lib/setup-status.ts +34 -0
- package/src/lib/storage.ts +150 -0
- package/src/lib/supabase-client.ts +58 -0
- package/src/lib/testing/test-db.ts +75 -0
- package/src/lib/url-validator.ts +168 -0
- package/src/lib/utils.ts +6 -0
- package/src/mocks/README.md +42 -0
- package/src/mocks/activity.fixtures.ts +281 -0
- package/src/mocks/annotation.fixtures.ts +325 -0
- package/src/mocks/attachment.fixtures.ts +80 -0
- package/src/mocks/email.fixtures.ts +61 -0
- package/src/mocks/index.ts +33 -0
- package/src/mocks/issue.fixtures.ts +364 -0
- package/src/mocks/landing.fixtures.ts +118 -0
- package/src/mocks/notification.fixtures.ts +111 -0
- package/src/mocks/project-activity.fixtures.ts +69 -0
- package/src/mocks/project-invitation.fixtures.ts +95 -0
- package/src/mocks/project-member.fixtures.ts +93 -0
- package/src/mocks/project.fixtures.ts +249 -0
- package/src/mocks/settings.fixtures.ts +56 -0
- package/src/mocks/share.fixtures.ts +48 -0
- package/src/mocks/team-member.fixtures.ts +147 -0
- package/src/mocks/team.fixtures.ts +35 -0
- package/src/mocks/user-settings.fixtures.ts +77 -0
- package/src/mocks/user.fixtures.ts +21 -0
- package/src/providers/theme-provider.tsx +11 -0
- package/src/proxy/__tests__/proxy-setup-gate.test.ts +43 -0
- package/src/proxy.ts +169 -0
- package/src/server/annotations/__tests__/annotation-limit.property.test.ts +291 -0
- package/src/server/annotations/__tests__/attachment-deletion-cascade.property.test.ts +385 -0
- package/src/server/annotations/__tests__/comment-delete-authorization.property.test.ts +419 -0
- package/src/server/annotations/__tests__/sanitize.property.test.ts +302 -0
- package/src/server/annotations/annotation-service.ts +305 -0
- package/src/server/annotations/comment-service.ts +288 -0
- package/src/server/annotations/index.ts +61 -0
- package/src/server/annotations/permission-utils.ts +125 -0
- package/src/server/annotations/sanitize.ts +134 -0
- package/src/server/annotations/types.ts +161 -0
- package/src/server/audit/audit-service.ts +85 -0
- package/src/server/audit/index.ts +11 -0
- package/src/server/audit/types.ts +75 -0
- package/src/server/auth/__tests__/README.md +368 -0
- package/src/server/auth/__tests__/account-linking.integration.test.ts +410 -0
- package/src/server/auth/__tests__/auth-integration.test.ts +811 -0
- package/src/server/auth/__tests__/cookies.test.ts +337 -0
- package/src/server/auth/__tests__/login.property.test.ts +428 -0
- package/src/server/auth/__tests__/oauth-integration.test.ts +555 -0
- package/src/server/auth/__tests__/password.test.ts +194 -0
- package/src/server/auth/__tests__/rate-limiter.test.ts +450 -0
- package/src/server/auth/__tests__/rbac.test.ts +474 -0
- package/src/server/auth/__tests__/session.test.ts +599 -0
- package/src/server/auth/__tests__/signup.property.test.ts +224 -0
- package/src/server/auth/__tests__/token-encryption.test.ts +171 -0
- package/src/server/auth/__tests__/tokens.test.ts +476 -0
- package/src/server/auth/__tests__/verify-email.property.test.ts +372 -0
- package/src/server/auth/cookies.ts +184 -0
- package/src/server/auth/password.ts +94 -0
- package/src/server/auth/rate-limiter.ts +257 -0
- package/src/server/auth/rbac.ts +1168 -0
- package/src/server/auth/session.ts +392 -0
- package/src/server/auth/token-encryption.ts +201 -0
- package/src/server/auth/tokens.ts +397 -0
- package/src/server/db/schema/account.ts +21 -0
- package/src/server/db/schema/annotation-read-status.ts +57 -0
- package/src/server/db/schema/better-auth-verifications.ts +27 -0
- package/src/server/db/schema/email-jobs.ts +24 -0
- package/src/server/db/schema/index.ts +20 -0
- package/src/server/db/schema/instance-settings.ts +42 -0
- package/src/server/db/schema/issue-activities.ts +97 -0
- package/src/server/db/schema/issue-attachments.ts +101 -0
- package/src/server/db/schema/issues.ts +139 -0
- package/src/server/db/schema/notifications.ts +119 -0
- package/src/server/db/schema/project-activities.ts +116 -0
- package/src/server/db/schema/project-invitations.ts +34 -0
- package/src/server/db/schema/project-members.ts +29 -0
- package/src/server/db/schema/projects.ts +46 -0
- package/src/server/db/schema/sessions.ts +17 -0
- package/src/server/db/schema/team-invitations.ts +22 -0
- package/src/server/db/schema/team-members.ts +18 -0
- package/src/server/db/schema/teams.ts +15 -0
- package/src/server/db/schema/user-roles.ts +14 -0
- package/src/server/db/schema/users.ts +17 -0
- package/src/server/db/schema/verification-tokens.ts +15 -0
- package/src/server/email/README.md +258 -0
- package/src/server/email/__tests__/client.property.test.ts +218 -0
- package/src/server/email/__tests__/payload.property.test.ts +205 -0
- package/src/server/email/__tests__/queue.test.ts +407 -0
- package/src/server/email/__tests__/render-template.test.tsx +172 -0
- package/src/server/email/client.ts +70 -0
- package/src/server/email/index.ts +20 -0
- package/src/server/email/providers/console-provider.ts +43 -0
- package/src/server/email/providers/index.ts +5 -0
- package/src/server/email/providers/resend-provider.ts +59 -0
- package/src/server/email/providers/smtp-provider.ts +65 -0
- package/src/server/email/queue.ts +365 -0
- package/src/server/email/render-template.tsx +117 -0
- package/src/server/email/templates/layout.tsx +66 -0
- package/src/server/email/templates/ownership-transfer-email.tsx +75 -0
- package/src/server/email/templates/password-reset-email.tsx +72 -0
- package/src/server/email/templates/project-invitation-email.tsx +70 -0
- package/src/server/email/templates/security-alert-email.tsx +161 -0
- package/src/server/email/templates/team-invitation-email.tsx +68 -0
- package/src/server/email/templates/verification-email.tsx +61 -0
- package/src/server/email/templates/welcome-email.tsx +60 -0
- package/src/server/email/worker.ts +182 -0
- package/src/server/issues/activity-service.ts +422 -0
- package/src/server/issues/attachment-service.ts +379 -0
- package/src/server/issues/index.ts +68 -0
- package/src/server/issues/issue-service.ts +569 -0
- package/src/server/issues/types.ts +233 -0
- package/src/server/notifications/__tests__/notification-service.integration.test.ts +405 -0
- package/src/server/notifications/index.ts +13 -0
- package/src/server/notifications/notification-service.ts +526 -0
- package/src/server/notifications/types.ts +234 -0
- package/src/server/projects/__tests__/activity-logging.integration.test.ts +319 -0
- package/src/server/projects/__tests__/invitation-email.integration.test.ts +258 -0
- package/src/server/projects/__tests__/invitation-service.integration.test.ts +651 -0
- package/src/server/projects/__tests__/member-service.property.test.ts +397 -0
- package/src/server/projects/__tests__/project-service.property.test.ts +116 -0
- package/src/server/projects/activity-service.ts +548 -0
- package/src/server/projects/index.ts +11 -0
- package/src/server/projects/invitation-service.ts +773 -0
- package/src/server/projects/member-service.ts +458 -0
- package/src/server/projects/project-service.ts +491 -0
- package/src/server/projects/schemas.ts +310 -0
- package/src/server/projects/types.ts +166 -0
- package/src/server/projects/utils.ts +128 -0
- package/src/server/setup/__tests__/health-check.property.test.ts +70 -0
- package/src/server/setup/__tests__/sample-data.property.test.ts +82 -0
- package/src/server/setup/__tests__/setup.property.test.ts +95 -0
- package/src/server/setup/health-check-service.ts +294 -0
- package/src/server/setup/index.ts +35 -0
- package/src/server/setup/sample-data-service.ts +233 -0
- package/src/server/setup/setup-service.ts +229 -0
- package/src/server/setup/types.ts +96 -0
- package/src/server/teams/__tests__/export.property.test.ts +542 -0
- package/src/server/teams/__tests__/get-members.integration.test.ts +105 -0
- package/src/server/teams/__tests__/invitation-flow.integration.test.ts +402 -0
- package/src/server/teams/__tests__/invitations.property.test.ts +235 -0
- package/src/server/teams/__tests__/member-management-flow.integration.test.ts +306 -0
- package/src/server/teams/__tests__/members.property.test.ts +180 -0
- package/src/server/teams/__tests__/ownership-transfer.property.test.ts +173 -0
- package/src/server/teams/__tests__/resource-limits.property.test.ts +382 -0
- package/src/server/teams/__tests__/team-context-management.integration.test.ts +396 -0
- package/src/server/teams/__tests__/team-context.property.test.ts +854 -0
- package/src/server/teams/__tests__/team-creation-flow.integration.test.ts +310 -0
- package/src/server/teams/__tests__/team-creation.property.test.ts +280 -0
- package/src/server/teams/errors.ts +396 -0
- package/src/server/teams/export-service.ts +383 -0
- package/src/server/teams/index.ts +10 -0
- package/src/server/teams/invitation-service.ts +708 -0
- package/src/server/teams/member-service.ts +334 -0
- package/src/server/teams/resource-limits.ts +211 -0
- package/src/server/teams/slug.ts +58 -0
- package/src/server/teams/team-context.ts +648 -0
- package/src/server/teams/team-service.ts +660 -0
- package/src/server/teams/types.ts +81 -0
- package/src/server/teams/validation.ts +209 -0
- package/src/styles/globals.css +160 -0
- package/src/types/deployment.ts +39 -0
- package/supabase/config.toml +357 -0
- package/supabase/seed.sql +480 -0
- package/tests/e2e/.gitkeep +0 -0
- package/tests/e2e/QUICK_START.md +98 -0
- package/tests/e2e/README.md +301 -0
- package/tests/e2e/auth.spec.ts +583 -0
- package/tests/e2e/global-setup.ts +23 -0
- package/tests/e2e/global-teardown.ts +23 -0
- package/tests/e2e/helpers/auth-helpers.ts +310 -0
- package/tests/e2e/helpers/test-fixtures.ts +286 -0
- package/tests/e2e/smoke-test.spec.ts +330 -0
- package/tsconfig.json +48 -0
- package/vitest.config.ts +50 -0
- package/vitest.setup.ts +56 -0
- package/dist/index.js +0 -778
|
@@ -0,0 +1,1779 @@
|
|
|
1
|
+
# Drizzle Database Commands Explained
|
|
2
|
+
|
|
3
|
+
This guide explains the difference between `db:generate`, `db:migrate`, and `db:push` commands in Drizzle ORM and when to use each one.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Quick Reference](#quick-reference)
|
|
8
|
+
- [Command Details](#command-details)
|
|
9
|
+
- [db:generate](#dbgenerate)
|
|
10
|
+
- [db:migrate](#dbmigrate)
|
|
11
|
+
- [db:push](#dbpush)
|
|
12
|
+
- [Visual Comparison](#visual-comparison)
|
|
13
|
+
- [When to Use Each Command](#when-to-use-each-command)
|
|
14
|
+
- [Real-World Scenarios](#real-world-scenarios)
|
|
15
|
+
- [Common Mistakes](#common-mistakes)
|
|
16
|
+
- [Best Practices](#best-practices)
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Quick Reference
|
|
21
|
+
|
|
22
|
+
| Command | Creates Files? | Applies to DB? | Use Case | Commit to Git? |
|
|
23
|
+
|---------|---------------|----------------|----------|----------------|
|
|
24
|
+
| `bun run db:generate` | ✅ Yes (SQL) | ❌ No | Create migration files from schema changes | ✅ Yes |
|
|
25
|
+
| `bun run db:migrate` | ❌ No | ✅ Yes | Apply migration files to database | N/A |
|
|
26
|
+
| `bun run db:push` | ❌ No | ✅ Yes | Quick sync schema to database (prototyping) | ❌ No |
|
|
27
|
+
|
|
28
|
+
**TL;DR:**
|
|
29
|
+
- **`generate`** = Convert TypeScript schema → SQL files
|
|
30
|
+
- **`migrate`** = Run SQL files → Database
|
|
31
|
+
- **`push`** = Sync TypeScript schema → Database (no files)
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Command Details
|
|
36
|
+
|
|
37
|
+
### `db:generate`
|
|
38
|
+
|
|
39
|
+
**What it does:** Creates migration SQL files from your schema changes
|
|
40
|
+
|
|
41
|
+
**Command:**
|
|
42
|
+
```bash
|
|
43
|
+
bun run db:generate
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**When to use:** After you modify your Drizzle schema files in `src/server/db/schema/`
|
|
47
|
+
|
|
48
|
+
**Workflow:**
|
|
49
|
+
```typescript
|
|
50
|
+
// 1. Edit your schema
|
|
51
|
+
// src/server/db/schema/users.ts
|
|
52
|
+
export const users = pgTable('users', {
|
|
53
|
+
id: uuid('id').primaryKey(),
|
|
54
|
+
name: text('name').notNull(),
|
|
55
|
+
email: text('email').notNull().unique(),
|
|
56
|
+
// Add a new column:
|
|
57
|
+
avatar: text('avatar'), // ← NEW
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// 2. Run generate
|
|
61
|
+
// $ bun run db:generate
|
|
62
|
+
// Drizzle asks: "What should we name this migration?"
|
|
63
|
+
// You type: "add_avatar_column"
|
|
64
|
+
|
|
65
|
+
// 3. Drizzle creates a new migration file
|
|
66
|
+
// drizzle/0002_add_avatar_column.sql
|
|
67
|
+
// ALTER TABLE "users" ADD COLUMN "avatar" text;
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
**Output:**
|
|
71
|
+
- Creates a new SQL file in `drizzle/` directory
|
|
72
|
+
- File naming: `XXXX_description.sql` (e.g., `0002_add_avatar_column.sql`)
|
|
73
|
+
- Contains SQL statements to transform database from previous state to new state
|
|
74
|
+
|
|
75
|
+
**Think of it as:** "Convert my TypeScript schema changes into SQL migration files"
|
|
76
|
+
|
|
77
|
+
**Example output:**
|
|
78
|
+
```bash
|
|
79
|
+
$ bun run db:generate
|
|
80
|
+
|
|
81
|
+
drizzle-kit: v0.31.7
|
|
82
|
+
drizzle-orm: v0.44.7
|
|
83
|
+
|
|
84
|
+
No config path provided, using default 'drizzle.config.ts'
|
|
85
|
+
Reading config file '/path/to/project/drizzle.config.ts'
|
|
86
|
+
|
|
87
|
+
? Migration name (leave blank to use timestamp): › add_avatar_column
|
|
88
|
+
|
|
89
|
+
✔ Generated migration file: drizzle/0002_add_avatar_column.sql
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
### `db:migrate`
|
|
95
|
+
|
|
96
|
+
**What it does:** Executes migration SQL files against your database
|
|
97
|
+
|
|
98
|
+
**Command:**
|
|
99
|
+
```bash
|
|
100
|
+
bun run db:migrate
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**When to use:** After generating migrations, to apply them to your database
|
|
104
|
+
|
|
105
|
+
**Workflow:**
|
|
106
|
+
```bash
|
|
107
|
+
# 1. You have migration files in drizzle/
|
|
108
|
+
# drizzle/0000_initial_schema.sql
|
|
109
|
+
# drizzle/0001_add_teams.sql
|
|
110
|
+
# drizzle/0002_add_avatar_column.sql
|
|
111
|
+
|
|
112
|
+
# 2. Run migrate
|
|
113
|
+
$ bun run db:migrate
|
|
114
|
+
|
|
115
|
+
# 3. Drizzle:
|
|
116
|
+
# - Reads all .sql files in drizzle/
|
|
117
|
+
# - Checks which ones are already applied (stored in drizzle.__drizzle_migrations table)
|
|
118
|
+
# - Runs only the new ones in order
|
|
119
|
+
# - Records them as applied
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Output:**
|
|
123
|
+
- Executes SQL against your database
|
|
124
|
+
- Creates/updates `drizzle.__drizzle_migrations` table to track applied migrations
|
|
125
|
+
- Your database schema now matches your TypeScript schema
|
|
126
|
+
|
|
127
|
+
**Think of it as:** "Run the SQL migration files against my database"
|
|
128
|
+
|
|
129
|
+
**Example output:**
|
|
130
|
+
```bash
|
|
131
|
+
$ bun run db:migrate
|
|
132
|
+
|
|
133
|
+
drizzle-kit: v0.31.7
|
|
134
|
+
drizzle-orm: v0.44.7
|
|
135
|
+
|
|
136
|
+
No config path provided, using default 'drizzle.config.ts'
|
|
137
|
+
Reading config file '/path/to/project/drizzle.config.ts'
|
|
138
|
+
|
|
139
|
+
Applying migrations...
|
|
140
|
+
✔ 0002_add_avatar_column.sql applied successfully
|
|
141
|
+
|
|
142
|
+
All migrations applied successfully!
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
**Migration tracking table:**
|
|
146
|
+
```sql
|
|
147
|
+
-- Drizzle creates this table automatically
|
|
148
|
+
CREATE TABLE drizzle.__drizzle_migrations (
|
|
149
|
+
id SERIAL PRIMARY KEY,
|
|
150
|
+
hash TEXT NOT NULL,
|
|
151
|
+
created_at BIGINT
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
-- Example data
|
|
155
|
+
SELECT * FROM drizzle.__drizzle_migrations;
|
|
156
|
+
-- id | hash | created_at
|
|
157
|
+
-- 1 | 0000_initial_schema | 1704067200000
|
|
158
|
+
-- 2 | 0001_add_teams | 1704153600000
|
|
159
|
+
-- 3 | 0002_add_avatar_column | 1704240000000
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
### `db:push`
|
|
165
|
+
|
|
166
|
+
**What it does:** Directly syncs your TypeScript schema to the database WITHOUT creating migration files
|
|
167
|
+
|
|
168
|
+
**Command:**
|
|
169
|
+
```bash
|
|
170
|
+
bun run db:push
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**When to use:** During rapid prototyping or local development when you don't care about migration history
|
|
174
|
+
|
|
175
|
+
**Workflow:**
|
|
176
|
+
```typescript
|
|
177
|
+
// 1. Edit your schema
|
|
178
|
+
export const users = pgTable('users', {
|
|
179
|
+
id: uuid('id').primaryKey(),
|
|
180
|
+
name: text('name').notNull(),
|
|
181
|
+
email: text('email').notNull().unique(),
|
|
182
|
+
avatar: text('avatar'), // ← NEW
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
// 2. Run push (skips generate step)
|
|
186
|
+
$ bun run db:push
|
|
187
|
+
|
|
188
|
+
// 3. Drizzle:
|
|
189
|
+
# - Compares your TypeScript schema to actual database
|
|
190
|
+
# - Generates SQL on-the-fly
|
|
191
|
+
# - Applies changes immediately
|
|
192
|
+
# - NO migration file created
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Output:**
|
|
196
|
+
- Database schema updated immediately
|
|
197
|
+
- No migration files created
|
|
198
|
+
- No migration history tracked
|
|
199
|
+
- Changes are applied directly
|
|
200
|
+
|
|
201
|
+
**Think of it as:** "Just make my database match my schema right now, I don't need migration files"
|
|
202
|
+
|
|
203
|
+
**Example output:**
|
|
204
|
+
```bash
|
|
205
|
+
$ bun run db:push
|
|
206
|
+
|
|
207
|
+
drizzle-kit: v0.31.7
|
|
208
|
+
drizzle-orm: v0.44.7
|
|
209
|
+
|
|
210
|
+
No config path provided, using default 'drizzle.config.ts'
|
|
211
|
+
Reading config file '/path/to/project/drizzle.config.ts'
|
|
212
|
+
|
|
213
|
+
Pulling schema from database...
|
|
214
|
+
Comparing schemas...
|
|
215
|
+
|
|
216
|
+
Changes to be applied:
|
|
217
|
+
ALTER TABLE "users" ADD COLUMN "avatar" text;
|
|
218
|
+
|
|
219
|
+
? Do you want to apply these changes? › (Y/n)
|
|
220
|
+
|
|
221
|
+
✔ Changes applied successfully!
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Visual Comparison
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
230
|
+
│ DEVELOPMENT WORKFLOW │
|
|
231
|
+
└─────────────────────────────────────────────────────────────┘
|
|
232
|
+
|
|
233
|
+
Option 1: PRODUCTION-READY (with migration history)
|
|
234
|
+
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
|
235
|
+
│ Edit Schema │ → │ db:generate │ → │ db:migrate │
|
|
236
|
+
│ (TypeScript) │ │ (Create SQL) │ │ (Run SQL) │
|
|
237
|
+
└──────────────┘ └──────────────┘ └──────────────┘
|
|
238
|
+
↓
|
|
239
|
+
drizzle/0002_xxx.sql
|
|
240
|
+
(Committed to Git)
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
Option 2: RAPID PROTOTYPING (no migration history)
|
|
244
|
+
┌──────────────┐ ┌──────────────┐
|
|
245
|
+
│ Edit Schema │ → │ db:push │
|
|
246
|
+
│ (TypeScript) │ │ (Sync Now) │
|
|
247
|
+
└──────────────┘ └──────────────┘
|
|
248
|
+
(No files created)
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
---
|
|
252
|
+
|
|
253
|
+
## When to Use Each Command
|
|
254
|
+
|
|
255
|
+
### Use `db:generate` + `db:migrate` when:
|
|
256
|
+
|
|
257
|
+
✅ Working on production code
|
|
258
|
+
✅ Need to track schema changes over time
|
|
259
|
+
✅ Working in a team (others need to apply your changes)
|
|
260
|
+
✅ Want to review SQL before applying
|
|
261
|
+
✅ Need rollback capability
|
|
262
|
+
✅ Deploying to staging/production
|
|
263
|
+
✅ Want to maintain migration history
|
|
264
|
+
✅ Need to audit schema changes
|
|
265
|
+
|
|
266
|
+
**Example workflow:**
|
|
267
|
+
```bash
|
|
268
|
+
# 1. Edit schema
|
|
269
|
+
vim src/server/db/schema/users.ts
|
|
270
|
+
|
|
271
|
+
# 2. Generate migration
|
|
272
|
+
bun run db:generate
|
|
273
|
+
# Drizzle asks: "What should we name this migration?"
|
|
274
|
+
# You type: "add_avatar_column"
|
|
275
|
+
|
|
276
|
+
# 3. Review the generated SQL
|
|
277
|
+
cat drizzle/0002_add_avatar_column.sql
|
|
278
|
+
|
|
279
|
+
# 4. Apply to local database
|
|
280
|
+
bun run db:migrate
|
|
281
|
+
|
|
282
|
+
# 5. Test your changes
|
|
283
|
+
bun dev
|
|
284
|
+
|
|
285
|
+
# 6. Commit migration file
|
|
286
|
+
git add drizzle/0002_add_avatar_column.sql
|
|
287
|
+
git add src/server/db/schema/users.ts
|
|
288
|
+
git commit -m "feat: add avatar column to users"
|
|
289
|
+
|
|
290
|
+
# 7. Push to remote
|
|
291
|
+
git push
|
|
292
|
+
|
|
293
|
+
# 8. Teammate pulls and runs
|
|
294
|
+
git pull
|
|
295
|
+
bun run db:migrate # ← Applies your migration to their database
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
---
|
|
299
|
+
|
|
300
|
+
### Use `db:push` when:
|
|
301
|
+
|
|
302
|
+
✅ Rapid prototyping / experimenting
|
|
303
|
+
✅ Local development only
|
|
304
|
+
✅ Don't care about migration history
|
|
305
|
+
✅ Want quick feedback loop
|
|
306
|
+
✅ Schema is still in flux
|
|
307
|
+
✅ Testing different schema designs
|
|
308
|
+
✅ Throwaway experiments
|
|
309
|
+
|
|
310
|
+
**Example workflow:**
|
|
311
|
+
```bash
|
|
312
|
+
# Rapid iteration cycle
|
|
313
|
+
vim src/server/db/schema/users.ts # Add column
|
|
314
|
+
bun run db:push # Apply immediately
|
|
315
|
+
bun dev # Test
|
|
316
|
+
|
|
317
|
+
vim src/server/db/schema/users.ts # Change column type
|
|
318
|
+
bun run db:push # Apply immediately
|
|
319
|
+
bun dev # Test
|
|
320
|
+
|
|
321
|
+
vim src/server/db/schema/users.ts # Remove column
|
|
322
|
+
bun run db:push # Apply immediately
|
|
323
|
+
bun dev # Test
|
|
324
|
+
|
|
325
|
+
# Once happy with schema, switch to generate + migrate
|
|
326
|
+
bun run db:generate # Create migration file
|
|
327
|
+
git add drizzle/0002_final_schema.sql
|
|
328
|
+
git commit -m "feat: finalize user schema"
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Real-World Scenarios
|
|
334
|
+
|
|
335
|
+
### Scenario 1: Adding a new feature (Production-ready)
|
|
336
|
+
|
|
337
|
+
**Goal:** Add a new `projects` table to the database
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
# 1. Create new table in schema
|
|
341
|
+
cat > src/server/db/schema/projects.ts << 'EOF'
|
|
342
|
+
import { pgTable, uuid, text, timestamp } from 'drizzle-orm/pg-core'
|
|
343
|
+
import { teams } from './teams'
|
|
344
|
+
|
|
345
|
+
export const projects = pgTable('projects', {
|
|
346
|
+
id: uuid('id').primaryKey().defaultRandom(),
|
|
347
|
+
name: text('name').notNull(),
|
|
348
|
+
teamId: uuid('team_id').notNull().references(() => teams.id),
|
|
349
|
+
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
350
|
+
})
|
|
351
|
+
EOF
|
|
352
|
+
|
|
353
|
+
# 2. Generate migration
|
|
354
|
+
bun run db:generate
|
|
355
|
+
# Name: "create_projects_table"
|
|
356
|
+
|
|
357
|
+
# 3. Review SQL
|
|
358
|
+
cat drizzle/0003_create_projects_table.sql
|
|
359
|
+
# CREATE TABLE "projects" (
|
|
360
|
+
# "id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
361
|
+
# "name" text NOT NULL,
|
|
362
|
+
# "team_id" uuid NOT NULL REFERENCES "teams"("id"),
|
|
363
|
+
# "created_at" timestamp DEFAULT now() NOT NULL
|
|
364
|
+
# );
|
|
365
|
+
|
|
366
|
+
# 4. Apply locally
|
|
367
|
+
bun run db:migrate
|
|
368
|
+
|
|
369
|
+
# 5. Test
|
|
370
|
+
bun dev
|
|
371
|
+
|
|
372
|
+
# 6. Commit
|
|
373
|
+
git add drizzle/0003_create_projects_table.sql
|
|
374
|
+
git add src/server/db/schema/projects.ts
|
|
375
|
+
git commit -m "feat: add projects table"
|
|
376
|
+
|
|
377
|
+
# 7. Deploy to production
|
|
378
|
+
git push origin main
|
|
379
|
+
# In production:
|
|
380
|
+
DATABASE_URL=$PROD_URL bun run db:migrate
|
|
381
|
+
```
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
### Scenario 2: Experimenting with schema (Prototyping)
|
|
386
|
+
|
|
387
|
+
**Goal:** Try different schema designs quickly
|
|
388
|
+
|
|
389
|
+
```bash
|
|
390
|
+
# Quick iteration without migration files
|
|
391
|
+
vim src/server/db/schema/experiments.ts
|
|
392
|
+
# Add table with some columns
|
|
393
|
+
bun run db:push # Instant sync
|
|
394
|
+
|
|
395
|
+
# Try different column types
|
|
396
|
+
vim src/server/db/schema/experiments.ts
|
|
397
|
+
# Change text to varchar(255)
|
|
398
|
+
bun run db:push # Instant sync
|
|
399
|
+
|
|
400
|
+
# Add indexes
|
|
401
|
+
vim src/server/db/schema/experiments.ts
|
|
402
|
+
# Add index on email column
|
|
403
|
+
bun run db:push # Instant sync
|
|
404
|
+
|
|
405
|
+
# Add relations
|
|
406
|
+
vim src/server/db/schema/experiments.ts
|
|
407
|
+
# Add foreign key to users
|
|
408
|
+
bun run db:push # Instant sync
|
|
409
|
+
|
|
410
|
+
# Once satisfied, create proper migration
|
|
411
|
+
bun run db:generate
|
|
412
|
+
# Name: "create_experiments_table"
|
|
413
|
+
bun run db:migrate
|
|
414
|
+
git add drizzle/0004_create_experiments_table.sql
|
|
415
|
+
git commit -m "feat: add experiments table"
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
---
|
|
419
|
+
|
|
420
|
+
### Scenario 3: Team collaboration
|
|
421
|
+
|
|
422
|
+
**Goal:** Share schema changes with team members
|
|
423
|
+
|
|
424
|
+
**Developer A:**
|
|
425
|
+
```bash
|
|
426
|
+
# 1. Add new column
|
|
427
|
+
vim src/server/db/schema/users.ts
|
|
428
|
+
# Add: role: text('role').notNull().default('member')
|
|
429
|
+
|
|
430
|
+
# 2. Generate migration
|
|
431
|
+
bun run db:generate
|
|
432
|
+
# Name: "add_role_column"
|
|
433
|
+
|
|
434
|
+
# 3. Apply locally
|
|
435
|
+
bun run db:migrate
|
|
436
|
+
|
|
437
|
+
# 4. Test
|
|
438
|
+
bun dev
|
|
439
|
+
|
|
440
|
+
# 5. Commit and push
|
|
441
|
+
git add drizzle/0005_add_role_column.sql
|
|
442
|
+
git add src/server/db/schema/users.ts
|
|
443
|
+
git commit -m "feat: add role column to users"
|
|
444
|
+
git push
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
**Developer B:**
|
|
448
|
+
```bash
|
|
449
|
+
# 1. Pull changes
|
|
450
|
+
git pull
|
|
451
|
+
|
|
452
|
+
# 2. Apply migration to local database
|
|
453
|
+
bun run db:migrate
|
|
454
|
+
# ✅ Database now has role column
|
|
455
|
+
|
|
456
|
+
# 3. Continue development
|
|
457
|
+
bun dev
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
### Scenario 4: Fixing a production issue
|
|
463
|
+
|
|
464
|
+
**Goal:** Add missing index to improve query performance
|
|
465
|
+
|
|
466
|
+
```bash
|
|
467
|
+
# 1. Add index to schema
|
|
468
|
+
vim src/server/db/schema/issues.ts
|
|
469
|
+
# Add: index('idx_issues_status').on(issues.status)
|
|
470
|
+
|
|
471
|
+
# 2. Generate migration
|
|
472
|
+
bun run db:generate
|
|
473
|
+
# Name: "add_status_index"
|
|
474
|
+
|
|
475
|
+
# 3. Review SQL (important for production!)
|
|
476
|
+
cat drizzle/0006_add_status_index.sql
|
|
477
|
+
# CREATE INDEX "idx_issues_status" ON "issues" ("status");
|
|
478
|
+
|
|
479
|
+
# 4. Test locally
|
|
480
|
+
bun run db:migrate
|
|
481
|
+
bun dev
|
|
482
|
+
|
|
483
|
+
# 5. Commit
|
|
484
|
+
git add drizzle/0006_add_status_index.sql
|
|
485
|
+
git add src/server/db/schema/issues.ts
|
|
486
|
+
git commit -m "perf: add index on issues.status"
|
|
487
|
+
git push
|
|
488
|
+
|
|
489
|
+
# 6. Deploy to production
|
|
490
|
+
# (After code deployment)
|
|
491
|
+
DATABASE_URL=$PROD_URL bun run db:migrate
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
---
|
|
495
|
+
|
|
496
|
+
### Scenario 5: Resetting local database
|
|
497
|
+
|
|
498
|
+
**Goal:** Start fresh with a clean database
|
|
499
|
+
|
|
500
|
+
```bash
|
|
501
|
+
# Option 1: Using Supabase (recommended)
|
|
502
|
+
npx supabase stop
|
|
503
|
+
npx supabase start
|
|
504
|
+
bun run db:migrate # Apply all migrations
|
|
505
|
+
|
|
506
|
+
# Option 2: Using db:push (quick but no history)
|
|
507
|
+
# Drop all tables manually or via SQL
|
|
508
|
+
psql $DATABASE_URL -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
|
|
509
|
+
bun run db:push # Recreate schema
|
|
510
|
+
|
|
511
|
+
# Option 3: Using migrations (proper way)
|
|
512
|
+
# Drop all tables manually
|
|
513
|
+
psql $DATABASE_URL -c "DROP SCHEMA public CASCADE; CREATE SCHEMA public;"
|
|
514
|
+
bun run db:migrate # Apply all migrations in order
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
## Common Mistakes
|
|
520
|
+
|
|
521
|
+
### ❌ Mistake 1: Using `db:push` in production
|
|
522
|
+
|
|
523
|
+
**Don't do this:**
|
|
524
|
+
```bash
|
|
525
|
+
# DON'T DO THIS IN PRODUCTION
|
|
526
|
+
DATABASE_URL=$PROD_URL bun run db:push
|
|
527
|
+
```
|
|
528
|
+
|
|
529
|
+
**Why it's bad:**
|
|
530
|
+
- No migration history
|
|
531
|
+
- Can't rollback changes
|
|
532
|
+
- Team can't reproduce changes
|
|
533
|
+
- No audit trail
|
|
534
|
+
- Risky for production data
|
|
535
|
+
|
|
536
|
+
**Do this instead:**
|
|
537
|
+
```bash
|
|
538
|
+
# Proper production workflow
|
|
539
|
+
bun run db:generate
|
|
540
|
+
bun run db:migrate # Test locally first
|
|
541
|
+
DATABASE_URL=$PROD_URL bun run db:migrate # Then production
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
---
|
|
545
|
+
|
|
546
|
+
### ❌ Mistake 2: Forgetting to commit migration files
|
|
547
|
+
|
|
548
|
+
**Don't do this:**
|
|
549
|
+
```bash
|
|
550
|
+
bun run db:generate
|
|
551
|
+
bun run db:migrate
|
|
552
|
+
git add src/server/db/schema/users.ts
|
|
553
|
+
git commit -m "feat: add column" # ← Forgot drizzle/*.sql
|
|
554
|
+
git push
|
|
555
|
+
```
|
|
556
|
+
|
|
557
|
+
**Why it's bad:**
|
|
558
|
+
- Teammates can't apply your schema changes
|
|
559
|
+
- Production deployment will fail
|
|
560
|
+
- Schema drift between environments
|
|
561
|
+
|
|
562
|
+
**Do this instead:**
|
|
563
|
+
```bash
|
|
564
|
+
bun run db:generate
|
|
565
|
+
bun run db:migrate
|
|
566
|
+
git add src/server/db/schema/users.ts
|
|
567
|
+
git add drizzle/0002_add_column.sql # ← Don't forget this!
|
|
568
|
+
git commit -m "feat: add column"
|
|
569
|
+
git push
|
|
570
|
+
```
|
|
571
|
+
|
|
572
|
+
---
|
|
573
|
+
|
|
574
|
+
### ❌ Mistake 3: Editing migration files after applying
|
|
575
|
+
|
|
576
|
+
**Don't do this:**
|
|
577
|
+
```bash
|
|
578
|
+
bun run db:migrate # Applied migration
|
|
579
|
+
vim drizzle/0003_xxx.sql # Edit the SQL
|
|
580
|
+
bun run db:migrate # Won't re-run (already applied)
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
**Why it's bad:**
|
|
584
|
+
- Migration already recorded as applied
|
|
585
|
+
- Your database doesn't match the migration file
|
|
586
|
+
- Other environments will get different schema
|
|
587
|
+
|
|
588
|
+
**Do this instead:**
|
|
589
|
+
```bash
|
|
590
|
+
# Create a NEW migration to fix issues
|
|
591
|
+
vim src/server/db/schema/users.ts # Fix schema
|
|
592
|
+
bun run db:generate # Create new migration
|
|
593
|
+
# Name: "fix_previous_migration"
|
|
594
|
+
bun run db:migrate # Apply fix
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
---
|
|
598
|
+
|
|
599
|
+
### ❌ Mistake 4: Running migrations out of order
|
|
600
|
+
|
|
601
|
+
**Don't do this:**
|
|
602
|
+
```bash
|
|
603
|
+
# Apply only specific migration
|
|
604
|
+
psql $DATABASE_URL < drizzle/0005_new_feature.sql
|
|
605
|
+
# Skip 0003 and 0004
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
**Why it's bad:**
|
|
609
|
+
- Migrations may depend on previous changes
|
|
610
|
+
- Migration tracking table out of sync
|
|
611
|
+
- Schema inconsistencies
|
|
612
|
+
|
|
613
|
+
**Do this instead:**
|
|
614
|
+
```bash
|
|
615
|
+
# Always run migrations in order
|
|
616
|
+
bun run db:migrate # Applies all pending migrations
|
|
617
|
+
```
|
|
618
|
+
|
|
619
|
+
---
|
|
620
|
+
|
|
621
|
+
### ❌ Mistake 5: Not testing migrations locally
|
|
622
|
+
|
|
623
|
+
**Don't do this:**
|
|
624
|
+
```bash
|
|
625
|
+
bun run db:generate
|
|
626
|
+
git add drizzle/0003_xxx.sql
|
|
627
|
+
git commit -m "feat: add table"
|
|
628
|
+
git push
|
|
629
|
+
# Deploy to production without testing
|
|
630
|
+
DATABASE_URL=$PROD_URL bun run db:migrate # 🔥 Hope it works!
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
**Why it's bad:**
|
|
634
|
+
- Migration might fail in production
|
|
635
|
+
- Could cause downtime
|
|
636
|
+
- Data loss risk
|
|
637
|
+
|
|
638
|
+
**Do this instead:**
|
|
639
|
+
```bash
|
|
640
|
+
bun run db:generate
|
|
641
|
+
bun run db:migrate # Test locally first
|
|
642
|
+
bun dev # Verify app works
|
|
643
|
+
# Test thoroughly
|
|
644
|
+
git add drizzle/0003_xxx.sql
|
|
645
|
+
git commit -m "feat: add table"
|
|
646
|
+
git push
|
|
647
|
+
# Deploy to staging first
|
|
648
|
+
DATABASE_URL=$STAGING_URL bun run db:migrate
|
|
649
|
+
# Test staging
|
|
650
|
+
# Then production
|
|
651
|
+
DATABASE_URL=$PROD_URL bun run db:migrate
|
|
652
|
+
```
|
|
653
|
+
|
|
654
|
+
---
|
|
655
|
+
|
|
656
|
+
## Best Practices
|
|
657
|
+
|
|
658
|
+
### 1. Local Development Workflow
|
|
659
|
+
|
|
660
|
+
**For rapid iteration:**
|
|
661
|
+
```bash
|
|
662
|
+
# Use db:push for quick experiments
|
|
663
|
+
bun run db:push
|
|
664
|
+
bun dev
|
|
665
|
+
# Iterate quickly
|
|
666
|
+
|
|
667
|
+
# Once schema is stable, create proper migration
|
|
668
|
+
bun run db:generate
|
|
669
|
+
bun run db:migrate
|
|
670
|
+
git add drizzle/*.sql
|
|
671
|
+
git commit
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
**For production-ready features:**
|
|
675
|
+
```bash
|
|
676
|
+
# Always use generate + migrate
|
|
677
|
+
bun run db:generate
|
|
678
|
+
bun run db:migrate
|
|
679
|
+
git add drizzle/*.sql
|
|
680
|
+
git commit
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
---
|
|
684
|
+
|
|
685
|
+
### 2. Migration Naming
|
|
686
|
+
|
|
687
|
+
**Use descriptive names:**
|
|
688
|
+
```bash
|
|
689
|
+
# Good names
|
|
690
|
+
add_avatar_column
|
|
691
|
+
create_projects_table
|
|
692
|
+
add_status_index
|
|
693
|
+
rename_user_to_account
|
|
694
|
+
|
|
695
|
+
# Bad names
|
|
696
|
+
migration_1
|
|
697
|
+
update
|
|
698
|
+
fix
|
|
699
|
+
changes
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
---
|
|
703
|
+
|
|
704
|
+
### 3. Review Generated SQL
|
|
705
|
+
|
|
706
|
+
**Always review before applying:**
|
|
707
|
+
```bash
|
|
708
|
+
bun run db:generate
|
|
709
|
+
# Name: "add_email_unique_constraint"
|
|
710
|
+
|
|
711
|
+
# Review the SQL
|
|
712
|
+
cat drizzle/0007_add_email_unique_constraint.sql
|
|
713
|
+
# ALTER TABLE "users" ADD CONSTRAINT "users_email_unique" UNIQUE("email");
|
|
714
|
+
|
|
715
|
+
# Looks good? Apply it
|
|
716
|
+
bun run db:migrate
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
---
|
|
720
|
+
|
|
721
|
+
### 4. Commit Migration Files
|
|
722
|
+
|
|
723
|
+
**Always commit migration files with schema changes:**
|
|
724
|
+
```bash
|
|
725
|
+
git add src/server/db/schema/users.ts
|
|
726
|
+
git add drizzle/0008_add_verified_column.sql
|
|
727
|
+
git commit -m "feat: add email verification"
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
---
|
|
731
|
+
|
|
732
|
+
### 5. Test Before Production
|
|
733
|
+
|
|
734
|
+
**Testing checklist:**
|
|
735
|
+
```bash
|
|
736
|
+
# 1. Test locally
|
|
737
|
+
bun run db:migrate
|
|
738
|
+
bun dev
|
|
739
|
+
# Test all features
|
|
740
|
+
|
|
741
|
+
# 2. Test in staging
|
|
742
|
+
DATABASE_URL=$STAGING_URL bun run db:migrate
|
|
743
|
+
# Run integration tests
|
|
744
|
+
|
|
745
|
+
# 3. Deploy to production
|
|
746
|
+
DATABASE_URL=$PROD_URL bun run db:migrate
|
|
747
|
+
# Monitor for issues
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
---
|
|
751
|
+
|
|
752
|
+
### 6. Keep Migrations Small
|
|
753
|
+
|
|
754
|
+
**Good: Small, focused migrations**
|
|
755
|
+
```bash
|
|
756
|
+
# Migration 1: Add column
|
|
757
|
+
bun run db:generate # add_role_column
|
|
758
|
+
|
|
759
|
+
# Migration 2: Add index
|
|
760
|
+
bun run db:generate # add_role_index
|
|
761
|
+
|
|
762
|
+
# Migration 3: Add constraint
|
|
763
|
+
bun run db:generate # add_role_check_constraint
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
**Bad: Large, complex migrations**
|
|
767
|
+
```bash
|
|
768
|
+
# Migration 1: Everything at once
|
|
769
|
+
# - Add 5 tables
|
|
770
|
+
# - Add 10 columns
|
|
771
|
+
# - Add 15 indexes
|
|
772
|
+
# - Migrate data
|
|
773
|
+
# Hard to debug if something fails!
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
---
|
|
777
|
+
|
|
778
|
+
### 7. Document Complex Migrations
|
|
779
|
+
|
|
780
|
+
**Add comments to migration files:**
|
|
781
|
+
```sql
|
|
782
|
+
-- drizzle/0009_migrate_user_data.sql
|
|
783
|
+
-- This migration moves user data from old_users to users table
|
|
784
|
+
-- Run during maintenance window (low traffic)
|
|
785
|
+
-- Estimated time: 5 minutes for 100k users
|
|
786
|
+
|
|
787
|
+
BEGIN;
|
|
788
|
+
|
|
789
|
+
-- Copy data
|
|
790
|
+
INSERT INTO users (id, name, email)
|
|
791
|
+
SELECT id, name, email FROM old_users;
|
|
792
|
+
|
|
793
|
+
-- Verify counts match
|
|
794
|
+
DO $$
|
|
795
|
+
DECLARE
|
|
796
|
+
old_count INTEGER;
|
|
797
|
+
new_count INTEGER;
|
|
798
|
+
BEGIN
|
|
799
|
+
SELECT COUNT(*) INTO old_count FROM old_users;
|
|
800
|
+
SELECT COUNT(*) INTO new_count FROM users;
|
|
801
|
+
|
|
802
|
+
IF old_count != new_count THEN
|
|
803
|
+
RAISE EXCEPTION 'Data migration failed: counts do not match';
|
|
804
|
+
END IF;
|
|
805
|
+
END $$;
|
|
806
|
+
|
|
807
|
+
COMMIT;
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
---
|
|
811
|
+
|
|
812
|
+
### 8. Use Transactions for Safety
|
|
813
|
+
|
|
814
|
+
**Drizzle migrations run in transactions by default, but be aware:**
|
|
815
|
+
```sql
|
|
816
|
+
-- Safe: Wrapped in transaction
|
|
817
|
+
BEGIN;
|
|
818
|
+
ALTER TABLE users ADD COLUMN role text;
|
|
819
|
+
ALTER TABLE users ADD COLUMN verified boolean DEFAULT false;
|
|
820
|
+
COMMIT;
|
|
821
|
+
|
|
822
|
+
-- If second statement fails, first is rolled back
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
---
|
|
826
|
+
|
|
827
|
+
### 9. Backup Before Major Changes
|
|
828
|
+
|
|
829
|
+
**Before destructive migrations:**
|
|
830
|
+
```bash
|
|
831
|
+
# Backup production database
|
|
832
|
+
pg_dump $PROD_URL > backup_$(date +%Y%m%d_%H%M%S).sql
|
|
833
|
+
|
|
834
|
+
# Run migration
|
|
835
|
+
DATABASE_URL=$PROD_URL bun run db:migrate
|
|
836
|
+
|
|
837
|
+
# If something goes wrong, restore
|
|
838
|
+
psql $PROD_URL < backup_20240101_120000.sql
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
---
|
|
842
|
+
|
|
843
|
+
### 10. Monitor After Migration
|
|
844
|
+
|
|
845
|
+
**Post-migration checklist:**
|
|
846
|
+
```bash
|
|
847
|
+
# 1. Check application health
|
|
848
|
+
curl https://ui-syncup.com/api/health
|
|
849
|
+
|
|
850
|
+
# 2. Check database connectivity
|
|
851
|
+
psql $PROD_URL -c "SELECT 1;"
|
|
852
|
+
|
|
853
|
+
# 3. Verify table structure
|
|
854
|
+
psql $PROD_URL -c "\d users"
|
|
855
|
+
|
|
856
|
+
# 4. Check row counts
|
|
857
|
+
psql $PROD_URL -c "SELECT COUNT(*) FROM users;"
|
|
858
|
+
|
|
859
|
+
# 5. Monitor error logs
|
|
860
|
+
vercel logs --follow
|
|
861
|
+
|
|
862
|
+
# 6. Check performance metrics
|
|
863
|
+
# Monitor response times, error rates
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
---
|
|
867
|
+
|
|
868
|
+
## Summary
|
|
869
|
+
|
|
870
|
+
**Key Takeaways:**
|
|
871
|
+
|
|
872
|
+
1. **`db:generate`** creates SQL migration files from schema changes
|
|
873
|
+
2. **`db:migrate`** applies SQL migration files to database
|
|
874
|
+
3. **`db:push`** syncs schema directly without creating files
|
|
875
|
+
|
|
876
|
+
**When to use what:**
|
|
877
|
+
|
|
878
|
+
- **Production:** Always use `generate` + `migrate`
|
|
879
|
+
- **Prototyping:** Use `push` for speed
|
|
880
|
+
- **Team work:** Always use `generate` + `migrate` and commit files
|
|
881
|
+
- **Experiments:** Use `push`, then `generate` when ready
|
|
882
|
+
|
|
883
|
+
**Golden Rules:**
|
|
884
|
+
|
|
885
|
+
✅ Always test migrations locally first
|
|
886
|
+
✅ Review generated SQL before applying
|
|
887
|
+
✅ Commit migration files with schema changes
|
|
888
|
+
✅ Use descriptive migration names
|
|
889
|
+
✅ Keep migrations small and focused
|
|
890
|
+
✅ Never use `db:push` in production
|
|
891
|
+
✅ Always backup before major changes
|
|
892
|
+
|
|
893
|
+
---
|
|
894
|
+
|
|
895
|
+
## Working with Multiple Environments
|
|
896
|
+
|
|
897
|
+
### Environment Setup
|
|
898
|
+
|
|
899
|
+
UI SyncUp uses different database environments for different purposes:
|
|
900
|
+
|
|
901
|
+
| Environment | Database | Purpose | When to Use |
|
|
902
|
+
|-------------|----------|---------|-------------|
|
|
903
|
+
| **Local** | Local Supabase | Development & experimentation | Daily development, testing features |
|
|
904
|
+
| **Remote Dev** | Remote Supabase (develop) | Shared development | Testing with team, integration testing |
|
|
905
|
+
| **Staging** | Remote Supabase (staging) | Pre-production testing | Final testing before production |
|
|
906
|
+
| **Production** | Remote Supabase (production) | Live application | Production deployments only |
|
|
907
|
+
|
|
908
|
+
---
|
|
909
|
+
|
|
910
|
+
### Configuration Files
|
|
911
|
+
|
|
912
|
+
Create separate environment files for each environment:
|
|
913
|
+
|
|
914
|
+
```bash
|
|
915
|
+
# .env.local (Local Supabase)
|
|
916
|
+
DATABASE_URL="postgresql://postgres:postgres@127.0.0.1:54322/postgres"
|
|
917
|
+
DIRECT_URL="postgresql://postgres:postgres@127.0.0.1:54322/postgres"
|
|
918
|
+
SUPABASE_URL="http://127.0.0.1:54321"
|
|
919
|
+
SUPABASE_ANON_KEY="your-local-anon-key"
|
|
920
|
+
SUPABASE_SERVICE_ROLE_KEY="your-local-service-role-key"
|
|
921
|
+
|
|
922
|
+
# .env.develop (Remote Supabase - Develop)
|
|
923
|
+
DATABASE_URL="postgresql://postgres.[DEV-REF]:[PASSWORD]@aws-0-us-west-1.pooler.supabase.com:5432/postgres"
|
|
924
|
+
DIRECT_URL="postgresql://postgres:[PASSWORD]@db.[DEV-REF].supabase.co:5432/postgres"
|
|
925
|
+
SUPABASE_URL="https://[DEV-REF].supabase.co"
|
|
926
|
+
SUPABASE_ANON_KEY="your-dev-anon-key"
|
|
927
|
+
SUPABASE_SERVICE_ROLE_KEY="your-dev-service-role-key"
|
|
928
|
+
|
|
929
|
+
# .env.staging (Remote Supabase - Staging)
|
|
930
|
+
DATABASE_URL="postgresql://postgres.[STAGING-REF]:[PASSWORD]@aws-0-us-west-1.pooler.supabase.com:5432/postgres"
|
|
931
|
+
DIRECT_URL="postgresql://postgres:[PASSWORD]@db.[STAGING-REF].supabase.co:5432/postgres"
|
|
932
|
+
SUPABASE_URL="https://[STAGING-REF].supabase.co"
|
|
933
|
+
SUPABASE_ANON_KEY="your-staging-anon-key"
|
|
934
|
+
SUPABASE_SERVICE_ROLE_KEY="your-staging-service-role-key"
|
|
935
|
+
|
|
936
|
+
# .env.production (Remote Supabase - Production)
|
|
937
|
+
DATABASE_URL="postgresql://postgres.[PROD-REF]:[PASSWORD]@aws-0-us-west-1.pooler.supabase.com:5432/postgres"
|
|
938
|
+
DIRECT_URL="postgresql://postgres:[PASSWORD]@db.[PROD-REF].supabase.co:5432/postgres"
|
|
939
|
+
SUPABASE_URL="https://[PROD-REF].supabase.co"
|
|
940
|
+
SUPABASE_ANON_KEY="your-prod-anon-key"
|
|
941
|
+
SUPABASE_SERVICE_ROLE_KEY="your-prod-service-role-key"
|
|
942
|
+
```
|
|
943
|
+
|
|
944
|
+
**Add to `.gitignore`:**
|
|
945
|
+
```bash
|
|
946
|
+
# Environment files (never commit these!)
|
|
947
|
+
.env.local
|
|
948
|
+
.env.develop
|
|
949
|
+
.env.staging
|
|
950
|
+
.env.production
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
---
|
|
954
|
+
|
|
955
|
+
### Helper Scripts
|
|
956
|
+
|
|
957
|
+
Add environment-specific scripts to `package.json`:
|
|
958
|
+
|
|
959
|
+
```json
|
|
960
|
+
{
|
|
961
|
+
"scripts": {
|
|
962
|
+
"dev": "next dev",
|
|
963
|
+
"dev:local": "next dev",
|
|
964
|
+
"dev:remote": "dotenv -e .env.develop -- next dev",
|
|
965
|
+
|
|
966
|
+
"db:generate": "drizzle-kit generate",
|
|
967
|
+
"db:migrate": "drizzle-kit migrate",
|
|
968
|
+
"db:push": "drizzle-kit push",
|
|
969
|
+
"db:studio": "drizzle-kit studio",
|
|
970
|
+
|
|
971
|
+
"db:migrate:local": "dotenv -e .env.local -- drizzle-kit migrate",
|
|
972
|
+
"db:migrate:develop": "dotenv -e .env.develop -- drizzle-kit migrate",
|
|
973
|
+
"db:migrate:staging": "dotenv -e .env.staging -- drizzle-kit migrate",
|
|
974
|
+
"db:migrate:production": "dotenv -e .env.production -- drizzle-kit migrate",
|
|
975
|
+
|
|
976
|
+
"db:push:local": "dotenv -e .env.local -- drizzle-kit push",
|
|
977
|
+
"db:push:develop": "dotenv -e .env.develop -- drizzle-kit push",
|
|
978
|
+
|
|
979
|
+
"db:studio:local": "dotenv -e .env.local -- drizzle-kit studio",
|
|
980
|
+
"db:studio:develop": "dotenv -e .env.develop -- drizzle-kit studio",
|
|
981
|
+
|
|
982
|
+
"supabase:start": "supabase start",
|
|
983
|
+
"supabase:stop": "supabase stop",
|
|
984
|
+
"supabase:status": "supabase status"
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
```
|
|
988
|
+
|
|
989
|
+
**Install dotenv-cli:**
|
|
990
|
+
```bash
|
|
991
|
+
bun add -D dotenv-cli
|
|
992
|
+
```
|
|
993
|
+
|
|
994
|
+
---
|
|
995
|
+
|
|
996
|
+
### Daily Development Workflow
|
|
997
|
+
|
|
998
|
+
#### Working with Local Supabase (Recommended for Daily Development)
|
|
999
|
+
|
|
1000
|
+
**Advantages:**
|
|
1001
|
+
- ✅ Fast iteration (no network latency)
|
|
1002
|
+
- ✅ Work offline
|
|
1003
|
+
- ✅ Free to experiment (no cost)
|
|
1004
|
+
- ✅ Can reset database anytime
|
|
1005
|
+
- ✅ No impact on team members
|
|
1006
|
+
|
|
1007
|
+
**Setup:**
|
|
1008
|
+
```bash
|
|
1009
|
+
# 1. Start local Supabase
|
|
1010
|
+
npx supabase start
|
|
1011
|
+
|
|
1012
|
+
# 2. Apply migrations
|
|
1013
|
+
bun run db:migrate:local
|
|
1014
|
+
|
|
1015
|
+
# 3. Start development server
|
|
1016
|
+
bun dev
|
|
1017
|
+
|
|
1018
|
+
# 4. Open Supabase Studio (optional)
|
|
1019
|
+
# Visit: http://127.0.0.1:54323
|
|
1020
|
+
```
|
|
1021
|
+
|
|
1022
|
+
**Daily workflow:**
|
|
1023
|
+
```bash
|
|
1024
|
+
# Morning: Start local Supabase
|
|
1025
|
+
npx supabase start
|
|
1026
|
+
|
|
1027
|
+
# Develop features
|
|
1028
|
+
vim src/server/db/schema/users.ts
|
|
1029
|
+
bun run db:push:local # Quick iteration
|
|
1030
|
+
bun dev
|
|
1031
|
+
|
|
1032
|
+
# Test changes
|
|
1033
|
+
# ...
|
|
1034
|
+
|
|
1035
|
+
# Once stable, create migration
|
|
1036
|
+
bun run db:generate
|
|
1037
|
+
bun run db:migrate:local
|
|
1038
|
+
|
|
1039
|
+
# Commit
|
|
1040
|
+
git add drizzle/*.sql
|
|
1041
|
+
git commit -m "feat: add new feature"
|
|
1042
|
+
|
|
1043
|
+
# Evening: Stop local Supabase (optional)
|
|
1044
|
+
npx supabase stop
|
|
1045
|
+
```
|
|
1046
|
+
|
|
1047
|
+
---
|
|
1048
|
+
|
|
1049
|
+
#### Working with Remote Supabase Dev (For Team Collaboration)
|
|
1050
|
+
|
|
1051
|
+
**Advantages:**
|
|
1052
|
+
- ✅ Shared data with team
|
|
1053
|
+
- ✅ Test integrations with real data
|
|
1054
|
+
- ✅ Closer to production environment
|
|
1055
|
+
- ✅ Test with larger datasets
|
|
1056
|
+
|
|
1057
|
+
**When to use:**
|
|
1058
|
+
- Testing features that require shared data
|
|
1059
|
+
- Integration testing with team members
|
|
1060
|
+
- Testing with production-like data
|
|
1061
|
+
- Debugging issues that only occur with real data
|
|
1062
|
+
|
|
1063
|
+
**Setup:**
|
|
1064
|
+
```bash
|
|
1065
|
+
# 1. Load remote dev environment
|
|
1066
|
+
export $(cat .env.develop | xargs)
|
|
1067
|
+
|
|
1068
|
+
# 2. Start development server
|
|
1069
|
+
bun run dev:remote
|
|
1070
|
+
|
|
1071
|
+
# Or use the script
|
|
1072
|
+
bun run dev:remote
|
|
1073
|
+
```
|
|
1074
|
+
|
|
1075
|
+
**Workflow:**
|
|
1076
|
+
```bash
|
|
1077
|
+
# 1. Develop locally first
|
|
1078
|
+
npx supabase start
|
|
1079
|
+
bun run db:migrate:local
|
|
1080
|
+
bun dev
|
|
1081
|
+
# Test thoroughly
|
|
1082
|
+
|
|
1083
|
+
# 2. Create migration
|
|
1084
|
+
bun run db:generate
|
|
1085
|
+
# Name: "add_new_feature"
|
|
1086
|
+
|
|
1087
|
+
# 3. Test migration locally
|
|
1088
|
+
bun run db:migrate:local
|
|
1089
|
+
bun dev
|
|
1090
|
+
# Verify everything works
|
|
1091
|
+
|
|
1092
|
+
# 4. Apply to remote dev
|
|
1093
|
+
bun run db:migrate:develop
|
|
1094
|
+
|
|
1095
|
+
# 5. Test with remote dev
|
|
1096
|
+
bun run dev:remote
|
|
1097
|
+
# Verify with shared data
|
|
1098
|
+
|
|
1099
|
+
# 6. Commit and push
|
|
1100
|
+
git add drizzle/*.sql
|
|
1101
|
+
git add src/server/db/schema/*.ts
|
|
1102
|
+
git commit -m "feat: add new feature"
|
|
1103
|
+
git push
|
|
1104
|
+
|
|
1105
|
+
# 7. Notify team
|
|
1106
|
+
# Post in Slack: "Applied migration to dev: add_new_feature"
|
|
1107
|
+
```
|
|
1108
|
+
|
|
1109
|
+
---
|
|
1110
|
+
|
|
1111
|
+
### Real-World Scenarios (Following Best Practices)
|
|
1112
|
+
|
|
1113
|
+
#### Scenario 1: Adding a New Feature (Full Workflow)
|
|
1114
|
+
|
|
1115
|
+
**Goal:** Add a new `comments` table with proper workflow
|
|
1116
|
+
|
|
1117
|
+
**Step 1: Local Development**
|
|
1118
|
+
```bash
|
|
1119
|
+
# 1. Start local Supabase
|
|
1120
|
+
npx supabase start
|
|
1121
|
+
|
|
1122
|
+
# 2. Create schema
|
|
1123
|
+
cat > src/server/db/schema/comments.ts << 'EOF'
|
|
1124
|
+
import { pgTable, uuid, text, timestamp } from 'drizzle-orm/pg-core'
|
|
1125
|
+
import { issues } from './issues'
|
|
1126
|
+
import { users } from './users'
|
|
1127
|
+
|
|
1128
|
+
export const comments = pgTable('comments', {
|
|
1129
|
+
id: uuid('id').primaryKey().defaultRandom(),
|
|
1130
|
+
issueId: uuid('issue_id').notNull().references(() => issues.id, { onDelete: 'cascade' }),
|
|
1131
|
+
userId: uuid('user_id').notNull().references(() => users.id),
|
|
1132
|
+
content: text('content').notNull(),
|
|
1133
|
+
createdAt: timestamp('created_at').notNull().defaultNow(),
|
|
1134
|
+
updatedAt: timestamp('updated_at').notNull().defaultNow(),
|
|
1135
|
+
})
|
|
1136
|
+
EOF
|
|
1137
|
+
|
|
1138
|
+
# 3. Quick iteration with push
|
|
1139
|
+
bun run db:push:local
|
|
1140
|
+
bun dev
|
|
1141
|
+
# Test the feature
|
|
1142
|
+
|
|
1143
|
+
# 4. Make adjustments
|
|
1144
|
+
vim src/server/db/schema/comments.ts
|
|
1145
|
+
# Add index on issueId for performance
|
|
1146
|
+
bun run db:push:local
|
|
1147
|
+
bun dev
|
|
1148
|
+
# Test again
|
|
1149
|
+
```
|
|
1150
|
+
|
|
1151
|
+
**Step 2: Create Proper Migration**
|
|
1152
|
+
```bash
|
|
1153
|
+
# 1. Generate migration
|
|
1154
|
+
bun run db:generate
|
|
1155
|
+
# Name: "create_comments_table"
|
|
1156
|
+
|
|
1157
|
+
# 2. Review SQL
|
|
1158
|
+
cat drizzle/0010_create_comments_table.sql
|
|
1159
|
+
|
|
1160
|
+
# 3. Apply to local
|
|
1161
|
+
bun run db:migrate:local
|
|
1162
|
+
|
|
1163
|
+
# 4. Test thoroughly
|
|
1164
|
+
bun dev
|
|
1165
|
+
# Test all comment features
|
|
1166
|
+
# - Create comment
|
|
1167
|
+
# - Edit comment
|
|
1168
|
+
# - Delete comment
|
|
1169
|
+
# - List comments
|
|
1170
|
+
```
|
|
1171
|
+
|
|
1172
|
+
**Step 3: Test with Remote Dev**
|
|
1173
|
+
```bash
|
|
1174
|
+
# 1. Apply migration to remote dev
|
|
1175
|
+
bun run db:migrate:develop
|
|
1176
|
+
|
|
1177
|
+
# 2. Test with remote dev environment
|
|
1178
|
+
bun run dev:remote
|
|
1179
|
+
|
|
1180
|
+
# 3. Test with shared data
|
|
1181
|
+
# - Create comments on existing issues
|
|
1182
|
+
# - Test with multiple users
|
|
1183
|
+
# - Verify permissions work correctly
|
|
1184
|
+
```
|
|
1185
|
+
|
|
1186
|
+
**Step 4: Code Review & Commit**
|
|
1187
|
+
```bash
|
|
1188
|
+
# 1. Commit changes
|
|
1189
|
+
git add src/server/db/schema/comments.ts
|
|
1190
|
+
git add drizzle/0010_create_comments_table.sql
|
|
1191
|
+
git commit -m "feat: add comments table and API"
|
|
1192
|
+
|
|
1193
|
+
# 2. Push and create PR
|
|
1194
|
+
git push origin feature/add-comments
|
|
1195
|
+
gh pr create --title "Add comments feature" --body "Adds comments table and API endpoints"
|
|
1196
|
+
|
|
1197
|
+
# 3. Notify team
|
|
1198
|
+
# Slack: "PR ready for review. Migration applied to dev environment."
|
|
1199
|
+
```
|
|
1200
|
+
|
|
1201
|
+
**Step 5: Deploy to Staging**
|
|
1202
|
+
```bash
|
|
1203
|
+
# After PR approval and merge to develop branch
|
|
1204
|
+
|
|
1205
|
+
# 1. Apply migration to staging
|
|
1206
|
+
bun run db:migrate:staging
|
|
1207
|
+
|
|
1208
|
+
# 2. Deploy code to staging (Vercel automatic)
|
|
1209
|
+
# Wait for deployment to complete
|
|
1210
|
+
|
|
1211
|
+
# 3. Test on staging
|
|
1212
|
+
# Visit: https://staging-ui-syncup.vercel.app
|
|
1213
|
+
# Test all comment features
|
|
1214
|
+
|
|
1215
|
+
# 4. Run integration tests
|
|
1216
|
+
bun run test:ui
|
|
1217
|
+
```
|
|
1218
|
+
|
|
1219
|
+
**Step 6: Deploy to Production**
|
|
1220
|
+
```bash
|
|
1221
|
+
# After staging tests pass
|
|
1222
|
+
|
|
1223
|
+
# 1. Merge to main
|
|
1224
|
+
git checkout main
|
|
1225
|
+
git merge develop
|
|
1226
|
+
git push origin main
|
|
1227
|
+
|
|
1228
|
+
# 2. Apply migration to production
|
|
1229
|
+
bun run db:migrate:production
|
|
1230
|
+
|
|
1231
|
+
# 3. Monitor deployment
|
|
1232
|
+
# Watch Vercel deployment
|
|
1233
|
+
# Monitor error logs
|
|
1234
|
+
# Check application health
|
|
1235
|
+
|
|
1236
|
+
# 4. Verify in production
|
|
1237
|
+
curl https://ui-syncup.com/api/health
|
|
1238
|
+
# Test comment features
|
|
1239
|
+
```
|
|
1240
|
+
|
|
1241
|
+
---
|
|
1242
|
+
|
|
1243
|
+
#### Scenario 2: Fixing a Bug in Production
|
|
1244
|
+
|
|
1245
|
+
**Goal:** Add missing index causing slow queries
|
|
1246
|
+
|
|
1247
|
+
**Step 1: Reproduce Locally**
|
|
1248
|
+
```bash
|
|
1249
|
+
# 1. Start local Supabase
|
|
1250
|
+
npx supabase start
|
|
1251
|
+
|
|
1252
|
+
# 2. Apply all migrations to match production
|
|
1253
|
+
bun run db:migrate:local
|
|
1254
|
+
|
|
1255
|
+
# 3. Reproduce the issue
|
|
1256
|
+
bun dev
|
|
1257
|
+
# Test slow query
|
|
1258
|
+
# Confirm it's slow without index
|
|
1259
|
+
```
|
|
1260
|
+
|
|
1261
|
+
**Step 2: Fix Locally**
|
|
1262
|
+
```bash
|
|
1263
|
+
# 1. Add index to schema
|
|
1264
|
+
vim src/server/db/schema/issues.ts
|
|
1265
|
+
# Add: index('idx_issues_project_status').on(issues.projectId, issues.status)
|
|
1266
|
+
|
|
1267
|
+
# 2. Generate migration
|
|
1268
|
+
bun run db:generate
|
|
1269
|
+
# Name: "add_project_status_index"
|
|
1270
|
+
|
|
1271
|
+
# 3. Review SQL
|
|
1272
|
+
cat drizzle/0011_add_project_status_index.sql
|
|
1273
|
+
# CREATE INDEX "idx_issues_project_status" ON "issues" ("project_id", "status");
|
|
1274
|
+
|
|
1275
|
+
# 4. Apply locally
|
|
1276
|
+
bun run db:migrate:local
|
|
1277
|
+
|
|
1278
|
+
# 5. Test performance improvement
|
|
1279
|
+
bun dev
|
|
1280
|
+
# Verify query is now fast
|
|
1281
|
+
```
|
|
1282
|
+
|
|
1283
|
+
**Step 3: Fast-Track to Production**
|
|
1284
|
+
```bash
|
|
1285
|
+
# For critical performance fixes, skip staging
|
|
1286
|
+
|
|
1287
|
+
# 1. Commit
|
|
1288
|
+
git add src/server/db/schema/issues.ts
|
|
1289
|
+
git add drizzle/0011_add_project_status_index.sql
|
|
1290
|
+
git commit -m "perf: add index on issues(project_id, status)"
|
|
1291
|
+
|
|
1292
|
+
# 2. Push to main (hotfix)
|
|
1293
|
+
git push origin main
|
|
1294
|
+
|
|
1295
|
+
# 3. Apply to production immediately
|
|
1296
|
+
bun run db:migrate:production
|
|
1297
|
+
|
|
1298
|
+
# 4. Monitor
|
|
1299
|
+
# Watch query performance
|
|
1300
|
+
# Check error rates
|
|
1301
|
+
# Verify improvement
|
|
1302
|
+
|
|
1303
|
+
# 5. Backport to other environments
|
|
1304
|
+
bun run db:migrate:develop
|
|
1305
|
+
bun run db:migrate:staging
|
|
1306
|
+
```
|
|
1307
|
+
|
|
1308
|
+
---
|
|
1309
|
+
|
|
1310
|
+
#### Scenario 3: Data Migration (Complex)
|
|
1311
|
+
|
|
1312
|
+
**Goal:** Migrate user roles from string to enum
|
|
1313
|
+
|
|
1314
|
+
**Step 1: Plan Migration**
|
|
1315
|
+
```bash
|
|
1316
|
+
# Create migration plan document
|
|
1317
|
+
cat > docs/migrations/0012_migrate_user_roles.md << 'EOF'
|
|
1318
|
+
# Migration: User Roles to Enum
|
|
1319
|
+
|
|
1320
|
+
## Current State
|
|
1321
|
+
- roles stored as text: 'owner', 'admin', 'member', 'viewer'
|
|
1322
|
+
- No constraints, allows invalid values
|
|
1323
|
+
|
|
1324
|
+
## Target State
|
|
1325
|
+
- roles stored as enum: user_role
|
|
1326
|
+
- Enforced at database level
|
|
1327
|
+
|
|
1328
|
+
## Steps
|
|
1329
|
+
1. Create enum type
|
|
1330
|
+
2. Add new column with enum type
|
|
1331
|
+
3. Migrate data from old column to new
|
|
1332
|
+
4. Verify data integrity
|
|
1333
|
+
5. Drop old column
|
|
1334
|
+
6. Rename new column
|
|
1335
|
+
|
|
1336
|
+
## Rollback Plan
|
|
1337
|
+
- Keep old column until verified
|
|
1338
|
+
- Can rollback by dropping new column
|
|
1339
|
+
|
|
1340
|
+
## Estimated Time
|
|
1341
|
+
- 100k users: ~30 seconds
|
|
1342
|
+
- Downtime: None (additive changes)
|
|
1343
|
+
EOF
|
|
1344
|
+
```
|
|
1345
|
+
|
|
1346
|
+
**Step 2: Test Locally**
|
|
1347
|
+
```bash
|
|
1348
|
+
# 1. Create migration
|
|
1349
|
+
cat > drizzle/0012_migrate_user_roles.sql << 'EOF'
|
|
1350
|
+
-- Step 1: Create enum type
|
|
1351
|
+
CREATE TYPE user_role AS ENUM ('owner', 'admin', 'member', 'viewer');
|
|
1352
|
+
|
|
1353
|
+
-- Step 2: Add new column
|
|
1354
|
+
ALTER TABLE users ADD COLUMN role_new user_role;
|
|
1355
|
+
|
|
1356
|
+
-- Step 3: Migrate data
|
|
1357
|
+
UPDATE users SET role_new = role::user_role WHERE role IS NOT NULL;
|
|
1358
|
+
|
|
1359
|
+
-- Step 4: Verify counts match
|
|
1360
|
+
DO $$
|
|
1361
|
+
DECLARE
|
|
1362
|
+
total_count INTEGER;
|
|
1363
|
+
migrated_count INTEGER;
|
|
1364
|
+
BEGIN
|
|
1365
|
+
SELECT COUNT(*) INTO total_count FROM users WHERE role IS NOT NULL;
|
|
1366
|
+
SELECT COUNT(*) INTO migrated_count FROM users WHERE role_new IS NOT NULL;
|
|
1367
|
+
|
|
1368
|
+
IF total_count != migrated_count THEN
|
|
1369
|
+
RAISE EXCEPTION 'Migration failed: counts do not match (% vs %)', total_count, migrated_count;
|
|
1370
|
+
END IF;
|
|
1371
|
+
|
|
1372
|
+
RAISE NOTICE 'Migration successful: % users migrated', migrated_count;
|
|
1373
|
+
END $$;
|
|
1374
|
+
|
|
1375
|
+
-- Step 5: Drop old column
|
|
1376
|
+
ALTER TABLE users DROP COLUMN role;
|
|
1377
|
+
|
|
1378
|
+
-- Step 6: Rename new column
|
|
1379
|
+
ALTER TABLE users RENAME COLUMN role_new TO role;
|
|
1380
|
+
|
|
1381
|
+
-- Step 7: Add NOT NULL constraint
|
|
1382
|
+
ALTER TABLE users ALTER COLUMN role SET NOT NULL;
|
|
1383
|
+
EOF
|
|
1384
|
+
|
|
1385
|
+
# 2. Apply to local
|
|
1386
|
+
bun run db:migrate:local
|
|
1387
|
+
|
|
1388
|
+
# 3. Verify
|
|
1389
|
+
psql "postgresql://postgres:postgres@127.0.0.1:54322/postgres" -c "SELECT role, COUNT(*) FROM users GROUP BY role;"
|
|
1390
|
+
|
|
1391
|
+
# 4. Test application
|
|
1392
|
+
bun dev
|
|
1393
|
+
# Verify all role-based features work
|
|
1394
|
+
```
|
|
1395
|
+
|
|
1396
|
+
**Step 3: Test with Remote Dev**
|
|
1397
|
+
```bash
|
|
1398
|
+
# 1. Apply to remote dev
|
|
1399
|
+
bun run db:migrate:develop
|
|
1400
|
+
|
|
1401
|
+
# 2. Test with real data
|
|
1402
|
+
bun run dev:remote
|
|
1403
|
+
|
|
1404
|
+
# 3. Verify data integrity
|
|
1405
|
+
psql "$DEVELOP_DIRECT_URL" -c "SELECT role, COUNT(*) FROM users GROUP BY role;"
|
|
1406
|
+
|
|
1407
|
+
# 4. Test all role-based features
|
|
1408
|
+
# - Owner permissions
|
|
1409
|
+
# - Admin permissions
|
|
1410
|
+
# - Member permissions
|
|
1411
|
+
# - Viewer permissions
|
|
1412
|
+
```
|
|
1413
|
+
|
|
1414
|
+
**Step 4: Deploy to Staging**
|
|
1415
|
+
```bash
|
|
1416
|
+
# 1. Apply to staging
|
|
1417
|
+
bun run db:migrate:staging
|
|
1418
|
+
|
|
1419
|
+
# 2. Run full test suite
|
|
1420
|
+
bun run test:ui
|
|
1421
|
+
|
|
1422
|
+
# 3. Manual testing
|
|
1423
|
+
# Test all user flows
|
|
1424
|
+
# Verify no regressions
|
|
1425
|
+
```
|
|
1426
|
+
|
|
1427
|
+
**Step 5: Deploy to Production**
|
|
1428
|
+
```bash
|
|
1429
|
+
# 1. Schedule maintenance window (optional)
|
|
1430
|
+
# For large tables, notify users
|
|
1431
|
+
|
|
1432
|
+
# 2. Backup production database
|
|
1433
|
+
# Supabase does this automatically, but verify
|
|
1434
|
+
|
|
1435
|
+
# 3. Apply migration
|
|
1436
|
+
bun run db:migrate:production
|
|
1437
|
+
|
|
1438
|
+
# 4. Monitor closely
|
|
1439
|
+
# Watch error logs
|
|
1440
|
+
# Check query performance
|
|
1441
|
+
# Verify user reports
|
|
1442
|
+
|
|
1443
|
+
# 5. Verify data
|
|
1444
|
+
psql "$PRODUCTION_DIRECT_URL" -c "SELECT role, COUNT(*) FROM users GROUP BY role;"
|
|
1445
|
+
```
|
|
1446
|
+
|
|
1447
|
+
---
|
|
1448
|
+
|
|
1449
|
+
#### Scenario 4: Team Member Onboarding
|
|
1450
|
+
|
|
1451
|
+
**Goal:** Help new team member set up their development environment
|
|
1452
|
+
|
|
1453
|
+
**Step 1: Clone Repository**
|
|
1454
|
+
```bash
|
|
1455
|
+
# 1. Clone repo
|
|
1456
|
+
git clone https://github.com/your-org/ui-syncup.git
|
|
1457
|
+
cd ui-syncup
|
|
1458
|
+
|
|
1459
|
+
# 2. Install dependencies
|
|
1460
|
+
bun install
|
|
1461
|
+
```
|
|
1462
|
+
|
|
1463
|
+
**Step 2: Set Up Local Supabase**
|
|
1464
|
+
```bash
|
|
1465
|
+
# 1. Start local Supabase
|
|
1466
|
+
npx supabase start
|
|
1467
|
+
|
|
1468
|
+
# 2. Copy environment template
|
|
1469
|
+
cp .env.example .env.local
|
|
1470
|
+
|
|
1471
|
+
# 3. Update .env.local with local Supabase credentials
|
|
1472
|
+
# Get credentials from: npx supabase status
|
|
1473
|
+
vim .env.local
|
|
1474
|
+
|
|
1475
|
+
# 4. Apply all migrations
|
|
1476
|
+
bun run db:migrate:local
|
|
1477
|
+
|
|
1478
|
+
# 5. Verify setup
|
|
1479
|
+
psql "postgresql://postgres:postgres@127.0.0.1:54322/postgres" -c "\dt"
|
|
1480
|
+
```
|
|
1481
|
+
|
|
1482
|
+
**Step 3: Test Local Development**
|
|
1483
|
+
```bash
|
|
1484
|
+
# 1. Start development server
|
|
1485
|
+
bun dev
|
|
1486
|
+
|
|
1487
|
+
# 2. Open browser
|
|
1488
|
+
# Visit: http://localhost:3000
|
|
1489
|
+
|
|
1490
|
+
# 3. Test basic features
|
|
1491
|
+
# - Sign up
|
|
1492
|
+
# - Create team
|
|
1493
|
+
# - Create project
|
|
1494
|
+
# - Create issue
|
|
1495
|
+
```
|
|
1496
|
+
|
|
1497
|
+
**Step 4: Set Up Remote Dev Access (Optional)**
|
|
1498
|
+
```bash
|
|
1499
|
+
# 1. Get remote dev credentials from team lead
|
|
1500
|
+
# Team lead shares .env.develop (via 1Password or similar)
|
|
1501
|
+
|
|
1502
|
+
# 2. Save to .env.develop
|
|
1503
|
+
vim .env.develop
|
|
1504
|
+
|
|
1505
|
+
# 3. Test remote dev connection
|
|
1506
|
+
bun run dev:remote
|
|
1507
|
+
|
|
1508
|
+
# 4. Verify can connect to shared data
|
|
1509
|
+
# Visit: http://localhost:3000
|
|
1510
|
+
# Should see shared team data
|
|
1511
|
+
```
|
|
1512
|
+
|
|
1513
|
+
**Step 5: Make First Contribution**
|
|
1514
|
+
```bash
|
|
1515
|
+
# 1. Create feature branch
|
|
1516
|
+
git checkout -b feature/my-first-feature
|
|
1517
|
+
|
|
1518
|
+
# 2. Make changes
|
|
1519
|
+
vim src/features/issues/components/issue-card.tsx
|
|
1520
|
+
|
|
1521
|
+
# 3. Test locally
|
|
1522
|
+
bun dev
|
|
1523
|
+
|
|
1524
|
+
# 4. Commit and push
|
|
1525
|
+
git add .
|
|
1526
|
+
git commit -m "feat: improve issue card UI"
|
|
1527
|
+
git push origin feature/my-first-feature
|
|
1528
|
+
|
|
1529
|
+
# 5. Create PR
|
|
1530
|
+
gh pr create --title "Improve issue card UI"
|
|
1531
|
+
```
|
|
1532
|
+
|
|
1533
|
+
---
|
|
1534
|
+
|
|
1535
|
+
#### Scenario 5: Debugging Production Issue Locally
|
|
1536
|
+
|
|
1537
|
+
**Goal:** Reproduce and fix a production bug locally
|
|
1538
|
+
|
|
1539
|
+
**Step 1: Get Production Data (Anonymized)**
|
|
1540
|
+
```bash
|
|
1541
|
+
# 1. Export anonymized data from production
|
|
1542
|
+
# (Team lead or DevOps does this)
|
|
1543
|
+
pg_dump "$PRODUCTION_DIRECT_URL" \
|
|
1544
|
+
--data-only \
|
|
1545
|
+
--table=issues \
|
|
1546
|
+
--table=projects \
|
|
1547
|
+
--table=teams \
|
|
1548
|
+
> production_data_anonymized.sql
|
|
1549
|
+
|
|
1550
|
+
# 2. Anonymize sensitive data
|
|
1551
|
+
sed -i 's/user@example.com/test@example.com/g' production_data_anonymized.sql
|
|
1552
|
+
sed -i 's/John Doe/Test User/g' production_data_anonymized.sql
|
|
1553
|
+
```
|
|
1554
|
+
|
|
1555
|
+
**Step 2: Load Data Locally**
|
|
1556
|
+
```bash
|
|
1557
|
+
# 1. Start local Supabase
|
|
1558
|
+
npx supabase start
|
|
1559
|
+
|
|
1560
|
+
# 2. Apply migrations
|
|
1561
|
+
bun run db:migrate:local
|
|
1562
|
+
|
|
1563
|
+
# 3. Import anonymized data
|
|
1564
|
+
psql "postgresql://postgres:postgres@127.0.0.1:54322/postgres" < production_data_anonymized.sql
|
|
1565
|
+
|
|
1566
|
+
# 4. Verify data loaded
|
|
1567
|
+
psql "postgresql://postgres:postgres@127.0.0.1:54322/postgres" -c "SELECT COUNT(*) FROM issues;"
|
|
1568
|
+
```
|
|
1569
|
+
|
|
1570
|
+
**Step 3: Reproduce Issue**
|
|
1571
|
+
```bash
|
|
1572
|
+
# 1. Start development server
|
|
1573
|
+
bun dev
|
|
1574
|
+
|
|
1575
|
+
# 2. Follow reproduction steps from bug report
|
|
1576
|
+
# - Navigate to specific project
|
|
1577
|
+
# - Perform specific action
|
|
1578
|
+
# - Observe error
|
|
1579
|
+
|
|
1580
|
+
# 3. Check logs
|
|
1581
|
+
# Look for error messages
|
|
1582
|
+
# Identify root cause
|
|
1583
|
+
```
|
|
1584
|
+
|
|
1585
|
+
**Step 4: Fix and Test**
|
|
1586
|
+
```bash
|
|
1587
|
+
# 1. Fix the bug
|
|
1588
|
+
vim src/features/issues/api/update-issue.ts
|
|
1589
|
+
|
|
1590
|
+
# 2. Test fix locally
|
|
1591
|
+
bun dev
|
|
1592
|
+
# Verify bug is fixed
|
|
1593
|
+
|
|
1594
|
+
# 3. Run tests
|
|
1595
|
+
bun run test
|
|
1596
|
+
|
|
1597
|
+
# 4. Commit fix
|
|
1598
|
+
git add .
|
|
1599
|
+
git commit -m "fix: resolve issue update bug"
|
|
1600
|
+
git push
|
|
1601
|
+
```
|
|
1602
|
+
|
|
1603
|
+
**Step 5: Deploy Fix**
|
|
1604
|
+
```bash
|
|
1605
|
+
# 1. Create PR
|
|
1606
|
+
gh pr create --title "Fix issue update bug"
|
|
1607
|
+
|
|
1608
|
+
# 2. After approval, merge
|
|
1609
|
+
gh pr merge
|
|
1610
|
+
|
|
1611
|
+
# 3. Deploy to production
|
|
1612
|
+
# Vercel automatic deployment
|
|
1613
|
+
|
|
1614
|
+
# 4. Verify fix in production
|
|
1615
|
+
# Test the specific scenario
|
|
1616
|
+
# Monitor error logs
|
|
1617
|
+
```
|
|
1618
|
+
|
|
1619
|
+
---
|
|
1620
|
+
|
|
1621
|
+
### Environment Switching Best Practices
|
|
1622
|
+
|
|
1623
|
+
#### Quick Environment Switching
|
|
1624
|
+
|
|
1625
|
+
Create a helper script `scripts/switch-env.sh`:
|
|
1626
|
+
|
|
1627
|
+
```bash
|
|
1628
|
+
#!/bin/bash
|
|
1629
|
+
|
|
1630
|
+
ENV=$1
|
|
1631
|
+
|
|
1632
|
+
if [ -z "$ENV" ]; then
|
|
1633
|
+
echo "Usage: ./scripts/switch-env.sh [local|develop|staging|production]"
|
|
1634
|
+
exit 1
|
|
1635
|
+
fi
|
|
1636
|
+
|
|
1637
|
+
case $ENV in
|
|
1638
|
+
local)
|
|
1639
|
+
cp .env.local .env
|
|
1640
|
+
echo "✅ Switched to LOCAL environment"
|
|
1641
|
+
echo "📍 Database: Local Supabase (127.0.0.1:54322)"
|
|
1642
|
+
;;
|
|
1643
|
+
develop)
|
|
1644
|
+
cp .env.develop .env
|
|
1645
|
+
echo "✅ Switched to DEVELOP environment"
|
|
1646
|
+
echo "📍 Database: Remote Supabase (develop)"
|
|
1647
|
+
;;
|
|
1648
|
+
staging)
|
|
1649
|
+
cp .env.staging .env
|
|
1650
|
+
echo "✅ Switched to STAGING environment"
|
|
1651
|
+
echo "📍 Database: Remote Supabase (staging)"
|
|
1652
|
+
;;
|
|
1653
|
+
production)
|
|
1654
|
+
echo "⚠️ WARNING: Switching to PRODUCTION environment"
|
|
1655
|
+
echo "⚠️ This should only be used for read-only operations"
|
|
1656
|
+
read -p "Are you sure? (yes/no): " confirm
|
|
1657
|
+
if [ "$confirm" = "yes" ]; then
|
|
1658
|
+
cp .env.production .env
|
|
1659
|
+
echo "✅ Switched to PRODUCTION environment"
|
|
1660
|
+
echo "📍 Database: Remote Supabase (production)"
|
|
1661
|
+
else
|
|
1662
|
+
echo "❌ Cancelled"
|
|
1663
|
+
exit 1
|
|
1664
|
+
fi
|
|
1665
|
+
;;
|
|
1666
|
+
*)
|
|
1667
|
+
echo "❌ Invalid environment: $ENV"
|
|
1668
|
+
echo "Valid options: local, develop, staging, production"
|
|
1669
|
+
exit 1
|
|
1670
|
+
;;
|
|
1671
|
+
esac
|
|
1672
|
+
```
|
|
1673
|
+
|
|
1674
|
+
**Usage:**
|
|
1675
|
+
```bash
|
|
1676
|
+
chmod +x scripts/switch-env.sh
|
|
1677
|
+
|
|
1678
|
+
# Switch to local
|
|
1679
|
+
./scripts/switch-env.sh local
|
|
1680
|
+
bun dev
|
|
1681
|
+
|
|
1682
|
+
# Switch to remote dev
|
|
1683
|
+
./scripts/switch-env.sh develop
|
|
1684
|
+
bun dev
|
|
1685
|
+
|
|
1686
|
+
# Switch back to local
|
|
1687
|
+
./scripts/switch-env.sh local
|
|
1688
|
+
bun dev
|
|
1689
|
+
```
|
|
1690
|
+
|
|
1691
|
+
---
|
|
1692
|
+
|
|
1693
|
+
#### Environment Verification
|
|
1694
|
+
|
|
1695
|
+
Create a helper script `scripts/verify-env.ts`:
|
|
1696
|
+
|
|
1697
|
+
```typescript
|
|
1698
|
+
import { config } from 'dotenv'
|
|
1699
|
+
|
|
1700
|
+
config({ path: '.env' })
|
|
1701
|
+
|
|
1702
|
+
const env = {
|
|
1703
|
+
DATABASE_URL: process.env.DATABASE_URL,
|
|
1704
|
+
SUPABASE_URL: process.env.SUPABASE_URL,
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
console.log('🔍 Current Environment Configuration:')
|
|
1708
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
|
|
1709
|
+
|
|
1710
|
+
if (env.DATABASE_URL?.includes('127.0.0.1')) {
|
|
1711
|
+
console.log('📍 Environment: LOCAL')
|
|
1712
|
+
console.log('🗄️ Database: Local Supabase')
|
|
1713
|
+
console.log('🔗 URL:', env.SUPABASE_URL)
|
|
1714
|
+
} else if (env.SUPABASE_URL?.includes('supabase.co')) {
|
|
1715
|
+
const projectRef = env.SUPABASE_URL.match(/https:\/\/([^.]+)\.supabase\.co/)?.[1]
|
|
1716
|
+
console.log('📍 Environment: REMOTE')
|
|
1717
|
+
console.log('🗄️ Database: Remote Supabase')
|
|
1718
|
+
console.log('🔗 Project:', projectRef)
|
|
1719
|
+
console.log('🔗 URL:', env.SUPABASE_URL)
|
|
1720
|
+
} else {
|
|
1721
|
+
console.log('⚠️ Environment: UNKNOWN')
|
|
1722
|
+
console.log('⚠️ Please check your .env file')
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
console.log('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━')
|
|
1726
|
+
```
|
|
1727
|
+
|
|
1728
|
+
**Usage:**
|
|
1729
|
+
```bash
|
|
1730
|
+
# Check current environment
|
|
1731
|
+
bun run scripts/verify-env.ts
|
|
1732
|
+
|
|
1733
|
+
# Output:
|
|
1734
|
+
# 🔍 Current Environment Configuration:
|
|
1735
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1736
|
+
# 📍 Environment: LOCAL
|
|
1737
|
+
# 🗄️ Database: Local Supabase
|
|
1738
|
+
# 🔗 URL: http://127.0.0.1:54321
|
|
1739
|
+
# ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
1740
|
+
```
|
|
1741
|
+
|
|
1742
|
+
---
|
|
1743
|
+
|
|
1744
|
+
### Safety Checklist
|
|
1745
|
+
|
|
1746
|
+
Before running commands against remote environments:
|
|
1747
|
+
|
|
1748
|
+
**Pre-flight Checklist:**
|
|
1749
|
+
```bash
|
|
1750
|
+
# 1. Verify environment
|
|
1751
|
+
bun run scripts/verify-env.ts
|
|
1752
|
+
|
|
1753
|
+
# 2. Confirm you're in the right environment
|
|
1754
|
+
echo $DATABASE_URL
|
|
1755
|
+
|
|
1756
|
+
# 3. For production, double-check
|
|
1757
|
+
if [[ $DATABASE_URL == *"production"* ]]; then
|
|
1758
|
+
echo "⚠️ WARNING: You are about to modify PRODUCTION"
|
|
1759
|
+
echo "⚠️ Press Ctrl+C to cancel, or Enter to continue"
|
|
1760
|
+
read
|
|
1761
|
+
fi
|
|
1762
|
+
|
|
1763
|
+
# 4. Run command
|
|
1764
|
+
bun run db:migrate
|
|
1765
|
+
```
|
|
1766
|
+
|
|
1767
|
+
---
|
|
1768
|
+
|
|
1769
|
+
## Additional Resources
|
|
1770
|
+
|
|
1771
|
+
- [Drizzle ORM Documentation](https://orm.drizzle.team/docs/overview)
|
|
1772
|
+
- [Drizzle Kit Documentation](https://orm.drizzle.team/kit-docs/overview)
|
|
1773
|
+
- [Drizzle Migrations Guide](https://orm.drizzle.team/docs/migrations)
|
|
1774
|
+
- [Supabase Documentation](https://supabase.com/docs)
|
|
1775
|
+
- [PostgreSQL Documentation](https://www.postgresql.org/docs/)
|
|
1776
|
+
|
|
1777
|
+
---
|
|
1778
|
+
|
|
1779
|
+
For questions or issues, refer to the main [SUPABASE_LOCAL_SETUP.md](./SUPABASE_LOCAL_SETUP.md) or [REMOTE_DATABASE_SETUP.md](./REMOTE_DATABASE_SETUP.md) documentation.
|