Initial independent version of CrAPP

This commit is contained in:
Ivan Cacciari
2026-08-06 08:36:47 +02:00
commit 330669176d
167 changed files with 24096 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
// This file is auto-generated by Lovable. Do not modify it.
import { createLovableAuth } from "@lovable.dev/cloud-auth-js";
import { supabase } from "../supabase/client";
const lovableAuth = createLovableAuth();
type SignInOptions = {
redirect_uri?: string;
extraParams?: Record<string, string>;
};
export const lovable = {
auth: {
signInWithOAuth: async (provider: "google" | "apple" | "microsoft" | "lovable", opts?: SignInOptions) => {
const result = await lovableAuth.signInWithOAuth(provider, {
redirect_uri: opts?.redirect_uri ?? window.location.origin,
extraParams: {
...opts?.extraParams,
},
});
if (result.redirected) {
return result;
}
if (result.error) {
return result;
}
try {
await supabase.auth.setSession(result.tokens);
} catch (e) {
return { error: e instanceof Error ? e : new Error(String(e)) };
}
return result;
},
},
};
@@ -0,0 +1,15 @@
// This file is automatically generated. Do not edit it directly.
import { createMiddleware } from '@tanstack/react-start'
import { supabase } from './client'
// Must be registered as a global `functionMiddleware` in `src/start.ts`; otherwise
// the browser never attaches the bearer token to serverFn RPCs.
export const attachSupabaseAuth = createMiddleware({ type: 'function' }).client(
async ({ next }) => {
const { data } = await supabase.auth.getSession()
const token = data.session?.access_token
return next({
headers: token ? { Authorization: `Bearer ${token}` } : {},
})
},
)
@@ -0,0 +1,109 @@
// This file is automatically generated. Do not edit it directly.
import { createMiddleware } from '@tanstack/react-start'
import { getRequest } from '@tanstack/react-start/server'
import { createClient } from '@supabase/supabase-js'
import type { Database } from './types'
function isNewSupabaseApiKey(value: string): boolean {
return value.startsWith('sb_publishable_') || value.startsWith('sb_secret_');
}
function createSupabaseFetch(supabaseKey: string): typeof fetch {
return (input, init) => {
const headers = new Headers(
typeof Request !== 'undefined' && input instanceof Request ? input.headers : undefined,
);
if (init?.headers) {
new Headers(init.headers).forEach((value, key) => headers.set(key, value));
}
// New Supabase API keys are opaque strings, not bearer JWTs.
if (isNewSupabaseApiKey(supabaseKey) && headers.get('Authorization') === `Bearer ${supabaseKey}`) {
headers.delete('Authorization');
}
headers.set('apikey', supabaseKey);
return fetch(input, { ...init, headers });
};
}
export const requireSupabaseAuth = createMiddleware({ type: 'function' }).server(
async ({ next }) => {
const SUPABASE_URL = process.env['SUPABASE_URL'];
const SUPABASE_PUBLISHABLE_KEY = process.env['SUPABASE_PUBLISHABLE_KEY'];
if (!SUPABASE_URL || !SUPABASE_PUBLISHABLE_KEY) {
const missing = [
...(!SUPABASE_URL ? ['SUPABASE_URL'] : []),
...(!SUPABASE_PUBLISHABLE_KEY ? ['SUPABASE_PUBLISHABLE_KEY'] : []),
];
const message = `Missing Supabase environment variable(s): ${missing.join(', ')}. Connect Supabase in Lovable Cloud.`;
console.error(`[Supabase] ${message}`);
throw new Error(message);
}
const request = getRequest();
if (!request?.headers) {
throw new Error('Unauthorized: No request headers available');
}
const authHeader = request.headers.get('authorization');
if (!authHeader) {
throw new Error('Unauthorized: No authorization header provided');
}
if (!authHeader.startsWith('Bearer ')) {
throw new Error('Unauthorized: Only Bearer tokens are supported');
}
const token = authHeader.replace('Bearer ', '');
if (!token) {
throw new Error('Unauthorized: No token provided');
}
if (token.split('.').length !== 3) {
throw new Error('Unauthorized: Invalid token');
}
const supabase = createClient<Database>(
SUPABASE_URL!,
SUPABASE_PUBLISHABLE_KEY!,
{
global: {
fetch: createSupabaseFetch(SUPABASE_PUBLISHABLE_KEY!),
headers: {
Authorization: `Bearer ${token}`,
},
},
auth: {
storage: undefined,
persistSession: false,
autoRefreshToken: false,
},
}
);
const { data, error } = await supabase.auth.getClaims(token);
if (error || !data?.claims) {
throw new Error('Unauthorized: Invalid token');
}
if (!data.claims.sub) {
throw new Error('Unauthorized: No user ID found in token');
}
return next({
context: {
supabase,
userId: data.claims.sub,
claims: data.claims,
},
});
},
);
@@ -0,0 +1,69 @@
// This file is automatically generated. Do not edit it directly.
// Server-side Supabase client with service role key - bypasses RLS.
// Use this for admin operations in server functions and server routes only.
// For user-authenticated queries (with RLS), use the auth middleware instead.
import { createClient } from '@supabase/supabase-js';
import type { Database } from './types';
function isNewSupabaseApiKey(value: string): boolean {
return value.startsWith('sb_publishable_') || value.startsWith('sb_secret_');
}
function createSupabaseFetch(supabaseKey: string): typeof fetch {
return (input, init) => {
const headers = new Headers(
typeof Request !== 'undefined' && input instanceof Request ? input.headers : undefined,
);
if (init?.headers) {
new Headers(init.headers).forEach((value, key) => headers.set(key, value));
}
// New Supabase API keys are opaque strings, not bearer JWTs.
if (isNewSupabaseApiKey(supabaseKey) && headers.get('Authorization') === `Bearer ${supabaseKey}`) {
headers.delete('Authorization');
}
headers.set('apikey', supabaseKey);
return fetch(input, { ...init, headers });
};
}
function createSupabaseAdminClient() {
const SUPABASE_URL = process.env['SUPABASE_URL'];
const SUPABASE_SERVICE_ROLE_KEY = process.env['SUPABASE_SERVICE_ROLE_KEY'];
if (!SUPABASE_URL || !SUPABASE_SERVICE_ROLE_KEY) {
const missing = [
...(!SUPABASE_URL ? ['SUPABASE_URL'] : []),
...(!SUPABASE_SERVICE_ROLE_KEY ? ['SUPABASE_SERVICE_ROLE_KEY'] : []),
];
const message = `Missing Supabase environment variable(s): ${missing.join(', ')}. Connect Supabase in Lovable Cloud.`;
console.error(`[Supabase] ${message}`);
throw new Error(message);
}
return createClient<Database>(SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY, {
global: {
fetch: createSupabaseFetch(SUPABASE_SERVICE_ROLE_KEY),
},
auth: {
storage: undefined,
persistSession: false,
autoRefreshToken: false,
}
});
}
let _supabaseAdmin: ReturnType<typeof createSupabaseAdminClient> | undefined;
// Server-side Supabase client with service role - bypasses RLS
// SECURITY: Only use this for trusted server-side operations, never expose to client code
// Load inside server handlers: const { supabaseAdmin } = await import("@/integrations/supabase/client.server");
// Top-level import is safe only in other .server.ts modules - route files and *.functions.ts ship to the client bundle.
export const supabaseAdmin = new Proxy({} as ReturnType<typeof createSupabaseAdminClient>, {
get(_, prop, receiver) {
if (!_supabaseAdmin) _supabaseAdmin = createSupabaseAdminClient();
return Reflect.get(_supabaseAdmin, prop, receiver);
},
});
+68
View File
@@ -0,0 +1,68 @@
// This file is automatically generated. Do not edit it directly.
import { createClient } from '@supabase/supabase-js';
import type { Database } from './types';
function isNewSupabaseApiKey(value: string): boolean {
return value.startsWith('sb_publishable_') || value.startsWith('sb_secret_');
}
function createSupabaseFetch(supabaseKey: string): typeof fetch {
return (input, init) => {
const headers = new Headers(
typeof Request !== 'undefined' && input instanceof Request ? input.headers : undefined,
);
if (init?.headers) {
new Headers(init.headers).forEach((value, key) => headers.set(key, value));
}
// New Supabase API keys are opaque strings, not bearer JWTs.
if (isNewSupabaseApiKey(supabaseKey) && headers.get('Authorization') === `Bearer ${supabaseKey}`) {
headers.delete('Authorization');
}
headers.set('apikey', supabaseKey);
return fetch(input, { ...init, headers });
};
}
function createSupabaseClient() {
// Use import.meta.env for client-side (Vite build-time replacement)
// Fall back to process.env for SSR (server-side rendering)
const SUPABASE_URL = import.meta.env['VITE_SUPABASE_URL'] || process.env['SUPABASE_URL'];
const SUPABASE_PUBLISHABLE_KEY = import.meta.env['VITE_SUPABASE_PUBLISHABLE_KEY'] || process.env['SUPABASE_PUBLISHABLE_KEY'];
if (!SUPABASE_URL || !SUPABASE_PUBLISHABLE_KEY) {
const missing = [
...(!SUPABASE_URL ? ['SUPABASE_URL'] : []),
...(!SUPABASE_PUBLISHABLE_KEY ? ['SUPABASE_PUBLISHABLE_KEY'] : []),
];
const message = `Missing Supabase environment variable(s): ${missing.join(', ')}. Connect Supabase in Lovable Cloud.`;
console.error(`[Supabase] ${message}`);
throw new Error(message);
}
return createClient<Database>(SUPABASE_URL, SUPABASE_PUBLISHABLE_KEY, {
global: {
fetch: createSupabaseFetch(SUPABASE_PUBLISHABLE_KEY),
},
auth: {
storage: typeof window !== 'undefined' ? localStorage : undefined,
persistSession: true,
autoRefreshToken: true,
}
});
}
let _supabase: ReturnType<typeof createSupabaseClient> | undefined;
// Import the supabase client like this:
// import { supabase } from "@/integrations/supabase/client";
export const supabase = new Proxy({} as ReturnType<typeof createSupabaseClient>, {
get(_, prop, receiver) {
if (!_supabase) _supabase = createSupabaseClient();
return Reflect.get(_supabase, prop, receiver);
},
});
+600
View File
@@ -0,0 +1,600 @@
export type Json =
| string
| number
| boolean
| null
| { [key: string]: Json | undefined }
| Json[]
export type Database = {
// Allows to automatically instantiate createClient with right options
// instead of createClient<Database, { PostgrestVersion: 'XX' }>(URL, KEY)
__InternalSupabase: {
PostgrestVersion: "14.15"
}
public: {
Tables: {
badge_social_voti: {
Row: {
categoria: string
created_at: string
id: string
match_id: string
updated_at: string
votante_id: string
votato_id: string
votato_nome: string
}
Insert: {
categoria: string
created_at?: string
id?: string
match_id: string
updated_at?: string
votante_id: string
votato_id: string
votato_nome: string
}
Update: {
categoria?: string
created_at?: string
id?: string
match_id?: string
updated_at?: string
votante_id?: string
votato_id?: string
votato_nome?: string
}
Relationships: []
}
cacche_partita: {
Row: {
created_at: string
evento_id: string
giocatore_id: string
id: string
quantita: number
updated_at: string
}
Insert: {
created_at?: string
evento_id: string
giocatore_id: string
id?: string
quantita?: number
updated_at?: string
}
Update: {
created_at?: string
evento_id?: string
giocatore_id?: string
id?: string
quantita?: number
updated_at?: string
}
Relationships: []
}
eventi: {
Row: {
aggiornato_il: string
avversario: string | null
casa: boolean | null
creato_da: string | null
creato_il: string
data: string
id: string
luogo: string
ora: string
tipo: string
titolo: string
}
Insert: {
aggiornato_il?: string
avversario?: string | null
casa?: boolean | null
creato_da?: string | null
creato_il?: string
data: string
id?: string
luogo: string
ora: string
tipo: string
titolo: string
}
Update: {
aggiornato_il?: string
avversario?: string | null
casa?: boolean | null
creato_da?: string | null
creato_il?: string
data?: string
id?: string
luogo?: string
ora?: string
tipo?: string
titolo?: string
}
Relationships: []
}
eventi_app: {
Row: {
aggiornato_il: string
campionato: boolean
casa: boolean
convocati: string[]
creato_il: string
data: string
id: string
luogo: string
note: string
ora: string
pagelle_chiuse: boolean
tipo: string
titolo: string
}
Insert: {
aggiornato_il?: string
campionato?: boolean
casa?: boolean
convocati?: string[]
creato_il?: string
data: string
id: string
luogo?: string
note?: string
ora?: string
pagelle_chiuse?: boolean
tipo: string
titolo: string
}
Update: {
aggiornato_il?: string
campionato?: boolean
casa?: boolean
convocati?: string[]
creato_il?: string
data?: string
id?: string
luogo?: string
note?: string
ora?: string
pagelle_chiuse?: boolean
tipo?: string
titolo?: string
}
Relationships: []
}
giocatori: {
Row: {
aggiornato_il: string
auth_user_id: string | null
creato_il: string
foto: string | null
id: string
nascita: string
nome: string
numero: number
ruolo: string
}
Insert: {
aggiornato_il?: string
auth_user_id?: string | null
creato_il?: string
foto?: string | null
id?: string
nascita: string
nome: string
numero: number
ruolo: string
}
Update: {
aggiornato_il?: string
auth_user_id?: string | null
creato_il?: string
foto?: string | null
id?: string
nascita?: string
nome?: string
numero?: number
ruolo?: string
}
Relationships: []
}
mvp_voti: {
Row: {
created_at: string
id: string
match_id: string
updated_at: string
votante_id: string
votato_id: string
votato_nome: string
}
Insert: {
created_at?: string
id?: string
match_id: string
updated_at?: string
votante_id: string
votato_id: string
votato_nome: string
}
Update: {
created_at?: string
id?: string
match_id?: string
updated_at?: string
votante_id?: string
votato_id?: string
votato_nome?: string
}
Relationships: []
}
pagelle_voti: {
Row: {
created_at: string
id: string
match_id: string
updated_at: string
votante_id: string
votato_id: string
voto: number
}
Insert: {
created_at?: string
id?: string
match_id: string
updated_at?: string
votante_id: string
votato_id: string
voto: number
}
Update: {
created_at?: string
id?: string
match_id?: string
updated_at?: string
votante_id?: string
votato_id?: string
voto?: number
}
Relationships: []
}
presenze: {
Row: {
aggiornato_da: string | null
aggiornato_il: string
evento_id: string
giocatore_id: string
id: string
stato: string
}
Insert: {
aggiornato_da?: string | null
aggiornato_il?: string
evento_id: string
giocatore_id: string
id?: string
stato: string
}
Update: {
aggiornato_da?: string | null
aggiornato_il?: string
evento_id?: string
giocatore_id?: string
id?: string
stato?: string
}
Relationships: [
{
foreignKeyName: "presenze_evento_id_fkey"
columns: ["evento_id"]
isOneToOne: false
referencedRelation: "eventi"
referencedColumns: ["id"]
},
{
foreignKeyName: "presenze_giocatore_id_fkey"
columns: ["giocatore_id"]
isOneToOne: false
referencedRelation: "giocatori"
referencedColumns: ["id"]
},
]
}
promemoria_push: {
Row: {
creato_il: string
endpoint: string
id: string
testo: string
titolo: string
}
Insert: {
creato_il?: string
endpoint: string
id?: string
testo: string
titolo: string
}
Update: {
creato_il?: string
endpoint?: string
id?: string
testo?: string
titolo?: string
}
Relationships: []
}
push_subscriptions: {
Row: {
auth: string
created_at: string
endpoint: string
giocatore_id: string
id: string
p256dh: string
}
Insert: {
auth: string
created_at?: string
endpoint: string
giocatore_id: string
id?: string
p256dh: string
}
Update: {
auth?: string
created_at?: string
endpoint?: string
giocatore_id?: string
id?: string
p256dh?: string
}
Relationships: []
}
risposte_presenze: {
Row: {
aggiornato_il: string
evento_id: string
giocatore_id: string
stato: string
}
Insert: {
aggiornato_il?: string
evento_id: string
giocatore_id: string
stato: string
}
Update: {
aggiornato_il?: string
evento_id?: string
giocatore_id?: string
stato?: string
}
Relationships: []
}
scout_live: {
Row: {
aggiornato_il: string
evento_id: string
stato: Json
}
Insert: {
aggiornato_il?: string
evento_id: string
stato?: Json
}
Update: {
aggiornato_il?: string
evento_id?: string
stato?: Json
}
Relationships: []
}
scout_sessioni: {
Row: {
aggiornato_il: string
evento_id: string
giocatore_id: string
giocatore_nome: string
}
Insert: {
aggiornato_il?: string
evento_id: string
giocatore_id: string
giocatore_nome: string
}
Update: {
aggiornato_il?: string
evento_id?: string
giocatore_id?: string
giocatore_nome?: string
}
Relationships: []
}
turni_palloni: {
Row: {
aggiornato_da: string | null
aggiornato_il: string
evento_id: string
giocatore_id: string
}
Insert: {
aggiornato_da?: string | null
aggiornato_il?: string
evento_id: string
giocatore_id: string
}
Update: {
aggiornato_da?: string | null
aggiornato_il?: string
evento_id?: string
giocatore_id?: string
}
Relationships: []
}
user_roles: {
Row: {
id: string
role: Database["public"]["Enums"]["app_role"]
user_id: string
}
Insert: {
id?: string
role: Database["public"]["Enums"]["app_role"]
user_id: string
}
Update: {
id?: string
role?: Database["public"]["Enums"]["app_role"]
user_id?: string
}
Relationships: []
}
}
Views: {
[_ in never]: never
}
Functions: {
has_role: {
Args: {
_role: Database["public"]["Enums"]["app_role"]
_user_id: string
}
Returns: boolean
}
}
Enums: {
app_role: "admin" | "user"
}
CompositeTypes: {
[_ in never]: never
}
}
}
type DatabaseWithoutInternals = Omit<Database, "__InternalSupabase">
type DefaultSchema = DatabaseWithoutInternals[Extract<keyof Database, "public">]
export type Tables<
DefaultSchemaTableNameOrOptions extends
| keyof (DefaultSchema["Tables"] & DefaultSchema["Views"])
| { schema: keyof DatabaseWithoutInternals },
TableName extends DefaultSchemaTableNameOrOptions extends {
schema: keyof DatabaseWithoutInternals
}
? keyof (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] &
DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Views"])
: never = never,
> = DefaultSchemaTableNameOrOptions extends {
schema: keyof DatabaseWithoutInternals
}
? (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] &
DatabaseWithoutInternals[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 DatabaseWithoutInternals },
TableName extends DefaultSchemaTableNameOrOptions extends {
schema: keyof DatabaseWithoutInternals
}
? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"]
: never = never,
> = DefaultSchemaTableNameOrOptions extends {
schema: keyof DatabaseWithoutInternals
}
? DatabaseWithoutInternals[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 DatabaseWithoutInternals },
TableName extends DefaultSchemaTableNameOrOptions extends {
schema: keyof DatabaseWithoutInternals
}
? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"]
: never = never,
> = DefaultSchemaTableNameOrOptions extends {
schema: keyof DatabaseWithoutInternals
}
? DatabaseWithoutInternals[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 DatabaseWithoutInternals },
EnumName extends DefaultSchemaEnumNameOrOptions extends {
schema: keyof DatabaseWithoutInternals
}
? keyof DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"]
: never = never,
> = DefaultSchemaEnumNameOrOptions extends {
schema: keyof DatabaseWithoutInternals
}
? DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"][EnumName]
: DefaultSchemaEnumNameOrOptions extends keyof DefaultSchema["Enums"]
? DefaultSchema["Enums"][DefaultSchemaEnumNameOrOptions]
: never
export type CompositeTypes<
PublicCompositeTypeNameOrOptions extends
| keyof DefaultSchema["CompositeTypes"]
| { schema: keyof DatabaseWithoutInternals },
CompositeTypeName extends PublicCompositeTypeNameOrOptions extends {
schema: keyof DatabaseWithoutInternals
}
? keyof DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"]
: never = never,
> = PublicCompositeTypeNameOrOptions extends {
schema: keyof DatabaseWithoutInternals
}
? DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"][CompositeTypeName]
: PublicCompositeTypeNameOrOptions extends keyof DefaultSchema["CompositeTypes"]
? DefaultSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions]
: never
export const Constants = {
public: {
Enums: {
app_role: ["admin", "user"],
},
},
} as const