refactor(backend): root scripts use legacySupabase client where possible

- Call loadDynamicConfig() without dead supabaseService argument (Cosmos-backed).
- Use getLegacySupabaseClient() for raw .from() queries in maintenance scripts.
- manualOverrideCloseTrades: typed imports + legacy client for lifecycle SELECT.
- verify_realtime: ESM .js imports and comment for subscribeToProfiles.
- verifyTenantIsolation: comment for singleton monkey-patch.

Made-with: Cursor
This commit is contained in:
Saravana Achu Mac 2026-04-04 20:44:24 -07:00
parent eb70ef6c03
commit 6fac10de9d
17 changed files with 97 additions and 42 deletions

View File

@ -1,5 +1,5 @@
import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js';
import fs from 'fs';
import path from 'path';
@ -7,6 +7,12 @@ import path from 'path';
async function applyStandardRiskProfiles() {
logger.info('🚀 APPLYING STANDARD RISK PROFILES (5 TO 1)...');
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('❌ Legacy Supabase client not configured.');
return;
}
// 1. Load Data
const proposedPath = path.resolve('schema/proposed_risk_profiles.json');
if (!fs.existsSync(proposedPath)) {
@ -27,17 +33,17 @@ async function applyStandardRiskProfiles() {
logger.info('🧹 Wiping existing data for a fresh start...');
// @ts-ignore
await supabaseService.client.from('positions').delete().neq('id', '00000000-0000-0000-0000-000000000000');
await legacyClient.from('positions').delete().neq('id', '00000000-0000-0000-0000-000000000000');
// @ts-ignore
await supabaseService.client.from('orders').delete().neq('id', '00000000-0000-0000-0000-000000000000');
await legacyClient.from('orders').delete().neq('id', '00000000-0000-0000-0000-000000000000');
// @ts-ignore
await supabaseService.client.from('trade_history').delete().neq('id', '00000000-0000-0000-0000-000000000000');
await legacyClient.from('trade_history').delete().neq('id', '00000000-0000-0000-0000-000000000000');
// @ts-ignore
await supabaseService.client.from('alerts').delete().neq('id', '00000000-0000-0000-0000-000000000000');
await legacyClient.from('alerts').delete().neq('id', '00000000-0000-0000-0000-000000000000');
// @ts-ignore
await supabaseService.client.from('operational_events').delete().neq('id', '00000000-0000-0000-0000-000000000000');
await legacyClient.from('operational_events').delete().neq('id', '00000000-0000-0000-0000-000000000000');
// @ts-ignore
await supabaseService.client.from('trade_profiles').delete().neq('user_id', '00000000-0000-0000-0000-000000000000');
await legacyClient.from('trade_profiles').delete().neq('user_id', '00000000-0000-0000-0000-000000000000');
// 4. Prepare & Insert Profiles
const insertPayload = Object.values(proposedProfiles).map((p: any) => {
@ -57,7 +63,7 @@ async function applyStandardRiskProfiles() {
});
// @ts-ignore
const { data, error } = await supabaseService.client
const { data, error } = await legacyClient
.from('trade_profiles')
.insert(insertPayload);

View File

@ -1,9 +1,16 @@
import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js';
async function createAggressiveProfile() {
logger.info('🚀 CREATING AGGRESSIVE TEST PROFILE (70% VOTING)...');
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('❌ Legacy Supabase client not configured.');
return;
}
// 1. Get User
const users = await supabaseService.getActiveUsers();
if (users.length === 0) {
@ -46,7 +53,7 @@ async function createAggressiveProfile() {
// 3. Insert Profile
// @ts-ignore
const { data, error } = await supabaseService.client
const { data, error } = await legacyClient
.from('trade_profiles')
.insert([aggressiveProfile])
.select()

View File

@ -1,11 +1,17 @@
import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js';
import { v4 as uuidv4 } from 'uuid';
async function createLowRiskProfile() {
logger.info('🛡️ CREATING LOW RISK & SCALP PROFILES EXAMPLE...');
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('❌ Legacy Supabase client not configured.');
return;
}
// 1. Get User
const users = await supabaseService.getActiveUsers();
if (users.length === 0) {
@ -43,7 +49,7 @@ async function createLowRiskProfile() {
// Insert Low Risk Profile
// @ts-ignore
const { data, error } = await supabaseService.client
const { data, error } = await legacyClient
.from('trade_profiles')
.insert([lowRiskProfile])
.select()

View File

@ -1,10 +1,16 @@
import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js';
async function debugDatabaseLogging() {
logger.info('🔍 Starting Database Logging Debug...');
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('Legacy Supabase client not configured.');
return;
}
// 1. Get Real User & Profile
const profiles = await supabaseService.getActiveProfiles();
if (profiles.length === 0) {
@ -35,7 +41,7 @@ async function debugDatabaseLogging() {
// Call private client directly to get full error if service swallows it
// @ts-ignore
const { data: orderData, error: orderError } = await supabaseService.client
const { data: orderData, error: orderError } = await legacyClient
.from('orders')
.insert([testOrder])
.select();
@ -65,7 +71,7 @@ async function debugDatabaseLogging() {
logger.info('📝 Attempting to insert Trade History:', testTrade);
// @ts-ignore
const { data: tradeData, error: tradeError } = await supabaseService.client
const { data: tradeData, error: tradeError } = await legacyClient
.from('trade_history')
.insert([testTrade])
.select();
@ -79,7 +85,7 @@ async function debugDatabaseLogging() {
// Cleanup (Consistency)
logger.info('🧹 Cleaning up test data...');
// @ts-ignore
await supabaseService.client.from('orders').delete().eq('order_id', testOrder.order_id);
await legacyClient.from('orders').delete().eq('order_id', testOrder.order_id);
}
}

View File

@ -1,10 +1,16 @@
import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js';
async function fixHighRiskRules() {
logger.info('🔧 Syncing High Risk Rules with Dashboard UI...');
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('❌ Legacy Supabase client not configured.');
return;
}
const profiles = await supabaseService.getActiveProfiles();
const highRiskProfile = profiles.find(p => p.name.includes('Scalp'));
@ -21,7 +27,7 @@ async function fixHighRiskRules() {
];
// @ts-ignore
const { error } = await supabaseService.client
const { error } = await legacyClient
.from('trade_profiles')
.update({
strategy_config: {

View File

@ -1,10 +1,16 @@
import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js';
async function forceResetRules() {
logger.info('🔨 FORCING CLEAN RULE SET (ALL RULES POPULATED)...');
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('❌ Legacy Supabase client not configured.');
return;
}
const profiles = await supabaseService.getActiveProfiles();
const highRiskStart = profiles.find(p => p.name.includes('Scalp') || p.name.includes('High'));
@ -27,7 +33,7 @@ async function forceResetRules() {
};
// @ts-ignore
const { error } = await supabaseService.client
const { error } = await legacyClient
.from('trade_profiles')
.update({ strategy_config: newConfig })
.eq('id', highRiskStart.id);

View File

@ -4,10 +4,11 @@ import { config, loadDynamicConfig } from '../src/config/index.js';
import { normalizeOrderAction, normalizeTradeSide } from '../src/domain/tradingEnums.js';
import { healthTracker } from '../src/services/healthTracker.js';
import {
ReconciliationBackfillAuditInsert,
ReconciliationBackfillOrderInsert,
type ReconciliationBackfillAuditInsert,
type ReconciliationBackfillOrderInsert,
supabaseService
} from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import { buildAlpacaSubTag } from '../src/utils/alpacaSubTag.js';
type CliOptions = {
@ -135,7 +136,7 @@ const run = async (): Promise<void> => {
throw new Error('Provide at least one --trade=<TRADE_ID>.');
}
await loadDynamicConfig(supabaseService);
await loadDynamicConfig();
healthTracker.recordTradingControl({
mode: 'PAUSED',
@ -144,7 +145,7 @@ const run = async (): Promise<void> => {
reason: 'Manual override close cycle'
});
const client = supabaseService.getClient();
const client = getLegacySupabaseClient();
if (!client) {
throw new Error('Supabase client is not available.');
}

View File

@ -65,7 +65,7 @@ const normalizeProfileIds = (profileIds: Set<string>): string[] => {
const run = async (): Promise<void> => {
const options = parseOptions(process.argv.slice(2));
await loadDynamicConfig(supabaseService);
await loadDynamicConfig();
const originalDryRun = config.RECON_EXIT_BACKFILL_DRY_RUN;
const originalAllowlist = [...config.RECON_EXIT_BACKFILL_PROFILE_ALLOWLIST];

View File

@ -96,7 +96,7 @@ const normalizeProfileIds = (profileIds: Set<string>): string[] => {
const run = async (): Promise<void> => {
const options = parseOptions(process.argv.slice(2));
await loadDynamicConfig(supabaseService);
await loadDynamicConfig();
const originalEnabled = config.ENABLE_RECON_ORDER_COVERAGE_SYNC;
const originalDryRun = config.RECON_ORDER_COVERAGE_DRY_RUN;

View File

@ -186,7 +186,7 @@ const normalizeExchangeEvidence = (rows: any[]): Map<string, ExchangeEvidence> =
const run = async (): Promise<void> => {
const options = parseOptions(process.argv.slice(2));
logger.silent = true;
await loadDynamicConfig(supabaseService);
await loadDynamicConfig();
healthTracker.recordTradingControl({
mode: 'PAUSED',

View File

@ -71,7 +71,7 @@ const normalizeProfileIds = (profileIds: Set<string>): string[] => {
const run = async (): Promise<void> => {
const options = parseOptions(process.argv.slice(2));
await loadDynamicConfig(supabaseService);
await loadDynamicConfig();
const originalEnabled = config.ENABLE_RECON_SUBTAG_REPAIR;
const originalDryRun = config.RECON_SUBTAG_REPAIR_DRY_RUN;

View File

@ -1,8 +1,14 @@
import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js';
async function updateProfileName() {
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('❌ Legacy Supabase client not configured.');
return;
}
const profiles = await supabaseService.getActiveProfiles();
if (profiles.length === 0) return;
@ -11,7 +17,7 @@ async function updateProfileName() {
// Update Name in DB
// @ts-ignore
await supabaseService.client
await legacyClient
.from('trade_profiles')
.update({ name: newName })
.eq('id', targetProfile.id);

View File

@ -1,11 +1,17 @@
import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
import logger from '../src/utils/logger.js';
import { v4 as uuidv4 } from 'uuid';
async function setupHighRiskProfile() {
logger.info('🚀 SETTING UP HIGH-RISK SCALPER PROFILE...');
const legacyClient = getLegacySupabaseClient();
if (!legacyClient) {
logger.error('❌ Legacy Supabase client not configured.');
return;
}
// 1. Get or Create Profile
const profiles = await supabaseService.getActiveProfiles();
let targetProfile = profiles.find(p => p.name.includes('Scalp') || p.name.includes('High'));
@ -32,7 +38,7 @@ async function setupHighRiskProfile() {
// In a real scenario, we'd update table 'trade_profiles' -> allocated_capital = 1000, risk = 5.
// Let's try to update it if we can access the client.
// @ts-ignore
const { error: updateError } = await supabaseService.client
const { error: updateError } = await legacyClient
.from('trade_profiles')
.update({
allocated_capital: 1000,
@ -81,7 +87,7 @@ async function setupHighRiskProfile() {
// A. Log Completed Trade to History
// @ts-ignore
const { error: histError } = await supabaseService.client
const { error: histError } = await legacyClient
.from('trade_history')
.insert([{
user_id: userId,
@ -104,7 +110,7 @@ async function setupHighRiskProfile() {
// B. Log "Order" for this trade (Matched Pair)
// 1. Entry Order
// @ts-ignore
await supabaseService.client.from('orders').insert([{
await legacyClient.from('orders').insert([{
user_id: userId,
profile_id: profileId,
order_id: uuidv4(),
@ -119,7 +125,7 @@ async function setupHighRiskProfile() {
// 2. Exit Order
// @ts-ignore
await supabaseService.client.from('orders').insert([{
await legacyClient.from('orders').insert([{
user_id: userId,
profile_id: profileId,
order_id: uuidv4(),

View File

@ -3,6 +3,7 @@ import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { ApiServer } from './src/services/apiServer.js';
// Direct supabaseService: monkey-patches loadLatestBotStateSnapshot on the singleton for isolation checks.
import { supabaseService } from './src/services/SupabaseService.js';
const __filename = fileURLToPath(import.meta.url);

View File

@ -1,16 +1,15 @@
import { supabaseService } from '../src/services/SupabaseService.js';
import { loadDynamicConfig, config } from '../src/config/index.js';
import logger from '../src/utils/logger.js';
async function testDynamicConfigLoading() {
logger.info('--- Testing Dynamic Config Loading from Supabase ---');
logger.info('--- Testing Dynamic Config Loading (control-plane storage) ---');
// 1. Initial State (from .env)
const initialSymbols = [...config.SYMBOLS];
logger.info(`Initial Symbols (.env): ${initialSymbols.join(', ')}`);
// 2. Load from DB
await loadDynamicConfig(supabaseService);
await loadDynamicConfig();
// 3. Final State
logger.info(`Final Symbols (After DB Load): ${config.SYMBOLS.join(', ')}`);

View File

@ -1,8 +1,12 @@
import { supabaseService } from '../src/services/SupabaseService.js';
import { getLegacySupabaseClient } from '../src/services/legacySupabaseClient.js';
async function check() {
const { data } = await supabaseService.client.from('trade_profiles').select('name, risk_per_trade_percent');
const client = getLegacySupabaseClient();
if (!client) {
console.error('Legacy Supabase client is not configured.');
process.exit(1);
}
const { data } = await client.from('trade_profiles').select('name, risk_per_trade_percent');
console.log('--- CURRENT PROFILES ---');
console.log(JSON.stringify(data, null, 2));
process.exit(0);

View File

@ -1,7 +1,8 @@
import { supabaseService } from '../src/services/SupabaseService';
// Direct supabaseService: subscribeToProfiles is only implemented on SupabaseService (not exposed via legacySupabaseClient).
import { supabaseService } from '../src/services/SupabaseService.js';
import { createClient } from '@supabase/supabase-js';
import * as dotenv from 'dotenv';
import logger from '../src/utils/logger';
import logger from '../src/utils/logger.js';
dotenv.config();
const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_KEY!);