govdata.js
v0.1.0
Published
A modern TypeScript package for accessing U.S. government data systems including FPDS, SAM.gov opportunities, and Wage Determinations
Downloads
14
Maintainers
Readme
govdata.js
A modern TypeScript package for accessing U.S. government data systems. Provides clean, structured data from FPDS (Federal Procurement Data System) with exact compatibility to existing Python scripts.
Features
- FPDS Integration: Access historical contract award data with full field mapping
- TypeScript Support: Full type definitions and IntelliSense support
- Platform Agnostic: Works in Node.js, Deno, and browser environments
- Zero Dependencies: Minimal external dependencies for better security
- Data-Only Philosophy: Returns clean data without built-in persistence
- Multiple Contract Support: Search multiple contracts in a single request
- Concurrent Processing: Configurable concurrency with custom semaphore
- CLI Interface: Simple command-line interface for contract lookup
- JSON by Default: Returns JSON by default, CSV optional
Installation
npm install @bidstream/govdata.jsQuick Start
import { FPDSRequest, ContractProcessor } from '@bidstream/govdata.js';
// Get single contract data
const fpdsRequest = new FPDSRequest({
PIID: 'HT001525D9012',
LAST_MOD_DATE: '[2022/01/01, 2024/12/31]'
});
const contracts = await fpdsRequest.getData();
// Search multiple contracts at once
const multipleContracts = await FPDSRequest.searchContracts({
contracts: ['HT001525D9012', 'HT001525D9013', 'HT001525D9014'],
dateRange: '[2022/01/01, 2024/12/31]'
});
// Convert to JSON (default) or CSV
const json = ContractProcessor.formatAsJSON(contracts);
const csv = ContractProcessor.convertToCSV(contracts);API Reference
FPDSRequest
class FPDSRequest {
constructor(params: FPDSSearchParams, config?: FPDSRequestConfig);
async getData(): Promise<FPDSRecord[]>;
async getPage(pageNumber: number): Promise<FPDSRecord[]>;
async *getDataStream(): AsyncGenerator<FPDSRecord[]>;
// Static method for multiple contracts
static async searchContracts(request: ContractSearchRequest, config?: FPDSRequestConfig): Promise<FPDSRecord[]>;
get totalPages(): number;
get totalRecords(): number;
get searchUrl(): string;
}Search Parameters
interface FPDSSearchParams {
PIID?: string | string[]; // Contract number(s) - can be single or array
LAST_MOD_DATE?: string; // Date range "[2022/01/01, 2024/12/31]"
NAICS_CODE?: string; // NAICS code filter
PSC_CODE?: string; // PSC code filter
CONTRACTING_AGENCY?: string; // Agency filter
VENDOR_NAME?: string; // Vendor name search
// ... and 100+ additional FPDS parameters
}
interface ContractSearchRequest {
contracts: string[]; // Array of contract numbers
dateRange?: string; // Optional date range filter
metadata?: Record<string, any>; // Optional metadata to attach to results
}FPDSRecord Interface
interface FPDSRecord {
contract_hash: string; // SHA256: contract_number:award_date
contract_number: string; // PIID
title: string;
link: string;
award_date: string;
award_amount: number;
total_potential_value: number;
contract_type: string;
project_description: string;
naics_code: string;
naics_description: string;
psc_code: string;
psc_description: string;
contracting_agency: string;
vendor_name: string;
vendor_uei: string;
business_size: string;
vendor_city: string;
vendor_state: string;
sdvosb_status: string; // "Yes"/"No"
small_business_status: string; // "Yes"/"No"
women_owned_status: string; // "Yes"/"No"
// ... 47+ total fields matching Python scripts exactly
source_metadata?: Record<string, any>; // Optional metadata from source
}Examples
Single Contract Search
import { FPDSRequest } from '@bidstream/govdata.js';
// Simple contract lookup
const request = new FPDSRequest({ PIID: 'HT001525D9012' });
const contracts = await request.getData();
console.log(`Found ${contracts.length} contracts`);Multiple Contract Search
import { FPDSRequest } from '@bidstream/govdata.js';
// Search multiple contracts concurrently
const contracts = await FPDSRequest.searchContracts({
contracts: ['HT001525D9012', 'HT001525D9013', 'HT001525D9014'],
dateRange: '[2022/01/01, 2024/12/31]',
metadata: { source: 'my_application', batch_id: '123' }
});
console.log(`Found ${contracts.length} total contracts across all searches`);Advanced FPDS Search
import { FPDSRequest } from '@bidstream/govdata.js';
// Complex search with multiple parameters
const request = new FPDSRequest({
LAST_MOD_DATE: '[2023/01/01, 2024/12/31]',
NAICS_CODE: '541511',
CONTRACTING_AGENCY: 'HEALTH AND HUMAN SERVICES'
}, {
threadCount: 15,
timeout: 45000
});
const contracts = await request.getData();
console.log(`Found ${contracts.length} contracts across ${request.totalPages} pages`);Data Processing
import { FPDSRequest, ContractProcessor } from '@bidstream/govdata.js';
const request = new FPDSRequest({ PIID: 'HT001525D9012' });
const contracts = await request.getData();
// Get as JSON (default)
const jsonOutput = ContractProcessor.formatAsJSON(contracts);
console.log('JSON Output:', jsonOutput);
// Convert to CSV for export
const csvOutput = ContractProcessor.convertToCSV(contracts);
console.log('CSV Output:', csvOutput);
// Save to database (your choice of database)
await saveToDatabase(contracts);Error Handling
import { FPDSRequest, GovDataError } from '@bidstream/govdata.js';
try {
const contracts = await FPDSRequest.searchContracts({
contracts: ['invalid-contract-1', 'invalid-contract-2']
});
console.log('Results:', contracts);
} catch (error) {
if (error instanceof GovDataError) {
console.error(`GovData Error: ${error.message}`);
console.error(`Code: ${error.code}`);
if (error.suggestions) {
console.error(`Suggestions: ${error.suggestions.join(', ')}`);
}
} else {
console.error('Unexpected error:', error);
}
}CLI Usage
# Install globally
npm install -g @bidstream/govdata.js
# Search single contract (outputs JSON to console by default)
govdata fpds --contract "HT001525D9012"
# Search multiple contracts and save as JSON
govdata fpds --contract "HT001525D9012" "HT001525D9013" --output contracts.json
# Search single contract with date range and save as CSV
govdata fpds --contract "HT001525D9012" --date-range "[2022/01/01, 2024/12/31]" --output contract.csv
# Search by NAICS code and save as CSV
govdata fpds --naics "541511" --date-range "[2023/01/01, 2024/12/31]" --output it_contracts.csv
# Search by agency with filters
govdata fpds --agency "HEALTH AND HUMAN SERVICES" --naics "541511" --output hhs_it.json
# Batch process multiple contracts with high concurrency
govdata fpds --contract "HT001525D9012" "HT001525D9013" "HT001525D9014" --threads 15 --output batch.csvCLI Options
--contract <contracts...>: One or more contract numbers (PIID)--date-range <range>: Date range in format[YYYY/MM/DD, YYYY/MM/DD]--output <file>: Output file (.csv for CSV, anything else for JSON)--threads <count>: Number of concurrent threads (default: 10)--naics <code>: NAICS code filter--psc <code>: PSC code filter--agency <name>: Contracting agency filter--vendor <name>: Vendor name filter
Use in Your Application
Node.js API Route (Next.js)
// pages/api/contracts.ts
import { FPDSRequest } from '@bidstream/govdata.js';
export default async function handler(req, res) {
const { contracts, dateRange } = req.body;
try {
const results = await FPDSRequest.searchContracts({
contracts,
dateRange,
metadata: { request_id: req.headers['x-request-id'] }
});
// Save to your database
await saveContractsToDatabase(results);
res.json({ success: true, count: results.length, data: results });
} catch (error) {
res.status(500).json({ error: error.message });
}
}Supabase Edge Function
// supabase/functions/fetch-contracts/index.ts
import { FPDSRequest } from '@bidstream/govdata.js';
Deno.serve(async (req) => {
const { contracts, dateRange } = await req.json();
const results = await FPDSRequest.searchContracts({
contracts,
dateRange
});
// Insert into Supabase
const { data, error } = await supabase
.from('contracts')
.insert(results);
return new Response(JSON.stringify({
success: !error,
count: results.length
}));
});Configuration
interface FPDSRequestConfig {
threadCount?: number; // Default: 10
timeout?: number; // Default: 30000ms
retryAttempts?: number; // Default: 3
retryDelay?: number; // Default: 1000ms
}Performance
- Concurrent Processing: Configurable thread count for parallel requests
- Memory Efficient: Streaming support for large datasets
- Retry Logic: Automatic retry with exponential backoff
- Timeout Handling: Configurable timeouts for all requests
- Individual Failure Tolerance: Single contract failures don't stop batch processing
Browser Support
// Works in modern browsers with fetch support
import { FPDSRequest } from '@bidstream/govdata.js';
const request = new FPDSRequest({ PIID: 'contract123' });
const contracts = await request.getData();License
MIT License - see LICENSE file for details.
Support
- Documentation: https://github.com/bidstream/govdata.js
- Issues: https://github.com/bidstream/govdata.js/issues
