import 'dotenv/config'; import { z } from 'zod'; import { ParseRestClient } from '../src/db/parse-rest.client.js'; import { VOC_PARSE_CLASSES } from '../src/db/parse-rest.schema.js'; interface Row { objectId: string; productId: string; slot?: string; model?: string } async function main(): Promise { const env=z.object({PARSE_SERVER_URL:z.url(),PARSE_APP_ID:z.string().min(1),PARSE_MASTER_KEY:z.string().min(1),SAAS_DEFAULT_WORKSPACE_ID:z.string().default('demashi')}).parse(process.env); const apply=process.argv.includes('--apply=true'); const client=new ParseRestClient({serverUrl:env.PARSE_SERVER_URL,appId:env.PARSE_APP_ID,masterKey:env.PARSE_MASTER_KEY,timeoutMs:30_000}); const sources=await client.find<{productId:string}>(VOC_PARSE_CLASSES.listingSourceSnapshot,{where:{workspaceId:env.SAAS_DEFAULT_WORKSPACE_ID,platform:'jd',isCurrent:true,catalogIncluded:true,catalogCohort:'listing-jd-v3-formal-625'},limit:1000,keys:['productId']}); const ids=new Set(sources.results.map((row)=>row.productId)); if(ids.size!==625)throw new Error(`listing_cohort_count_mismatch:${ids.size}:625`); const current=await client.find(VOC_PARSE_CLASSES.listingCurrentScore,{where:{workspaceId:env.SAAS_DEFAULT_WORKSPACE_ID,slot:'formal_ai'},limit:10_000,keys:['productId','slot','model']}); const selected=current.results.filter((row)=>ids.has(row.productId)); if(!apply){console.log(JSON.stringify({mode:'dry-run',cohort:ids.size,formalScoresToDelete:selected.length,models:Object.fromEntries([...new Set(selected.map((row)=>row.model??'unknown'))].map((model)=>[model,selected.filter((row)=>row.model===model).length])),applyRequired:'--apply=true'},null,2));return;} let deleted=0; for(const row of selected){await client.delete(VOC_PARSE_CLASSES.listingCurrentScore,row.objectId);deleted+=1;} console.log(JSON.stringify({mode:'completed',cohort:ids.size,deleted},null,2)); } await main();