From a834abc31c712991dfe46eee85f98234cd6b24c5 Mon Sep 17 00:00:00 2001 From: Christian Kellner Date: Tue, 2 Jun 2026 09:24:45 +0200 Subject: [PATCH] fixing filtering of lists (#311) * fixing listing filtering by applying the correct id --- lib/FredyPipelineExecutioner.js | 32 ++++++++++++------------- lib/services/storage/listingsStorage.js | 7 ++++-- test/mocks/mockStore.js | 3 +++ 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/lib/FredyPipelineExecutioner.js b/lib/FredyPipelineExecutioner.js index 9b1a151..134fd5d 100755 --- a/lib/FredyPipelineExecutioner.js +++ b/lib/FredyPipelineExecutioner.js @@ -5,9 +5,10 @@ import { NoNewListingsWarning } from './errors.js'; import { - storeListings, - getKnownListingHashesForJobAndProvider, deleteListingsById, + getKnownListingHashesForJobAndProvider, + storeListings, + updateListingDistance, } from './services/storage/listingsStorage.js'; import { getJob } from './services/storage/jobStorage.js'; import * as notify from './notification/notify.js'; @@ -16,8 +17,7 @@ import urlModifier from './services/queryStringMutator.js'; import logger from './services/logger.js'; import { geocodeAddress } from './services/geocoding/geoCodingService.js'; import { distanceMeters } from './services/listings/distanceCalculator.js'; -import { getUserSettings, getSettings } from './services/storage/settingsStorage.js'; -import { updateListingDistance } from './services/storage/listingsStorage.js'; +import { getSettings, getUserSettings } from './services/storage/settingsStorage.js'; import booleanPointInPolygon from '@turf/boolean-point-in-polygon'; import { formatListing } from './utils/formatListing.js'; @@ -97,9 +97,9 @@ class FredyPipelineExecutioner { } /** - * Optionally enrich new listings with data from their detail pages. + * Optionally, enrich new listings with data from their detail pages. * Only called when the provider config defines a `fetchDetails` function. - * Runs all fetches in parallel. Each individual fetch must handle its own errors + * Runs all fetches in parallel. Each fetch must handle its own errors * and always resolve (never reject) to avoid aborting other listings. * * @param {Listing[]} newListings New listings to enrich. @@ -132,7 +132,7 @@ class FredyPipelineExecutioner { for (const listing of newListings) { if (listing.address) { const coords = await geocodeAddress(listing.address); - if (coords) { + if (coords && coords.lat !== -1 && coords.lng !== -1) { listing.latitude = coords.lat; listing.longitude = coords.lng; } @@ -264,15 +264,15 @@ class FredyPipelineExecutioner { const requiredKeys = this._providerConfig.requiredFieldNames; const requireValues = ['id', 'link', 'title']; - const filteredListings = listings - // this should never filter some listings out, because the normalize function should always extract all fields. - .filter((item) => requiredKeys.every((key) => key in item)) - // TODO: move blacklist filter to this file, so it will handle for all providers in same way. - .filter(this._providerConfig.filter) - // filter out listings that are missing required fields - .filter((item) => requireValues.every((key) => item[key] != null)); - - return filteredListings; + return ( + listings + // this should never filter some listings out, because the normalize function should always extract all fields. + .filter((item) => requiredKeys.every((key) => key in item)) + // TODO: move blacklist filter to this file, so it will handle for all providers in same way. + .filter(this._providerConfig.filter) + // filter out listings that are missing required fields + .filter((item) => requireValues.every((key) => item[key] != null)) + ); } /** diff --git a/lib/services/storage/listingsStorage.js b/lib/services/storage/listingsStorage.js index 43a51d6..fa01b0a 100755 --- a/lib/services/storage/listingsStorage.js +++ b/lib/services/storage/listingsStorage.js @@ -214,6 +214,8 @@ export const storeListings = (jobId, providerId, listings) => { longitude: item.longitude || null, }; stmt.run(params); + // Propagate the DB primary key back so downstream pipeline steps use the correct id + item.id = params.id; } }); @@ -417,9 +419,10 @@ export const deleteListingsByJobId = (jobId, hardDelete = false) => { }; /** - * Delete listings by a list of listing IDs. + * Delete listings by a list of listing IDs (the nanoid primary key stored in the `id` column). + * Used by API routes that receive row IDs from the client. * - * @param {string[]} ids - Array of listing IDs to delete. + * @param {string[]} ids - Array of DB row IDs to delete. * @param {boolean} [hardDelete=false] - Whether to hard delete from DB or just mark as deleted. * @returns {any} The result from SqliteConnection.execute. */ diff --git a/test/mocks/mockStore.js b/test/mocks/mockStore.js index adbad3d..cce745a 100644 --- a/test/mocks/mockStore.js +++ b/test/mocks/mockStore.js @@ -32,4 +32,7 @@ export const deletedIds = []; export const deleteListingsById = (ids) => { deletedIds.push(...ids); }; +export const deleteListingsByHash = (hashes) => { + deletedIds.push(...hashes); +}; /* eslint-enable no-unused-vars */