BID · Console
Baseline · Intelligence · Decision
src/tools/retrieval/connectors/sec-submissions.ts 2,339 bytes · typescript
/**
 * SEC EDGAR submissions connector.
 *
 * Returns a company's filing history (most recent filings list),
 * optionally narrowed to specific filing types (e.g. "10-K,10-Q").
 * Backed by https://data.sec.gov/submissions/CIK{cik}.json. Result is
 * capped at 50 most-recent filings.
 */

import {
  RetrievalError,
  type FetchParams,
  type RawPayload,
  type RetrievalConnector,
} from '../interface.js';
import { secSubmissions, type SecSubmissions } from './sec-edgar.js';

const MAX_FILINGS_RETURNED = 50;

export class SecSubmissionsConnector implements RetrievalConnector {
  readonly name = 'sec-submissions';
  readonly authRequired = false;
  readonly rateLimit = { requestsPerSecond: 10, burstSize: 10 };

  async isAvailable(): Promise<boolean> {
    return true;
  }

  async fetch(params: FetchParams): Promise<RawPayload> {
    const cik = params.entity?.id;
    if (typeof cik !== 'string' || !cik.trim()) {
      throw new RetrievalError(
        'invalid-request',
        'sec-submissions: entity.id (CIK) is required.',
      );
    }
    const filingTypes =
      Array.isArray(params.filingTypes) && params.filingTypes.length > 0
        ? params.filingTypes.join(',')
        : typeof params.query?.filingTypes === 'string'
          ? (params.query.filingTypes as string)
          : undefined;
    const full = await secSubmissions(cik, filingTypes);
    const capped: SecSubmissions = {
      ...full,
      filings: full.filings.slice(0, MAX_FILINGS_RETURNED),
    };
    return {
      source: this.name,
      sourceUrl: capped.sourceUrl,
      capturedAt: capped.capturedAt,
      contentType: 'application/json',
      rawContent: JSON.stringify(capped),
      metadata: {
        cik: capped.cik,
        entity: cik,
        filingTypesFilter: capped.filingTypesFilter ?? null,
        filingsReturned: capped.filings.length,
        filingsAvailable: full.filings.length,
        capLimit: MAX_FILINGS_RETURNED,
      },
    };
  }
}

/** Standalone fetcher with the 50-row cap applied. */
export async function fetchSecSubmissions(
  cik: string,
  filingTypes?: string,
): Promise<SecSubmissions> {
  const full = await secSubmissions(cik, filingTypes);
  return { ...full, filings: full.filings.slice(0, MAX_FILINGS_RETURNED) };
}

export type { SecSubmissions, SecFilingHit } from './sec-edgar.js';