import { loadEnvConfig } from '@next/env' loadEnvConfig(process.cwd()) const CONFIRM_TOKEN = 'sync-product-inventory-snapshot' function arg(name: string) { const prefix = `--${name}=` return process.argv.slice(2).find((value) => value.startsWith(prefix))?.slice(prefix.length) ?? '' } function required(name: string) { const value = process.env[name]?.trim() if (!value) throw new Error(`${name} is required.`) return value } function identity(url: string) { const parsed = new URL(url) return [ parsed.protocol.replace(':', ''), decodeURIComponent(parsed.username || ''), parsed.hostname, parsed.port || '', parsed.pathname.replace(/^\//, ''), parsed.searchParams.get('schema') ?? '', ].join('|') } function sourceIdentity() { return [ 'sqlserver', required('JST_REPORT_DB_USER'), required('JST_REPORT_DB_HOST'), process.env.JST_REPORT_DB_PORT?.trim() || '1433', required('JST_REPORT_DB_NAME'), process.env.JST_REPORT_DB_SCHEMA?.trim() || 'rpt', ].join('|') } async function main() { if (!process.argv.includes('--apply') || arg('confirm') !== CONFIRM_TOKEN) { throw new Error(`写入商品库存快照需要 --apply 和 --confirm=${CONFIRM_TOKEN}`) } const databaseUrl = required('DATABASE_URL') if (arg('expected-database-identity') !== identity(databaseUrl)) { throw new Error('expected database identity mismatch') } if (arg('expected-source-database-identity') !== sourceIdentity()) { throw new Error('expected source identity mismatch') } const { prisma } = await import('../src/lib/prisma') const { productInventorySnapshotService } = await import( '../src/server/services/product-inventory-snapshot.service' ) try { console.log(JSON.stringify({ stage: 'start' })) const result = await productInventorySnapshotService.sync() console.log(JSON.stringify({ stage: 'completed', ...result }, null, 2)) } finally { await prisma.$disconnect() } } void main().catch((error) => { console.error(error instanceof Error ? error.message : String(error)) process.exitCode = 1 })