Remove dead code in app and XBRL loader
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
import type {
|
||||
FinancialStatementKind,
|
||||
FinancialUnit
|
||||
} from '@/lib/types';
|
||||
import {
|
||||
INCOME_SURFACES,
|
||||
BALANCE_SURFACES,
|
||||
CASH_FLOW_SURFACES
|
||||
} from '@/lib/generated';
|
||||
|
||||
export type CanonicalRowDefinition = {
|
||||
key: string;
|
||||
label: string;
|
||||
category: string;
|
||||
order: number;
|
||||
unit: FinancialUnit;
|
||||
};
|
||||
|
||||
function toCanonicalRow(surface: { surface_key: string; label: string; category: string; order: number; unit: string }) {
|
||||
return {
|
||||
key: surface.surface_key,
|
||||
label: surface.label,
|
||||
category: surface.category,
|
||||
order: surface.order,
|
||||
unit: surface.unit as FinancialUnit
|
||||
};
|
||||
}
|
||||
|
||||
export const CANONICAL_ROW_DEFINITIONS: Record<Extract<FinancialStatementKind, 'income' | 'balance' | 'cash_flow'>, CanonicalRowDefinition[]> = {
|
||||
income: INCOME_SURFACES.map(toCanonicalRow),
|
||||
balance: BALANCE_SURFACES.map(toCanonicalRow),
|
||||
cash_flow: CASH_FLOW_SURFACES.map(toCanonicalRow)
|
||||
};
|
||||
@@ -9,11 +9,15 @@ import type {
|
||||
IssuerOverlayDiagnostics,
|
||||
IssuerOverlayStats,
|
||||
} from "@/lib/server/db/schema";
|
||||
import {
|
||||
ensureIssuerOverlayRow,
|
||||
getIssuerOverlay,
|
||||
listIssuerOverlayRevisions,
|
||||
publishIssuerOverlayRevision,
|
||||
} from "./issuer-overlays";
|
||||
|
||||
let tempDir: string | null = null;
|
||||
let sqliteClient: Database | null = null;
|
||||
let overlayRepo: typeof import("./issuer-overlays") | null = null;
|
||||
|
||||
function resetDbSingletons() {
|
||||
const globalState = globalThis as typeof globalThis & {
|
||||
__fiscalSqliteClient?: Database;
|
||||
@@ -90,8 +94,6 @@ describe("issuer overlay repo", () => {
|
||||
};
|
||||
globalState.__fiscalSqliteClient = sqliteClient;
|
||||
globalState.__fiscalDrizzleDb = undefined;
|
||||
|
||||
overlayRepo = await import("./issuer-overlays");
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
@@ -108,35 +110,27 @@ describe("issuer overlay repo", () => {
|
||||
});
|
||||
|
||||
it("creates an empty overlay row on ensure", async () => {
|
||||
if (!overlayRepo) {
|
||||
throw new Error("overlay repo not initialized");
|
||||
}
|
||||
|
||||
const overlay = await overlayRepo.ensureIssuerOverlayRow("aapl");
|
||||
const overlay = await ensureIssuerOverlayRow("aapl");
|
||||
expect(overlay?.ticker).toBe("AAPL");
|
||||
expect(overlay?.status).toBe("empty");
|
||||
expect(overlay?.active_revision).toBeNull();
|
||||
});
|
||||
|
||||
it("publishes and deduplicates overlay revisions by content hash", async () => {
|
||||
if (!overlayRepo) {
|
||||
throw new Error("overlay repo not initialized");
|
||||
}
|
||||
|
||||
const first = await overlayRepo.publishIssuerOverlayRevision({
|
||||
const first = await publishIssuerOverlayRevision({
|
||||
ticker: "AAPL",
|
||||
definition: sampleDefinition(),
|
||||
diagnostics: sampleDiagnostics(),
|
||||
stats: sampleStats(),
|
||||
});
|
||||
const second = await overlayRepo.publishIssuerOverlayRevision({
|
||||
const second = await publishIssuerOverlayRevision({
|
||||
ticker: "AAPL",
|
||||
definition: sampleDefinition(),
|
||||
diagnostics: sampleDiagnostics(),
|
||||
stats: sampleStats(),
|
||||
});
|
||||
const overlay = await overlayRepo.getIssuerOverlay("AAPL");
|
||||
const revisions = await overlayRepo.listIssuerOverlayRevisions("AAPL");
|
||||
const overlay = await getIssuerOverlay("AAPL");
|
||||
const revisions = await listIssuerOverlayRevisions("AAPL");
|
||||
|
||||
expect(first.published).toBe(true);
|
||||
expect(second.published).toBe(false);
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
type IssuerOverlayStats,
|
||||
} from "@/lib/server/db/schema";
|
||||
|
||||
export type IssuerOverlayRevisionRecord = {
|
||||
type IssuerOverlayRevisionRecord = {
|
||||
id: number;
|
||||
ticker: string;
|
||||
revision_number: number;
|
||||
@@ -22,7 +22,7 @@ export type IssuerOverlayRevisionRecord = {
|
||||
created_at: string;
|
||||
};
|
||||
|
||||
export type IssuerOverlayRecord = {
|
||||
type IssuerOverlayRecord = {
|
||||
ticker: string;
|
||||
status: "empty" | "active" | "error";
|
||||
active_revision_id: number | null;
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
import type { FinancialStatementKind } from '@/lib/types';
|
||||
|
||||
export function classifyStatementRole(roleUri: string): FinancialStatementKind | null {
|
||||
const normalized = roleUri.toLowerCase();
|
||||
|
||||
if (/cash\s*flow|statementsof?cashflows|netcash/.test(normalized)) {
|
||||
return 'cash_flow';
|
||||
}
|
||||
|
||||
if (/shareholders?|stockholders?|equity|retainedearnings/.test(normalized)) {
|
||||
return 'equity';
|
||||
}
|
||||
|
||||
if (/comprehensive\s*income/.test(normalized)) {
|
||||
return 'comprehensive_income';
|
||||
}
|
||||
|
||||
if (/balance\s*sheet|financial\s*position|assets?andliabilities/.test(normalized)) {
|
||||
return 'balance';
|
||||
}
|
||||
|
||||
if (/operations|income\s*statement|statementsofincome|profit/.test(normalized)) {
|
||||
return 'income';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export function conceptStatementFallback(localName: string): FinancialStatementKind | null {
|
||||
const normalized = localName.toLowerCase();
|
||||
|
||||
if (/cash|operatingactivities|investingactivities|financingactivities/.test(normalized)) {
|
||||
return 'cash_flow';
|
||||
}
|
||||
|
||||
if (/equity|retainedearnings|additionalpaidincapital/.test(normalized)) {
|
||||
return 'equity';
|
||||
}
|
||||
|
||||
if (/comprehensiveincome/.test(normalized)) {
|
||||
return 'comprehensive_income';
|
||||
}
|
||||
|
||||
if (/asset|liabilit|debt/.test(normalized)) {
|
||||
return 'balance';
|
||||
}
|
||||
|
||||
if (/revenue|income|profit|expense|costof/.test(normalized)) {
|
||||
return 'income';
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -232,11 +232,6 @@ export type TaxonomyHydrationInput = {
|
||||
issuerOverlay?: IssuerOverlayDefinition | null;
|
||||
};
|
||||
|
||||
export type TickerAutomationRequest = {
|
||||
ticker: string;
|
||||
source: TickerAutomationSource;
|
||||
};
|
||||
|
||||
export type TaxonomyHydrationResult = {
|
||||
filing_id: number;
|
||||
ticker: string;
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
export {
|
||||
normalizeTicker,
|
||||
normalizeTickerOrNull,
|
||||
normalizeTags,
|
||||
normalizeTagsOrNull,
|
||||
normalizeOptionalString,
|
||||
normalizeRecord,
|
||||
normalizePositiveInteger,
|
||||
nowIso,
|
||||
todayIso
|
||||
} from './normalize';
|
||||
|
||||
export {
|
||||
asRecord,
|
||||
asOptionalRecord,
|
||||
asPositiveNumber,
|
||||
asBoolean,
|
||||
asStringArray,
|
||||
asEnum
|
||||
} from './validation';
|
||||
|
||||
export { withRetry, type RetryOptions } from './retry';
|
||||
@@ -1,51 +0,0 @@
|
||||
export function normalizeTicker(ticker: string): string {
|
||||
return ticker.trim().toUpperCase();
|
||||
}
|
||||
|
||||
export function normalizeTickerOrNull(ticker: unknown): string | null {
|
||||
if (typeof ticker !== 'string') return null;
|
||||
const normalized = ticker.trim().toUpperCase();
|
||||
return normalized || null;
|
||||
}
|
||||
|
||||
export function normalizeTags(tags?: unknown): string[] {
|
||||
if (!Array.isArray(tags)) return [];
|
||||
|
||||
const unique = new Set<string>();
|
||||
for (const entry of tags) {
|
||||
if (typeof entry !== 'string') continue;
|
||||
const tag = entry.trim();
|
||||
if (tag) unique.add(tag);
|
||||
}
|
||||
return [...unique];
|
||||
}
|
||||
|
||||
export function normalizeTagsOrNull(tags?: unknown): string[] | null {
|
||||
const result = normalizeTags(tags);
|
||||
return result.length > 0 ? result : null;
|
||||
}
|
||||
|
||||
export function normalizeOptionalString(value?: unknown): string | null {
|
||||
if (typeof value !== 'string') return null;
|
||||
const normalized = value.trim();
|
||||
return normalized || null;
|
||||
}
|
||||
|
||||
export function normalizeRecord(value?: unknown): Record<string, unknown> | null {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) return null;
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
export function normalizePositiveInteger(value?: unknown): number | null {
|
||||
if (value === null || value === undefined || !Number.isFinite(value as number)) return null;
|
||||
const normalized = Math.trunc(value as number);
|
||||
return normalized > 0 ? normalized : null;
|
||||
}
|
||||
|
||||
export function nowIso(): string {
|
||||
return new Date().toISOString();
|
||||
}
|
||||
|
||||
export function todayIso(): string {
|
||||
return new Date().toISOString().slice(0, 10);
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
export interface RetryOptions {
|
||||
type RetryOptions = {
|
||||
maxRetries: number;
|
||||
baseDelayMs: number;
|
||||
maxDelayMs: number;
|
||||
jitterFactor: number;
|
||||
retryableErrors: RegExp[];
|
||||
}
|
||||
};
|
||||
|
||||
const DEFAULT_RETRY_OPTIONS: RetryOptions = {
|
||||
maxRetries: 3,
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
export function asRecord(value: unknown): Record<string, unknown> {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
||||
return {};
|
||||
}
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
export function asOptionalRecord(value: unknown): Record<string, unknown> | null {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
||||
return null;
|
||||
}
|
||||
return value as Record<string, unknown>;
|
||||
}
|
||||
|
||||
export function asPositiveNumber(value: unknown): number | null {
|
||||
const parsed = typeof value === 'number' ? value : Number(value);
|
||||
return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
|
||||
}
|
||||
|
||||
export function asBoolean(value: unknown, fallback = false): boolean {
|
||||
if (typeof value === 'boolean') {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (typeof value === 'string') {
|
||||
const normalized = value.trim().toLowerCase();
|
||||
if (normalized === 'true' || normalized === '1' || normalized === 'yes') {
|
||||
return true;
|
||||
}
|
||||
if (normalized === 'false' || normalized === '0' || normalized === 'no') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
export function asStringArray(value: unknown): string[] {
|
||||
const source = Array.isArray(value)
|
||||
? value
|
||||
: typeof value === 'string'
|
||||
? value.split(',')
|
||||
: [];
|
||||
|
||||
const unique = new Set<string>();
|
||||
for (const entry of source) {
|
||||
if (typeof entry !== 'string') continue;
|
||||
const tag = entry.trim();
|
||||
if (tag) unique.add(tag);
|
||||
}
|
||||
return [...unique];
|
||||
}
|
||||
|
||||
export function asEnum<T extends string>(value: unknown, allowed: readonly T[]): T | undefined {
|
||||
return allowed.includes(value as T) ? (value as T) : undefined;
|
||||
}
|
||||
Reference in New Issue
Block a user