Add company overview skeleton and cache
This commit is contained in:
102
lib/server/repos/company-overview-cache.ts
Normal file
102
lib/server/repos/company-overview-cache.ts
Normal file
@@ -0,0 +1,102 @@
|
||||
import { and, eq } from 'drizzle-orm';
|
||||
import { drizzle } from 'drizzle-orm/bun-sqlite';
|
||||
import type { CompanyAnalysis } from '@/lib/types';
|
||||
import { getSqliteClient } from '@/lib/server/db';
|
||||
import { companyOverviewCache, schema } from '@/lib/server/db/schema';
|
||||
|
||||
export const CURRENT_COMPANY_OVERVIEW_CACHE_VERSION = 1;
|
||||
|
||||
export type CompanyOverviewCacheRecord = {
|
||||
id: number;
|
||||
user_id: string;
|
||||
ticker: string;
|
||||
cache_version: number;
|
||||
source_signature: string;
|
||||
payload: CompanyAnalysis;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
};
|
||||
|
||||
function toRecord(row: typeof companyOverviewCache.$inferSelect): CompanyOverviewCacheRecord {
|
||||
return {
|
||||
id: row.id,
|
||||
user_id: row.user_id,
|
||||
ticker: row.ticker,
|
||||
cache_version: row.cache_version,
|
||||
source_signature: row.source_signature,
|
||||
payload: row.payload as CompanyAnalysis,
|
||||
created_at: row.created_at,
|
||||
updated_at: row.updated_at
|
||||
};
|
||||
}
|
||||
|
||||
function getDb() {
|
||||
return drizzle(getSqliteClient(), { schema });
|
||||
}
|
||||
|
||||
export async function getCompanyOverviewCache(input: { userId: string; ticker: string }) {
|
||||
const normalizedTicker = input.ticker.trim().toUpperCase();
|
||||
if (!normalizedTicker) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const [row] = await getDb()
|
||||
.select()
|
||||
.from(companyOverviewCache)
|
||||
.where(and(
|
||||
eq(companyOverviewCache.user_id, input.userId),
|
||||
eq(companyOverviewCache.ticker, normalizedTicker)
|
||||
))
|
||||
.limit(1);
|
||||
|
||||
return row ? toRecord(row) : null;
|
||||
}
|
||||
|
||||
export async function upsertCompanyOverviewCache(input: {
|
||||
userId: string;
|
||||
ticker: string;
|
||||
sourceSignature: string;
|
||||
payload: CompanyAnalysis;
|
||||
}) {
|
||||
const now = new Date().toISOString();
|
||||
const normalizedTicker = input.ticker.trim().toUpperCase();
|
||||
|
||||
const [saved] = await getDb()
|
||||
.insert(companyOverviewCache)
|
||||
.values({
|
||||
user_id: input.userId,
|
||||
ticker: normalizedTicker,
|
||||
cache_version: CURRENT_COMPANY_OVERVIEW_CACHE_VERSION,
|
||||
source_signature: input.sourceSignature,
|
||||
payload: input.payload as unknown as Record<string, unknown>,
|
||||
created_at: now,
|
||||
updated_at: now
|
||||
})
|
||||
.onConflictDoUpdate({
|
||||
target: [companyOverviewCache.user_id, companyOverviewCache.ticker],
|
||||
set: {
|
||||
cache_version: CURRENT_COMPANY_OVERVIEW_CACHE_VERSION,
|
||||
source_signature: input.sourceSignature,
|
||||
payload: input.payload as unknown as Record<string, unknown>,
|
||||
updated_at: now
|
||||
}
|
||||
})
|
||||
.returning();
|
||||
|
||||
return toRecord(saved);
|
||||
}
|
||||
|
||||
export async function deleteCompanyOverviewCache(input: { userId: string; ticker: string }) {
|
||||
const normalizedTicker = input.ticker.trim().toUpperCase();
|
||||
|
||||
return await getDb()
|
||||
.delete(companyOverviewCache)
|
||||
.where(and(
|
||||
eq(companyOverviewCache.user_id, input.userId),
|
||||
eq(companyOverviewCache.ticker, normalizedTicker)
|
||||
));
|
||||
}
|
||||
|
||||
export const __companyOverviewCacheInternals = {
|
||||
CACHE_VERSION: CURRENT_COMPANY_OVERVIEW_CACHE_VERSION
|
||||
};
|
||||
Reference in New Issue
Block a user