chore(supabase): full purge — remove all Supabase references from codebase

- Delete supabase/ directory (config.toml, push-migrations.js,
  ADMIN_CREATE_STOP_FIX.sql, 137 archived migration files)
- Remove @supabase/ssr and @supabase/supabase-js from package.json
- Strip *.supabase.co from next.config.ts image hostnames
- Strip https://*.supabase.co from vercel.json CSP connect-src
- Remove 'supabase/**' ignore from eslint.config.mjs
- Clean supabase references from src/lib/db.ts, vitest.config.ts,
  db/seeds/2026-tuxedo-tour-stops.sql, src/actions/storefront.ts,
  scripts/import-tuxedo-stops.ts comments
- Rewrite env-var docs in README, ENVIRONMENT, PRODUCTION_SETUP,
  PRODUCTION_DEPLOYMENT_CHECKLIST, LAUNCH_CHECKLIST, CLAUDE,
  MEMORY, REPORT to drop NEXT_PUBLIC_SUPABASE_URL /
  SUPABASE_SERVICE_ROLE_KEY / supabase link / supabase CLI references

The canonical migration runner is now scripts/migrate.js (uses pg
directly via DATABASE_URL). Migrations live in db/migrations/. The
Supabase CLI is no longer in the codebase. The only remaining
'@supabase/*' in the dep tree is @supabase/auth-js as a transitive
of @neondatabase/auth (Neon Auth / Better Auth).

