Making progress on rewrite. Looking into supabase cache helpers.

This commit is contained in:
2025-06-23 16:59:02 -05:00
parent 63574f0729
commit 13cf089870
21 changed files with 740 additions and 13 deletions

View File

@@ -0,0 +1,23 @@
'use client';
import { createBrowserClient } from '@supabase/ssr';
import type { Database } from '@/utils/supabase/database.types';
import type { SupabaseClient } from '@/utils/supabase/types';
import { useMemo } from 'react';
let client: SupabaseClient | undefined;
const getSupbaseClient = () => {
if (client) return client;
client = createBrowserClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
);
return client;
};
const useSupabaseClient = () => {
return useMemo(getSupbaseClient, []);
};
export { useSupabaseClient };

View File

@@ -0,0 +1,203 @@
export type Json =
| string
| number
| boolean
| null
| { [key: string]: Json | undefined }
| Json[];
export type Database = {
public: {
Tables: {
profiles: {
Row: {
avatar_url: string | null;
email: string | null;
full_name: string | null;
id: string;
provider: string | null;
updated_at: string | null;
};
Insert: {
avatar_url?: string | null;
email?: string | null;
full_name?: string | null;
id: string;
provider?: string | null;
updated_at?: string | null;
};
Update: {
avatar_url?: string | null;
email?: string | null;
full_name?: string | null;
id?: string;
provider?: string | null;
updated_at?: string | null;
};
Relationships: [];
};
statuses: {
Row: {
created_at: string;
id: string;
status: string;
updated_by_id: string | null;
user_id: string;
};
Insert: {
created_at?: string;
id?: string;
status: string;
updated_by_id?: string | null;
user_id: string;
};
Update: {
created_at?: string;
id?: string;
status?: string;
updated_by_id?: string | null;
user_id?: string;
};
Relationships: [
{
foreignKeyName: 'statuses_updated_by_id_fkey';
columns: ['updated_by_id'];
isOneToOne: false;
referencedRelation: 'profiles';
referencedColumns: ['id'];
},
{
foreignKeyName: 'statuses_user_id_fkey';
columns: ['user_id'];
isOneToOne: false;
referencedRelation: 'profiles';
referencedColumns: ['id'];
},
];
};
};
Views: {
[_ in never]: never;
};
Functions: {
[_ in never]: never;
};
Enums: {
[_ in never]: never;
};
CompositeTypes: {
[_ in never]: never;
};
};
};
type DefaultSchema = Database[Extract<keyof Database, 'public'>];
export type Tables<
DefaultSchemaTableNameOrOptions extends
| keyof (DefaultSchema['Tables'] & DefaultSchema['Views'])
| { schema: keyof Database },
TableName extends DefaultSchemaTableNameOrOptions extends {
schema: keyof Database;
}
? keyof (Database[DefaultSchemaTableNameOrOptions['schema']]['Tables'] &
Database[DefaultSchemaTableNameOrOptions['schema']]['Views'])
: never = never,
> = DefaultSchemaTableNameOrOptions extends { schema: keyof Database }
? (Database[DefaultSchemaTableNameOrOptions['schema']]['Tables'] &
Database[DefaultSchemaTableNameOrOptions['schema']]['Views'])[TableName] extends {
Row: infer R;
}
? R
: never
: DefaultSchemaTableNameOrOptions extends keyof (DefaultSchema['Tables'] &
DefaultSchema['Views'])
? (DefaultSchema['Tables'] &
DefaultSchema['Views'])[DefaultSchemaTableNameOrOptions] extends {
Row: infer R;
}
? R
: never
: never;
export type TablesInsert<
DefaultSchemaTableNameOrOptions extends
| keyof DefaultSchema['Tables']
| { schema: keyof Database },
TableName extends DefaultSchemaTableNameOrOptions extends {
schema: keyof Database;
}
? keyof Database[DefaultSchemaTableNameOrOptions['schema']]['Tables']
: never = never,
> = DefaultSchemaTableNameOrOptions extends { schema: keyof Database }
? Database[DefaultSchemaTableNameOrOptions['schema']]['Tables'][TableName] extends {
Insert: infer I;
}
? I
: never
: DefaultSchemaTableNameOrOptions extends keyof DefaultSchema['Tables']
? DefaultSchema['Tables'][DefaultSchemaTableNameOrOptions] extends {
Insert: infer I;
}
? I
: never
: never;
export type TablesUpdate<
DefaultSchemaTableNameOrOptions extends
| keyof DefaultSchema['Tables']
| { schema: keyof Database },
TableName extends DefaultSchemaTableNameOrOptions extends {
schema: keyof Database;
}
? keyof Database[DefaultSchemaTableNameOrOptions['schema']]['Tables']
: never = never,
> = DefaultSchemaTableNameOrOptions extends { schema: keyof Database }
? Database[DefaultSchemaTableNameOrOptions['schema']]['Tables'][TableName] extends {
Update: infer U;
}
? U
: never
: DefaultSchemaTableNameOrOptions extends keyof DefaultSchema['Tables']
? DefaultSchema['Tables'][DefaultSchemaTableNameOrOptions] extends {
Update: infer U;
}
? U
: never
: never;
export type Enums<
DefaultSchemaEnumNameOrOptions extends
| keyof DefaultSchema['Enums']
| { schema: keyof Database },
EnumName extends DefaultSchemaEnumNameOrOptions extends {
schema: keyof Database;
}
? keyof Database[DefaultSchemaEnumNameOrOptions['schema']]['Enums']
: never = never,
> = DefaultSchemaEnumNameOrOptions extends { schema: keyof Database }
? Database[DefaultSchemaEnumNameOrOptions['schema']]['Enums'][EnumName]
: DefaultSchemaEnumNameOrOptions extends keyof DefaultSchema['Enums']
? DefaultSchema['Enums'][DefaultSchemaEnumNameOrOptions]
: never;
export type CompositeTypes<
PublicCompositeTypeNameOrOptions extends
| keyof DefaultSchema['CompositeTypes']
| { schema: keyof Database },
CompositeTypeName extends PublicCompositeTypeNameOrOptions extends {
schema: keyof Database;
}
? keyof Database[PublicCompositeTypeNameOrOptions['schema']]['CompositeTypes']
: never = never,
> = PublicCompositeTypeNameOrOptions extends { schema: keyof Database }
? Database[PublicCompositeTypeNameOrOptions['schema']]['CompositeTypes'][CompositeTypeName]
: PublicCompositeTypeNameOrOptions extends keyof DefaultSchema['CompositeTypes']
? DefaultSchema['CompositeTypes'][PublicCompositeTypeNameOrOptions]
: never;
export const Constants = {
public: {
Enums: {},
},
} as const;

