mirror of https://github.com/buster-so/buster.git
move supabase start to its own commands
This commit is contained in:
parent
052901012e
commit
299ed5d697
|
@ -8,18 +8,18 @@
|
||||||
"inputs": ["server/**/*", "libs/**/*", "Cargo.toml", "Cargo.lock"]
|
"inputs": ["server/**/*", "libs/**/*", "Cargo.toml", "Cargo.lock"]
|
||||||
},
|
},
|
||||||
"start": {
|
"start": {
|
||||||
"dependsOn": ["@buster/database#start", "build"],
|
"dependsOn": ["@buster-app/supabase#start", "build"],
|
||||||
"cache": true,
|
"cache": true,
|
||||||
"persistent": true
|
"persistent": true
|
||||||
},
|
},
|
||||||
"dev": {
|
"dev": {
|
||||||
"dependsOn": ["@buster/database#start"],
|
"dependsOn": ["@buster-app/supabase#start"],
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": true,
|
"persistent": true,
|
||||||
"outputs": []
|
"outputs": []
|
||||||
},
|
},
|
||||||
"dev:fast": {
|
"dev:fast": {
|
||||||
"dependsOn": ["@buster/database#start"],
|
"dependsOn": ["@buster-app/supabase#start"],
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": true,
|
"persistent": true,
|
||||||
"outputs": []
|
"outputs": []
|
||||||
|
|
|
@ -3,19 +3,19 @@
|
||||||
"extends": ["//"],
|
"extends": ["//"],
|
||||||
"tasks": {
|
"tasks": {
|
||||||
"start": {
|
"start": {
|
||||||
"dependsOn": ["@buster/database#start"],
|
"dependsOn": ["@buster-app/supabase#start"],
|
||||||
"cache": true,
|
"cache": true,
|
||||||
"persistent": false,
|
"persistent": false,
|
||||||
"outputs": []
|
"outputs": []
|
||||||
},
|
},
|
||||||
"dev": {
|
"dev": {
|
||||||
"dependsOn": ["@buster/database#start"],
|
"dependsOn": ["@buster-app/supabase#start"],
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": true,
|
"persistent": true,
|
||||||
"outputs": []
|
"outputs": []
|
||||||
},
|
},
|
||||||
"dev:fast": {
|
"dev:fast": {
|
||||||
"dependsOn": ["@buster/database#start"],
|
"dependsOn": ["@buster-app/supabase#start"],
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": true,
|
"persistent": true,
|
||||||
"outputs": []
|
"outputs": []
|
||||||
|
|
|
@ -7,14 +7,14 @@
|
||||||
"outputs": ["dist/**"]
|
"outputs": ["dist/**"]
|
||||||
},
|
},
|
||||||
"start": {
|
"start": {
|
||||||
"dependsOn": ["@buster/database#start", "build"],
|
"dependsOn": ["@buster-app/supabase#start", "build"],
|
||||||
"cache": true,
|
"cache": true,
|
||||||
"persistent": true
|
"persistent": true
|
||||||
},
|
},
|
||||||
"dev": {
|
"dev": {
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": true,
|
"persistent": true,
|
||||||
"dependsOn": ["@buster/database#start", "^build"],
|
"dependsOn": ["@buster-app/supabase#start", "^build"],
|
||||||
"with": [
|
"with": [
|
||||||
"@buster/ai#dev",
|
"@buster/ai#dev",
|
||||||
"@buster/server-shared#dev",
|
"@buster/server-shared#dev",
|
||||||
|
@ -28,7 +28,7 @@
|
||||||
"dev:fast": {
|
"dev:fast": {
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": true,
|
"persistent": true,
|
||||||
"dependsOn": ["@buster/database#start", "^build"],
|
"dependsOn": ["@buster-app/supabase#start", "^build"],
|
||||||
"with": [
|
"with": [
|
||||||
"@buster/ai#dev:fast",
|
"@buster/ai#dev:fast",
|
||||||
"@buster/server-shared#dev:fast",
|
"@buster/server-shared#dev:fast",
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
main
|
|
@ -3,3 +3,4 @@ volumes/storage
|
||||||
.env
|
.env
|
||||||
test.http
|
test.http
|
||||||
docker-compose.override.yml
|
docker-compose.override.yml
|
||||||
|
.temp
|
||||||
|
|
|
@ -2,12 +2,12 @@
|
||||||
"name": "@buster-app/supabase",
|
"name": "@buster-app/supabase",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"private": false,
|
"private": false,
|
||||||
"dependencies": {
|
"dependencies": {},
|
||||||
"@buster/database": "workspace:*"
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "biome check . --write",
|
"lint": "biome check . --write",
|
||||||
"lint:fix": "biome check . --write",
|
"lint:fix": "biome check . --write",
|
||||||
"start": "echo 'Please run this command through Turbo from the root: turbo start'"
|
"start": "supabase start",
|
||||||
|
"stop": "supabase stop",
|
||||||
|
"reset": "supabase stop && supabase start && supabase db reset"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,19 @@
|
||||||
"extends": ["//"],
|
"extends": ["//"],
|
||||||
"tasks": {
|
"tasks": {
|
||||||
"start": {
|
"start": {
|
||||||
"dependsOn": ["@buster/database#start"],
|
"dependsOn": [],
|
||||||
|
"cache": false,
|
||||||
|
"persistent": false,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
"stop": {
|
||||||
|
"dependsOn": [],
|
||||||
|
"cache": false,
|
||||||
|
"persistent": false,
|
||||||
|
"outputs": []
|
||||||
|
},
|
||||||
|
"reset": {
|
||||||
|
"dependsOn": ["stop"],
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": false,
|
"persistent": false,
|
||||||
"outputs": []
|
"outputs": []
|
||||||
|
|
|
@ -15,8 +15,8 @@
|
||||||
"dev": {
|
"dev": {
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": true,
|
"persistent": true,
|
||||||
"dependsOn": ["^build"],
|
"dependsOn": ["^build","@buster-app/supabase#start"],
|
||||||
"with": ["@buster-app/supabase#start"]
|
"with": ["@buster/database#dev"]
|
||||||
},
|
},
|
||||||
"dev:fast": {
|
"dev:fast": {
|
||||||
"cache": false,
|
"cache": false,
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { useMutation } from '@tanstack/react-query';
|
||||||
import { Link } from '@tanstack/react-router';
|
import { Link } from '@tanstack/react-router';
|
||||||
import type React from 'react';
|
import type React from 'react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
@ -5,32 +6,26 @@ import { Button } from '@/components/ui/buttons';
|
||||||
import { SuccessCard } from '@/components/ui/card/SuccessCard';
|
import { SuccessCard } from '@/components/ui/card/SuccessCard';
|
||||||
import { Input } from '@/components/ui/inputs';
|
import { Input } from '@/components/ui/inputs';
|
||||||
import { Text, Title } from '@/components/ui/typography';
|
import { Text, Title } from '@/components/ui/typography';
|
||||||
import { useBusterNotifications } from '@/context/BusterNotifications';
|
|
||||||
import { resetPasswordEmailSend } from '@/integrations/supabase/resetPassword';
|
import { resetPasswordEmailSend } from '@/integrations/supabase/resetPassword';
|
||||||
import { cn } from '@/lib/classMerge';
|
import { cn } from '@/lib/classMerge';
|
||||||
import { isValidEmail } from '@/lib/email';
|
import { isValidEmail } from '@/lib/email';
|
||||||
import { timeout } from '@/lib/timeout';
|
|
||||||
|
|
||||||
export const ResetEmailForm: React.FC<{
|
export const ResetEmailForm: React.FC<{
|
||||||
queryEmail: string;
|
queryEmail: string;
|
||||||
}> = ({ queryEmail }) => {
|
}> = ({ queryEmail }) => {
|
||||||
const [loading, setLoading] = useState(false);
|
|
||||||
const [email, setEmail] = useState(queryEmail);
|
const [email, setEmail] = useState(queryEmail);
|
||||||
const [emailSent, setEmailSent] = useState(false);
|
const [emailSent, setEmailSent] = useState(false);
|
||||||
const { openErrorNotification } = useBusterNotifications();
|
const { mutateAsync: resetPasswordEmailSendMutation, isPending: loading } = useMutation({
|
||||||
|
mutationFn: resetPasswordEmailSend,
|
||||||
|
});
|
||||||
|
|
||||||
const disabled = !email || !isValidEmail(email);
|
const disabled = !email || !isValidEmail(email);
|
||||||
|
|
||||||
const handleResetPassword = async () => {
|
const handleResetPassword = async () => {
|
||||||
if (disabled) return;
|
if (disabled) return;
|
||||||
setLoading(true);
|
const [res] = await Promise.all([resetPasswordEmailSendMutation({ data: { email } })]);
|
||||||
const [res] = await Promise.all([resetPasswordEmailSend({ data: { email } }), timeout(450)]);
|
|
||||||
if (res?.error) {
|
setEmailSent(true);
|
||||||
openErrorNotification(res.error);
|
|
||||||
} else {
|
|
||||||
setEmailSent(true);
|
|
||||||
}
|
|
||||||
setLoading(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (emailSent) {
|
if (emailSent) {
|
||||||
|
|
|
@ -3,6 +3,7 @@ import type { User } from '@supabase/supabase-js';
|
||||||
import { useRouter } from '@tanstack/react-router';
|
import { useRouter } from '@tanstack/react-router';
|
||||||
import type React from 'react';
|
import type React from 'react';
|
||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
|
import { useGetMyUserInfo } from '@/api/buster_rest/users';
|
||||||
import { Button } from '@/components/ui/buttons';
|
import { Button } from '@/components/ui/buttons';
|
||||||
import { SuccessCard } from '@/components/ui/card/SuccessCard';
|
import { SuccessCard } from '@/components/ui/card/SuccessCard';
|
||||||
import { Input } from '@/components/ui/inputs';
|
import { Input } from '@/components/ui/inputs';
|
||||||
|
@ -13,8 +14,8 @@ import { PolicyCheck } from './PolicyCheck';
|
||||||
|
|
||||||
export const ResetPasswordForm: React.FC<{
|
export const ResetPasswordForm: React.FC<{
|
||||||
supabaseUser: Pick<User, 'email'>;
|
supabaseUser: Pick<User, 'email'>;
|
||||||
busterUser: UserResponse;
|
}> = ({ supabaseUser }) => {
|
||||||
}> = ({ supabaseUser, busterUser }) => {
|
const { data: busterUser } = useGetMyUserInfo();
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [resetSuccess, setResetSuccess] = useState(false);
|
const [resetSuccess, setResetSuccess] = useState(false);
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { createServerFn } from '@tanstack/react-start';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { env } from '@/env';
|
import { env } from '@/env';
|
||||||
import { ServerRoute as AuthCallbackRoute } from '../../routes/auth.callback';
|
import { ServerRoute as AuthCallbackRoute } from '../../routes/auth.callback';
|
||||||
|
import { Route as AuthResetPasswordRoute } from '../../routes/auth.reset-password';
|
||||||
import { getSupabaseServerClient } from './server';
|
import { getSupabaseServerClient } from './server';
|
||||||
|
|
||||||
export const resetPasswordEmailSend = createServerFn({ method: 'POST' })
|
export const resetPasswordEmailSend = createServerFn({ method: 'POST' })
|
||||||
|
@ -10,14 +11,17 @@ export const resetPasswordEmailSend = createServerFn({ method: 'POST' })
|
||||||
const supabase = await getSupabaseServerClient();
|
const supabase = await getSupabaseServerClient();
|
||||||
const url = env.VITE_PUBLIC_URL;
|
const url = env.VITE_PUBLIC_URL;
|
||||||
|
|
||||||
const authURLFull = `${url}${AuthCallbackRoute.to}`;
|
const authURLFull = `${url}${AuthResetPasswordRoute.to}`;
|
||||||
|
|
||||||
|
console.log('email', email);
|
||||||
|
console.log('authURLFull', authURLFull);
|
||||||
|
|
||||||
const { error } = await supabase.auth.resetPasswordForEmail(email, {
|
const { error } = await supabase.auth.resetPasswordForEmail(email, {
|
||||||
redirectTo: authURLFull,
|
redirectTo: authURLFull,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return { error: error.message };
|
throw new Error(error.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -28,6 +32,12 @@ export const resetPassword = createServerFn({ method: 'POST' })
|
||||||
.handler(async ({ data: { password } }) => {
|
.handler(async ({ data: { password } }) => {
|
||||||
const supabase = await getSupabaseServerClient();
|
const supabase = await getSupabaseServerClient();
|
||||||
|
|
||||||
|
const { data: user } = await supabase.auth.getUser();
|
||||||
|
|
||||||
|
if (!user?.user) {
|
||||||
|
throw new Error('User not found');
|
||||||
|
}
|
||||||
|
|
||||||
const { error } = await supabase.auth.updateUser({ password });
|
const { error } = await supabase.auth.updateUser({ password });
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
|
|
|
@ -127,6 +127,7 @@ import { Route as AppAppAssetChatsChatIdReportsReportIdMetricsMetricIdContentCha
|
||||||
import { Route as AppAppAssetChatsChatIdDashboardsDashboardIdMetricsMetricIdContentSqlRouteImport } from './routes/app/_app/_asset/chats.$chatId/dashboards.$dashboardId/metrics.$metricId/_content/sql'
|
import { Route as AppAppAssetChatsChatIdDashboardsDashboardIdMetricsMetricIdContentSqlRouteImport } from './routes/app/_app/_asset/chats.$chatId/dashboards.$dashboardId/metrics.$metricId/_content/sql'
|
||||||
import { Route as AppAppAssetChatsChatIdDashboardsDashboardIdMetricsMetricIdContentResultsRouteImport } from './routes/app/_app/_asset/chats.$chatId/dashboards.$dashboardId/metrics.$metricId/_content/results'
|
import { Route as AppAppAssetChatsChatIdDashboardsDashboardIdMetricsMetricIdContentResultsRouteImport } from './routes/app/_app/_asset/chats.$chatId/dashboards.$dashboardId/metrics.$metricId/_content/results'
|
||||||
import { Route as AppAppAssetChatsChatIdDashboardsDashboardIdMetricsMetricIdContentChartRouteImport } from './routes/app/_app/_asset/chats.$chatId/dashboards.$dashboardId/metrics.$metricId/_content/chart'
|
import { Route as AppAppAssetChatsChatIdDashboardsDashboardIdMetricsMetricIdContentChartRouteImport } from './routes/app/_app/_asset/chats.$chatId/dashboards.$dashboardId/metrics.$metricId/_content/chart'
|
||||||
|
import { ServerRoute as AuthConfirmServerRouteImport } from './routes/auth.confirm'
|
||||||
import { ServerRoute as AuthCallbackServerRouteImport } from './routes/auth.callback'
|
import { ServerRoute as AuthCallbackServerRouteImport } from './routes/auth.callback'
|
||||||
|
|
||||||
const AppAppAssetReportsReportIdRouteImport = createFileRoute(
|
const AppAppAssetReportsReportIdRouteImport = createFileRoute(
|
||||||
|
@ -939,6 +940,11 @@ const AppAppAssetChatsChatIdDashboardsDashboardIdMetricsMetricIdContentChartRout
|
||||||
AppAppAssetChatsChatIdDashboardsDashboardIdMetricsMetricIdContentRoute,
|
AppAppAssetChatsChatIdDashboardsDashboardIdMetricsMetricIdContentRoute,
|
||||||
} as any,
|
} as any,
|
||||||
)
|
)
|
||||||
|
const AuthConfirmServerRoute = AuthConfirmServerRouteImport.update({
|
||||||
|
id: '/auth/confirm',
|
||||||
|
path: '/auth/confirm',
|
||||||
|
getParentRoute: () => rootServerRouteImport,
|
||||||
|
} as any)
|
||||||
const AuthCallbackServerRoute = AuthCallbackServerRouteImport.update({
|
const AuthCallbackServerRoute = AuthCallbackServerRouteImport.update({
|
||||||
id: '/auth/callback',
|
id: '/auth/callback',
|
||||||
path: '/auth/callback',
|
path: '/auth/callback',
|
||||||
|
@ -1621,24 +1627,28 @@ export interface RootRouteChildren {
|
||||||
}
|
}
|
||||||
export interface FileServerRoutesByFullPath {
|
export interface FileServerRoutesByFullPath {
|
||||||
'/auth/callback': typeof AuthCallbackServerRoute
|
'/auth/callback': typeof AuthCallbackServerRoute
|
||||||
|
'/auth/confirm': typeof AuthConfirmServerRoute
|
||||||
}
|
}
|
||||||
export interface FileServerRoutesByTo {
|
export interface FileServerRoutesByTo {
|
||||||
'/auth/callback': typeof AuthCallbackServerRoute
|
'/auth/callback': typeof AuthCallbackServerRoute
|
||||||
|
'/auth/confirm': typeof AuthConfirmServerRoute
|
||||||
}
|
}
|
||||||
export interface FileServerRoutesById {
|
export interface FileServerRoutesById {
|
||||||
__root__: typeof rootServerRouteImport
|
__root__: typeof rootServerRouteImport
|
||||||
'/auth/callback': typeof AuthCallbackServerRoute
|
'/auth/callback': typeof AuthCallbackServerRoute
|
||||||
|
'/auth/confirm': typeof AuthConfirmServerRoute
|
||||||
}
|
}
|
||||||
export interface FileServerRouteTypes {
|
export interface FileServerRouteTypes {
|
||||||
fileServerRoutesByFullPath: FileServerRoutesByFullPath
|
fileServerRoutesByFullPath: FileServerRoutesByFullPath
|
||||||
fullPaths: '/auth/callback'
|
fullPaths: '/auth/callback' | '/auth/confirm'
|
||||||
fileServerRoutesByTo: FileServerRoutesByTo
|
fileServerRoutesByTo: FileServerRoutesByTo
|
||||||
to: '/auth/callback'
|
to: '/auth/callback' | '/auth/confirm'
|
||||||
id: '__root__' | '/auth/callback'
|
id: '__root__' | '/auth/callback' | '/auth/confirm'
|
||||||
fileServerRoutesById: FileServerRoutesById
|
fileServerRoutesById: FileServerRoutesById
|
||||||
}
|
}
|
||||||
export interface RootServerRouteChildren {
|
export interface RootServerRouteChildren {
|
||||||
AuthCallbackServerRoute: typeof AuthCallbackServerRoute
|
AuthCallbackServerRoute: typeof AuthCallbackServerRoute
|
||||||
|
AuthConfirmServerRoute: typeof AuthConfirmServerRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
declare module '@tanstack/react-router' {
|
declare module '@tanstack/react-router' {
|
||||||
|
@ -2522,6 +2532,13 @@ declare module '@tanstack/react-router' {
|
||||||
}
|
}
|
||||||
declare module '@tanstack/react-start/server' {
|
declare module '@tanstack/react-start/server' {
|
||||||
interface ServerFileRoutesByPath {
|
interface ServerFileRoutesByPath {
|
||||||
|
'/auth/confirm': {
|
||||||
|
id: '/auth/confirm'
|
||||||
|
path: '/auth/confirm'
|
||||||
|
fullPath: '/auth/confirm'
|
||||||
|
preLoaderRoute: typeof AuthConfirmServerRouteImport
|
||||||
|
parentRoute: typeof rootServerRouteImport
|
||||||
|
}
|
||||||
'/auth/callback': {
|
'/auth/callback': {
|
||||||
id: '/auth/callback'
|
id: '/auth/callback'
|
||||||
path: '/auth/callback'
|
path: '/auth/callback'
|
||||||
|
@ -3309,6 +3326,7 @@ export const routeTree = rootRouteImport
|
||||||
._addFileTypes<FileRouteTypes>()
|
._addFileTypes<FileRouteTypes>()
|
||||||
const rootServerRouteChildren: RootServerRouteChildren = {
|
const rootServerRouteChildren: RootServerRouteChildren = {
|
||||||
AuthCallbackServerRoute: AuthCallbackServerRoute,
|
AuthCallbackServerRoute: AuthCallbackServerRoute,
|
||||||
|
AuthConfirmServerRoute: AuthConfirmServerRoute,
|
||||||
}
|
}
|
||||||
export const serverRouteTree = rootServerRouteImport
|
export const serverRouteTree = rootServerRouteImport
|
||||||
._addFileChildren(rootServerRouteChildren)
|
._addFileChildren(rootServerRouteChildren)
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
import type { EmailOtpType } from '@supabase/supabase-js';
|
||||||
|
import { redirect } from '@tanstack/react-router';
|
||||||
|
import { createServerFileRoute } from '@tanstack/react-start/server';
|
||||||
|
import { z } from 'zod';
|
||||||
|
import { getSupabaseServerClient } from '@/integrations/supabase/server';
|
||||||
|
import { Route as AuthResetPasswordRoute } from './auth.reset-password';
|
||||||
|
|
||||||
|
const searchParamsSchema = z.object({
|
||||||
|
code: z.string().optional(),
|
||||||
|
token_hash: z.string().optional(),
|
||||||
|
next: z.string().optional(),
|
||||||
|
type: z.string().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const ServerRoute = createServerFileRoute('/auth/confirm').methods({
|
||||||
|
GET: async ({ request }) => {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
const { data: searchParams } = searchParamsSchema.safeParse({
|
||||||
|
code: url.searchParams.get('code') || undefined,
|
||||||
|
token_hash: url.searchParams.get('token_hash') || undefined,
|
||||||
|
type: url.searchParams.get('type') || undefined,
|
||||||
|
next: url.searchParams.get('next') || undefined,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!searchParams) {
|
||||||
|
return new Response('Invalid search params', { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const supabase = await getSupabaseServerClient();
|
||||||
|
|
||||||
|
const { token_hash, type } = searchParams;
|
||||||
|
|
||||||
|
if (!token_hash || !type) {
|
||||||
|
return new Response('Invalid search params', { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data, error } = await supabase.auth.verifyOtp({
|
||||||
|
token_hash: token_hash,
|
||||||
|
type: type as EmailOtpType,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
throw redirect({
|
||||||
|
to: AuthResetPasswordRoute.to,
|
||||||
|
search: {
|
||||||
|
email: data.user?.email || '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
console.error('Error verifying OTP', error);
|
||||||
|
return new Response('Error verifying OTP', { status: 400 });
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,17 +1,10 @@
|
||||||
import { createFileRoute } from '@tanstack/react-router';
|
import { createFileRoute } from '@tanstack/react-router';
|
||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
import { prefetchGetMyUserInfo } from '@/api/buster_rest/users';
|
|
||||||
import { ResetEmailForm } from '@/components/features/auth/ResetEmailForm';
|
import { ResetEmailForm } from '@/components/features/auth/ResetEmailForm';
|
||||||
import { ResetPasswordForm } from '@/components/features/auth/ResetPasswordForm';
|
import { ResetPasswordForm } from '@/components/features/auth/ResetPasswordForm';
|
||||||
import { useGetSupabaseUser } from '@/context/Supabase';
|
import { useGetSupabaseUser } from '@/context/Supabase';
|
||||||
|
|
||||||
export const Route = createFileRoute('/auth/reset-password')({
|
export const Route = createFileRoute('/auth/reset-password')({
|
||||||
loader: async ({ context }) => {
|
|
||||||
const user = await prefetchGetMyUserInfo(context.queryClient);
|
|
||||||
return {
|
|
||||||
user,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
head: () => ({
|
head: () => ({
|
||||||
meta: [
|
meta: [
|
||||||
{ title: 'Reset Password' },
|
{ title: 'Reset Password' },
|
||||||
|
@ -22,26 +15,17 @@ export const Route = createFileRoute('/auth/reset-password')({
|
||||||
}),
|
}),
|
||||||
component: RouteComponent,
|
component: RouteComponent,
|
||||||
validateSearch: z.object({
|
validateSearch: z.object({
|
||||||
email: z.string(),
|
email: z.string().optional(),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
function RouteComponent() {
|
function RouteComponent() {
|
||||||
const { user } = Route.useLoaderData();
|
|
||||||
const { email } = Route.useSearch();
|
const { email } = Route.useSearch();
|
||||||
const supabaseUser = useGetSupabaseUser();
|
const supabaseUser = useGetSupabaseUser();
|
||||||
|
|
||||||
if (email) {
|
if (email || supabaseUser?.is_anonymous || !supabaseUser) {
|
||||||
return <ResetEmailForm queryEmail={email} />;
|
return <ResetEmailForm queryEmail={email || ''} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!supabaseUser || !user) {
|
return <ResetPasswordForm supabaseUser={supabaseUser} />;
|
||||||
return (
|
|
||||||
<div className="flex h-full flex-col items-center justify-center p-10">
|
|
||||||
We were unable to find your account
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return <ResetPasswordForm supabaseUser={supabaseUser} busterUser={user} />;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,15 +31,12 @@
|
||||||
"build": "tsc",
|
"build": "tsc",
|
||||||
"build:dry-run": "tsc",
|
"build:dry-run": "tsc",
|
||||||
"db:init": "echo 'Initializing database...'",
|
"db:init": "echo 'Initializing database...'",
|
||||||
"start": "supabase start",
|
|
||||||
"db:reset": "supabase stop && supabase start && supabase db reset",
|
|
||||||
"db:seed": "tsx scripts/seed.ts",
|
"db:seed": "tsx scripts/seed.ts",
|
||||||
"db:dump": "tsx scripts/dump.ts",
|
"db:dump": "tsx scripts/dump.ts",
|
||||||
"db:migrate": "drizzle-kit migrate",
|
"db:migrate": "drizzle-kit migrate",
|
||||||
"db:generate": "drizzle-kit generate",
|
"db:generate": "drizzle-kit generate",
|
||||||
"db:push": "drizzle-kit push",
|
"db:push": "drizzle-kit push",
|
||||||
"db:studio": "drizzle-kit studio",
|
"db:studio": "drizzle-kit studio",
|
||||||
"db:stop": "supabase stop",
|
|
||||||
"dev": "tsc --watch",
|
"dev": "tsc --watch",
|
||||||
"lint": "biome check --write",
|
"lint": "biome check --write",
|
||||||
"test": "vitest run",
|
"test": "vitest run",
|
||||||
|
@ -53,6 +50,7 @@
|
||||||
"@buster/env-utils": "workspace:*",
|
"@buster/env-utils": "workspace:*",
|
||||||
"@buster/typescript-config": "workspace:*",
|
"@buster/typescript-config": "workspace:*",
|
||||||
"@buster/vitest-config": "workspace:*",
|
"@buster/vitest-config": "workspace:*",
|
||||||
|
"@buster-app/supabase": "workspace:*",
|
||||||
"ai": "catalog:",
|
"ai": "catalog:",
|
||||||
"drizzle-kit": "^0.31.4",
|
"drizzle-kit": "^0.31.4",
|
||||||
"drizzle-orm": "catalog:",
|
"drizzle-orm": "catalog:",
|
||||||
|
|
|
@ -1,48 +0,0 @@
|
||||||
#!/usr/bin/env tsx
|
|
||||||
|
|
||||||
import { exec } from 'node:child_process';
|
|
||||||
import { promisify } from 'node:util';
|
|
||||||
|
|
||||||
const execAsync = promisify(exec);
|
|
||||||
|
|
||||||
async function runCommand(command: string): Promise<void> {
|
|
||||||
console.log(`🔄 Running: ${command}`);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const { stdout, stderr } = await execAsync(command);
|
|
||||||
|
|
||||||
if (stdout) {
|
|
||||||
console.log(stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stderr) {
|
|
||||||
console.error(stderr);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`✅ Successfully completed: ${command}\n`);
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`❌ Error running command: ${command}`);
|
|
||||||
console.error(error);
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function startSupabase(): Promise<void> {
|
|
||||||
console.log('🚀 Starting Supabase setup...\n');
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Start Supabase
|
|
||||||
await runCommand('npm run db:start-supabase');
|
|
||||||
|
|
||||||
// Reset the database
|
|
||||||
await runCommand('npm run db:reset');
|
|
||||||
|
|
||||||
console.log('🎉 Supabase setup completed successfully!');
|
|
||||||
} catch (error) {
|
|
||||||
console.error('💥 Supabase setup failed:', error);
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the script
|
|
||||||
startSupabase();
|
|
|
@ -1,4 +0,0 @@
|
||||||
# Supabase
|
|
||||||
.branches
|
|
||||||
.temp
|
|
||||||
.env
|
|
|
@ -9,25 +9,17 @@
|
||||||
"db:init": {
|
"db:init": {
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": false,
|
"persistent": false,
|
||||||
"dependsOn": ["db:seed"]
|
"dependsOn": ["db:seed", "@buster-app/supabase#start"]
|
||||||
},
|
|
||||||
"start": {
|
|
||||||
"cache": false,
|
|
||||||
"persistent": false,
|
|
||||||
"outputs": []
|
|
||||||
},
|
|
||||||
"db:reset": {
|
|
||||||
"cache": false,
|
|
||||||
"persistent": false
|
|
||||||
},
|
},
|
||||||
"db:migrate": {
|
"db:migrate": {
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": false
|
"persistent": false,
|
||||||
|
"dependsOn": ["@buster-app/supabase#start"]
|
||||||
},
|
},
|
||||||
"db:seed": {
|
"db:seed": {
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": false,
|
"persistent": false,
|
||||||
"dependsOn": ["db:migrate"]
|
"dependsOn": ["db:migrate", "@buster-app/supabase#start"]
|
||||||
},
|
},
|
||||||
"db:dump": {
|
"db:dump": {
|
||||||
"cache": false,
|
"cache": false,
|
||||||
|
@ -45,14 +37,9 @@
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": true
|
"persistent": true
|
||||||
},
|
},
|
||||||
"db:stop": {
|
|
||||||
"cache": false,
|
|
||||||
"persistent": false
|
|
||||||
},
|
|
||||||
"dev": {
|
"dev": {
|
||||||
"cache": false,
|
"cache": false,
|
||||||
"persistent": true,
|
"persistent": true
|
||||||
"dependsOn": ["start"]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -329,11 +329,7 @@ importers:
|
||||||
specifier: ^4.17.12
|
specifier: ^4.17.12
|
||||||
version: 4.17.12
|
version: 4.17.12
|
||||||
|
|
||||||
apps/supabase:
|
apps/supabase: {}
|
||||||
dependencies:
|
|
||||||
'@buster/database':
|
|
||||||
specifier: workspace:*
|
|
||||||
version: link:../../packages/database
|
|
||||||
|
|
||||||
apps/trigger:
|
apps/trigger:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -1159,6 +1155,9 @@ importers:
|
||||||
|
|
||||||
packages/database:
|
packages/database:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
'@buster-app/supabase':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../../apps/supabase
|
||||||
'@buster/env-utils':
|
'@buster/env-utils':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../env-utils
|
version: link:../env-utils
|
||||||
|
|
Loading…
Reference in New Issue