UNPKG

@lineai/gov-deals

Version:

Explore Federal contracts for government building renovations, city hall renovations, courthouse updates, library modernizations, federal building improvement contracts, base housing and facilities upgrades.

128 lines 9.23 kB
"use strict"; /** * CSV-based data source for opportunities * Provides same interface as SAM.gov API but reads from local CSV file */ Object.defineProperty(exports, "__esModule", { value: true }); exports.CsvClient = void 0; const fs_1 = require("fs"); const sync_1 = require("csv-parse/sync"); const field_mapping_1 = require("./field-mapping"); const opportunities_1 = require("../../types/opportunities"); const errors_1 = require("../../core/errors"); /** * CSV-based client that mimics SAM.gov API */ class CsvClient { constructor(options) { var _a, _b; this.cache = null; if (!options.csvPath) { throw new Error('CSV file path is required'); } this.csvPath = options.csvPath; this.cacheResults = (_a = options.cacheResults) !== null && _a !== void 0 ? _a : true; this.encoding = (_b = options.encoding) !== null && _b !== void 0 ? _b : 'utf-8'; } /** * Load and parse CSV data */ async loadData() { // Return cached data if available if (this.cache && this.cacheResults) { return this.cache; } try { // Read CSV file const csvContent = await fs_1.promises.readFile(this.csvPath, this.encoding); // Parse CSV with proper options const records = (0, sync_1.parse)(csvContent, { columns: true, skip_empty_lines: true, relax_quotes: true, relax_column_count: true, skip_records_with_error: true, // Skip problematic rows }); // Cache if enabled if (this.cacheResults) { this.cache = records; } return records; } catch (error) { throw new Error(`Failed to load CSV file: ${error instanceof Error ? error.message : String(error)}`); } } /** * Search opportunities with filtering and pagination */ async search(filters, pagination) { // Load all data const allRecords = await this.loadData(); // Apply filters let filteredRecords = allRecords; if (filters) { filteredRecords = allRecords.filter(row => (0, field_mapping_1.filterCsvRow)(row, filters)); } // Calculate pagination const limit = (pagination === null || pagination === void 0 ? void 0 : pagination.limit) || 100; const page = (pagination === null || pagination === void 0 ? void 0 : pagination.page) || 1; const offset = (page - 1) * limit; // Get paginated results const paginatedRecords = filteredRecords.slice(offset, offset + limit); // Transform to SAM format const opportunities = paginatedRecords.map(field_mapping_1.mapCsvToSamOpportunity); // Build response const response = { totalRecords: filteredRecords.length, limit, offset, opportunitiesData: opportunities, links: [], // CSV doesn't have links }; // Validate response format const result = opportunities_1.SamOpportunitySearchResponseSchema.safeParse(response); if (!result.success) { console.error('CSV mapping validation errors:', result.error.errors); // Continue anyway - the data is still useful even if not perfectly typed } return response; } /** * Get opportunity by ID */ async getById(noticeId) { const allRecords = await this.loadData(); const record = allRecords.find(row => row.NoticeId === noticeId); if (!record) { throw new errors_1.ValidationError(`Opportunity with ID ${noticeId} not found`); } return (0, field_mapping_1.mapCsvToSamOpportunity)(record); } /** * Get opportunity description (from CSV Description field) */ async getDescription(noticeId) { const allRecords = await this.loadData(); const record = allRecords.find(row => row.NoticeId === noticeId); if (!record) { throw new errors_1.ValidationError(`Opportunity with ID ${noticeId} not found`); } return record.Description || 'No description available'; } /** * Search for construction opportunities */ async searchConstruction(additionalFilters, pagination) { const constructionFilters = Object.assign({ naicsCodes: ['236', '238'], keywords: 'renovation construction building modernization' }, additionalFilters); return this.search(constructionFilters, pagination); } /** * Clear cache if needed */ clearCache() { this.cache = null; } } exports.CsvClient = CsvClient; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xpZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2RhdGFzb3VyY2VzL2Nzdi9jbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRzs7O0FBRUgsMkJBQW9DO0FBQ3BDLHlDQUF1QztBQUN2QyxtREFJeUI7QUFDekIsNkRBS21DO0FBRW5DLDhDQUFvRDtBQVFwRDs7R0FFRztBQUNILE1BQWEsU0FBUztJQU1wQixZQUFZLE9BQXlCOztRQUo3QixVQUFLLEdBQStCLElBQUksQ0FBQztRQUsvQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRTtZQUNwQixNQUFNLElBQUksS0FBSyxDQUFDLDJCQUEyQixDQUFDLENBQUM7U0FDOUM7UUFFRCxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUM7UUFDL0IsSUFBSSxDQUFDLFlBQVksR0FBRyxNQUFBLE9BQU8sQ0FBQyxZQUFZLG1DQUFJLElBQUksQ0FBQztRQUNqRCxJQUFJLENBQUMsUUFBUSxHQUFHLE1BQUEsT0FBTyxDQUFDLFFBQVEsbUNBQUksT0FBTyxDQUFDO0lBQzlDLENBQUM7SUFFRDs7T0FFRztJQUNLLEtBQUssQ0FBQyxRQUFRO1FBQ3BCLGtDQUFrQztRQUNsQyxJQUFJLElBQUksQ0FBQyxLQUFLLElBQUksSUFBSSxDQUFDLFlBQVksRUFBRTtZQUNuQyxPQUFPLElBQUksQ0FBQyxLQUFLLENBQUM7U0FDbkI7UUFFRCxJQUFJO1lBQ0YsZ0JBQWdCO1lBQ2hCLE1BQU0sVUFBVSxHQUFHLE1BQU0sYUFBRSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUVsRSxnQ0FBZ0M7WUFDaEMsTUFBTSxPQUFPLEdBQUcsSUFBQSxZQUFLLEVBQUMsVUFBVSxFQUFFO2dCQUNoQyxPQUFPLEVBQUUsSUFBSTtnQkFDYixnQkFBZ0IsRUFBRSxJQUFJO2dCQUN0QixZ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