View File

@@ -0,0 +1,5 @@
export { useSupabaseClient } from './client';
export { updateSession } from './middleware';
export { useSupabaseServer } from './server';
export type { Database } from './database.types';
export type * from './types';

View File

@@ -0,0 +1,56 @@
import { createServerClient } from '@supabase/ssr';
import { type NextRequest, NextResponse } from 'next/server';
import type { Database } from '@/utils/supabase/database.types';
export const updateSession = async (
request: NextRequest,
): Promise<NextResponse> => {
try {
// Create an unmodified response
let response = NextResponse.next({
request: {
headers: request.headers,
},
});
const supabase = createServerClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return request.cookies.getAll();
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value }) =>
request.cookies.set(name, value),
);
response = NextResponse.next({
request,
});
cookiesToSet.forEach(({ name, value, options }) =>
response.cookies.set(name, value, options),
);
},
},
},
);
// This will refresh session if expired - required for Server Components
// https://supabase.com/docs/guides/auth/server-side/nextjs
const user = await supabase.auth.getUser();
// protected routes
if (request.nextUrl.pathname.startsWith('/reset-password') && user.error) {
return NextResponse.redirect(new URL('/sign-in', request.url));
}
return response;
} catch (e) {
return NextResponse.next({
request: {
headers: request.headers,
},
});
}
};

View File

@@ -0,0 +1,30 @@
'use server';
import 'server-only';
import { createServerClient } from '@supabase/ssr';
import type { Database } from '@/utils/supabase/database.types';
import { cookies } from 'next/headers';
export const useSupabaseServer = async () => {
const cookieStore = await cookies();
return createServerClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return cookieStore.getAll();
},
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) => {
cookieStore.set(name, value, options);
});
} catch (error) {
console.error(`Error setting cookies: ${error as string}`);
}
},
},
},
);
};

View File

@@ -0,0 +1,30 @@
import type { Database } from '@/utils/supabase/database.types';
import type { SupabaseClient as SBClient } from '@supabase/supabase-js'
export type SupabaseClient = SBClient<Database>;
export type { User } from '@supabase/supabase-js';
// Table row types
export type Profile = Database['public']['Tables']['profiles']['Row'];
export type Status = Database['public']['Tables']['statuses']['Row'];
// Insert types
export type ProfileInsert = Database['public']['Tables']['profiles']['Insert'];
export type StatusInsert = Database['public']['Tables']['statuses']['Insert'];
// Update types
export type ProfileUpdate = Database['public']['Tables']['profiles']['Update'];
export type StatusUpdate = Database['public']['Tables']['statuses']['Update'];
// Generic helper to get any table's row type
export type TableRow<T extends keyof Database['public']['Tables']> =
Database['public']['Tables'][T]['Row'];
// Generic helper to get any table's insert type
export type TableInsert<T extends keyof Database['public']['Tables']> =
Database['public']['Tables'][T]['Insert'];
// Generic helper to get any table's update type
export type TableUpdate<T extends keyof Database['public']['Tables']> =
Database['public']['Tables'][T]['Update'];