ugly-app 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/settings.local.json +18 -0
- package/.env.example +9 -0
- package/.yarn-metadata.json +113 -0
- package/README.md +709 -0
- package/dist/cli/authCommands.d.ts +6 -0
- package/dist/cli/authCommands.d.ts.map +1 -0
- package/dist/cli/authCommands.js +50 -0
- package/dist/cli/authCommands.js.map +1 -0
- package/dist/cli/build.d.ts +2 -0
- package/dist/cli/build.d.ts.map +1 -0
- package/dist/cli/build.js +26 -0
- package/dist/cli/build.js.map +1 -0
- package/dist/cli/configure.d.ts +2 -0
- package/dist/cli/configure.d.ts.map +1 -0
- package/dist/cli/configure.js +53 -0
- package/dist/cli/configure.js.map +1 -0
- package/dist/cli/dev.d.ts +2 -0
- package/dist/cli/dev.d.ts.map +1 -0
- package/dist/cli/dev.js +66 -0
- package/dist/cli/dev.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +340 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/initDb.d.ts +2 -0
- package/dist/cli/initDb.d.ts.map +1 -0
- package/dist/cli/initDb.js +110 -0
- package/dist/cli/initDb.js.map +1 -0
- package/dist/cli/logQuery.d.ts +12 -0
- package/dist/cli/logQuery.d.ts.map +1 -0
- package/dist/cli/logQuery.js +176 -0
- package/dist/cli/logQuery.js.map +1 -0
- package/dist/cli/migrate.d.ts +4 -0
- package/dist/cli/migrate.d.ts.map +1 -0
- package/dist/cli/migrate.js +62 -0
- package/dist/cli/migrate.js.map +1 -0
- package/dist/cli/publishAssets.d.ts +6 -0
- package/dist/cli/publishAssets.d.ts.map +1 -0
- package/dist/cli/publishAssets.js +87 -0
- package/dist/cli/publishAssets.js.map +1 -0
- package/dist/cli/purgeAssets.d.ts +2 -0
- package/dist/cli/purgeAssets.d.ts.map +1 -0
- package/dist/cli/purgeAssets.js +36 -0
- package/dist/cli/purgeAssets.js.map +1 -0
- package/dist/cli/scaffold.d.ts +2 -0
- package/dist/cli/scaffold.d.ts.map +1 -0
- package/dist/cli/scaffold.js +37 -0
- package/dist/cli/scaffold.js.map +1 -0
- package/dist/cli/serverLogQuery.d.ts +6 -0
- package/dist/cli/serverLogQuery.d.ts.map +1 -0
- package/dist/cli/serverLogQuery.js +76 -0
- package/dist/cli/serverLogQuery.js.map +1 -0
- package/dist/cli/storageClient.d.ts +3 -0
- package/dist/cli/storageClient.d.ts.map +1 -0
- package/dist/cli/storageClient.js +22 -0
- package/dist/cli/storageClient.js.map +1 -0
- package/dist/cli/uglyappConfig.d.ts +29 -0
- package/dist/cli/uglyappConfig.d.ts.map +1 -0
- package/dist/cli/uglyappConfig.js +125 -0
- package/dist/cli/uglyappConfig.js.map +1 -0
- package/dist/client/AppProvider.d.ts +32 -0
- package/dist/client/AppProvider.d.ts.map +1 -0
- package/dist/client/AppProvider.js +126 -0
- package/dist/client/AppProvider.js.map +1 -0
- package/dist/client/ErrorLog.d.ts +16 -0
- package/dist/client/ErrorLog.d.ts.map +1 -0
- package/dist/client/ErrorLog.js +28 -0
- package/dist/client/ErrorLog.js.map +1 -0
- package/dist/client/FeedbackContext.d.ts +7 -0
- package/dist/client/FeedbackContext.d.ts.map +1 -0
- package/dist/client/FeedbackContext.js +15 -0
- package/dist/client/FeedbackContext.js.map +1 -0
- package/dist/client/Logger.d.ts +2 -0
- package/dist/client/Logger.d.ts.map +1 -0
- package/dist/client/Logger.js +72 -0
- package/dist/client/Logger.js.map +1 -0
- package/dist/client/LoginPopup.d.ts +7 -0
- package/dist/client/LoginPopup.d.ts.map +1 -0
- package/dist/client/LoginPopup.js +55 -0
- package/dist/client/LoginPopup.js.map +1 -0
- package/dist/client/Router.d.ts +56 -0
- package/dist/client/Router.d.ts.map +1 -0
- package/dist/client/Router.js +224 -0
- package/dist/client/Router.js.map +1 -0
- package/dist/client/Screenshot.d.ts +7 -0
- package/dist/client/Screenshot.d.ts.map +1 -0
- package/dist/client/Screenshot.js +54 -0
- package/dist/client/Screenshot.js.map +1 -0
- package/dist/client/ViewFlipper.d.ts +16 -0
- package/dist/client/ViewFlipper.d.ts.map +1 -0
- package/dist/client/ViewFlipper.js +156 -0
- package/dist/client/ViewFlipper.js.map +1 -0
- package/dist/client/animation/Animated.d.ts +14 -0
- package/dist/client/animation/Animated.d.ts.map +1 -0
- package/dist/client/animation/Animated.js +97 -0
- package/dist/client/animation/Animated.js.map +1 -0
- package/dist/client/animation/animatedValue.d.ts +41 -0
- package/dist/client/animation/animatedValue.d.ts.map +1 -0
- package/dist/client/animation/animatedValue.js +123 -0
- package/dist/client/animation/animatedValue.js.map +1 -0
- package/dist/client/animations/FadeIn.d.ts +6 -0
- package/dist/client/animations/FadeIn.d.ts.map +1 -0
- package/dist/client/animations/FadeIn.js +24 -0
- package/dist/client/animations/FadeIn.js.map +1 -0
- package/dist/client/animations/SlideFromBottom.d.ts +6 -0
- package/dist/client/animations/SlideFromBottom.d.ts.map +1 -0
- package/dist/client/animations/SlideFromBottom.js +24 -0
- package/dist/client/animations/SlideFromBottom.js.map +1 -0
- package/dist/client/animations/SlideFromRight.d.ts +6 -0
- package/dist/client/animations/SlideFromRight.d.ts.map +1 -0
- package/dist/client/animations/SlideFromRight.js +24 -0
- package/dist/client/animations/SlideFromRight.js.map +1 -0
- package/dist/client/audio/AudioPlayer.d.ts +11 -0
- package/dist/client/audio/AudioPlayer.d.ts.map +1 -0
- package/dist/client/audio/AudioPlayer.js +51 -0
- package/dist/client/audio/AudioPlayer.js.map +1 -0
- package/dist/client/audio/AudioRecorder.d.ts +11 -0
- package/dist/client/audio/AudioRecorder.d.ts.map +1 -0
- package/dist/client/audio/AudioRecorder.js +66 -0
- package/dist/client/audio/AudioRecorder.js.map +1 -0
- package/dist/client/audio/audioPlayer.worklet.d.ts +2 -0
- package/dist/client/audio/audioPlayer.worklet.d.ts.map +1 -0
- package/dist/client/audio/audioPlayer.worklet.js +46 -0
- package/dist/client/audio/audioPlayer.worklet.js.map +1 -0
- package/dist/client/audio/useSTT.d.ts +19 -0
- package/dist/client/audio/useSTT.d.ts.map +1 -0
- package/dist/client/audio/useSTT.js +91 -0
- package/dist/client/audio/useSTT.js.map +1 -0
- package/dist/client/audio/useTTS.d.ts +17 -0
- package/dist/client/audio/useTTS.d.ts.map +1 -0
- package/dist/client/audio/useTTS.js +70 -0
- package/dist/client/audio/useTTS.js.map +1 -0
- package/dist/client/components/Button.d.ts +22 -0
- package/dist/client/components/Button.d.ts.map +1 -0
- package/dist/client/components/Button.js +27 -0
- package/dist/client/components/Button.js.map +1 -0
- package/dist/client/components/Card.d.ts +8 -0
- package/dist/client/components/Card.d.ts.map +1 -0
- package/dist/client/components/Card.js +6 -0
- package/dist/client/components/Card.js.map +1 -0
- package/dist/client/components/EnumInput.d.ts +16 -0
- package/dist/client/components/EnumInput.d.ts.map +1 -0
- package/dist/client/components/EnumInput.js +11 -0
- package/dist/client/components/EnumInput.js.map +1 -0
- package/dist/client/components/FeedbackButton.d.ts +9 -0
- package/dist/client/components/FeedbackButton.d.ts.map +1 -0
- package/dist/client/components/FeedbackButton.js +112 -0
- package/dist/client/components/FeedbackButton.js.map +1 -0
- package/dist/client/components/Header.d.ts +10 -0
- package/dist/client/components/Header.d.ts.map +1 -0
- package/dist/client/components/Header.js +12 -0
- package/dist/client/components/Header.js.map +1 -0
- package/dist/client/components/Image.d.ts +20 -0
- package/dist/client/components/Image.d.ts.map +1 -0
- package/dist/client/components/Image.js +12 -0
- package/dist/client/components/Image.js.map +1 -0
- package/dist/client/components/Input.d.ts +14 -0
- package/dist/client/components/Input.d.ts.map +1 -0
- package/dist/client/components/Input.js +19 -0
- package/dist/client/components/Input.js.map +1 -0
- package/dist/client/components/Modal.d.ts +9 -0
- package/dist/client/components/Modal.d.ts.map +1 -0
- package/dist/client/components/Modal.js +19 -0
- package/dist/client/components/Modal.js.map +1 -0
- package/dist/client/components/PageLayout.d.ts +9 -0
- package/dist/client/components/PageLayout.d.ts.map +1 -0
- package/dist/client/components/PageLayout.js +6 -0
- package/dist/client/components/PageLayout.js.map +1 -0
- package/dist/client/components/Panel.d.ts +8 -0
- package/dist/client/components/Panel.d.ts.map +1 -0
- package/dist/client/components/Panel.js +5 -0
- package/dist/client/components/Panel.js.map +1 -0
- package/dist/client/components/PopupPanel.d.ts +9 -0
- package/dist/client/components/PopupPanel.d.ts.map +1 -0
- package/dist/client/components/PopupPanel.js +5 -0
- package/dist/client/components/PopupPanel.js.map +1 -0
- package/dist/client/components/Pressable.d.ts +14 -0
- package/dist/client/components/Pressable.d.ts.map +1 -0
- package/dist/client/components/Pressable.js +8 -0
- package/dist/client/components/Pressable.js.map +1 -0
- package/dist/client/components/ScrollView.d.ts +9 -0
- package/dist/client/components/ScrollView.d.ts.map +1 -0
- package/dist/client/components/ScrollView.js +7 -0
- package/dist/client/components/ScrollView.js.map +1 -0
- package/dist/client/components/SettingGroup.d.ts +10 -0
- package/dist/client/components/SettingGroup.d.ts.map +1 -0
- package/dist/client/components/SettingGroup.js +8 -0
- package/dist/client/components/SettingGroup.js.map +1 -0
- package/dist/client/components/Text.d.ts +21 -0
- package/dist/client/components/Text.d.ts.map +1 -0
- package/dist/client/components/Text.js +43 -0
- package/dist/client/components/Text.js.map +1 -0
- package/dist/client/components/Toast.d.ts +10 -0
- package/dist/client/components/Toast.d.ts.map +1 -0
- package/dist/client/components/Toast.js +21 -0
- package/dist/client/components/Toast.js.map +1 -0
- package/dist/client/components/View.d.ts +9 -0
- package/dist/client/components/View.d.ts.map +1 -0
- package/dist/client/components/View.js +5 -0
- package/dist/client/components/View.js.map +1 -0
- package/dist/client/components/index.d.ts +33 -0
- package/dist/client/components/index.d.ts.map +1 -0
- package/dist/client/components/index.js +17 -0
- package/dist/client/components/index.js.map +1 -0
- package/dist/client/components/zIndex.d.ts +10 -0
- package/dist/client/components/zIndex.d.ts.map +1 -0
- package/dist/client/components/zIndex.js +12 -0
- package/dist/client/components/zIndex.js.map +1 -0
- package/dist/client/createSocket.d.ts +26 -0
- package/dist/client/createSocket.d.ts.map +1 -0
- package/dist/client/createSocket.js +138 -0
- package/dist/client/createSocket.js.map +1 -0
- package/dist/client/index.d.ts +27 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +20 -0
- package/dist/client/index.js.map +1 -0
- package/dist/playwright/index.d.ts +16 -0
- package/dist/playwright/index.d.ts.map +1 -0
- package/dist/playwright/index.js +32 -0
- package/dist/playwright/index.js.map +1 -0
- package/dist/server/App.d.ts +43 -0
- package/dist/server/App.d.ts.map +1 -0
- package/dist/server/App.js +215 -0
- package/dist/server/App.js.map +1 -0
- package/dist/server/Auth.d.ts +21 -0
- package/dist/server/Auth.d.ts.map +1 -0
- package/dist/server/Auth.js +171 -0
- package/dist/server/Auth.js.map +1 -0
- package/dist/server/Cache.d.ts +38 -0
- package/dist/server/Cache.d.ts.map +1 -0
- package/dist/server/Cache.js +113 -0
- package/dist/server/Cache.js.map +1 -0
- package/dist/server/ChangeStream.d.ts +22 -0
- package/dist/server/ChangeStream.d.ts.map +1 -0
- package/dist/server/ChangeStream.js +93 -0
- package/dist/server/ChangeStream.js.map +1 -0
- package/dist/server/DB.d.ts +17 -0
- package/dist/server/DB.d.ts.map +1 -0
- package/dist/server/DB.js +442 -0
- package/dist/server/DB.js.map +1 -0
- package/dist/server/Email.d.ts +22 -0
- package/dist/server/Email.d.ts.map +1 -0
- package/dist/server/Email.js +64 -0
- package/dist/server/Email.js.map +1 -0
- package/dist/server/EmailTemplate.d.ts +17 -0
- package/dist/server/EmailTemplate.d.ts.map +1 -0
- package/dist/server/EmailTemplate.js +29 -0
- package/dist/server/EmailTemplate.js.map +1 -0
- package/dist/server/FeedbackReport.d.ts +19 -0
- package/dist/server/FeedbackReport.d.ts.map +1 -0
- package/dist/server/FeedbackReport.js +94 -0
- package/dist/server/FeedbackReport.js.map +1 -0
- package/dist/server/ImageGen.d.ts +5 -0
- package/dist/server/ImageGen.d.ts.map +1 -0
- package/dist/server/ImageGen.js +5 -0
- package/dist/server/ImageGen.js.map +1 -0
- package/dist/server/Logging.d.ts +59 -0
- package/dist/server/Logging.d.ts.map +1 -0
- package/dist/server/Logging.js +293 -0
- package/dist/server/Logging.js.map +1 -0
- package/dist/server/Nats.d.ts +56 -0
- package/dist/server/Nats.d.ts.map +1 -0
- package/dist/server/Nats.js +162 -0
- package/dist/server/Nats.js.map +1 -0
- package/dist/server/NatsStore.d.ts +26 -0
- package/dist/server/NatsStore.d.ts.map +1 -0
- package/dist/server/NatsStore.js +86 -0
- package/dist/server/NatsStore.js.map +1 -0
- package/dist/server/PushNotification.d.ts +33 -0
- package/dist/server/PushNotification.d.ts.map +1 -0
- package/dist/server/PushNotification.js +131 -0
- package/dist/server/PushNotification.js.map +1 -0
- package/dist/server/RateLimit.d.ts +28 -0
- package/dist/server/RateLimit.d.ts.map +1 -0
- package/dist/server/RateLimit.js +101 -0
- package/dist/server/RateLimit.js.map +1 -0
- package/dist/server/Redis.d.ts +61 -0
- package/dist/server/Redis.d.ts.map +1 -0
- package/dist/server/Redis.js +226 -0
- package/dist/server/Redis.js.map +1 -0
- package/dist/server/Router.d.ts +27 -0
- package/dist/server/Router.d.ts.map +1 -0
- package/dist/server/Router.js +71 -0
- package/dist/server/Router.js.map +1 -0
- package/dist/server/Socket.d.ts +8 -0
- package/dist/server/Socket.d.ts.map +1 -0
- package/dist/server/Socket.js +278 -0
- package/dist/server/Socket.js.map +1 -0
- package/dist/server/SpendTracker.d.ts +18 -0
- package/dist/server/SpendTracker.d.ts.map +1 -0
- package/dist/server/SpendTracker.js +110 -0
- package/dist/server/SpendTracker.js.map +1 -0
- package/dist/server/Storage.d.ts +16 -0
- package/dist/server/Storage.d.ts.map +1 -0
- package/dist/server/Storage.js +95 -0
- package/dist/server/Storage.js.map +1 -0
- package/dist/server/TextGen.d.ts +5 -0
- package/dist/server/TextGen.d.ts.map +1 -0
- package/dist/server/TextGen.js +6 -0
- package/dist/server/TextGen.js.map +1 -0
- package/dist/server/WorkerQueue.d.ts +27 -0
- package/dist/server/WorkerQueue.d.ts.map +1 -0
- package/dist/server/WorkerQueue.js +147 -0
- package/dist/server/WorkerQueue.js.map +1 -0
- package/dist/server/ai/ImageGenClient.d.ts +6 -0
- package/dist/server/ai/ImageGenClient.d.ts.map +1 -0
- package/dist/server/ai/ImageGenClient.js +29 -0
- package/dist/server/ai/ImageGenClient.js.map +1 -0
- package/dist/server/ai/ProviderBalance.d.ts +15 -0
- package/dist/server/ai/ProviderBalance.d.ts.map +1 -0
- package/dist/server/ai/ProviderBalance.js +110 -0
- package/dist/server/ai/ProviderBalance.js.map +1 -0
- package/dist/server/ai/ProviderSelector.d.ts +13 -0
- package/dist/server/ai/ProviderSelector.d.ts.map +1 -0
- package/dist/server/ai/ProviderSelector.js +25 -0
- package/dist/server/ai/ProviderSelector.js.map +1 -0
- package/dist/server/ai/TextGenClient.d.ts +9 -0
- package/dist/server/ai/TextGenClient.d.ts.map +1 -0
- package/dist/server/ai/TextGenClient.js +72 -0
- package/dist/server/ai/TextGenClient.js.map +1 -0
- package/dist/server/ai/fallbacks.d.ts +9 -0
- package/dist/server/ai/fallbacks.d.ts.map +1 -0
- package/dist/server/ai/fallbacks.js +77 -0
- package/dist/server/ai/fallbacks.js.map +1 -0
- package/dist/server/ai/index.d.ts +12 -0
- package/dist/server/ai/index.d.ts.map +1 -0
- package/dist/server/ai/index.js +37 -0
- package/dist/server/ai/index.js.map +1 -0
- package/dist/server/ai/providers/Claude.d.ts +3 -0
- package/dist/server/ai/providers/Claude.d.ts.map +1 -0
- package/dist/server/ai/providers/Claude.js +124 -0
- package/dist/server/ai/providers/Claude.js.map +1 -0
- package/dist/server/ai/providers/FAL.d.ts +3 -0
- package/dist/server/ai/providers/FAL.d.ts.map +1 -0
- package/dist/server/ai/providers/FAL.js +24 -0
- package/dist/server/ai/providers/FAL.js.map +1 -0
- package/dist/server/ai/providers/Fireworks.d.ts +3 -0
- package/dist/server/ai/providers/Fireworks.d.ts.map +1 -0
- package/dist/server/ai/providers/Fireworks.js +79 -0
- package/dist/server/ai/providers/Fireworks.js.map +1 -0
- package/dist/server/ai/providers/Google.d.ts +3 -0
- package/dist/server/ai/providers/Google.d.ts.map +1 -0
- package/dist/server/ai/providers/Google.js +105 -0
- package/dist/server/ai/providers/Google.js.map +1 -0
- package/dist/server/ai/providers/GoogleImage.d.ts +3 -0
- package/dist/server/ai/providers/GoogleImage.d.ts.map +1 -0
- package/dist/server/ai/providers/GoogleImage.js +24 -0
- package/dist/server/ai/providers/GoogleImage.js.map +1 -0
- package/dist/server/ai/providers/Groq.d.ts +3 -0
- package/dist/server/ai/providers/Groq.d.ts.map +1 -0
- package/dist/server/ai/providers/Groq.js +99 -0
- package/dist/server/ai/providers/Groq.js.map +1 -0
- package/dist/server/ai/providers/Kie.d.ts +3 -0
- package/dist/server/ai/providers/Kie.d.ts.map +1 -0
- package/dist/server/ai/providers/Kie.js +79 -0
- package/dist/server/ai/providers/Kie.js.map +1 -0
- package/dist/server/ai/providers/KieImage.d.ts +3 -0
- package/dist/server/ai/providers/KieImage.d.ts.map +1 -0
- package/dist/server/ai/providers/KieImage.js +50 -0
- package/dist/server/ai/providers/KieImage.js.map +1 -0
- package/dist/server/ai/providers/OpenAIText.d.ts +3 -0
- package/dist/server/ai/providers/OpenAIText.d.ts.map +1 -0
- package/dist/server/ai/providers/OpenAIText.js +103 -0
- package/dist/server/ai/providers/OpenAIText.js.map +1 -0
- package/dist/server/ai/providers/Together.d.ts +3 -0
- package/dist/server/ai/providers/Together.d.ts.map +1 -0
- package/dist/server/ai/providers/Together.js +99 -0
- package/dist/server/ai/providers/Together.js.map +1 -0
- package/dist/server/ai/providers/TogetherImage.d.ts +3 -0
- package/dist/server/ai/providers/TogetherImage.d.ts.map +1 -0
- package/dist/server/ai/providers/TogetherImage.js +24 -0
- package/dist/server/ai/providers/TogetherImage.js.map +1 -0
- package/dist/server/ai/providers/Wavespeed.d.ts +3 -0
- package/dist/server/ai/providers/Wavespeed.d.ts.map +1 -0
- package/dist/server/ai/providers/Wavespeed.js +53 -0
- package/dist/server/ai/providers/Wavespeed.js.map +1 -0
- package/dist/server/ai/registry.d.ts +10 -0
- package/dist/server/ai/registry.d.ts.map +1 -0
- package/dist/server/ai/registry.js +26 -0
- package/dist/server/ai/registry.js.map +1 -0
- package/dist/server/ai/types.d.ts +67 -0
- package/dist/server/ai/types.d.ts.map +1 -0
- package/dist/server/ai/types.js +17 -0
- package/dist/server/ai/types.js.map +1 -0
- package/dist/server/audio/STTStream.d.ts +12 -0
- package/dist/server/audio/STTStream.d.ts.map +1 -0
- package/dist/server/audio/STTStream.js +59 -0
- package/dist/server/audio/STTStream.js.map +1 -0
- package/dist/server/audio/TTSStream.d.ts +16 -0
- package/dist/server/audio/TTSStream.d.ts.map +1 -0
- package/dist/server/audio/TTSStream.js +151 -0
- package/dist/server/audio/TTSStream.js.map +1 -0
- package/dist/server/audio/index.d.ts +5 -0
- package/dist/server/audio/index.d.ts.map +1 -0
- package/dist/server/audio/index.js +14 -0
- package/dist/server/audio/index.js.map +1 -0
- package/dist/server/audio/resample.d.ts +7 -0
- package/dist/server/audio/resample.d.ts.map +1 -0
- package/dist/server/audio/resample.js +17 -0
- package/dist/server/audio/resample.js.map +1 -0
- package/dist/server/audio/stt/GroqWhisper.d.ts +3 -0
- package/dist/server/audio/stt/GroqWhisper.d.ts.map +1 -0
- package/dist/server/audio/stt/GroqWhisper.js +91 -0
- package/dist/server/audio/stt/GroqWhisper.js.map +1 -0
- package/dist/server/audio/stt/registry.d.ts +5 -0
- package/dist/server/audio/stt/registry.d.ts.map +1 -0
- package/dist/server/audio/stt/registry.js +11 -0
- package/dist/server/audio/stt/registry.js.map +1 -0
- package/dist/server/audio/stt/types.d.ts +25 -0
- package/dist/server/audio/stt/types.d.ts.map +1 -0
- package/dist/server/audio/stt/types.js +2 -0
- package/dist/server/audio/stt/types.js.map +1 -0
- package/dist/server/audio/stt/vad.d.ts +18 -0
- package/dist/server/audio/stt/vad.d.ts.map +1 -0
- package/dist/server/audio/stt/vad.js +90 -0
- package/dist/server/audio/stt/vad.js.map +1 -0
- package/dist/server/audio/tts/InWorld.d.ts +3 -0
- package/dist/server/audio/tts/InWorld.d.ts.map +1 -0
- package/dist/server/audio/tts/InWorld.js +147 -0
- package/dist/server/audio/tts/InWorld.js.map +1 -0
- package/dist/server/audio/tts/providers/Azure.d.ts +3 -0
- package/dist/server/audio/tts/providers/Azure.d.ts.map +1 -0
- package/dist/server/audio/tts/providers/Azure.js +31 -0
- package/dist/server/audio/tts/providers/Azure.js.map +1 -0
- package/dist/server/audio/tts/registry.d.ts +6 -0
- package/dist/server/audio/tts/registry.d.ts.map +1 -0
- package/dist/server/audio/tts/registry.js +12 -0
- package/dist/server/audio/tts/registry.js.map +1 -0
- package/dist/server/audio/tts/types.d.ts +20 -0
- package/dist/server/audio/tts/types.d.ts.map +1 -0
- package/dist/server/audio/tts/types.js +2 -0
- package/dist/server/audio/tts/types.js.map +1 -0
- package/dist/server/billing/BillingGateway.d.ts +40 -0
- package/dist/server/billing/BillingGateway.d.ts.map +1 -0
- package/dist/server/billing/BillingGateway.js +116 -0
- package/dist/server/billing/BillingGateway.js.map +1 -0
- package/dist/server/billing/BillingLedger.d.ts +67 -0
- package/dist/server/billing/BillingLedger.d.ts.map +1 -0
- package/dist/server/billing/BillingLedger.js +214 -0
- package/dist/server/billing/BillingLedger.js.map +1 -0
- package/dist/server/billing/CreditStore.d.ts +58 -0
- package/dist/server/billing/CreditStore.d.ts.map +1 -0
- package/dist/server/billing/CreditStore.js +112 -0
- package/dist/server/billing/CreditStore.js.map +1 -0
- package/dist/server/billing/LimitEnforcer.d.ts +73 -0
- package/dist/server/billing/LimitEnforcer.d.ts.map +1 -0
- package/dist/server/billing/LimitEnforcer.js +276 -0
- package/dist/server/billing/LimitEnforcer.js.map +1 -0
- package/dist/server/billing/UserLimitCache.d.ts +35 -0
- package/dist/server/billing/UserLimitCache.d.ts.map +1 -0
- package/dist/server/billing/UserLimitCache.js +91 -0
- package/dist/server/billing/UserLimitCache.js.map +1 -0
- package/dist/server/billing/index.d.ts +6 -0
- package/dist/server/billing/index.d.ts.map +1 -0
- package/dist/server/billing/index.js +4 -0
- package/dist/server/billing/index.js.map +1 -0
- package/dist/server/billing/types.d.ts +95 -0
- package/dist/server/billing/types.d.ts.map +1 -0
- package/dist/server/billing/types.js +19 -0
- package/dist/server/billing/types.js.map +1 -0
- package/dist/server/embeddings/EmbeddingClient.d.ts +8 -0
- package/dist/server/embeddings/EmbeddingClient.d.ts.map +1 -0
- package/dist/server/embeddings/EmbeddingClient.js +30 -0
- package/dist/server/embeddings/EmbeddingClient.js.map +1 -0
- package/dist/server/embeddings/index.d.ts +5 -0
- package/dist/server/embeddings/index.d.ts.map +1 -0
- package/dist/server/embeddings/index.js +6 -0
- package/dist/server/embeddings/index.js.map +1 -0
- package/dist/server/embeddings/providers/OpenAI.d.ts +3 -0
- package/dist/server/embeddings/providers/OpenAI.d.ts.map +1 -0
- package/dist/server/embeddings/providers/OpenAI.js +28 -0
- package/dist/server/embeddings/providers/OpenAI.js.map +1 -0
- package/dist/server/embeddings/registry.d.ts +7 -0
- package/dist/server/embeddings/registry.d.ts.map +1 -0
- package/dist/server/embeddings/registry.js +15 -0
- package/dist/server/embeddings/registry.js.map +1 -0
- package/dist/server/embeddings/types.d.ts +12 -0
- package/dist/server/embeddings/types.d.ts.map +1 -0
- package/dist/server/embeddings/types.js +2 -0
- package/dist/server/embeddings/types.js.map +1 -0
- package/dist/server/index.d.ts +59 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +41 -0
- package/dist/server/index.js.map +1 -0
- package/dist/shared/Api.d.ts +40 -0
- package/dist/shared/Api.d.ts.map +1 -0
- package/dist/shared/Api.js +30 -0
- package/dist/shared/Api.js.map +1 -0
- package/dist/shared/Audio.d.ts +108 -0
- package/dist/shared/Audio.d.ts.map +1 -0
- package/dist/shared/Audio.js +3 -0
- package/dist/shared/Audio.js.map +1 -0
- package/dist/shared/DB.d.ts +339 -0
- package/dist/shared/DB.d.ts.map +1 -0
- package/dist/shared/DB.js +51 -0
- package/dist/shared/DB.js.map +1 -0
- package/dist/shared/Errors.d.ts +10 -0
- package/dist/shared/Errors.d.ts.map +1 -0
- package/dist/shared/Errors.js +19 -0
- package/dist/shared/Errors.js.map +1 -0
- package/dist/shared/FeedbackReport.d.ts +38 -0
- package/dist/shared/FeedbackReport.d.ts.map +1 -0
- package/dist/shared/FeedbackReport.js +14 -0
- package/dist/shared/FeedbackReport.js.map +1 -0
- package/dist/shared/Router.d.ts +28 -0
- package/dist/shared/Router.d.ts.map +1 -0
- package/dist/shared/Router.js +82 -0
- package/dist/shared/Router.js.map +1 -0
- package/dist/shared/Socket.d.ts +26 -0
- package/dist/shared/Socket.d.ts.map +1 -0
- package/dist/shared/Socket.js +2 -0
- package/dist/shared/Socket.js.map +1 -0
- package/dist/shared/index.d.ts +28 -0
- package/dist/shared/index.d.ts.map +1 -0
- package/dist/shared/index.js +61 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/webrtc/index.d.ts +14 -0
- package/dist/webrtc/index.d.ts.map +1 -0
- package/dist/webrtc/index.js +24 -0
- package/dist/webrtc/index.js.map +1 -0
- package/package.json +97 -0
- package/templates/.claude/skills/assets.md +39 -0
- package/templates/.claude/skills/check-errors.md +35 -0
- package/templates/.claude/skills/check-feedback.md +23 -0
- package/templates/.claude/skills/check-perf.md +22 -0
- package/templates/.claude/skills/create-test-users.md +34 -0
- package/templates/.claude/skills/extend-api.md +37 -0
- package/templates/.claude/skills/fix-code.md +5 -0
- package/templates/.claude/skills/fix-errors.md +9 -0
- package/templates/.claude/skills/fix-feedback.md +8 -0
- package/templates/.claude/skills/fix-perf.md +8 -0
- package/templates/.claude/skills/uploads.md +38 -0
- package/templates/.claude/skills/use-ai.md +49 -0
- package/templates/.env.example +49 -0
- package/templates/.husky/pre-commit +2 -0
- package/templates/CLAUDE.md +199 -0
- package/templates/client/App.tsx +33 -0
- package/templates/client/index.html +14 -0
- package/templates/client/main.tsx +52 -0
- package/templates/client/pages/AuthDemoPage.tsx +85 -0
- package/templates/client/pages/HomePage.tsx +111 -0
- package/templates/client/pages/SearchPage.tsx +48 -0
- package/templates/client/pages/UserPage.tsx +33 -0
- package/templates/client/router.ts +4 -0
- package/templates/docker-compose.yml +50 -0
- package/templates/index.html +14 -0
- package/templates/package.json +56 -0
- package/templates/playwright.config.ts +21 -0
- package/templates/server/index.ts +24 -0
- package/templates/shared/api.ts +36 -0
- package/templates/shared/collections.ts +11 -0
- package/templates/shared/dbIndexes.ts +11 -0
- package/templates/shared/pages.ts +8 -0
- package/templates/vite.config.ts +17 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Project Structure & Conventions
|
|
2
|
+
|
|
3
|
+
Generated by `website-core`. See the full framework docs at [npm:website-core](https://www.npmjs.com/package/website-core).
|
|
4
|
+
|
|
5
|
+
## Stack
|
|
6
|
+
- Server: Express + TypeScript (`server/index.ts`)
|
|
7
|
+
- Client: React + Vite (`client/main.tsx`)
|
|
8
|
+
- Shared: Types + API definitions (`shared/`)
|
|
9
|
+
- CLI: `web` commands from website-core (see package.json scripts)
|
|
10
|
+
|
|
11
|
+
## Commands
|
|
12
|
+
- `yarn dev` — Start dev server (docker + server + vite + tsc watch + eslint watch)
|
|
13
|
+
- `yarn build` — Build for production
|
|
14
|
+
- `yarn deploy:single` — Deploy to single server
|
|
15
|
+
- `yarn deploy:multi` — Deploy to multiple servers
|
|
16
|
+
- `yarn db:migrate` — Run database migrations
|
|
17
|
+
- `yarn db:init` — (Re)create database indexes
|
|
18
|
+
- `yarn logs` — Show local dev logs
|
|
19
|
+
- `yarn error` — Show local error logs
|
|
20
|
+
- `yarn feedback` — Show user feedback from production
|
|
21
|
+
|
|
22
|
+
## Adding a new API endpoint
|
|
23
|
+
|
|
24
|
+
1. Add to `shared/api.ts` using `fn()` or `req()` with Zod schemas:
|
|
25
|
+
```typescript
|
|
26
|
+
import { fn, req, z } from 'website-core/shared';
|
|
27
|
+
|
|
28
|
+
export const functions = defineFunctions({
|
|
29
|
+
myFunction: fn({
|
|
30
|
+
input: z.object({ name: z.string() }),
|
|
31
|
+
output: z.object({ greeting: z.string() }),
|
|
32
|
+
}),
|
|
33
|
+
});
|
|
34
|
+
```
|
|
35
|
+
2. Register handler in `server/index.ts`:
|
|
36
|
+
```typescript
|
|
37
|
+
app.registerFunction('myFunction', async (ctx, input) => {
|
|
38
|
+
const { name } = input as { name: string };
|
|
39
|
+
return { greeting: `Hello, ${name}` };
|
|
40
|
+
});
|
|
41
|
+
```
|
|
42
|
+
3. Available in handlers: `ctx.db`, `ctx.storage`, `ctx.rateLimit`, `ctx.userId`, `ctx.user`
|
|
43
|
+
|
|
44
|
+
## Adding a new database collection
|
|
45
|
+
|
|
46
|
+
1. Add to `shared/collections.ts`:
|
|
47
|
+
```typescript
|
|
48
|
+
export const collections = defineCollections({
|
|
49
|
+
myCollection: { cache: false, trackable: true, public: true, parent: null },
|
|
50
|
+
});
|
|
51
|
+
```
|
|
52
|
+
2. Add TypeScript interface to `shared/types.ts` (create if needed)
|
|
53
|
+
3. Add indexes to `shared/dbIndexes.ts` (create if needed)
|
|
54
|
+
4. Run `yarn db:init`
|
|
55
|
+
|
|
56
|
+
## Changing existing data (DB migrations)
|
|
57
|
+
|
|
58
|
+
NEVER just change a TypeScript type for existing data — write a migration:
|
|
59
|
+
1. Create `server/migrations/NNN-description.ts`:
|
|
60
|
+
```typescript
|
|
61
|
+
export const name = 'NNN-description';
|
|
62
|
+
export async function up(db: Db) {
|
|
63
|
+
await db.collection('myCollection').updateMany({}, { $set: { newField: 'default' } });
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
2. Run `yarn db:migrate`
|
|
67
|
+
|
|
68
|
+
## Static assets
|
|
69
|
+
- Build-time files (favicon, fonts, OG images): `client/public/`
|
|
70
|
+
- User-uploaded files: `ctx.storage.getUploadUrl()` then `ctx.storage.moveToPublic()`
|
|
71
|
+
- Never hardcode `/asset/...` paths — use the buildId from `shared/Build.ts`
|
|
72
|
+
|
|
73
|
+
## Environment variables
|
|
74
|
+
- Adding a new one: add to `.env` AND `.env.example` with a comment
|
|
75
|
+
- Never read `process.env` in client code (use `import.meta.env.VITE_*`)
|
|
76
|
+
- Never commit `.env`
|
|
77
|
+
|
|
78
|
+
## Auth
|
|
79
|
+
- Default: ugly.bot OAuth popup — works out of the box, no config needed
|
|
80
|
+
- `ctx.userId`: always a non-null string in authenticated handlers
|
|
81
|
+
- Public handlers: use `defineRequests()` for unauthenticated reads
|
|
82
|
+
|
|
83
|
+
## Showing Popups / Modals
|
|
84
|
+
|
|
85
|
+
**Always use `useRouter().openPopup()` — never build custom fixed overlays.**
|
|
86
|
+
|
|
87
|
+
The `RouterProvider` (in `client/main.tsx`) manages a popup layer with proper z-index, backdrop, and animation. Use it for all popups, modals, and sheets.
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
import { useRouter } from '@/router'
|
|
91
|
+
|
|
92
|
+
function MyComponent() {
|
|
93
|
+
const { openPopup } = useRouter()
|
|
94
|
+
|
|
95
|
+
function handleOpen() {
|
|
96
|
+
openPopup(<MyContent />, { mode: 'transient' })
|
|
97
|
+
// mode: 'block' — dark backdrop (40%), clicking it does NOT dismiss
|
|
98
|
+
// mode: 'transient' — light backdrop (20%), clicking it dismisses
|
|
99
|
+
// mode: 'contextMenu'— same as transient, for menus/pickers
|
|
100
|
+
// slideFrom: 'bottom' | 'top' | 'left' | 'right' | 'none'
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
To dismiss programmatically:
|
|
106
|
+
```tsx
|
|
107
|
+
const handle = openPopup(<MyContent />, { mode: 'block' })
|
|
108
|
+
handle.hide()
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
For simple dialogs, `Modal` from `website-core/client` wraps content with backdrop + Escape key handling:
|
|
112
|
+
```tsx
|
|
113
|
+
import { Modal } from 'website-core/client'
|
|
114
|
+
{open && <Modal title="My Dialog" onClose={() => setOpen(false)}><p>Content</p></Modal>}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**In tests:** mock `../../router` to stub `useRouter`:
|
|
118
|
+
```tsx
|
|
119
|
+
const mockOpenPopup = vi.fn().mockReturnValue({ id: '1', hide: vi.fn() })
|
|
120
|
+
vi.mock('../../router', () => ({ useRouter: () => ({ openPopup: mockOpenPopup }) }))
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Common mistakes to avoid
|
|
124
|
+
- Do NOT use in-memory Maps for per-user state — use Redis or MongoDB (multi-server safe)
|
|
125
|
+
- Do NOT change collection field types without a migration
|
|
126
|
+
- Do NOT make NATS subscriptions without storing and calling the returned `unsub()` function
|
|
127
|
+
- Do NOT skip `ctx.rateLimit.check()` before expensive operations (AI, storage, email)
|
|
128
|
+
- Do NOT add `any` types — the TypeScript config enforces `noExplicitAny`
|
|
129
|
+
|
|
130
|
+
## Feedback System
|
|
131
|
+
|
|
132
|
+
The feedback button is always present at `[data-id="feedback-button"]` (bottom-right corner).
|
|
133
|
+
Bots can trigger it by calling `document.querySelector('[data-id="feedback-button"]').click()`.
|
|
134
|
+
Users see their feedback history at `GET /my_feedback` (returns markdown, requires auth cookie).
|
|
135
|
+
The maintain bot resolves feedback via the `resolveFeedback` socket function (requires MAINTAIN_BOT_USER_ID).
|
|
136
|
+
|
|
137
|
+
## AI Providers
|
|
138
|
+
|
|
139
|
+
Use `createTextGen(userId, { provider })` or `createImageGen(userId, { provider })`.
|
|
140
|
+
All providers are optional — only configured keys are active.
|
|
141
|
+
|
|
142
|
+
### Text Generation
|
|
143
|
+
|
|
144
|
+
| Provider | `provider` value | JSON | Tools | Vision | Best for |
|
|
145
|
+
|---|---|---|---|---|---|
|
|
146
|
+
| Together AI (Llama-4-Scout) | `'together'` | ✅ | ✅ | ✅ | Fast, cheap, 10M context |
|
|
147
|
+
| Anthropic (claude-sonnet-4-6) | `'claude'` | ✅ | ✅ | ✅ | Complex reasoning, code |
|
|
148
|
+
| OpenAI (gpt-4o) | `'openai'` | ✅ | ✅ | ✅ | General purpose |
|
|
149
|
+
| Google (gemini-2.0-flash) | `'google'` | ✅ | ✅ | ✅ | Very long context (1M) |
|
|
150
|
+
| Groq (llama-3.3-70b) | `'groq'` | ✅ | ✅ | ❌ | Ultra-fast, no vision |
|
|
151
|
+
|
|
152
|
+
Use `provider: 'auto'` (default) to let the system pick based on requirements.
|
|
153
|
+
|
|
154
|
+
### JSON Generation (type-safe)
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
import { z } from 'zod'
|
|
158
|
+
const schema = z.object({ title: z.string(), tags: z.array(z.string()) })
|
|
159
|
+
const result = await textGen.generateJson(schema, messages)
|
|
160
|
+
// result typed as { title: string, tags: string[] }
|
|
161
|
+
// Retries up to 3 times on schema validation failure
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Tool Calling
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
const result = await textGen.generateWithTools(messages, {
|
|
168
|
+
myTool: {
|
|
169
|
+
description: 'What the tool does',
|
|
170
|
+
input: z.object({ param: z.string() }),
|
|
171
|
+
handler: async ({ param }) => ({ result: 'value' })
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
// Tool loop runs automatically until model produces final text (max 5 rounds)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Image Generation
|
|
178
|
+
|
|
179
|
+
| Provider | `provider` value | Best for |
|
|
180
|
+
|---|---|---|
|
|
181
|
+
| Together AI (FLUX schnell) | `'together'` | Free tier, fast |
|
|
182
|
+
| FAL (FLUX pro) | `'fal'` | High quality |
|
|
183
|
+
| Google (Imagen 3) | `'google'` | Photorealistic |
|
|
184
|
+
|
|
185
|
+
### Adding a Custom Provider
|
|
186
|
+
|
|
187
|
+
```typescript
|
|
188
|
+
// In server/index.ts, before createApp():
|
|
189
|
+
import { registerTextGenProvider } from 'website-core'
|
|
190
|
+
|
|
191
|
+
registerTextGenProvider({
|
|
192
|
+
name: 'mistral',
|
|
193
|
+
apiKeyEnv: 'MISTRAL_API_KEY',
|
|
194
|
+
capabilities: { json: true, tools: true, vision: false, maxContextTokens: 32_000 },
|
|
195
|
+
costPerMillionInputTokens: 0.20,
|
|
196
|
+
costPerMillionOutputTokens: 0.60,
|
|
197
|
+
generate: (messages, opts) => { /* your implementation */ },
|
|
198
|
+
})
|
|
199
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { AppSocket } from 'website-core/client';
|
|
3
|
+
import { FeedbackButton } from 'website-core/client';
|
|
4
|
+
import type { AppRegistry } from '../shared/api.js';
|
|
5
|
+
import { AuthDemoPage } from './pages/AuthDemoPage.js';
|
|
6
|
+
import { HomePage } from './pages/HomePage.js';
|
|
7
|
+
import { SearchPage } from './pages/SearchPage.js';
|
|
8
|
+
import { UserPage } from './pages/UserPage.js';
|
|
9
|
+
|
|
10
|
+
interface AppProps {
|
|
11
|
+
socket: AppSocket<AppRegistry> | null;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function Router(): React.ReactElement {
|
|
15
|
+
const path = window.location.pathname;
|
|
16
|
+
|
|
17
|
+
if (path.startsWith('/auth-demo')) return <AuthDemoPage />;
|
|
18
|
+
if (path.startsWith('/user/')) {
|
|
19
|
+
const userId = path.split('/')[2] ?? '';
|
|
20
|
+
return <UserPage userId={userId} />;
|
|
21
|
+
}
|
|
22
|
+
if (path.startsWith('/search')) return <SearchPage />;
|
|
23
|
+
return <HomePage />;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export default function App({ socket }: AppProps): React.ReactElement {
|
|
27
|
+
return (
|
|
28
|
+
<>
|
|
29
|
+
<Router />
|
|
30
|
+
<FeedbackButton socket={socket} />
|
|
31
|
+
</>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>App</title>
|
|
8
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="root"></div>
|
|
12
|
+
<script type="module" src="/client/main.tsx"></script>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { createRoot } from 'react-dom/client';
|
|
2
|
+
import { AppProvider, createSocket, LoginPopup } from 'website-core/client';
|
|
3
|
+
import { functions, requests } from '../shared/api.js';
|
|
4
|
+
import App from './App.js';
|
|
5
|
+
import { RouterProvider } from './router.js';
|
|
6
|
+
|
|
7
|
+
const root = createRoot(document.getElementById('root')!);
|
|
8
|
+
|
|
9
|
+
const loginPopup = (
|
|
10
|
+
<LoginPopup
|
|
11
|
+
uglyBotUrl={import.meta.env.VITE_UGLY_BOT_URL ?? 'https://ugly.bot'}
|
|
12
|
+
onSuccess={() => {
|
|
13
|
+
window.location.reload();
|
|
14
|
+
}}
|
|
15
|
+
/>
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
// Token is injected server-side from the auth_token cookie — no localStorage needed
|
|
19
|
+
const token = (window as unknown as { __AUTH_TOKEN__?: string }).__AUTH_TOKEN__;
|
|
20
|
+
|
|
21
|
+
if (!token) {
|
|
22
|
+
root.render(
|
|
23
|
+
<RouterProvider
|
|
24
|
+
fallback={<div>404 — Page not found</div>}
|
|
25
|
+
loginFallback={loginPopup}
|
|
26
|
+
isAuthenticated={() => false}
|
|
27
|
+
>
|
|
28
|
+
<App socket={null} />
|
|
29
|
+
</RouterProvider>,
|
|
30
|
+
);
|
|
31
|
+
} else {
|
|
32
|
+
const userId = JSON.parse(atob(token.split('.')[1]!)).sub as string;
|
|
33
|
+
const socket = createSocket({ functions, requests, url: '/rpc' });
|
|
34
|
+
socket
|
|
35
|
+
.connect(token)
|
|
36
|
+
.then((user) => {
|
|
37
|
+
root.render(
|
|
38
|
+
<RouterProvider
|
|
39
|
+
fallback={<div>404 — Page not found</div>}
|
|
40
|
+
loginFallback={loginPopup}
|
|
41
|
+
isAuthenticated={() => true}
|
|
42
|
+
>
|
|
43
|
+
<AppProvider socket={socket} userId={userId} user={user}>
|
|
44
|
+
<App socket={socket} />
|
|
45
|
+
</AppProvider>
|
|
46
|
+
</RouterProvider>,
|
|
47
|
+
);
|
|
48
|
+
})
|
|
49
|
+
.catch(() => {
|
|
50
|
+
window.location.reload();
|
|
51
|
+
});
|
|
52
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Button, Card, PageLayout, Text, useApp } from 'website-core/client';
|
|
3
|
+
|
|
4
|
+
function AuthDemoAuthenticated(): React.ReactElement {
|
|
5
|
+
const app = useApp();
|
|
6
|
+
|
|
7
|
+
async function handleLogout(): Promise<void> {
|
|
8
|
+
await fetch('/auth/logout', { method: 'POST' });
|
|
9
|
+
window.location.reload();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<PageLayout
|
|
14
|
+
header={
|
|
15
|
+
<div className="px-6 py-4">
|
|
16
|
+
<a href="/" className="text-blue-600">
|
|
17
|
+
← Home
|
|
18
|
+
</a>
|
|
19
|
+
</div>
|
|
20
|
+
}
|
|
21
|
+
>
|
|
22
|
+
<div className="max-w-md mx-auto">
|
|
23
|
+
<Text size="xl" weight="bold">
|
|
24
|
+
Auth Demo
|
|
25
|
+
</Text>
|
|
26
|
+
<Card className="mt-4">
|
|
27
|
+
<Text weight="bold">Logged In</Text>
|
|
28
|
+
<pre className="mt-2 text-sm bg-gray-100 dark:bg-gray-900 p-3 rounded overflow-auto">
|
|
29
|
+
{JSON.stringify(
|
|
30
|
+
{
|
|
31
|
+
userId: app.userId,
|
|
32
|
+
email: app.user.email,
|
|
33
|
+
phone: app.user.phone,
|
|
34
|
+
},
|
|
35
|
+
null,
|
|
36
|
+
2,
|
|
37
|
+
)}
|
|
38
|
+
</pre>
|
|
39
|
+
<Button variant="secondary" onClick={handleLogout} className="mt-4">
|
|
40
|
+
Logout
|
|
41
|
+
</Button>
|
|
42
|
+
</Card>
|
|
43
|
+
</div>
|
|
44
|
+
</PageLayout>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function AuthDemoUnauthenticated(): React.ReactElement {
|
|
49
|
+
function handleLogin(): void {
|
|
50
|
+
// The RouterProvider's loginFallback will show the login popup for auth-required routes.
|
|
51
|
+
// For a manual trigger, redirect to initiate the OAuth flow.
|
|
52
|
+
window.location.href = '/?login=1';
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<PageLayout
|
|
57
|
+
header={
|
|
58
|
+
<div className="px-6 py-4">
|
|
59
|
+
<a href="/" className="text-blue-600">
|
|
60
|
+
← Home
|
|
61
|
+
</a>
|
|
62
|
+
</div>
|
|
63
|
+
}
|
|
64
|
+
>
|
|
65
|
+
<div className="max-w-md mx-auto">
|
|
66
|
+
<Text size="xl" weight="bold">
|
|
67
|
+
Auth Demo
|
|
68
|
+
</Text>
|
|
69
|
+
<Card className="mt-4">
|
|
70
|
+
<Text>You are not logged in.</Text>
|
|
71
|
+
<Button onClick={handleLogin} className="mt-4">
|
|
72
|
+
Login with ugly.bot
|
|
73
|
+
</Button>
|
|
74
|
+
</Card>
|
|
75
|
+
</div>
|
|
76
|
+
</PageLayout>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function AuthDemoPage(): React.ReactElement {
|
|
81
|
+
const isLoggedIn = !!(window as unknown as { __AUTH_TOKEN__?: string })
|
|
82
|
+
.__AUTH_TOKEN__;
|
|
83
|
+
if (isLoggedIn) return <AuthDemoAuthenticated />;
|
|
84
|
+
return <AuthDemoUnauthenticated />;
|
|
85
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Button, Card, PageLayout, Text, useApp } from 'website-core/client';
|
|
3
|
+
|
|
4
|
+
function HomePageAuthenticated(): React.ReactElement {
|
|
5
|
+
const app = useApp();
|
|
6
|
+
|
|
7
|
+
async function handleLogout(): Promise<void> {
|
|
8
|
+
await fetch('/auth/logout', { method: 'POST' });
|
|
9
|
+
window.location.reload();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<PageLayout
|
|
14
|
+
header={
|
|
15
|
+
<div className="flex items-center justify-between px-6 py-4">
|
|
16
|
+
<Text size="lg" weight="bold">
|
|
17
|
+
My App
|
|
18
|
+
</Text>
|
|
19
|
+
<Button variant="secondary" onClick={handleLogout}>
|
|
20
|
+
Logout
|
|
21
|
+
</Button>
|
|
22
|
+
</div>
|
|
23
|
+
}
|
|
24
|
+
>
|
|
25
|
+
<HomePageBody userId={app.userId} />
|
|
26
|
+
</PageLayout>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function HomePageUnauthenticated(): React.ReactElement {
|
|
31
|
+
function handleLogin(): void {
|
|
32
|
+
// Trigger login — navigate to /auth-demo or show login popup via RouterProvider
|
|
33
|
+
window.location.href = '/auth-demo';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<PageLayout
|
|
38
|
+
header={
|
|
39
|
+
<div className="flex items-center justify-between px-6 py-4">
|
|
40
|
+
<Text size="lg" weight="bold">
|
|
41
|
+
My App
|
|
42
|
+
</Text>
|
|
43
|
+
<Button variant="primary" onClick={handleLogin}>
|
|
44
|
+
Login
|
|
45
|
+
</Button>
|
|
46
|
+
</div>
|
|
47
|
+
}
|
|
48
|
+
>
|
|
49
|
+
<HomePageBody userId={null} />
|
|
50
|
+
</PageLayout>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function HomePageBody({
|
|
55
|
+
userId,
|
|
56
|
+
}: {
|
|
57
|
+
userId: string | null;
|
|
58
|
+
}): React.ReactElement {
|
|
59
|
+
return (
|
|
60
|
+
<div className="max-w-2xl mx-auto">
|
|
61
|
+
<Card>
|
|
62
|
+
<Text size="xl" weight="bold">
|
|
63
|
+
Welcome
|
|
64
|
+
</Text>
|
|
65
|
+
{userId ? (
|
|
66
|
+
<Text className="mt-2 text-gray-600 dark:text-gray-400">
|
|
67
|
+
Logged in as: {userId}
|
|
68
|
+
</Text>
|
|
69
|
+
) : (
|
|
70
|
+
<Text className="mt-2 text-gray-600 dark:text-gray-400">
|
|
71
|
+
This app was built with website-core.
|
|
72
|
+
</Text>
|
|
73
|
+
)}
|
|
74
|
+
</Card>
|
|
75
|
+
|
|
76
|
+
<div className="mt-6 grid gap-4">
|
|
77
|
+
<a href="/auth-demo" className="block">
|
|
78
|
+
<Card className="hover:shadow-md transition-shadow cursor-pointer">
|
|
79
|
+
<Text weight="medium">Auth Demo →</Text>
|
|
80
|
+
<Text size="sm" className="text-gray-500 mt-1">
|
|
81
|
+
See login/logout and user info
|
|
82
|
+
</Text>
|
|
83
|
+
</Card>
|
|
84
|
+
</a>
|
|
85
|
+
<a href="/user/example-user-id" className="block">
|
|
86
|
+
<Card className="hover:shadow-md transition-shadow cursor-pointer">
|
|
87
|
+
<Text weight="medium">Path Params Demo →</Text>
|
|
88
|
+
<Text size="sm" className="text-gray-500 mt-1">
|
|
89
|
+
URL: /user/:userId
|
|
90
|
+
</Text>
|
|
91
|
+
</Card>
|
|
92
|
+
</a>
|
|
93
|
+
<a href="/search?q=hello" className="block">
|
|
94
|
+
<Card className="hover:shadow-md transition-shadow cursor-pointer">
|
|
95
|
+
<Text weight="medium">Query Params Demo →</Text>
|
|
96
|
+
<Text size="sm" className="text-gray-500 mt-1">
|
|
97
|
+
URL: /search?q=...
|
|
98
|
+
</Text>
|
|
99
|
+
</Card>
|
|
100
|
+
</a>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function HomePage(): React.ReactElement {
|
|
107
|
+
const isLoggedIn = !!(window as unknown as { __AUTH_TOKEN__?: string })
|
|
108
|
+
.__AUTH_TOKEN__;
|
|
109
|
+
if (isLoggedIn) return <HomePageAuthenticated />;
|
|
110
|
+
return <HomePageUnauthenticated />;
|
|
111
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Card, Input, PageLayout, Text } from 'website-core/client';
|
|
3
|
+
|
|
4
|
+
export function SearchPage(): React.ReactElement {
|
|
5
|
+
const initialQ = new URLSearchParams(window.location.search).get('q') ?? '';
|
|
6
|
+
const [query, setQuery] = useState(initialQ);
|
|
7
|
+
|
|
8
|
+
function handleQueryChange(v: string): void {
|
|
9
|
+
setQuery(v);
|
|
10
|
+
const url = new URL(window.location.href);
|
|
11
|
+
url.searchParams.set('q', v);
|
|
12
|
+
window.history.replaceState(null, '', url.toString());
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<PageLayout
|
|
17
|
+
header={
|
|
18
|
+
<div className="px-6 py-4">
|
|
19
|
+
<a href="/" className="text-blue-600">
|
|
20
|
+
← Home
|
|
21
|
+
</a>
|
|
22
|
+
</div>
|
|
23
|
+
}
|
|
24
|
+
>
|
|
25
|
+
<div className="max-w-md mx-auto">
|
|
26
|
+
<Text size="xl" weight="bold">
|
|
27
|
+
Search
|
|
28
|
+
</Text>
|
|
29
|
+
<div className="mt-4">
|
|
30
|
+
<Input
|
|
31
|
+
label="Search query"
|
|
32
|
+
value={query}
|
|
33
|
+
onChange={handleQueryChange}
|
|
34
|
+
placeholder="Search..."
|
|
35
|
+
/>
|
|
36
|
+
</div>
|
|
37
|
+
<Card className="mt-4">
|
|
38
|
+
<Text size="sm" className="text-gray-500">
|
|
39
|
+
Query parameter:
|
|
40
|
+
</Text>
|
|
41
|
+
<Text weight="bold" className="font-mono mt-1">
|
|
42
|
+
?q={query}
|
|
43
|
+
</Text>
|
|
44
|
+
</Card>
|
|
45
|
+
</div>
|
|
46
|
+
</PageLayout>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Card, PageLayout, Text } from 'website-core/client';
|
|
3
|
+
|
|
4
|
+
export function UserPage({ userId }: { userId: string }): React.ReactElement {
|
|
5
|
+
return (
|
|
6
|
+
<PageLayout
|
|
7
|
+
header={
|
|
8
|
+
<div className="px-6 py-4">
|
|
9
|
+
<a href="/" className="text-blue-600">
|
|
10
|
+
← Home
|
|
11
|
+
</a>
|
|
12
|
+
</div>
|
|
13
|
+
}
|
|
14
|
+
>
|
|
15
|
+
<div className="max-w-md mx-auto">
|
|
16
|
+
<Text size="xl" weight="bold">
|
|
17
|
+
User Profile
|
|
18
|
+
</Text>
|
|
19
|
+
<Card className="mt-4">
|
|
20
|
+
<Text size="sm" className="text-gray-500">
|
|
21
|
+
Path parameter:
|
|
22
|
+
</Text>
|
|
23
|
+
<Text weight="bold" className="font-mono mt-1">
|
|
24
|
+
/user/{userId}
|
|
25
|
+
</Text>
|
|
26
|
+
<Text size="sm" className="text-gray-500 mt-3">
|
|
27
|
+
userId = <code>{userId}</code>
|
|
28
|
+
</Text>
|
|
29
|
+
</Card>
|
|
30
|
+
</div>
|
|
31
|
+
</PageLayout>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
services:
|
|
2
|
+
mongodb:
|
|
3
|
+
image: mongodb/mongodb-atlas-local:8.0
|
|
4
|
+
restart: unless-stopped
|
|
5
|
+
ports:
|
|
6
|
+
- '${PORT_MONGO:-3003}:27017'
|
|
7
|
+
volumes:
|
|
8
|
+
- mongodb_data:/data/db
|
|
9
|
+
|
|
10
|
+
minio:
|
|
11
|
+
image: minio/minio:RELEASE.2024-11-07T00-52-20Z
|
|
12
|
+
ports:
|
|
13
|
+
- '${PORT_MINIO:-3006}:9000'
|
|
14
|
+
- '${PORT_MINIO_CONSOLE:-3007}:9001'
|
|
15
|
+
command: server /data --console-address ":9001"
|
|
16
|
+
environment:
|
|
17
|
+
MINIO_ROOT_USER: minioadmin
|
|
18
|
+
MINIO_ROOT_PASSWORD: minioadmin
|
|
19
|
+
volumes:
|
|
20
|
+
- minio_data:/data
|
|
21
|
+
|
|
22
|
+
minio-init:
|
|
23
|
+
image: minio/mc:RELEASE.2024-11-07T00-37-53Z
|
|
24
|
+
depends_on: [minio]
|
|
25
|
+
restart: 'no'
|
|
26
|
+
entrypoint: >
|
|
27
|
+
/bin/sh -c "
|
|
28
|
+
until mc alias set local http://minio:9000 minioadmin minioadmin; do sleep 1; done;
|
|
29
|
+
mc mb --ignore-existing local/public;
|
|
30
|
+
mc mb --ignore-existing local/temp;
|
|
31
|
+
mc anonymous set download local/public;
|
|
32
|
+
mc anonymous set download local/temp;
|
|
33
|
+
exit 0;"
|
|
34
|
+
|
|
35
|
+
nats:
|
|
36
|
+
image: nats:2-alpine
|
|
37
|
+
command: ['-js']
|
|
38
|
+
ports:
|
|
39
|
+
- '${PORT_NATS:-3005}:4222'
|
|
40
|
+
restart: unless-stopped
|
|
41
|
+
|
|
42
|
+
redis:
|
|
43
|
+
image: redis:7-alpine
|
|
44
|
+
ports:
|
|
45
|
+
- '${PORT_REDIS:-3004}:6379'
|
|
46
|
+
restart: unless-stopped
|
|
47
|
+
|
|
48
|
+
volumes:
|
|
49
|
+
mongodb_data:
|
|
50
|
+
minio_data:
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
7
|
+
<title>App</title>
|
|
8
|
+
<script src="https://cdn.tailwindcss.com"></script>
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<div id="root"></div>
|
|
12
|
+
<script type="module" src="/client/main.tsx"></script>
|
|
13
|
+
</body>
|
|
14
|
+
</html>
|