Intial Version

This commit is contained in:
2025-12-03 18:00:10 -05:00
parent 43c4227da7
commit 0b86c88eb4
55 changed files with 8938 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient({
log: process.env.NODE_ENV === 'development' ? ['query', 'error', 'warn'] : ['error'],
});
export default prisma;

View File

@@ -0,0 +1,195 @@
import prisma from './prisma';
import { VendorListing } from '../scrapers/types';
export class PriceRepository {
async saveListings(listings: VendorListing[]): Promise<void> {
// Use a single timestamp for all listings in this batch
const batchTimestamp = new Date();
await prisma.vendorPrice.createMany({
data: listings.map(listing => ({
vendor: listing.vendor,
sellerName: listing.seller,
usdPrice: listing.priceUSD,
auecAmount: listing.amountAUEC,
usdPerMillion: listing.pricePerMillion,
deliveryTime: listing.deliveryTime,
url: listing.url,
timestamp: batchTimestamp,
})),
});
}
async savePriceIndex(lowestPrice: number, vendor: string, sellerName?: string): Promise<void> {
await prisma.priceIndex.create({
data: {
lowestPrice,
vendor,
sellerName,
},
});
}
async logScrape(status: string, message?: string, runtimeMs?: number): Promise<void> {
await prisma.scrapeLog.create({
data: {
status,
message,
runtimeMs,
},
});
}
async getLatestPrices() {
// Get the most recent timestamp across all vendors
const latest = await prisma.vendorPrice.findFirst({
orderBy: { timestamp: 'desc' },
select: { timestamp: true },
});
if (!latest) return [];
// Get all prices from that timestamp (all vendors)
return prisma.vendorPrice.findMany({
where: { timestamp: latest.timestamp },
orderBy: { usdPerMillion: 'asc' },
});
}
async getLatestPricesOld() {
// Get the most recent timestamp for each vendor
const latestEldorado = await prisma.vendorPrice.findFirst({
where: { vendor: 'eldorado' },
orderBy: { timestamp: 'desc' },
select: { timestamp: true },
});
const latestPlayerAuctions = await prisma.vendorPrice.findFirst({
where: { vendor: 'playerauctions' },
orderBy: { timestamp: 'desc' },
select: { timestamp: true },
});
// Get all prices from the latest scrape of each vendor
const prices = [];
if (latestEldorado) {
const eldoradoPrices = await prisma.vendorPrice.findMany({
where: {
vendor: 'eldorado',
timestamp: latestEldorado.timestamp,
},
});
prices.push(...eldoradoPrices);
}
if (latestPlayerAuctions) {
// Get all PlayerAuctions listings within 30 seconds of the latest timestamp
const timeWindow = new Date(latestPlayerAuctions.timestamp.getTime() - 30000);
const paPrices = await prisma.vendorPrice.findMany({
where: {
vendor: 'playerauctions',
timestamp: {
gte: timeWindow,
lte: latestPlayerAuctions.timestamp,
},
},
});
prices.push(...paPrices);
}
// Sort by price
return prices.sort((a, b) =>
Number(a.usdPerMillion) - Number(b.usdPerMillion)
);
}
async getLowestPrice() {
const latest = await prisma.priceIndex.findFirst({
orderBy: { timestamp: 'desc' },
});
return latest;
}
async getPricesBySeller(seller: string, platform?: string) {
return prisma.vendorPrice.findMany({
where: {
sellerName: seller,
...(platform && { vendor: platform }),
},
orderBy: { timestamp: 'desc' },
take: 100,
});
}
async getPricesByPlatform(platform: string) {
const latest = await prisma.vendorPrice.findFirst({
where: { vendor: platform },
orderBy: { timestamp: 'desc' },
select: { timestamp: true },
});
if (!latest) return [];
return prisma.vendorPrice.findMany({
where: {
vendor: platform,
timestamp: latest.timestamp,
},
orderBy: { usdPerMillion: 'asc' },
});
}
async getPriceHistory(from: Date, to: Date, seller?: string, platform?: string) {
return prisma.vendorPrice.findMany({
where: {
timestamp: {
gte: from,
lte: to,
},
...(seller && { sellerName: seller }),
...(platform && { vendor: platform }),
},
orderBy: { timestamp: 'asc' },
});
}
async getIndexHistory(range: string) {
const now = new Date();
let from = new Date();
switch (range) {
case '1h':
from = new Date(now.getTime() - 60 * 60 * 1000);
break;
case '6h':
from = new Date(now.getTime() - 6 * 60 * 60 * 1000);
break;
case '24h':
from = new Date(now.getTime() - 24 * 60 * 60 * 1000);
break;
case '7d':
from = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
break;
case '30d':
from = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
break;
case '90d':
from = new Date(now.getTime() - 90 * 24 * 60 * 60 * 1000);
break;
case 'all':
from = new Date(0);
break;
default:
from = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
}
return prisma.priceIndex.findMany({
where: {
timestamp: { gte: from },
},
orderBy: { timestamp: 'asc' },
});
}
}