Final source scan: grep -rln '@supabase\|rest/v1\|supabase\.co'
src/ tests/ db/ scripts/ next.config.ts vercel.json eslint.config.mjs
package.json returns zero. Verification: npm install clean
(11 added, 21 removed, 12 changed), tsc shows same 17 pre-existing
errors (Stripe dahlia API version + fetch preconnect mocks),
vitest 172/175 (3 pre-existing failures in getAdminUser.test.ts),
lint shows same 14 pre-existing errors. Live-tested: dev server
boots in 248ms, public storefronts (/) (/login) (/pricing) (/tuxedo)
(/indian-river-direct) all return 200; /admin/v2?demo=1 reaches 200
after dev_session redirect; storefront renders real brand content.
This commit is contained in:
Nora
2026-06-25 17:48:32 -06:00
parent 68a749f7af
commit 49b8e27219
171 changed files with 136 additions and 28594 deletions
@@ -1,163 +0,0 @@
-- Migration 064: Seed wholesale_settings for existing brands + fix RLS for service role
-- Also creates a seed function that bypasses RLS for initial setup
BEGIN;
-- Create a SECURITY DEFINER function that inserts wholesale_settings without RLS
-- This is only for initial seeding — not used in normal operation
CREATE OR REPLACE FUNCTION public.seed_wholesale_settings(
p_brand_id UUID,
p_require_approval BOOLEAN DEFAULT true,
p_wholesale_enabled BOOLEAN DEFAULT true,
p_pickup_location TEXT DEFAULT NULL,
p_from_email TEXT DEFAULT NULL,
p_invoice_business_name TEXT DEFAULT NULL
)
RETURNS JSONB
LANGUAGE plpgsql SECURITY DEFINER SET search_path = public
AS $$
BEGIN
INSERT INTO wholesale_settings (
brand_id, require_approval, wholesale_enabled,
pickup_location, from_email, invoice_business_name
)
VALUES (
p_brand_id,
COALESCE(p_require_approval, true),
COALESCE(p_wholesale_enabled, true),
p_pickup_location,
p_from_email,
p_invoice_business_name
)
ON CONFLICT (brand_id) DO UPDATE SET
require_approval = COALESCE(p_require_approval, wholesale_settings.require_approval),
wholesale_enabled = COALESCE(p_wholesale_enabled, wholesale_settings.wholesale_enabled),
pickup_location = COALESCE(p_pickup_location, wholesale_settings.pickup_location),
from_email = COALESCE(p_from_email, wholesale_settings.from_email),
invoice_business_name = COALESCE(p_invoice_business_name, wholesale_settings.invoice_business_name),
updated_at = now()
RETURNING jsonb_build_object('success', true, 'brand_id', brand_id);
END;
$$;
-- Update register_wholesale_customer to auto-create settings if missing
-- This ensures new brands always get settings on first registration
CREATE OR REPLACE FUNCTION public.register_wholesale_customer(
p_brand_id UUID DEFAULT NULL,
p_company_name TEXT DEFAULT NULL,
p_contact_name TEXT DEFAULT NULL,
p_email TEXT DEFAULT NULL,
p_phone TEXT DEFAULT NULL
)
RETURNS JSONB
LANGUAGE plpgsql SECURITY DEFINER SET search_path = public
AS $$
DECLARE
v_id UUID;
v_req_app BOOLEAN := true;
BEGIN
-- Reject duplicate email for this brand
IF EXISTS (SELECT 1 FROM wholesale_customers WHERE brand_id = p_brand_id AND email = p_email) THEN
RETURN jsonb_build_object('success', false, 'error', 'An account with this email already exists.');
END IF;
-- Auto-create wholesale_settings row if it doesn't exist for this brand
-- Uses SECURITY DEFINER to bypass RLS — so it works even without service role
IF NOT EXISTS (SELECT 1 FROM wholesale_settings WHERE brand_id = p_brand_id) THEN
INSERT INTO wholesale_settings (brand_id, require_approval, wholesale_enabled, pickup_location)
VALUES (p_brand_id, true, true, 'See your order confirmation for pickup details')
ON CONFLICT (brand_id) DO NOTHING;
END IF;
-- Read require_approval setting for this brand
BEGIN
SELECT require_approval INTO v_req_app
FROM wholesale_settings
WHERE brand_id = p_brand_id;
EXCEPTION WHEN OTHERS THEN
v_req_app := true;
END;
INSERT INTO wholesale_customers (
brand_id, company_name, contact_name, email, phone,
account_status, role
) VALUES (
p_brand_id,
p_company_name,
p_contact_name,
p_email,
p_phone,
CASE WHEN COALESCE(v_req_app, true) THEN 'pending_approval' ELSE 'active' END,
'buyer'
)
RETURNING id INTO v_id;
RETURN jsonb_build_object(
'success', true,
'id', v_id,
'requires_approval', COALESCE(v_req_app, true)
);
END;
$$;
-- Also fix get_wholesale_settings to return defaults if no settings exist
-- This prevents 406 errors when settings are missing
CREATE OR REPLACE FUNCTION public.get_wholesale_settings(p_brand_id UUID DEFAULT NULL)
RETURNS JSONB
LANGUAGE plpgsql SECURITY DEFINER SET search_path = public
AS $$
DECLARE
v_result JSONB;
BEGIN
SELECT jsonb_build_object(
'id', id,
'brand_id', brand_id,
'portal_page_id', portal_page_id,
'price_sheet_page_id', price_sheet_page_id,
'require_approval', require_approval,
'min_order_amount', min_order_amount,
'online_payment_enabled', online_payment_enabled,
'wholesale_enabled', COALESCE(wholesale_enabled, true),
'pickup_location', COALESCE(pickup_location, 'Contact us for pickup details'),
'fob_location', fob_location,
'from_email', from_email,
'invoice_business_name', COALESCE(invoice_business_name, 'Wholesale'),
'invoice_business_address', invoice_business_address,
'invoice_business_phone', invoice_business_phone,
'invoice_business_email', invoice_business_email,
'invoice_business_website', invoice_business_website,
'last_invoice_number', last_invoice_number
) INTO v_result
FROM wholesale_settings
WHERE brand_id = p_brand_id;
-- If still null, return safe defaults so client code doesn't break
IF v_result IS NULL THEN
RETURN jsonb_build_object(
'id', NULL,
'brand_id', p_brand_id,
'portal_page_id', NULL,
'price_sheet_page_id', NULL,
'require_approval', true,
'min_order_amount', 0,
'online_payment_enabled', false,
'wholesale_enabled', true,
'pickup_location', 'Contact us for pickup details',
'fob_location', NULL,
'from_email', NULL,
'invoice_business_name', 'Wholesale',
'invoice_business_address', NULL,
'invoice_business_phone', NULL,
'invoice_business_email', NULL,
'invoice_business_website', NULL,
'last_invoice_number', 0
);
END IF;
RETURN v_result;
END;
$$;
COMMIT;
NOTIFY pgrst, 'reload schema';