feat: add city/state/country to complex, new settings page with sidebar, and Biome linting
- Added city, state, and country optional fields to Complex model - Updated onboarding to include optional location fields - Created new settings page with sidebar navigation (Datos del Complejo, Canchas) - Replaced ESLint with Biome for frontend and backend linting - Added parallel dev script with concurrently - Migrated register-routes to use direct app.route() pattern
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import pino from 'pino'
|
||||
import pino from 'pino';
|
||||
|
||||
const isProd = Bun.env.NODE_ENV === 'production'
|
||||
const isProd = Bun.env.NODE_ENV === 'production';
|
||||
|
||||
export const logger = pino({
|
||||
level: Bun.env.LOG_LEVEL ?? (isProd ? 'info' : 'debug'),
|
||||
@@ -15,4 +15,4 @@ export const logger = pino({
|
||||
ignore: 'pid,hostname',
|
||||
},
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
import nodemailer from 'nodemailer'
|
||||
import nodemailer from 'nodemailer';
|
||||
|
||||
let cachedTransporter: ReturnType<typeof nodemailer.createTransport> | null = null
|
||||
let cachedTransporter: ReturnType<typeof nodemailer.createTransport> | null = null;
|
||||
|
||||
function getTransporter() {
|
||||
if (cachedTransporter) return cachedTransporter
|
||||
if (cachedTransporter) return cachedTransporter;
|
||||
|
||||
const smtpHost = Bun.env.SMTP_HOST
|
||||
const smtpPort = Number(Bun.env.SMTP_PORT ?? 587)
|
||||
const smtpUser = Bun.env.SMTP_USER
|
||||
const smtpPass = Bun.env.SMTP_PASS
|
||||
const smtpHost = Bun.env.SMTP_HOST;
|
||||
const smtpPort = Number(Bun.env.SMTP_PORT ?? 587);
|
||||
const smtpUser = Bun.env.SMTP_USER;
|
||||
const smtpPass = Bun.env.SMTP_PASS;
|
||||
|
||||
if (!smtpHost || !smtpUser || !smtpPass) {
|
||||
throw new Error(
|
||||
'Missing SMTP env vars. Set SMTP_HOST, SMTP_PORT, SMTP_USER and SMTP_PASS.',
|
||||
)
|
||||
throw new Error('Missing SMTP env vars. Set SMTP_HOST, SMTP_PORT, SMTP_USER and SMTP_PASS.');
|
||||
}
|
||||
|
||||
cachedTransporter = nodemailer.createTransport({
|
||||
@@ -24,21 +22,21 @@ function getTransporter() {
|
||||
user: smtpUser,
|
||||
pass: smtpPass,
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
return cachedTransporter
|
||||
return cachedTransporter;
|
||||
}
|
||||
|
||||
export async function sendMail(input: {
|
||||
to: string
|
||||
subject: string
|
||||
html: string
|
||||
text: string
|
||||
to: string;
|
||||
subject: string;
|
||||
html: string;
|
||||
text: string;
|
||||
}) {
|
||||
const smtpFrom = Bun.env.SMTP_FROM
|
||||
const smtpFrom = Bun.env.SMTP_FROM;
|
||||
|
||||
if (!smtpFrom) {
|
||||
throw new Error('Missing SMTP_FROM env var.')
|
||||
throw new Error('Missing SMTP_FROM env var.');
|
||||
}
|
||||
|
||||
await getTransporter().sendMail({
|
||||
@@ -47,5 +45,5 @@ export async function sendMail(input: {
|
||||
subject: input.subject,
|
||||
html: input.html,
|
||||
text: input.text,
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,50 +1,50 @@
|
||||
import { PrismaPg } from '@prisma/adapter-pg'
|
||||
import { PrismaClient } from '@/generated/prisma/client'
|
||||
import { PrismaClient } from '@/generated/prisma/client';
|
||||
import { PrismaPg } from '@prisma/adapter-pg';
|
||||
|
||||
const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient }
|
||||
const globalForPrisma = globalThis as unknown as { prisma?: PrismaClient };
|
||||
|
||||
function hasExpectedDelegates(client: PrismaClient) {
|
||||
const prismaClient = client as unknown as {
|
||||
court?: { findMany?: unknown }
|
||||
sport?: { findMany?: unknown }
|
||||
}
|
||||
court?: { findMany?: unknown };
|
||||
sport?: { findMany?: unknown };
|
||||
};
|
||||
|
||||
return (
|
||||
typeof prismaClient.court?.findMany === 'function' &&
|
||||
typeof prismaClient.sport?.findMany === 'function'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
function buildPrismaClient() {
|
||||
const databaseUrl = Bun.env.DATABASE_URL
|
||||
const databaseUrl = Bun.env.DATABASE_URL;
|
||||
|
||||
if (!databaseUrl) {
|
||||
throw new Error('Missing DATABASE_URL in backend environment.')
|
||||
throw new Error('Missing DATABASE_URL in backend environment.');
|
||||
}
|
||||
|
||||
const adapter = new PrismaPg({
|
||||
connectionString: databaseUrl,
|
||||
})
|
||||
});
|
||||
|
||||
return new PrismaClient({ adapter })
|
||||
return new PrismaClient({ adapter });
|
||||
}
|
||||
|
||||
export function getPrismaClient() {
|
||||
if (globalForPrisma.prisma && hasExpectedDelegates(globalForPrisma.prisma)) {
|
||||
return globalForPrisma.prisma
|
||||
return globalForPrisma.prisma;
|
||||
}
|
||||
|
||||
if (globalForPrisma.prisma && !hasExpectedDelegates(globalForPrisma.prisma)) {
|
||||
void globalForPrisma.prisma.$disconnect()
|
||||
void globalForPrisma.prisma.$disconnect();
|
||||
}
|
||||
|
||||
const prisma = buildPrismaClient()
|
||||
const prisma = buildPrismaClient();
|
||||
|
||||
if (Bun.env.NODE_ENV !== 'production') {
|
||||
globalForPrisma.prisma = prisma
|
||||
globalForPrisma.prisma = prisma;
|
||||
}
|
||||
|
||||
return prisma
|
||||
return prisma;
|
||||
}
|
||||
|
||||
export const db = getPrismaClient()
|
||||
export const db = getPrismaClient();
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { createClient } from '@supabase/supabase-js';
|
||||
|
||||
let cachedClient: ReturnType<typeof createClient> | null = null
|
||||
let cachedClient: ReturnType<typeof createClient> | null = null;
|
||||
|
||||
export function getSupabaseAdminClient() {
|
||||
if (cachedClient) return cachedClient
|
||||
if (cachedClient) return cachedClient;
|
||||
|
||||
const supabaseUrl = Bun.env.SUPABASE_URL ?? Bun.env.VITE_SUPABASE_URL
|
||||
const supabaseServiceRoleKey = Bun.env.SUPABASE_SERVICE_ROLE_KEY
|
||||
const supabaseUrl = Bun.env.SUPABASE_URL ?? Bun.env.VITE_SUPABASE_URL;
|
||||
const supabaseServiceRoleKey = Bun.env.SUPABASE_SERVICE_ROLE_KEY;
|
||||
|
||||
if (!supabaseUrl || !supabaseServiceRoleKey) {
|
||||
throw new Error(
|
||||
'Missing Supabase admin env vars. Set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY in backend environment.',
|
||||
)
|
||||
'Missing Supabase admin env vars. Set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY in backend environment.'
|
||||
);
|
||||
}
|
||||
|
||||
cachedClient = createClient(supabaseUrl, supabaseServiceRoleKey, {
|
||||
@@ -20,7 +20,7 @@ export function getSupabaseAdminClient() {
|
||||
persistSession: false,
|
||||
detectSessionInUrl: false,
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
return cachedClient
|
||||
return cachedClient;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
import { createClient } from '@supabase/supabase-js'
|
||||
import { createClient } from '@supabase/supabase-js';
|
||||
|
||||
const supabaseUrl = Bun.env.SUPABASE_URL ?? Bun.env.VITE_SUPABASE_URL
|
||||
const supabaseAnonKey =
|
||||
Bun.env.SUPABASE_ANON_KEY ?? Bun.env.VITE_SUPABASE_ANON_KEY
|
||||
const supabaseUrl = Bun.env.SUPABASE_URL ?? Bun.env.VITE_SUPABASE_URL;
|
||||
const supabaseAnonKey = Bun.env.SUPABASE_ANON_KEY ?? Bun.env.VITE_SUPABASE_ANON_KEY;
|
||||
|
||||
if (!supabaseUrl || !supabaseAnonKey) {
|
||||
throw new Error(
|
||||
'Missing Supabase env vars. Set SUPABASE_URL/SUPABASE_ANON_KEY (or VITE_SUPABASE_URL/VITE_SUPABASE_ANON_KEY) in backend environment.',
|
||||
)
|
||||
'Missing Supabase env vars. Set SUPABASE_URL/SUPABASE_ANON_KEY (or VITE_SUPABASE_URL/VITE_SUPABASE_ANON_KEY) in backend environment.'
|
||||
);
|
||||
}
|
||||
|
||||
export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
|
||||
@@ -16,4 +15,4 @@ export const supabase = createClient(supabaseUrl, supabaseAnonKey, {
|
||||
persistSession: false,
|
||||
detectSessionInUrl: false,
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user