vibefast-cli 1.2.1 → 1.3.1
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/README.md +30 -95
- package/dist/__tests__/recipes.test.js +94 -91
- package/dist/__tests__/recipes.test.js.map +1 -1
- package/dist/commands/add.d.ts.map +1 -1
- package/dist/commands/add.js +301 -125
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/checklist.d.ts.map +1 -1
- package/dist/commands/checklist.js +85 -44
- package/dist/commands/checklist.js.map +1 -1
- package/dist/commands/health.d.ts.map +1 -1
- package/dist/commands/health.js +13 -4
- package/dist/commands/health.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +118 -26
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/migrate.d.ts +3 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +202 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/remove.d.ts.map +1 -1
- package/dist/commands/remove.js +61 -3
- package/dist/commands/remove.js.map +1 -1
- package/dist/core/auth.d.ts.map +1 -1
- package/dist/core/auth.js +20 -18
- package/dist/core/auth.js.map +1 -1
- package/dist/core/codemod.d.ts +33 -0
- package/dist/core/codemod.d.ts.map +1 -1
- package/dist/core/codemod.js +116 -0
- package/dist/core/codemod.js.map +1 -1
- package/dist/core/detect.d.ts.map +1 -1
- package/dist/core/detect.js +24 -7
- package/dist/core/detect.js.map +1 -1
- package/dist/core/journal.d.ts +1 -0
- package/dist/core/journal.d.ts.map +1 -1
- package/dist/core/journal.js.map +1 -1
- package/dist/core/recipes.d.ts.map +1 -1
- package/dist/core/recipes.js +25 -7
- package/dist/core/recipes.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/docs/architecture.md +50 -0
- package/docs/commands.md +78 -0
- package/docs/contributing.md +27 -0
- package/docs/quickstart.md +50 -0
- package/docs/recipes.md +57 -0
- package/docs/troubleshooting.md +31 -0
- package/package.json +2 -2
- package/recipes/0/apps/native/src/components/advanced-ui/timeline/demo.tsx +445 -0
- package/recipes/0/apps/native/src/components/advanced-ui/timeline/timeline-view.tsx +355 -0
- package/recipes/0/apps/native/src/components/advanced-ui/timeline/types.ts +31 -0
- package/recipes/0/recipe.json +18 -0
- package/recipes/animated-chip/apps/native/src/components/advanced-ui/chip/demo.tsx +2 -1
- package/recipes/animated-chip/recipe.json +5 -2
- package/recipes/animated-chip-native@latest.zip +0 -0
- package/recipes/animated-chip@latest.zip +0 -0
- package/recipes/animated-switch/apps/native/src/components/advanced-ui/switch/demo.tsx +1 -1
- package/recipes/animated-switch/recipe.json +5 -2
- package/recipes/animated-switch-native@latest.zip +0 -0
- package/recipes/animated-switch@latest.zip +0 -0
- package/recipes/audio-recorder/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +2 -1
- package/recipes/audio-recorder/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +2 -2
- package/recipes/audio-recorder/recipe.json +7 -2
- package/recipes/audio-recorder-native@latest.zip +0 -0
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/components/audio-recorder.tsx +2 -1
- package/recipes/audio-recorder-supabase/apps/native/src/features/audio-recorder/demo/with-recording-list-demo.tsx +2 -1
- package/recipes/audio-recorder-supabase/recipe.json +12 -16
- package/recipes/audio-recorder-supabase-native@latest.zip +0 -0
- package/recipes/audio-recorder-supabase@latest.zip +0 -0
- package/recipes/audio-recorder@latest.zip +0 -0
- package/recipes/charts/apps/native/src/app/charts/index.tsx +3 -0
- package/recipes/charts/apps/native/src/features/charts/components/bar-chart.tsx +3 -1
- package/recipes/charts/apps/native/src/features/charts/components/candlestick-chart.tsx +3 -1
- package/recipes/charts/apps/native/src/features/charts/components/column-chart.tsx +3 -1
- package/recipes/charts/apps/native/src/features/charts/components/doughnut-chart.tsx +3 -1
- package/recipes/charts/apps/native/src/features/charts/components/line-chart.tsx +3 -1
- package/recipes/charts/apps/native/src/features/charts/components/radar-chart.tsx +3 -1
- package/recipes/charts/apps/native/src/features/charts/components/stacked-bar-chart.tsx +3 -1
- package/recipes/charts/recipe.json +13 -4
- package/recipes/charts-native@latest.zip +0 -0
- package/recipes/charts@latest.zip +0 -0
- package/recipes/chatbot/apps/native/src/features/chatbot/components/chat-markdown.tsx +86 -86
- package/recipes/chatbot/apps/native/src/features/chatbot/components/markdown/code-block.tsx +4 -4
- package/recipes/chatbot/recipe.json +3 -40
- package/recipes/chatbot-native@latest.zip +0 -0
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/chat-markdown.tsx +4 -1
- package/recipes/chatbot-supabase/apps/native/src/features/chatbot/components/markdown/code-block.tsx +86 -53
- package/recipes/chatbot-supabase/recipe.json +3 -42
- package/recipes/chatbot-supabase-native@latest.zip +0 -0
- package/recipes/chatbot-supabase@latest.zip +0 -0
- package/recipes/chatbot@latest.zip +0 -0
- package/recipes/glowing-button/recipe.json +6 -2
- package/recipes/glowing-button-native@latest.zip +0 -0
- package/recipes/glowing-button@latest.zip +0 -0
- package/recipes/image-analysis/apps/native/src/app/analysis/[type]/_layout.tsx +5 -0
- package/recipes/image-analysis/apps/native/src/app/analysis/[type]/analysis-options.tsx +50 -0
- package/recipes/image-analysis/apps/native/src/app/analysis/[type]/camera.tsx +2 -0
- package/recipes/image-analysis/apps/native/src/app/analysis/[type]/index.tsx +50 -0
- package/recipes/image-analysis/apps/native/src/app/analysis/[type]/loading.tsx +50 -0
- package/recipes/image-analysis/apps/native/src/app/analysis/[type]/results.tsx +2 -0
- package/recipes/image-analysis/apps/native/src/app/analysis/[type]/trait-details.tsx +3 -0
- package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/analysis-options-screen.tsx +2 -2
- package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/camera.tsx +72 -65
- package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/image-capture-screen.tsx +65 -47
- package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/loading-screen.tsx +43 -2
- package/recipes/image-analysis/apps/native/src/features/image-analyzer/app/loading.tsx +34 -1
- package/recipes/image-analysis/apps/native/src/features/image-analyzer/hooks/use-image-analysis.ts +83 -2
- package/recipes/image-analysis/recipe.json +11 -19
- package/recipes/image-analysis-native@latest.zip +0 -0
- package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/_layout.tsx +5 -0
- package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/analysis-options.tsx +50 -0
- package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/camera.tsx +2 -0
- package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/index.tsx +50 -0
- package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/loading.tsx +50 -0
- package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/results.tsx +2 -0
- package/recipes/image-analysis-supabase/apps/native/src/app/analysis/[type]/trait-details.tsx +3 -0
- package/recipes/image-analysis-supabase/recipe.json +10 -37
- package/recipes/image-analysis-supabase-native@latest.zip +0 -0
- package/recipes/image-analysis-supabase@latest.zip +0 -0
- package/recipes/image-analysis@latest.zip +0 -0
- package/recipes/image-analyzer/apps/native/src/app/(root)/(protected)/image-analyzer/index.tsx +2 -0
- package/recipes/image-generator/apps/native/src/app/image-generator/gallery.tsx +3 -0
- package/recipes/image-generator/apps/native/src/app/image-generator/index.tsx +3 -0
- package/recipes/image-generator/recipe.json +8 -18
- package/recipes/image-generator-native@latest.zip +0 -0
- package/recipes/image-generator-supabase/recipe.json +6 -35
- package/recipes/image-generator-supabase-native@latest.zip +0 -0
- package/recipes/image-generator-supabase@latest.zip +0 -0
- package/recipes/image-generator@latest.zip +0 -0
- package/recipes/ios-widget/recipe.json +18 -119
- package/recipes/ios-widget-native@latest.zip +0 -0
- package/recipes/ios-widget@latest.zip +0 -0
- package/recipes/number-stepper/apps/native/src/components/advanced-ui/stepper/demo.tsx +1 -1
- package/recipes/number-stepper/recipe.json +5 -2
- package/recipes/number-stepper-native@latest.zip +0 -0
- package/recipes/number-stepper@latest.zip +0 -0
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/interactive-onboarding.tsx +11 -18
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/ai-tone-step.tsx +5 -7
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/currency-step.tsx +9 -7
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-ai-step.tsx +8 -7
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-chatbot-step.tsx +6 -5
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-manual-step.tsx +4 -3
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/feature-scan-step.tsx +6 -5
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/main-reason-step.tsx +5 -7
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/notification-step.tsx +7 -6
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/overspend-step.tsx +5 -7
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/personalizing-step.tsx +8 -7
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/rating-step.tsx +6 -5
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/reminder-step.tsx +5 -6
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/safety-step.tsx +5 -4
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/struggle-step.tsx +5 -7
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/steps/welcome-step.tsx +7 -6
- package/recipes/onboarding/apps/native/src/features/onboarding/expense-tracker/components/ui/onboarding-header.tsx +4 -3
- package/recipes/onboarding/recipe.json +9 -6
- package/recipes/onboarding-native@latest.zip +0 -0
- package/recipes/onboarding@latest.zip +0 -0
- package/recipes/payments/apps/native/src/app/paywall/index.tsx +74 -0
- package/recipes/payments/apps/native/src/app/paywall/local.tsx +25 -0
- package/recipes/payments/apps/native/src/app/paywall/remote.tsx +23 -0
- package/recipes/payments/packages/backend/convex/payments.ts +21 -3
- package/recipes/payments/recipe.json +14 -34
- package/recipes/payments-native@latest.zip +0 -0
- package/recipes/payments-supabase/apps/native/src/app/paywall/index.tsx +74 -0
- package/recipes/payments-supabase/apps/native/src/app/paywall/local.tsx +25 -0
- package/recipes/payments-supabase/apps/native/src/app/paywall/remote.tsx +23 -0
- package/recipes/payments-supabase/recipe.json +16 -23
- package/recipes/payments-supabase-native@latest.zip +0 -0
- package/recipes/payments-supabase@latest.zip +0 -0
- package/recipes/payments@latest.zip +0 -0
- package/recipes/posthog/apps/native/src/components/analytics/navigation-tracker.tsx +14 -0
- package/recipes/posthog/apps/native/src/lib/hooks/use-navigation-analytics.ts +44 -0
- package/recipes/posthog/apps/native/src/providers/posthog-provider.tsx +51 -0
- package/recipes/posthog/recipe.json +60 -0
- package/recipes/posthog-native@latest.zip +0 -0
- package/recipes/progress-circle/apps/native/src/components/advanced-ui/progress-bars/progress-circle-page.tsx +1 -1
- package/recipes/progress-circle/recipe.json +5 -2
- package/recipes/progress-circle-native@latest.zip +0 -0
- package/recipes/progress-circle@latest.zip +0 -0
- package/recipes/quiz/apps/native/src/app/quiz/index.tsx +47 -0
- package/recipes/quiz/recipe.json +9 -6
- package/recipes/quiz-native@latest.zip +0 -0
- package/recipes/quiz@latest.zip +0 -0
- package/recipes/screen-kits/apps/native/src/app/screen-kits/_layout.tsx +12 -0
- package/recipes/screen-kits/apps/native/src/app/screen-kits/index.tsx +114 -0
- package/recipes/screen-kits/apps/native/src/features/screen-kits/index.ts +1 -0
- package/recipes/screen-kits/apps/native/src/features/screen-kits/types.ts +28 -0
- package/recipes/screen-kits/recipe.json +26 -0
- package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/_layout.tsx +12 -0
- package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/home.tsx +5 -0
- package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/index.tsx +5 -0
- package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/lesson-complete.tsx +5 -0
- package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/lesson-fail.tsx +5 -0
- package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/lesson.tsx +5 -0
- package/recipes/screen-kits-duolingo/apps/native/src/app/screen-kits/duolingo/skill-tree.tsx +5 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/components/duo-button.tsx +174 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/components/skill-button.tsx +186 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/components/xp-header.tsx +115 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/constants.ts +89 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/index.ts +3 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/home-screen.tsx +225 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/lesson-complete-screen.tsx +485 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/lesson-fail-screen.tsx +105 -0
- package/recipes/screen-kits-duolingo/apps/native/src/features/screen-kits/duolingo/screens/lesson-screen.tsx +384 -0
- package/recipes/screen-kits-duolingo/recipe.json +58 -0
- package/recipes/screen-kits-duolingo-native@latest.zip +0 -0
- package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/_layout.tsx +45 -0
- package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/asset-detail.tsx +3 -0
- package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/notifications.tsx +3 -0
- package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/receive.tsx +3 -0
- package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/send.tsx +3 -0
- package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/swap.tsx +3 -0
- package/recipes/screen-kits-finance/apps/native/src/app/screen-kits/finance/wallet.tsx +3 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/components/ActionButtons.tsx +78 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/components/AssetRow.tsx +94 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/components/BalanceCard.tsx +118 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/constants.ts +85 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/asset-detail.tsx +378 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/notifications.tsx +210 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/receive-modal.tsx +317 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/send-modal.tsx +420 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/swap-modal.tsx +363 -0
- package/recipes/screen-kits-finance/apps/native/src/features/screen-kits/finance/screens/wallet-dashboard.tsx +281 -0
- package/recipes/screen-kits-finance/recipe.json +46 -0
- package/recipes/screen-kits-finance-native@latest.zip +0 -0
- package/recipes/screen-kits-fitness/apps/native/assets/sounds/timer-beep.wav +0 -0
- package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/_layout.tsx +10 -0
- package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/index.tsx +6 -0
- package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/timer.tsx +3 -0
- package/recipes/screen-kits-fitness/apps/native/src/app/screen-kits/fitness/workout.tsx +3 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/components/timer-components.tsx +500 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/components/timer-settings-modal.tsx +352 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/components/workout-card.tsx +105 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/constants.ts +189 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/hooks/use-timer.ts +307 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/index.ts +1 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/screens/timer-screen.tsx +278 -0
- package/recipes/screen-kits-fitness/apps/native/src/features/screen-kits/fitness/screens/workout-dashboard.tsx +350 -0
- package/recipes/screen-kits-fitness/recipe.json +63 -0
- package/recipes/screen-kits-fitness-native@latest.zip +0 -0
- package/recipes/screen-kits-habits/apps/native/src/app/screen-kits/productivity/habits.tsx +1 -0
- package/recipes/screen-kits-habits/apps/native/src/app/screen-kits/productivity/kanban.tsx +1 -0
- package/recipes/screen-kits-habits/apps/native/src/app/screen-kits/productivity/routes.ts +4 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/AddTaskModal.tsx +246 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/DraggableTaskCard.tsx +92 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/KanbanColumn.tsx +238 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/TaskCard.tsx +144 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/components/add-habit-modal.tsx +271 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/constants.ts +295 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/kanban-utils.ts +62 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/screens/habit-tracker.tsx +1160 -0
- package/recipes/screen-kits-habits/apps/native/src/features/screen-kits/productivity/screens/kanban-board.tsx +432 -0
- package/recipes/screen-kits-habits/recipe.json +52 -0
- package/recipes/screen-kits-habits-native@latest.zip +0 -0
- package/recipes/screen-kits-native@latest.zip +0 -0
- package/recipes/sentry/apps/native/src/providers/sentry-provider.tsx +64 -0
- package/recipes/sentry/recipe.json +39 -0
- package/recipes/sentry-native@latest.zip +0 -0
- package/recipes/swipe-slider/apps/native/src/components/advanced-ui/sliders/swipe-slider-page.tsx +1 -1
- package/recipes/swipe-slider/recipe.json +5 -2
- package/recipes/swipe-slider-native@latest.zip +0 -0
- package/recipes/swipe-slider@latest.zip +0 -0
- package/recipes/timeline/apps/native/src/components/advanced-ui/timeline/demo.tsx +2 -1
- package/recipes/timeline/recipe.json +5 -2
- package/recipes/timeline-native@latest.zip +0 -0
- package/recipes/timeline@latest.zip +0 -0
- package/recipes/tracker-app/apps/native/src/app/tracker-app/index.tsx +1 -0
- package/recipes/tracker-app/recipe.json +10 -7
- package/recipes/tracker-app-native@latest.zip +0 -0
- package/recipes/tracker-app@latest.zip +0 -0
- package/recipes/upload-all.sh +8 -31
- package/recipes/voice-bot/apps/native/src/app/voice-bot/index.tsx +56 -0
- package/recipes/voice-bot/recipe.json +31 -7
- package/recipes/voice-bot-native@latest.zip +0 -0
- package/recipes/voice-bot@latest.zip +0 -0
- package/recipes/wake-word/apps/native/src/app/{(root)/(protected)/test-wake-word.tsx → test-wake-word.tsx} +43 -4
- package/recipes/wake-word/recipe.json +16 -26
- package/recipes/wake-word-native@latest.zip +0 -0
- package/recipes/wake-word@latest.zip +0 -0
- package/scripts/create-advanced-ui-recipes.sh +46 -19
- package/scripts/create-recipes.mjs +471 -117
- package/scripts/package-recipes.mjs +76 -0
- package/scripts/publish-all.sh +6 -2
- package/CHANGELOG.md +0 -198
- package/docs/archive/AUTO-DETECT-DEPS.md +0 -607
- package/docs/archive/FINAL-PACKAGE-STRATEGY.md +0 -583
- package/docs/archive/FINAL-SIMPLE-PLAN.md +0 -487
- package/docs/archive/FINAL-STATUS.md +0 -144
- package/docs/archive/FLOW-DIAGRAM.md +0 -1629
- package/docs/archive/GOTCHAS-AND-RISKS.md +0 -801
- package/docs/archive/IMPLEMENTATION-PLAN.md +0 -1360
- package/docs/archive/PLAN.md +0 -453
- package/docs/archive/PRODUCTION-READINESS.md +0 -684
- package/docs/archive/PRODUCTION-TEST-RESULTS.md +0 -465
- package/docs/archive/SIMPLIFIED-PLAN.md +0 -578
- package/docs/archive/STATUS.md +0 -199
- package/docs/archive/SUCCESS.md +0 -259
- package/docs/archive/TEST-SUMMARY.md +0 -261
- package/docs/archive/TESTING-CHECKLIST.md +0 -450
- package/docs/archive/USER-MODIFICATIONS.md +0 -448
- package/docs/decisions.md +0 -55
- package/docs/manual-testing.md +0 -91
- package/docs/next-steps.md +0 -12
- package/recipes/README.md +0 -156
- package/recipes/audio-recorder-supabase/packages/backend/src/services/recordings.ts +0 -369
- package/recipes/chatbot/apps/native/src/api-client/chatbot.ts +0 -83
- package/recipes/chatbot/packages/backend/convex/agents.ts +0 -115
- package/recipes/chatbot/packages/backend/convex/tools/index.ts +0 -18
- package/recipes/chatbot/packages/backend/convex/tools/knowledgeRetrieval.ts +0 -97
- package/recipes/chatbot/packages/backend/convex/tools/tavilySearch.ts +0 -83
- package/recipes/chatbot/packages/backend/convex/tools/userProfile.ts +0 -72
- package/recipes/chatbot-supabase/apps/native/src/api-client/supabase/chatbot.ts +0 -515
- package/recipes/chatbot-supabase/packages/backend/src/services/conversations.ts +0 -243
- package/recipes/chatbot-supabase/packages/backend/src/services/messages.ts +0 -327
- package/recipes/image-analysis/apps/native/src/api-client/image-analyzer.ts +0 -62
- package/recipes/image-analysis-supabase/packages/backend/src/services/image-analyses.ts +0 -132
- package/recipes/image-generator/apps/native/src/api-client/image-generator.ts +0 -34
- package/recipes/payments/apps/native/src/api-client/payments.ts +0 -44
- package/recipes/payments-supabase/packages/backend/src/services/payments.ts +0 -201
- package/recipes/posthog.json +0 -47
- package/recipes/revenuecat.json +0 -43
- package/recipes/sentry.json +0 -47
- package/recipes/wake-word/apps/native/assets/vosk-model/README.md +0 -103
- package/recipes/wake-word/apps/native/scripts/download-vosk-model.mjs +0 -127
- /package/recipes/{audio-recorder/apps/native/src/app/(root)/(protected) → audio-recorder-supabase/apps/native/src/app}/audio-recorder/index.tsx +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/AppIntent.swift +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Assets.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/CalorieTrackerWidget.swift +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/HabitTrackerWidget.swift +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/Info.plist +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/WidgetLiveActivity.swift +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/expo-target.config.js +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/generated.entitlements +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/index.swift +0 -0
- /package/recipes/ios-widget/{targets → apps/native/targets}/widget/widgets.swift +0 -0
|
@@ -1,607 +0,0 @@
|
|
|
1
|
-
# 🔍 Auto-Detecting Missing Dependencies
|
|
2
|
-
|
|
3
|
-
## The Problem
|
|
4
|
-
|
|
5
|
-
When we install a feature, we copy files that import packages:
|
|
6
|
-
following is an example we aint using that pck name in reality:
|
|
7
|
-
```typescript
|
|
8
|
-
// apps/native/src/features/charts/index.tsx
|
|
9
|
-
import { LineChart } from 'react-native-chart-kit'; // ← Package not installed!
|
|
10
|
-
import { Dimensions } from 'react-native';
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
If `react-native-chart-kit` isn't installed, the app will crash or fail to build.
|
|
14
|
-
|
|
15
|
-
## The Question
|
|
16
|
-
|
|
17
|
-
Can we **automatically detect** what packages are missing instead of manually specifying them in recipe.json?
|
|
18
|
-
|
|
19
|
-
**Answer: YES!** Multiple approaches:
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## Approach 1: Run TypeScript Type Checking ✅ BEST
|
|
24
|
-
|
|
25
|
-
### How It Works
|
|
26
|
-
|
|
27
|
-
TypeScript will error on missing packages:
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
$ pnpm tsc --noEmit
|
|
31
|
-
# Output:
|
|
32
|
-
# error TS2307: Cannot find module 'react-native-chart-kit' or its corresponding type declarations.
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
### Implementation
|
|
36
|
-
|
|
37
|
-
**File:** `src/core/typecheck.ts` (NEW)
|
|
38
|
-
|
|
39
|
-
```typescript
|
|
40
|
-
import { executeBash } from './shell.js';
|
|
41
|
-
import { log } from './log.js';
|
|
42
|
-
|
|
43
|
-
export interface TypeCheckResult {
|
|
44
|
-
success: boolean;
|
|
45
|
-
missingPackages: string[];
|
|
46
|
-
errors: string[];
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export async function runTypeCheck(cwd: string): Promise<TypeCheckResult> {
|
|
50
|
-
log.info('Running type check to detect missing packages...');
|
|
51
|
-
|
|
52
|
-
// Try different type checkers in order of preference
|
|
53
|
-
const checkers = [
|
|
54
|
-
{ cmd: 'pnpm tsc --noEmit', name: 'pnpm' },
|
|
55
|
-
{ cmd: 'yarn tsc --noEmit', name: 'yarn' },
|
|
56
|
-
{ cmd: 'npx tsc --noEmit', name: 'npm' },
|
|
57
|
-
];
|
|
58
|
-
|
|
59
|
-
let result;
|
|
60
|
-
for (const checker of checkers) {
|
|
61
|
-
result = await executeBash(checker.cmd, { cwd });
|
|
62
|
-
if (result.exitCode !== 127) { // 127 = command not found
|
|
63
|
-
break;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (!result || result.exitCode === 127) {
|
|
68
|
-
log.warn('TypeScript not found, skipping type check');
|
|
69
|
-
return { success: true, missingPackages: [], errors: [] };
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Parse TypeScript errors
|
|
73
|
-
const missingPackages = new Set<string>();
|
|
74
|
-
const errors: string[] = [];
|
|
75
|
-
|
|
76
|
-
const lines = result.stderr.split('\n');
|
|
77
|
-
|
|
78
|
-
for (const line of lines) {
|
|
79
|
-
// Match: error TS2307: Cannot find module 'package-name'
|
|
80
|
-
const match = line.match(/error TS2307: Cannot find module '([^']+)'/);
|
|
81
|
-
if (match) {
|
|
82
|
-
const moduleName = match[1];
|
|
83
|
-
|
|
84
|
-
// Extract package name (handle scoped packages and subpaths)
|
|
85
|
-
const packageName = extractPackageName(moduleName);
|
|
86
|
-
|
|
87
|
-
if (packageName && !isBuiltInModule(packageName)) {
|
|
88
|
-
missingPackages.add(packageName);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// Collect all errors for debugging
|
|
93
|
-
if (line.includes('error TS')) {
|
|
94
|
-
errors.push(line);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
return {
|
|
99
|
-
success: result.exitCode === 0,
|
|
100
|
-
missingPackages: Array.from(missingPackages),
|
|
101
|
-
errors,
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function extractPackageName(modulePath: string): string | null {
|
|
106
|
-
// Handle different import patterns:
|
|
107
|
-
// 'react-native-chart-kit' → 'react-native-chart-kit'
|
|
108
|
-
// 'react-native-chart-kit/dist/LineChart' → 'react-native-chart-kit'
|
|
109
|
-
// '@react-navigation/native' → '@react-navigation/native'
|
|
110
|
-
// '@react-navigation/native/lib/index' → '@react-navigation/native'
|
|
111
|
-
|
|
112
|
-
if (modulePath.startsWith('@')) {
|
|
113
|
-
// Scoped package: @scope/package
|
|
114
|
-
const parts = modulePath.split('/');
|
|
115
|
-
if (parts.length >= 2) {
|
|
116
|
-
return `${parts[0]}/${parts[1]}`;
|
|
117
|
-
}
|
|
118
|
-
} else {
|
|
119
|
-
// Regular package: package-name
|
|
120
|
-
const parts = modulePath.split('/');
|
|
121
|
-
return parts[0];
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
return null;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
function isBuiltInModule(packageName: string): boolean {
|
|
128
|
-
// Node.js built-in modules
|
|
129
|
-
const builtIns = [
|
|
130
|
-
'fs', 'path', 'crypto', 'http', 'https', 'url', 'util',
|
|
131
|
-
'stream', 'events', 'buffer', 'process', 'os', 'child_process',
|
|
132
|
-
];
|
|
133
|
-
|
|
134
|
-
// React Native built-ins
|
|
135
|
-
const rnBuiltIns = [
|
|
136
|
-
'react-native',
|
|
137
|
-
'react',
|
|
138
|
-
];
|
|
139
|
-
|
|
140
|
-
return builtIns.includes(packageName) || rnBuiltIns.includes(packageName);
|
|
141
|
-
}
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### Usage in add command
|
|
145
|
-
|
|
146
|
-
**File:** `src/commands/add.ts`
|
|
147
|
-
|
|
148
|
-
```typescript
|
|
149
|
-
// After copying files, BEFORE adding watermarks
|
|
150
|
-
|
|
151
|
-
if (!options.dryRun && !options.skipTypeCheck) {
|
|
152
|
-
log.plain('');
|
|
153
|
-
log.info('🔍 Checking for missing dependencies...');
|
|
154
|
-
|
|
155
|
-
const typeCheckResult = await runTypeCheck(paths.cwd);
|
|
156
|
-
|
|
157
|
-
if (typeCheckResult.missingPackages.length > 0) {
|
|
158
|
-
log.plain('');
|
|
159
|
-
log.warn('⚠ Missing packages detected:');
|
|
160
|
-
log.plain('');
|
|
161
|
-
|
|
162
|
-
typeCheckResult.missingPackages.forEach(pkg => {
|
|
163
|
-
log.plain(` • ${pkg}`);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
log.plain('');
|
|
167
|
-
|
|
168
|
-
// Try to find versions from recipe.json if available
|
|
169
|
-
const packagesWithVersions: Record<string, string> = {};
|
|
170
|
-
|
|
171
|
-
if (manifest.dependencies?.npm) {
|
|
172
|
-
typeCheckResult.missingPackages.forEach(pkg => {
|
|
173
|
-
if (manifest.dependencies.npm[pkg]) {
|
|
174
|
-
packagesWithVersions[pkg] = manifest.dependencies.npm[pkg];
|
|
175
|
-
} else {
|
|
176
|
-
// Default to latest
|
|
177
|
-
packagesWithVersions[pkg] = 'latest';
|
|
178
|
-
}
|
|
179
|
-
});
|
|
180
|
-
} else {
|
|
181
|
-
// No recipe dependencies, use latest for all
|
|
182
|
-
typeCheckResult.missingPackages.forEach(pkg => {
|
|
183
|
-
packagesWithVersions[pkg] = 'latest';
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Show install command
|
|
188
|
-
const pm = await detectPackageManager(paths.cwd);
|
|
189
|
-
const pkgList = Object.entries(packagesWithVersions)
|
|
190
|
-
.map(([name, version]) => version === 'latest' ? name : `${name}@${version}`)
|
|
191
|
-
.join(' ');
|
|
192
|
-
const installCmd = getInstallCommand(pm, pkgList.split(' '));
|
|
193
|
-
|
|
194
|
-
log.info('📦 Install with:');
|
|
195
|
-
log.plain(` ${installCmd}`);
|
|
196
|
-
log.plain('');
|
|
197
|
-
|
|
198
|
-
// Ask to install
|
|
199
|
-
if (!options.yes) {
|
|
200
|
-
const shouldInstall = promptYesNo(
|
|
201
|
-
'Install missing packages now? (Y/n): ',
|
|
202
|
-
true
|
|
203
|
-
);
|
|
204
|
-
|
|
205
|
-
if (shouldInstall) {
|
|
206
|
-
log.info('Installing packages...');
|
|
207
|
-
const result = await installPackages(packagesWithVersions, paths.cwd);
|
|
208
|
-
|
|
209
|
-
if (result.success) {
|
|
210
|
-
log.success('✓ Packages installed successfully!');
|
|
211
|
-
|
|
212
|
-
// Run type check again to verify
|
|
213
|
-
log.info('Verifying installation...');
|
|
214
|
-
const verifyResult = await runTypeCheck(paths.cwd);
|
|
215
|
-
|
|
216
|
-
if (verifyResult.missingPackages.length > 0) {
|
|
217
|
-
log.warn('⚠ Some packages are still missing:');
|
|
218
|
-
verifyResult.missingPackages.forEach(pkg => {
|
|
219
|
-
log.plain(` • ${pkg}`);
|
|
220
|
-
});
|
|
221
|
-
} else {
|
|
222
|
-
log.success('✓ All dependencies resolved!');
|
|
223
|
-
}
|
|
224
|
-
} else {
|
|
225
|
-
log.error(`✗ Installation failed: ${result.error}`);
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
} else {
|
|
229
|
-
// Auto-install in --yes mode
|
|
230
|
-
log.info('Installing packages...');
|
|
231
|
-
const result = await installPackages(packagesWithVersions, paths.cwd);
|
|
232
|
-
|
|
233
|
-
if (!result.success) {
|
|
234
|
-
log.error(`✗ Installation failed: ${result.error}`);
|
|
235
|
-
process.exit(1);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
} else if (typeCheckResult.success) {
|
|
239
|
-
log.success('✓ No missing dependencies detected');
|
|
240
|
-
} else {
|
|
241
|
-
log.warn('⚠ Type check completed with errors (but no missing packages)');
|
|
242
|
-
if (typeCheckResult.errors.length > 0 && process.env.DEBUG) {
|
|
243
|
-
log.plain('');
|
|
244
|
-
log.plain('Errors:');
|
|
245
|
-
typeCheckResult.errors.slice(0, 5).forEach(err => {
|
|
246
|
-
log.plain(` ${err}`);
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
```
|
|
252
|
-
|
|
253
|
-
### Add CLI flag
|
|
254
|
-
|
|
255
|
-
```typescript
|
|
256
|
-
export const addCommand = new Command('add')
|
|
257
|
-
.description('Add a VibeFast feature to your project')
|
|
258
|
-
.argument('<feature>', 'Feature name to install')
|
|
259
|
-
.option('--target <target>', 'Target platform (native or web)', 'native')
|
|
260
|
-
.option('--dry-run', 'Preview changes without applying')
|
|
261
|
-
.option('--force', 'Overwrite existing files without asking')
|
|
262
|
-
.option('--yes', 'Answer yes to all prompts')
|
|
263
|
-
.option('--skip-install', 'Skip package installation')
|
|
264
|
-
.option('--skip-type-check', 'Skip type checking for missing packages') // NEW
|
|
265
|
-
.action(async (feature: string, options) => {
|
|
266
|
-
// ...
|
|
267
|
-
});
|
|
268
|
-
```
|
|
269
|
-
|
|
270
|
-
---
|
|
271
|
-
|
|
272
|
-
## Approach 2: Parse Import Statements 🟡 FALLBACK
|
|
273
|
-
|
|
274
|
-
If TypeScript isn't available, parse imports manually.
|
|
275
|
-
|
|
276
|
-
### Implementation
|
|
277
|
-
|
|
278
|
-
**File:** `src/core/importParser.ts` (NEW)
|
|
279
|
-
|
|
280
|
-
```typescript
|
|
281
|
-
import { readFile } from 'fs/promises';
|
|
282
|
-
import { join } from 'path';
|
|
283
|
-
|
|
284
|
-
export async function extractImports(filePath: string): Promise<string[]> {
|
|
285
|
-
const content = await readFile(filePath, 'utf-8');
|
|
286
|
-
const imports = new Set<string>();
|
|
287
|
-
|
|
288
|
-
// Match various import patterns
|
|
289
|
-
const patterns = [
|
|
290
|
-
// import X from 'package'
|
|
291
|
-
/import\s+.*?\s+from\s+['"]([^'"]+)['"]/g,
|
|
292
|
-
// import 'package'
|
|
293
|
-
/import\s+['"]([^'"]+)['"]/g,
|
|
294
|
-
// require('package')
|
|
295
|
-
/require\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
|
|
296
|
-
// import('package')
|
|
297
|
-
/import\s*\(\s*['"]([^'"]+)['"]\s*\)/g,
|
|
298
|
-
];
|
|
299
|
-
|
|
300
|
-
for (const pattern of patterns) {
|
|
301
|
-
let match;
|
|
302
|
-
while ((match = pattern.exec(content)) !== null) {
|
|
303
|
-
const importPath = match[1];
|
|
304
|
-
|
|
305
|
-
// Skip relative imports
|
|
306
|
-
if (importPath.startsWith('.') || importPath.startsWith('/')) {
|
|
307
|
-
continue;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
imports.add(importPath);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
return Array.from(imports);
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
export async function extractImportsFromFiles(
|
|
318
|
-
filePaths: string[]
|
|
319
|
-
): Promise<string[]> {
|
|
320
|
-
const allImports = new Set<string>();
|
|
321
|
-
|
|
322
|
-
for (const filePath of filePaths) {
|
|
323
|
-
// Only parse JS/TS files
|
|
324
|
-
if (!/\.(js|jsx|ts|tsx)$/.test(filePath)) {
|
|
325
|
-
continue;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
try {
|
|
329
|
-
const imports = await extractImports(filePath);
|
|
330
|
-
imports.forEach(imp => allImports.add(imp));
|
|
331
|
-
} catch (error) {
|
|
332
|
-
// Skip files that can't be read
|
|
333
|
-
continue;
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
return Array.from(allImports).map(extractPackageName).filter(Boolean) as string[];
|
|
338
|
-
}
|
|
339
|
-
```
|
|
340
|
-
|
|
341
|
-
### Check Against Installed Packages
|
|
342
|
-
|
|
343
|
-
**File:** `src/core/packageChecker.ts` (NEW)
|
|
344
|
-
|
|
345
|
-
```typescript
|
|
346
|
-
import { readFile } from 'fs/promises';
|
|
347
|
-
import { join } from 'path';
|
|
348
|
-
import { exists } from './fsx.js';
|
|
349
|
-
|
|
350
|
-
export async function getInstalledPackages(cwd: string): Promise<Set<string>> {
|
|
351
|
-
const packageJsonPath = join(cwd, 'package.json');
|
|
352
|
-
|
|
353
|
-
if (!await exists(packageJsonPath)) {
|
|
354
|
-
return new Set();
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
const content = await readFile(packageJsonPath, 'utf-8');
|
|
358
|
-
const packageJson = JSON.parse(content);
|
|
359
|
-
|
|
360
|
-
const installed = new Set<string>();
|
|
361
|
-
|
|
362
|
-
// Add dependencies
|
|
363
|
-
if (packageJson.dependencies) {
|
|
364
|
-
Object.keys(packageJson.dependencies).forEach(pkg => installed.add(pkg));
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
// Add devDependencies
|
|
368
|
-
if (packageJson.devDependencies) {
|
|
369
|
-
Object.keys(packageJson.devDependencies).forEach(pkg => installed.add(pkg));
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
return installed;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
export async function findMissingPackages(
|
|
376
|
-
requiredPackages: string[],
|
|
377
|
-
cwd: string
|
|
378
|
-
): Promise<string[]> {
|
|
379
|
-
const installed = await getInstalledPackages(cwd);
|
|
380
|
-
|
|
381
|
-
return requiredPackages.filter(pkg => !installed.has(pkg));
|
|
382
|
-
}
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
### Usage
|
|
386
|
-
|
|
387
|
-
```typescript
|
|
388
|
-
// After copying files
|
|
389
|
-
|
|
390
|
-
// Extract imports from copied files
|
|
391
|
-
const imports = await extractImportsFromFiles(copiedFiles);
|
|
392
|
-
|
|
393
|
-
// Check which are missing
|
|
394
|
-
const missing = await findMissingPackages(imports, paths.cwd);
|
|
395
|
-
|
|
396
|
-
if (missing.length > 0) {
|
|
397
|
-
log.warn('⚠ Missing packages detected:');
|
|
398
|
-
missing.forEach(pkg => log.plain(` • ${pkg}`));
|
|
399
|
-
// ... prompt to install
|
|
400
|
-
}
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
---
|
|
404
|
-
|
|
405
|
-
## Approach 3: Run ESLint 🟢 BONUS
|
|
406
|
-
|
|
407
|
-
If the project has ESLint configured:
|
|
408
|
-
|
|
409
|
-
```typescript
|
|
410
|
-
export async function runESLint(cwd: string): Promise<string[]> {
|
|
411
|
-
const result = await executeBash('npx eslint . --format json', { cwd });
|
|
412
|
-
|
|
413
|
-
if (result.exitCode === 0) {
|
|
414
|
-
return [];
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
try {
|
|
418
|
-
const eslintOutput = JSON.parse(result.stdout);
|
|
419
|
-
const missingPackages = new Set<string>();
|
|
420
|
-
|
|
421
|
-
eslintOutput.forEach((file: any) => {
|
|
422
|
-
file.messages.forEach((msg: any) => {
|
|
423
|
-
// ESLint rule: import/no-unresolved
|
|
424
|
-
if (msg.ruleId === 'import/no-unresolved') {
|
|
425
|
-
const match = msg.message.match(/Unable to resolve path to module '([^']+)'/);
|
|
426
|
-
if (match) {
|
|
427
|
-
const packageName = extractPackageName(match[1]);
|
|
428
|
-
if (packageName) {
|
|
429
|
-
missingPackages.add(packageName);
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
});
|
|
434
|
-
});
|
|
435
|
-
|
|
436
|
-
return Array.from(missingPackages);
|
|
437
|
-
} catch (error) {
|
|
438
|
-
return [];
|
|
439
|
-
}
|
|
440
|
-
}
|
|
441
|
-
```
|
|
442
|
-
|
|
443
|
-
---
|
|
444
|
-
|
|
445
|
-
## Recommended Strategy: Hybrid Approach
|
|
446
|
-
|
|
447
|
-
### Step 1: Try TypeScript (Most Accurate)
|
|
448
|
-
```typescript
|
|
449
|
-
const typeCheckResult = await runTypeCheck(paths.cwd);
|
|
450
|
-
if (typeCheckResult.missingPackages.length > 0) {
|
|
451
|
-
return typeCheckResult.missingPackages;
|
|
452
|
-
}
|
|
453
|
-
```
|
|
454
|
-
|
|
455
|
-
### Step 2: Fallback to Import Parsing
|
|
456
|
-
```typescript
|
|
457
|
-
if (!typeCheckResult.success && typeCheckResult.missingPackages.length === 0) {
|
|
458
|
-
// TypeScript failed or not available, try parsing
|
|
459
|
-
const imports = await extractImportsFromFiles(copiedFiles);
|
|
460
|
-
const missing = await findMissingPackages(imports, paths.cwd);
|
|
461
|
-
return missing;
|
|
462
|
-
}
|
|
463
|
-
```
|
|
464
|
-
|
|
465
|
-
### Step 3: Use Recipe as Source of Truth
|
|
466
|
-
```typescript
|
|
467
|
-
// If detection fails, fall back to recipe.json
|
|
468
|
-
if (manifest.dependencies?.npm) {
|
|
469
|
-
return Object.keys(manifest.dependencies.npm);
|
|
470
|
-
}
|
|
471
|
-
```
|
|
472
|
-
|
|
473
|
-
---
|
|
474
|
-
|
|
475
|
-
## Complete Flow
|
|
476
|
-
|
|
477
|
-
```
|
|
478
|
-
┌─────────────────────────────────────────────────────────────────┐
|
|
479
|
-
│ DEPENDENCY DETECTION FLOW │
|
|
480
|
-
└─────────────────────────────────────────────────────────────────┘
|
|
481
|
-
|
|
482
|
-
Step 1: Install Feature Files
|
|
483
|
-
┌──────────────────────────────────────────────────────────────┐
|
|
484
|
-
│ $ vf add charts │
|
|
485
|
-
│ ✓ Files copied: 17 │
|
|
486
|
-
└──────────────────────────────────────────────────────────────┘
|
|
487
|
-
│
|
|
488
|
-
▼
|
|
489
|
-
Step 2: Run Type Check
|
|
490
|
-
┌──────────────────────────────────────────────────────────────┐
|
|
491
|
-
│ $ pnpm tsc --noEmit │
|
|
492
|
-
│ │
|
|
493
|
-
│ Output: │
|
|
494
|
-
│ error TS2307: Cannot find module 'react-native-chart-kit' │
|
|
495
|
-
│ error TS2307: Cannot find module 'react-native-svg' │
|
|
496
|
-
└──────────────────────────────────────────────────────────────┘
|
|
497
|
-
│
|
|
498
|
-
▼
|
|
499
|
-
Step 3: Parse Errors
|
|
500
|
-
┌──────────────────────────────────────────────────────────────┐
|
|
501
|
-
│ Detected missing packages: │
|
|
502
|
-
│ • react-native-chart-kit │
|
|
503
|
-
│ • react-native-svg │
|
|
504
|
-
└──────────────────────────────────────────────────────────────┘
|
|
505
|
-
│
|
|
506
|
-
▼
|
|
507
|
-
Step 4: Check Recipe for Versions
|
|
508
|
-
┌──────────────────────────────────────────────────────────────┐
|
|
509
|
-
│ recipe.json has: │
|
|
510
|
-
│ { │
|
|
511
|
-
│ "dependencies": { │
|
|
512
|
-
│ "npm": { │
|
|
513
|
-
│ "react-native-chart-kit": "^6.12.0", │
|
|
514
|
-
│ "react-native-svg": "^13.9.0" │
|
|
515
|
-
│ } │
|
|
516
|
-
│ } │
|
|
517
|
-
│ } │
|
|
518
|
-
│ │
|
|
519
|
-
│ Use these versions ✓ │
|
|
520
|
-
└──────────────────────────────────────────────────────────────┘
|
|
521
|
-
│
|
|
522
|
-
▼
|
|
523
|
-
Step 5: Prompt User
|
|
524
|
-
┌──────────────────────────────────────────────────────────────┐
|
|
525
|
-
│ ⚠ Missing packages detected: │
|
|
526
|
-
│ • react-native-chart-kit@^6.12.0 │
|
|
527
|
-
│ • react-native-svg@^13.9.0 │
|
|
528
|
-
│ │
|
|
529
|
-
│ 📦 Install with: │
|
|
530
|
-
│ pnpm add react-native-chart-kit@^6.12.0 react-native-svg@^13.9.0
|
|
531
|
-
│ │
|
|
532
|
-
│ Install missing packages now? (Y/n): _ │
|
|
533
|
-
└──────────────────────────────────────────────────────────────┘
|
|
534
|
-
│
|
|
535
|
-
▼
|
|
536
|
-
Step 6: Install Packages
|
|
537
|
-
┌──────────────────────────────────────────────────────────────┐
|
|
538
|
-
│ $ pnpm add react-native-chart-kit@^6.12.0 react-native-svg@^13.9.0
|
|
539
|
-
│ ✓ Packages installed │
|
|
540
|
-
└──────────────────────────────────────────────────────────────┘
|
|
541
|
-
│
|
|
542
|
-
▼
|
|
543
|
-
Step 7: Verify
|
|
544
|
-
┌──────────────────────────────────────────────────────────────┐
|
|
545
|
-
│ $ pnpm tsc --noEmit │
|
|
546
|
-
│ ✓ No errors │
|
|
547
|
-
│ ✓ All dependencies resolved! │
|
|
548
|
-
└──────────────────────────────────────────────────────────────┘
|
|
549
|
-
```
|
|
550
|
-
|
|
551
|
-
---
|
|
552
|
-
|
|
553
|
-
## Advantages of This Approach
|
|
554
|
-
|
|
555
|
-
1. **Automatic Detection** - No need to manually specify in recipe.json
|
|
556
|
-
2. **Accurate** - TypeScript knows exactly what's missing
|
|
557
|
-
3. **Version Aware** - Can still use recipe.json for specific versions
|
|
558
|
-
4. **Fallback** - Import parsing if TypeScript not available
|
|
559
|
-
5. **Verification** - Can re-run type check after install to confirm
|
|
560
|
-
|
|
561
|
-
## Disadvantages
|
|
562
|
-
|
|
563
|
-
1. **Slower** - Type checking takes 5-30 seconds
|
|
564
|
-
2. **Requires TypeScript** - Not all projects have it
|
|
565
|
-
3. **False Positives** - Might detect unrelated errors
|
|
566
|
-
4. **Version Guessing** - If not in recipe.json, defaults to 'latest'
|
|
567
|
-
|
|
568
|
-
---
|
|
569
|
-
|
|
570
|
-
## Recommendation
|
|
571
|
-
|
|
572
|
-
**Use BOTH approaches:**
|
|
573
|
-
|
|
574
|
-
1. **Recipe.json as primary** (fast, explicit, version-controlled)
|
|
575
|
-
2. **Type checking as verification** (catch missing deps in recipe.json)
|
|
576
|
-
|
|
577
|
-
```typescript
|
|
578
|
-
// After copying files
|
|
579
|
-
|
|
580
|
-
// 1. Check recipe.json first
|
|
581
|
-
if (manifest.dependencies?.npm) {
|
|
582
|
-
const recipeDeps = manifest.dependencies.npm;
|
|
583
|
-
// Show and install these
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
// 2. Run type check to verify
|
|
587
|
-
const typeCheckResult = await runTypeCheck(paths.cwd);
|
|
588
|
-
if (typeCheckResult.missingPackages.length > 0) {
|
|
589
|
-
log.warn('⚠ Additional missing packages detected:');
|
|
590
|
-
// Show packages not in recipe.json
|
|
591
|
-
const additional = typeCheckResult.missingPackages.filter(
|
|
592
|
-
pkg => !recipeDeps[pkg]
|
|
593
|
-
);
|
|
594
|
-
|
|
595
|
-
if (additional.length > 0) {
|
|
596
|
-
log.warn('These packages are missing from recipe.json:');
|
|
597
|
-
additional.forEach(pkg => log.plain(` • ${pkg}`));
|
|
598
|
-
log.info('Consider updating the recipe to include these.');
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
```
|
|
602
|
-
|
|
603
|
-
This gives us:
|
|
604
|
-
- ✅ Fast installation (recipe.json)
|
|
605
|
-
- ✅ Verification (type check)
|
|
606
|
-
- ✅ Catches recipe mistakes
|
|
607
|
-
- ✅ Best of both worlds
|