@factorypure/client-helpers 1.0.26 → 1.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +2 -0
- package/dist/index.js +53 -129
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -192,6 +192,7 @@ export declare const immersiveScrapeResultsSchema: z.ZodObject<{
|
|
|
192
192
|
position: z.ZodNumber;
|
|
193
193
|
title: z.ZodString;
|
|
194
194
|
found_product_id: z.ZodString;
|
|
195
|
+
type: z.ZodString;
|
|
195
196
|
product_link: z.ZodString;
|
|
196
197
|
immersive_product_page_token: z.ZodString;
|
|
197
198
|
source: z.ZodString;
|
|
@@ -361,6 +362,7 @@ export declare const HIDE_REASONS: {
|
|
|
361
362
|
REFURBISHED_USED: string;
|
|
362
363
|
SKIP_SKU: string;
|
|
363
364
|
VENDOR_EXCLUSION: string;
|
|
365
|
+
SCAM_SOURCE_EXCLUSION: string;
|
|
364
366
|
};
|
|
365
367
|
export declare const HIDE_OVERRIDE_REASONS: {
|
|
366
368
|
SKU_MATCH: string;
|
package/dist/index.js
CHANGED
|
@@ -84,6 +84,7 @@ export const immersiveScrapeResultsSchema = z.object({
|
|
|
84
84
|
position: z.number(),
|
|
85
85
|
title: z.string(),
|
|
86
86
|
found_product_id: z.string(),
|
|
87
|
+
type: z.string(),
|
|
87
88
|
product_link: z.string(),
|
|
88
89
|
immersive_product_page_token: z.string(),
|
|
89
90
|
source: z.string(),
|
|
@@ -166,6 +167,7 @@ export const HIDE_REASONS = {
|
|
|
166
167
|
REFURBISHED_USED: 'Refurbished/Used',
|
|
167
168
|
SKIP_SKU: 'Skipped SKU',
|
|
168
169
|
VENDOR_EXCLUSION: 'Vendor Exclusion',
|
|
170
|
+
SCAM_SOURCE_EXCLUSION: 'Scam Source Exclusion',
|
|
169
171
|
};
|
|
170
172
|
export const HIDE_OVERRIDE_REASONS = {
|
|
171
173
|
SKU_MATCH: 'SKU Match',
|
|
@@ -186,6 +188,7 @@ const HIDE_ALWAYS_MAP = {
|
|
|
186
188
|
[HIDE_REASONS.REFURBISHED_USED]: false,
|
|
187
189
|
[HIDE_REASONS.SKIP_SKU]: false,
|
|
188
190
|
[HIDE_REASONS.VENDOR_EXCLUSION]: false,
|
|
191
|
+
[HIDE_REASONS.SCAM_SOURCE_EXCLUSION]: true,
|
|
189
192
|
};
|
|
190
193
|
export const TOO_CHEAP_MULTIPLIER = 0.75;
|
|
191
194
|
export const TOO_EXPENSIVE_MULTIPLIER = 1.15;
|
|
@@ -199,81 +202,34 @@ export const filterScrapeResults = ({ scrapeResults, variant, filters, globalScr
|
|
|
199
202
|
filteredResults = handleExclusionsSearch(filteredResults, filters, variant);
|
|
200
203
|
filteredResults = handleSkipSkuSearch(filteredResults, filters, variant);
|
|
201
204
|
filteredResults = handleVendorExclusions(filteredResults, filters, variant);
|
|
205
|
+
filteredResults = filterScamExclusions(filteredResults, globalScrapeOptions?.scam_sources || []);
|
|
202
206
|
return filteredResults;
|
|
203
207
|
};
|
|
204
208
|
const handleVendorExclusions = (dataToSearch, filters, variant) => {
|
|
205
|
-
|
|
206
|
-
return dataToSearch;
|
|
207
|
-
}
|
|
208
|
-
const { title, sku } = variant;
|
|
209
|
-
function customEncoder(content) {
|
|
210
|
-
const tokens = [];
|
|
211
|
-
const str = content.toLowerCase();
|
|
212
|
-
// Remove symbols from the string (keep only letters, numbers, commas, and spaces)
|
|
213
|
-
const cleanedStr = str.replace(/[\/-]/g, ' ');
|
|
214
|
-
const cleanedStr2 = cleanedStr.replace(/[^a-z0-9,\/\s]/gi, '');
|
|
215
|
-
const words = cleanedStr2.split(/\s+/);
|
|
216
|
-
for (let word of words) {
|
|
217
|
-
tokens.push(word);
|
|
218
|
-
}
|
|
219
|
-
return tokens;
|
|
220
|
-
}
|
|
221
|
-
const index = new Index({
|
|
222
|
-
// @ts-ignore
|
|
223
|
-
charset: EnglishPreset,
|
|
224
|
-
// encoder: encoder,
|
|
225
|
-
encode: customEncoder,
|
|
226
|
-
tokenize: 'strict',
|
|
227
|
-
});
|
|
228
|
-
dataToSearch.forEach((item, id) => {
|
|
229
|
-
index.add(id, item.title);
|
|
230
|
-
});
|
|
231
|
-
const searchTerms = filters.match_values;
|
|
232
|
-
let final = null;
|
|
233
|
-
searchTerms.forEach((term) => {
|
|
234
|
-
if (final === null) {
|
|
235
|
-
final = index.search(term, {
|
|
236
|
-
resolve: false,
|
|
237
|
-
suggest: true,
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
|
-
else {
|
|
241
|
-
final = final.or({
|
|
242
|
-
index: index,
|
|
243
|
-
query: term,
|
|
244
|
-
resolve: false,
|
|
245
|
-
suggest: true,
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
final = final.and({
|
|
250
|
-
index: index,
|
|
251
|
-
query: sku,
|
|
252
|
-
resolve: false,
|
|
253
|
-
suggest: true,
|
|
254
|
-
});
|
|
209
|
+
// Build exclusion list
|
|
255
210
|
const nots = [];
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
211
|
+
const formatted = filters.skip_vendors
|
|
212
|
+
.filter((s) => s.toLowerCase() !== variant.vendor.toLowerCase())
|
|
213
|
+
.map((s) => `${s}`);
|
|
214
|
+
nots.push(...formatted);
|
|
215
|
+
// Find matching indices based on search criteria
|
|
216
|
+
const matchingIndices = [];
|
|
217
|
+
dataToSearch.forEach((item, index) => {
|
|
218
|
+
// NOT logic: Check if none of the exclusion terms match
|
|
219
|
+
const hasExclusion = nots.some((sku) => {
|
|
220
|
+
const escaped = sku.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
221
|
+
const matchRegex = new RegExp(`(?: |\/|\&|\=|"|'|\`)${escaped}(?: |\/|\&|\=|"|'|\`)`, 'gi');
|
|
222
|
+
const matches = item.title.match(matchRegex);
|
|
223
|
+
return matches && matches.length > 0;
|
|
267
224
|
});
|
|
225
|
+
if (!hasExclusion) {
|
|
226
|
+
matchingIndices.push(index);
|
|
227
|
+
}
|
|
268
228
|
});
|
|
269
|
-
|
|
270
|
-
const resultsArray = [];
|
|
271
|
-
result.forEach((i) => {
|
|
272
|
-
resultsArray.push(dataToSearch[i]);
|
|
273
|
-
});
|
|
229
|
+
// Mark items that don't match with hide reason
|
|
274
230
|
for (let index = 0; index < dataToSearch.length; index++) {
|
|
275
231
|
const element = dataToSearch[index];
|
|
276
|
-
if (!
|
|
232
|
+
if (!matchingIndices.includes(index)) {
|
|
277
233
|
if (!element.hide_reasons) {
|
|
278
234
|
element.hide_reasons = [];
|
|
279
235
|
}
|
|
@@ -283,74 +239,30 @@ const handleVendorExclusions = (dataToSearch, filters, variant) => {
|
|
|
283
239
|
return dataToSearch;
|
|
284
240
|
};
|
|
285
241
|
const handleSkipSkuSearch = (dataToSearch, filters, variant) => {
|
|
286
|
-
|
|
287
|
-
function customEncoder(content) {
|
|
288
|
-
const tokens = [];
|
|
289
|
-
const str = content.toLowerCase();
|
|
290
|
-
// Remove symbols from the string (keep only letters, numbers, commas, and spaces)
|
|
291
|
-
const cleanedStr = str.replace(/[\/-]/g, ' ');
|
|
292
|
-
const cleanedStr2 = cleanedStr.replace(/[^a-z0-9,\/\s]/gi, '');
|
|
293
|
-
const words = cleanedStr2.split(/\s+/);
|
|
294
|
-
for (let word of words) {
|
|
295
|
-
tokens.push(word);
|
|
296
|
-
}
|
|
297
|
-
return tokens;
|
|
298
|
-
}
|
|
299
|
-
const index = new Index({
|
|
300
|
-
// @ts-ignore
|
|
301
|
-
charset: EnglishPreset,
|
|
302
|
-
// encoder: encoder,
|
|
303
|
-
encode: customEncoder,
|
|
304
|
-
tokenize: 'strict',
|
|
305
|
-
});
|
|
306
|
-
dataToSearch.forEach((item, id) => {
|
|
307
|
-
index.add(id, item.title);
|
|
308
|
-
});
|
|
309
|
-
const searchTerms = filters.match_values;
|
|
310
|
-
let final = null;
|
|
311
|
-
searchTerms.forEach((term) => {
|
|
312
|
-
if (final === null) {
|
|
313
|
-
final = index.search(term, {
|
|
314
|
-
resolve: false,
|
|
315
|
-
suggest: true,
|
|
316
|
-
});
|
|
317
|
-
}
|
|
318
|
-
else {
|
|
319
|
-
final = final.or({
|
|
320
|
-
index: index,
|
|
321
|
-
query: term,
|
|
322
|
-
resolve: false,
|
|
323
|
-
suggest: true,
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
});
|
|
327
|
-
final = final.and({
|
|
328
|
-
index: index,
|
|
329
|
-
query: sku,
|
|
330
|
-
resolve: false,
|
|
331
|
-
suggest: true,
|
|
332
|
-
});
|
|
242
|
+
// Build exclusion list
|
|
333
243
|
const nots = [];
|
|
334
|
-
const formatted = filters.skip_skus
|
|
335
|
-
.filter((sku) => sku.toLowerCase() !== variant.sku.toLowerCase())
|
|
336
|
-
.map((sku) => ` ${sku} `);
|
|
244
|
+
const formatted = filters.skip_skus.filter((s) => s.toLowerCase() !== variant.sku.toLowerCase()).map((s) => `${s}`);
|
|
337
245
|
nots.push(...formatted);
|
|
338
|
-
nots.push(...filters.vendor_search_exclusions.filter((
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
246
|
+
nots.push(...filters.vendor_search_exclusions.filter((s) => s.toLowerCase() !== variant.sku.toLowerCase()));
|
|
247
|
+
// Find matching indices based on search criteria
|
|
248
|
+
const matchingIndices = [];
|
|
249
|
+
dataToSearch.forEach((item, index) => {
|
|
250
|
+
// NOT logic: Check if none of the exclusion terms match
|
|
251
|
+
const hasExclusion = nots.some((sku) => {
|
|
252
|
+
const escapedSku = sku.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
253
|
+
// this regex will pick up values from url eg. /product/sku12345/ without picking up partial matches and double counting eg. 15000 being counted twice in 15000 and xp15000
|
|
254
|
+
const skuRegex = new RegExp(`(?: |\/|\&|\=|"|'|\`)${escapedSku}(?: |\/|\&|\=|"|'|\`)`, 'gi');
|
|
255
|
+
const skuMatches = item.title.match(skuRegex);
|
|
256
|
+
return skuMatches && skuMatches.length > 0;
|
|
344
257
|
});
|
|
258
|
+
if (!hasExclusion) {
|
|
259
|
+
matchingIndices.push(index);
|
|
260
|
+
}
|
|
345
261
|
});
|
|
346
|
-
|
|
347
|
-
const resultsArray = [];
|
|
348
|
-
result.forEach((i) => {
|
|
349
|
-
resultsArray.push(dataToSearch[i]);
|
|
350
|
-
});
|
|
262
|
+
// Mark items that don't match with hide reason
|
|
351
263
|
for (let index = 0; index < dataToSearch.length; index++) {
|
|
352
264
|
const element = dataToSearch[index];
|
|
353
|
-
if (!
|
|
265
|
+
if (!matchingIndices.includes(index)) {
|
|
354
266
|
if (!element.hide_reasons) {
|
|
355
267
|
element.hide_reasons = [];
|
|
356
268
|
}
|
|
@@ -478,6 +390,18 @@ const filterCompetitors = (results, competitor_exclusions) => {
|
|
|
478
390
|
});
|
|
479
391
|
return results;
|
|
480
392
|
};
|
|
393
|
+
const filterScamExclusions = (results, scam_sources) => {
|
|
394
|
+
results.forEach((item) => {
|
|
395
|
+
if (!item.hide_reasons) {
|
|
396
|
+
item.hide_reasons = [];
|
|
397
|
+
}
|
|
398
|
+
const lowerSource = item.source.toLowerCase();
|
|
399
|
+
if (scam_sources.some((exclusion) => exclusion && lowerSource === exclusion.toLowerCase())) {
|
|
400
|
+
item.hide_reasons.push(HIDE_REASONS.SCAM_SOURCE_EXCLUSION);
|
|
401
|
+
}
|
|
402
|
+
});
|
|
403
|
+
return results;
|
|
404
|
+
};
|
|
481
405
|
const filterDuplicateResults = (results) => {
|
|
482
406
|
const filteredUniqueResultsMap = {};
|
|
483
407
|
results.forEach((item) => {
|