@factorypure/client-helpers 1.0.18 → 1.0.20

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.
Files changed (3) hide show
  1. package/dist/index.d.ts +460 -10
  2. package/dist/index.js +289 -250
  3. package/package.json +2 -2
package/dist/index.d.ts CHANGED
@@ -1,12 +1,310 @@
1
1
  import { z } from 'zod';
2
- export declare const scrapeResultsSchema: any;
2
+ export declare const regexUnitResultSchema: z.ZodObject<{
3
+ value: z.ZodString;
4
+ source: z.ZodString;
5
+ normalized: z.ZodString;
6
+ }, z.core.$strip>;
7
+ export declare const regexUnitResultsSchema: z.ZodObject<{
8
+ inch: z.ZodArray<z.ZodObject<{
9
+ value: z.ZodString;
10
+ source: z.ZodString;
11
+ normalized: z.ZodString;
12
+ }, z.core.$strip>>;
13
+ cm: z.ZodArray<z.ZodObject<{
14
+ value: z.ZodString;
15
+ source: z.ZodString;
16
+ normalized: z.ZodString;
17
+ }, z.core.$strip>>;
18
+ hp: z.ZodArray<z.ZodObject<{
19
+ value: z.ZodString;
20
+ source: z.ZodString;
21
+ normalized: z.ZodString;
22
+ }, z.core.$strip>>;
23
+ cc: z.ZodArray<z.ZodObject<{
24
+ value: z.ZodString;
25
+ source: z.ZodString;
26
+ normalized: z.ZodString;
27
+ }, z.core.$strip>>;
28
+ ton: z.ZodArray<z.ZodObject<{
29
+ value: z.ZodString;
30
+ source: z.ZodString;
31
+ normalized: z.ZodString;
32
+ }, z.core.$strip>>;
33
+ lbs: z.ZodArray<z.ZodObject<{
34
+ value: z.ZodString;
35
+ source: z.ZodString;
36
+ normalized: z.ZodString;
37
+ }, z.core.$strip>>;
38
+ volts: z.ZodArray<z.ZodObject<{
39
+ value: z.ZodString;
40
+ source: z.ZodString;
41
+ normalized: z.ZodString;
42
+ }, z.core.$strip>>;
43
+ amp: z.ZodArray<z.ZodObject<{
44
+ value: z.ZodString;
45
+ source: z.ZodString;
46
+ normalized: z.ZodString;
47
+ }, z.core.$strip>>;
48
+ watt: z.ZodArray<z.ZodObject<{
49
+ value: z.ZodString;
50
+ source: z.ZodString;
51
+ normalized: z.ZodString;
52
+ }, z.core.$strip>>;
53
+ mph: z.ZodArray<z.ZodObject<{
54
+ value: z.ZodString;
55
+ source: z.ZodString;
56
+ normalized: z.ZodString;
57
+ }, z.core.$strip>>;
58
+ mile: z.ZodArray<z.ZodObject<{
59
+ value: z.ZodString;
60
+ source: z.ZodString;
61
+ normalized: z.ZodString;
62
+ }, z.core.$strip>>;
63
+ ah: z.ZodArray<z.ZodObject<{
64
+ value: z.ZodString;
65
+ source: z.ZodString;
66
+ normalized: z.ZodString;
67
+ }, z.core.$strip>>;
68
+ }, z.core.$strip>;
69
+ export type RegexUnitResultType = z.infer<typeof regexUnitResultSchema>;
70
+ export type RegexUnitResultsType = z.infer<typeof regexUnitResultsSchema> & {
71
+ [key: string]: RegexUnitResultType[];
72
+ };
73
+ export declare const scrapeResultsSchema: z.ZodObject<{
74
+ id: z.ZodNumber;
75
+ scrape_id: z.ZodNumber;
76
+ variant_id: z.ZodNumber;
77
+ type: z.ZodString;
78
+ format: z.ZodNullable<z.ZodAny>;
79
+ position: z.ZodNumber;
80
+ title: z.ZodString;
81
+ found_product_id: z.ZodString;
82
+ product_link: z.ZodString;
83
+ inline_link: z.ZodNullable<z.ZodAny>;
84
+ immersive_product_page_token: z.ZodString;
85
+ serpapi_immersive_product_api: z.ZodString;
86
+ source: z.ZodString;
87
+ source_icon: z.ZodString;
88
+ multiple_sources: z.ZodNumber;
89
+ price: z.ZodString;
90
+ extracted_price: z.ZodNumber;
91
+ old_price: z.ZodNullable<z.ZodAny>;
92
+ extracted_old_price: z.ZodNullable<z.ZodAny>;
93
+ rating: z.ZodNullable<z.ZodAny>;
94
+ reviews: z.ZodNullable<z.ZodAny>;
95
+ snippet: z.ZodNullable<z.ZodAny>;
96
+ thumbnail: z.ZodString;
97
+ serpapi_thumbnail: z.ZodString;
98
+ tag: z.ZodNullable<z.ZodAny>;
99
+ extensions: z.ZodNullable<z.ZodAny>;
100
+ delivery: z.ZodNullable<z.ZodAny>;
101
+ created_at: z.ZodString;
102
+ store_id: z.ZodNumber;
103
+ match_score: z.ZodNullable<z.ZodNumber>;
104
+ ignore_result: z.ZodBoolean;
105
+ ignore_reasons: z.ZodArray<z.ZodString>;
106
+ hide_reasons: z.ZodArray<z.ZodString>;
107
+ hide_override_reasons: z.ZodArray<z.ZodString>;
108
+ regexUnitResults: z.ZodNullable<z.ZodObject<{
109
+ inch: z.ZodArray<z.ZodObject<{
110
+ value: z.ZodString;
111
+ source: z.ZodString;
112
+ normalized: z.ZodString;
113
+ }, z.core.$strip>>;
114
+ cm: z.ZodArray<z.ZodObject<{
115
+ value: z.ZodString;
116
+ source: z.ZodString;
117
+ normalized: z.ZodString;
118
+ }, z.core.$strip>>;
119
+ hp: z.ZodArray<z.ZodObject<{
120
+ value: z.ZodString;
121
+ source: z.ZodString;
122
+ normalized: z.ZodString;
123
+ }, z.core.$strip>>;
124
+ cc: z.ZodArray<z.ZodObject<{
125
+ value: z.ZodString;
126
+ source: z.ZodString;
127
+ normalized: z.ZodString;
128
+ }, z.core.$strip>>;
129
+ ton: z.ZodArray<z.ZodObject<{
130
+ value: z.ZodString;
131
+ source: z.ZodString;
132
+ normalized: z.ZodString;
133
+ }, z.core.$strip>>;
134
+ lbs: z.ZodArray<z.ZodObject<{
135
+ value: z.ZodString;
136
+ source: z.ZodString;
137
+ normalized: z.ZodString;
138
+ }, z.core.$strip>>;
139
+ volts: z.ZodArray<z.ZodObject<{
140
+ value: z.ZodString;
141
+ source: z.ZodString;
142
+ normalized: z.ZodString;
143
+ }, z.core.$strip>>;
144
+ amp: z.ZodArray<z.ZodObject<{
145
+ value: z.ZodString;
146
+ source: z.ZodString;
147
+ normalized: z.ZodString;
148
+ }, z.core.$strip>>;
149
+ watt: z.ZodArray<z.ZodObject<{
150
+ value: z.ZodString;
151
+ source: z.ZodString;
152
+ normalized: z.ZodString;
153
+ }, z.core.$strip>>;
154
+ mph: z.ZodArray<z.ZodObject<{
155
+ value: z.ZodString;
156
+ source: z.ZodString;
157
+ normalized: z.ZodString;
158
+ }, z.core.$strip>>;
159
+ mile: z.ZodArray<z.ZodObject<{
160
+ value: z.ZodString;
161
+ source: z.ZodString;
162
+ normalized: z.ZodString;
163
+ }, z.core.$strip>>;
164
+ ah: z.ZodArray<z.ZodObject<{
165
+ value: z.ZodString;
166
+ source: z.ZodString;
167
+ normalized: z.ZodString;
168
+ }, z.core.$strip>>;
169
+ }, z.core.$strip>>;
170
+ google_product_link: z.ZodOptional<z.ZodNull>;
171
+ calculated_sku: z.ZodOptional<z.ZodNull>;
172
+ calculated_sku_count: z.ZodOptional<z.ZodNull>;
173
+ raw_sku_results: z.ZodOptional<z.ZodNull>;
174
+ details_and_offers: z.ZodOptional<z.ZodNull>;
175
+ parsed_results: z.ZodOptional<z.ZodNull>;
176
+ lowest_price: z.ZodOptional<z.ZodNull>;
177
+ highest_price: z.ZodOptional<z.ZodNull>;
178
+ latest_source_count: z.ZodOptional<z.ZodNull>;
179
+ largest_source_count: z.ZodOptional<z.ZodNull>;
180
+ is_immersive: z.ZodOptional<z.ZodNull>;
181
+ brand: z.ZodOptional<z.ZodNull>;
182
+ company_id: z.ZodOptional<z.ZodNull>;
183
+ }, z.core.$strip>;
184
+ export declare const immersiveScrapeResultsSchema: z.ZodObject<{
185
+ id: z.ZodNumber;
186
+ scrape_id: z.ZodNumber;
187
+ variant_id: z.ZodNumber;
188
+ position: z.ZodNumber;
189
+ title: z.ZodString;
190
+ found_product_id: z.ZodString;
191
+ product_link: z.ZodString;
192
+ immersive_product_page_token: z.ZodString;
193
+ source: z.ZodString;
194
+ source_icon: z.ZodString;
195
+ price: z.ZodString;
196
+ extracted_price: z.ZodNumber;
197
+ old_price: z.ZodNullable<z.ZodAny>;
198
+ extracted_old_price: z.ZodNullable<z.ZodAny>;
199
+ total: z.ZodNullable<z.ZodAny>;
200
+ extracted_total: z.ZodNullable<z.ZodAny>;
201
+ rating: z.ZodNullable<z.ZodAny>;
202
+ reviews: z.ZodNullable<z.ZodAny>;
203
+ details_and_offers: z.ZodNullable<z.ZodArray<z.ZodString>>;
204
+ tag: z.ZodNullable<z.ZodAny>;
205
+ discount: z.ZodNullable<z.ZodAny>;
206
+ extensions: z.ZodNullable<z.ZodAny>;
207
+ delivery: z.ZodNullable<z.ZodAny>;
208
+ delivery_extracted: z.ZodNullable<z.ZodAny>;
209
+ created_at: z.ZodString;
210
+ store_id: z.ZodNumber;
211
+ serpapi_thumbnail: z.ZodString;
212
+ google_product_link: z.ZodString;
213
+ calculated_sku: z.ZodNullable<z.ZodString>;
214
+ calculated_sku_count: z.ZodNullable<z.ZodNumber>;
215
+ raw_sku_results: z.ZodNullable<z.ZodAny>;
216
+ parsed_results: z.ZodNullable<z.ZodString>;
217
+ lowest_price: z.ZodNullable<z.ZodNumber>;
218
+ highest_price: z.ZodNullable<z.ZodNumber>;
219
+ latest_source_count: z.ZodNullable<z.ZodNumber>;
220
+ largest_source_count: z.ZodNullable<z.ZodNumber>;
221
+ is_immersive: z.ZodBoolean;
222
+ score: z.ZodNullable<z.ZodNumber>;
223
+ ignore_result: z.ZodBoolean;
224
+ ignore_reasons: z.ZodArray<z.ZodString>;
225
+ hide_reasons: z.ZodArray<z.ZodString>;
226
+ hide_override_reasons: z.ZodArray<z.ZodString>;
227
+ brand: z.ZodNullable<z.ZodString>;
228
+ company_id: z.ZodNullable<z.ZodNumber>;
229
+ regexUnitResults: z.ZodNullable<z.ZodObject<{
230
+ inch: z.ZodArray<z.ZodObject<{
231
+ value: z.ZodString;
232
+ source: z.ZodString;
233
+ normalized: z.ZodString;
234
+ }, z.core.$strip>>;
235
+ cm: z.ZodArray<z.ZodObject<{
236
+ value: z.ZodString;
237
+ source: z.ZodString;
238
+ normalized: z.ZodString;
239
+ }, z.core.$strip>>;
240
+ hp: z.ZodArray<z.ZodObject<{
241
+ value: z.ZodString;
242
+ source: z.ZodString;
243
+ normalized: z.ZodString;
244
+ }, z.core.$strip>>;
245
+ cc: z.ZodArray<z.ZodObject<{
246
+ value: z.ZodString;
247
+ source: z.ZodString;
248
+ normalized: z.ZodString;
249
+ }, z.core.$strip>>;
250
+ ton: z.ZodArray<z.ZodObject<{
251
+ value: z.ZodString;
252
+ source: z.ZodString;
253
+ normalized: z.ZodString;
254
+ }, z.core.$strip>>;
255
+ lbs: z.ZodArray<z.ZodObject<{
256
+ value: z.ZodString;
257
+ source: z.ZodString;
258
+ normalized: z.ZodString;
259
+ }, z.core.$strip>>;
260
+ volts: z.ZodArray<z.ZodObject<{
261
+ value: z.ZodString;
262
+ source: z.ZodString;
263
+ normalized: z.ZodString;
264
+ }, z.core.$strip>>;
265
+ amp: z.ZodArray<z.ZodObject<{
266
+ value: z.ZodString;
267
+ source: z.ZodString;
268
+ normalized: z.ZodString;
269
+ }, z.core.$strip>>;
270
+ watt: z.ZodArray<z.ZodObject<{
271
+ value: z.ZodString;
272
+ source: z.ZodString;
273
+ normalized: z.ZodString;
274
+ }, z.core.$strip>>;
275
+ mph: z.ZodArray<z.ZodObject<{
276
+ value: z.ZodString;
277
+ source: z.ZodString;
278
+ normalized: z.ZodString;
279
+ }, z.core.$strip>>;
280
+ mile: z.ZodArray<z.ZodObject<{
281
+ value: z.ZodString;
282
+ source: z.ZodString;
283
+ normalized: z.ZodString;
284
+ }, z.core.$strip>>;
285
+ ah: z.ZodArray<z.ZodObject<{
286
+ value: z.ZodString;
287
+ source: z.ZodString;
288
+ normalized: z.ZodString;
289
+ }, z.core.$strip>>;
290
+ }, z.core.$strip>>;
291
+ }, z.core.$strip>;
3
292
  export type ScrapeResultsType = z.infer<typeof scrapeResultsSchema>;
4
- export declare const ResultIgnoreSchema: any;
293
+ export type ImmersiveScrapeResultsType = z.infer<typeof immersiveScrapeResultsSchema>;
294
+ export declare const ResultIgnoreSchema: z.ZodObject<{
295
+ id: z.ZodNumber;
296
+ variant_id: z.ZodNumber;
297
+ title: z.ZodString;
298
+ price: z.ZodString;
299
+ source: z.ZodString;
300
+ reason: z.ZodString;
301
+ duration_days: z.ZodNumber;
302
+ created_by: z.ZodNumber;
303
+ key_parts: z.ZodString;
304
+ }, z.core.$strip>;
5
305
  export type ResultIgnoreType = z.infer<typeof ResultIgnoreSchema>;
6
306
  export type ScrapeFiltersType = {
7
307
  found_id_exclusions: number[] | null;
8
- showHighPriceOutliers: boolean;
9
- showLowPriceOutliers: boolean;
10
308
  dayWindow: number | null;
11
309
  competitor_exclusions: string[];
12
310
  match_values: string[];
@@ -15,6 +313,7 @@ export type ScrapeFiltersType = {
15
313
  vendor_search_exclusions: string[];
16
314
  search_exclusions: string[];
17
315
  result_ignore_keys: ResultIgnoreType[];
316
+ brand_name_alternates: string[];
18
317
  };
19
318
  export type FilterOptionsType = {
20
319
  exclude_linked_variants_enabled?: boolean;
@@ -30,6 +329,32 @@ export type FilterOptionsType = {
30
329
  search_exclusions_enabled?: boolean;
31
330
  exclude_ignored_keys_enabled?: boolean;
32
331
  };
332
+ export declare const variantScrapeOptionsSchema: z.ZodObject<{
333
+ search_exclusions: z.ZodArray<z.ZodString>;
334
+ vendor_search_exclusions: z.ZodArray<z.ZodString>;
335
+ custom_search_value: z.ZodString;
336
+ match_values: z.ZodArray<z.ZodString>;
337
+ skip_skus: z.ZodArray<z.ZodString>;
338
+ competitor_exclusions: z.ZodArray<z.ZodString>;
339
+ disable_vendor_skip_skus: z.ZodBoolean;
340
+ disable_wattage_filter: z.ZodBoolean;
341
+ found_product_ids: z.ZodNullable<z.ZodArray<z.ZodNumber>>;
342
+ immersive_product_page_token: z.ZodNullable<z.ZodString>;
343
+ found_id_exclusions: z.ZodNullable<z.ZodArray<z.ZodNumber>>;
344
+ result_ignore_keys: z.ZodNullable<z.ZodArray<z.ZodObject<{
345
+ id: z.ZodNumber;
346
+ variant_id: z.ZodNumber;
347
+ title: z.ZodString;
348
+ price: z.ZodString;
349
+ source: z.ZodString;
350
+ reason: z.ZodString;
351
+ duration_days: z.ZodNumber;
352
+ created_by: z.ZodNumber;
353
+ key_parts: z.ZodString;
354
+ }, z.core.$strip>>>;
355
+ brand_name_alternates: z.ZodNullable<z.ZodArray<z.ZodString>>;
356
+ }, z.core.$strip>;
357
+ export type VariantScrapeOptionsType = z.infer<typeof variantScrapeOptionsSchema>;
33
358
  export declare const HIDE_REASONS: {
34
359
  IGNORED: string;
35
360
  HIGH_PRICE_OUTLIER: string;
@@ -53,8 +378,8 @@ export declare const HIDE_OVERRIDE_REASONS: {
53
378
  CALCULATED_SKU_PARTIAL_MATCH: string;
54
379
  };
55
380
  export declare const TOO_CHEAP_MULTIPLIER = 0.75;
56
- export declare const TOO_EXPENSIVE_MULTIPLIER = 1.25;
57
- export declare const filterScrapeResults: ({ scrapeResults, variant, filters, filterOptions, globalScrapeOptions, }: {
381
+ export declare const TOO_EXPENSIVE_MULTIPLIER = 1.15;
382
+ export declare const filterScrapeResults: ({ scrapeResults, variant, filters, globalScrapeOptions, }: {
58
383
  scrapeResults: ScrapeResultsType[];
59
384
  variant: {
60
385
  id: number;
@@ -64,11 +389,136 @@ export declare const filterScrapeResults: ({ scrapeResults, variant, filters, fi
64
389
  vendor: string;
65
390
  };
66
391
  filters: ScrapeFiltersType;
67
- filterOptions?: FilterOptionsType;
68
392
  globalScrapeOptions?: any;
69
- }) => z.infer<any>[];
70
- export declare const calculateIgnoreStatus: (result: ScrapeResultsType, variant: {
393
+ }) => {
71
394
  id: number;
395
+ scrape_id: number;
396
+ variant_id: number;
397
+ type: string;
398
+ format: any;
399
+ position: number;
400
+ title: string;
401
+ found_product_id: string;
402
+ product_link: string;
403
+ inline_link: any;
404
+ immersive_product_page_token: string;
405
+ serpapi_immersive_product_api: string;
406
+ source: string;
407
+ source_icon: string;
408
+ multiple_sources: number;
409
+ price: string;
410
+ extracted_price: number;
411
+ old_price: any;
412
+ extracted_old_price: any;
413
+ rating: any;
414
+ reviews: any;
415
+ snippet: any;
416
+ thumbnail: string;
417
+ serpapi_thumbnail: string;
418
+ tag: any;
419
+ extensions: any;
420
+ delivery: any;
421
+ created_at: string;
422
+ store_id: number;
423
+ match_score: number | null;
424
+ ignore_result: boolean;
425
+ ignore_reasons: string[];
426
+ hide_reasons: string[];
427
+ hide_override_reasons: string[];
428
+ regexUnitResults: {
429
+ inch: {
430
+ value: string;
431
+ source: string;
432
+ normalized: string;
433
+ }[];
434
+ cm: {
435
+ value: string;
436
+ source: string;
437
+ normalized: string;
438
+ }[];
439
+ hp: {
440
+ value: string;
441
+ source: string;
442
+ normalized: string;
443
+ }[];
444
+ cc: {
445
+ value: string;
446
+ source: string;
447
+ normalized: string;
448
+ }[];
449
+ ton: {
450
+ value: string;
451
+ source: string;
452
+ normalized: string;
453
+ }[];
454
+ lbs: {
455
+ value: string;
456
+ source: string;
457
+ normalized: string;
458
+ }[];
459
+ volts: {
460
+ value: string;
461
+ source: string;
462
+ normalized: string;
463
+ }[];
464
+ amp: {
465
+ value: string;
466
+ source: string;
467
+ normalized: string;
468
+ }[];
469
+ watt: {
470
+ value: string;
471
+ source: string;
472
+ normalized: string;
473
+ }[];
474
+ mph: {
475
+ value: string;
476
+ source: string;
477
+ normalized: string;
478
+ }[];
479
+ mile: {
480
+ value: string;
481
+ source: string;
482
+ normalized: string;
483
+ }[];
484
+ ah: {
485
+ value: string;
486
+ source: string;
487
+ normalized: string;
488
+ }[];
489
+ } | null;
490
+ google_product_link?: null | undefined;
491
+ calculated_sku?: null | undefined;
492
+ calculated_sku_count?: null | undefined;
493
+ raw_sku_results?: null | undefined;
494
+ details_and_offers?: null | undefined;
495
+ parsed_results?: null | undefined;
496
+ lowest_price?: null | undefined;
497
+ highest_price?: null | undefined;
498
+ latest_source_count?: null | undefined;
499
+ largest_source_count?: null | undefined;
500
+ is_immersive?: null | undefined;
501
+ brand?: null | undefined;
502
+ company_id?: null | undefined;
503
+ }[];
504
+ export declare const getRefurbishedKeywords: (variant: {
72
505
  sku?: string;
73
- }, result_ignore_keys: string[] | null) => boolean;
506
+ }) => string[];
74
507
  export declare function calculateVisibility(hide_reasons: string[], hide_override_reasons: string[]): boolean;
508
+ export declare const calculateHideReasons: (result: ScrapeResultsType | ImmersiveScrapeResultsType, variant: {
509
+ id: number;
510
+ title: string;
511
+ sku: string;
512
+ price: number;
513
+ vendor: string;
514
+ regexUnitResults?: RegexUnitResultsType;
515
+ }, variantScrapeOptions: VariantScrapeOptionsType) => string[];
516
+ export declare const calculateHideOverrideReasons: (result: ScrapeResultsType | ImmersiveScrapeResultsType, variant: {
517
+ id: number;
518
+ title: string;
519
+ sku: string;
520
+ price: number;
521
+ vendor: string;
522
+ found_product_ids?: string[];
523
+ }) => string[];
524
+ export declare function findUnitVariations(data: any): any;
package/dist/index.js CHANGED
@@ -1,10 +1,27 @@
1
1
  import { startOfDay, subDays } from 'date-fns';
2
2
  // @ts-ignore
3
3
  import { Index } from 'flexsearch';
4
- // @ts-ignore
5
4
  import EnglishPreset from 'flexsearch/lang/en';
6
- // @ts-ignore
7
5
  import { z } from 'zod';
6
+ export const regexUnitResultSchema = z.object({
7
+ value: z.string(),
8
+ source: z.string(),
9
+ normalized: z.string(),
10
+ });
11
+ export const regexUnitResultsSchema = z.object({
12
+ inch: z.array(regexUnitResultSchema),
13
+ cm: z.array(regexUnitResultSchema),
14
+ hp: z.array(regexUnitResultSchema),
15
+ cc: z.array(regexUnitResultSchema),
16
+ ton: z.array(regexUnitResultSchema),
17
+ lbs: z.array(regexUnitResultSchema),
18
+ volts: z.array(regexUnitResultSchema),
19
+ amp: z.array(regexUnitResultSchema),
20
+ watt: z.array(regexUnitResultSchema),
21
+ mph: z.array(regexUnitResultSchema),
22
+ mile: z.array(regexUnitResultSchema),
23
+ ah: z.array(regexUnitResultSchema),
24
+ });
8
25
  export const scrapeResultsSchema = z.object({
9
26
  id: z.number(),
10
27
  scrape_id: z.number(),
@@ -13,7 +30,7 @@ export const scrapeResultsSchema = z.object({
13
30
  format: z.nullable(z.any()),
14
31
  position: z.number(),
15
32
  title: z.string(),
16
- found_product_id: z.number(),
33
+ found_product_id: z.string(),
17
34
  product_link: z.string(),
18
35
  inline_link: z.nullable(z.any()),
19
36
  immersive_product_page_token: z.string(),
@@ -36,6 +53,72 @@ export const scrapeResultsSchema = z.object({
36
53
  created_at: z.string(),
37
54
  store_id: z.number(),
38
55
  match_score: z.number().nullable(),
56
+ ignore_result: z.boolean(),
57
+ ignore_reasons: z.array(z.string()),
58
+ hide_reasons: z.array(z.string()),
59
+ hide_override_reasons: z.array(z.string()),
60
+ regexUnitResults: z.nullable(regexUnitResultsSchema),
61
+ // add these properties as null to make ts play nice with the ImmersiveScrapeResultsType union
62
+ google_product_link: z.null().optional(),
63
+ calculated_sku: z.null().optional(),
64
+ calculated_sku_count: z.null().optional(),
65
+ raw_sku_results: z.null().optional(),
66
+ details_and_offers: z.null().optional(),
67
+ parsed_results: z.null().optional(),
68
+ lowest_price: z.null().optional(),
69
+ highest_price: z.null().optional(),
70
+ latest_source_count: z.null().optional(),
71
+ largest_source_count: z.null().optional(),
72
+ is_immersive: z.null().optional(),
73
+ brand: z.null().optional(),
74
+ company_id: z.null().optional(),
75
+ });
76
+ export const immersiveScrapeResultsSchema = z.object({
77
+ id: z.number(),
78
+ scrape_id: z.number(),
79
+ variant_id: z.number(),
80
+ position: z.number(),
81
+ title: z.string(),
82
+ found_product_id: z.string(),
83
+ product_link: z.string(),
84
+ immersive_product_page_token: z.string(),
85
+ source: z.string(),
86
+ source_icon: z.string(),
87
+ price: z.string(),
88
+ extracted_price: z.number(),
89
+ old_price: z.nullable(z.any()),
90
+ extracted_old_price: z.nullable(z.any()),
91
+ total: z.nullable(z.any()),
92
+ extracted_total: z.nullable(z.any()),
93
+ rating: z.nullable(z.any()),
94
+ reviews: z.nullable(z.any()),
95
+ details_and_offers: z.array(z.string()).nullable(),
96
+ tag: z.nullable(z.any()),
97
+ discount: z.nullable(z.any()),
98
+ extensions: z.nullable(z.any()),
99
+ delivery: z.nullable(z.any()),
100
+ delivery_extracted: z.nullable(z.any()),
101
+ created_at: z.string(),
102
+ store_id: z.number(),
103
+ serpapi_thumbnail: z.string(),
104
+ google_product_link: z.string(),
105
+ calculated_sku: z.string().nullable(),
106
+ calculated_sku_count: z.number().nullable(),
107
+ raw_sku_results: z.nullable(z.any()),
108
+ parsed_results: z.string().nullable(),
109
+ lowest_price: z.number().nullable(),
110
+ highest_price: z.number().nullable(),
111
+ latest_source_count: z.number().nullable(),
112
+ largest_source_count: z.number().nullable(),
113
+ is_immersive: z.boolean(),
114
+ score: z.number().nullable(),
115
+ ignore_result: z.boolean(),
116
+ ignore_reasons: z.array(z.string()),
117
+ hide_reasons: z.array(z.string()),
118
+ hide_override_reasons: z.array(z.string()),
119
+ brand: z.string().nullable(),
120
+ company_id: z.number().nullable(),
121
+ regexUnitResults: z.nullable(regexUnitResultsSchema),
39
122
  });
40
123
  export const ResultIgnoreSchema = z.object({
41
124
  id: z.number(),
@@ -48,6 +131,21 @@ export const ResultIgnoreSchema = z.object({
48
131
  created_by: z.number(),
49
132
  key_parts: z.string(),
50
133
  });
134
+ export const variantScrapeOptionsSchema = z.object({
135
+ search_exclusions: z.array(z.string()),
136
+ vendor_search_exclusions: z.array(z.string()),
137
+ custom_search_value: z.string(),
138
+ match_values: z.array(z.string()),
139
+ skip_skus: z.array(z.string()),
140
+ competitor_exclusions: z.array(z.string()),
141
+ disable_vendor_skip_skus: z.boolean(),
142
+ disable_wattage_filter: z.boolean(),
143
+ found_product_ids: z.array(z.number()).nullable(),
144
+ immersive_product_page_token: z.string().nullable(),
145
+ found_id_exclusions: z.array(z.number()).nullable(),
146
+ result_ignore_keys: z.array(ResultIgnoreSchema).nullable(),
147
+ brand_name_alternates: z.array(z.string()).nullable(),
148
+ });
51
149
  export const HIDE_REASONS = {
52
150
  IGNORED: 'Ignored',
53
151
  HIGH_PRICE_OUTLIER: 'Too Expensive',
@@ -86,158 +184,20 @@ const HIDE_ALWAYS_MAP = {
86
184
  [HIDE_REASONS.VENDOR_EXCLUSION]: false,
87
185
  };
88
186
  export const TOO_CHEAP_MULTIPLIER = 0.75;
89
- export const TOO_EXPENSIVE_MULTIPLIER = 1.25;
90
- const wattages = Array.from({ length: 41 }, (_, i) => (5000 + i * 500).toString());
91
- export const filterScrapeResults = ({ scrapeResults, variant, filters, filterOptions = {
92
- exclude_linked_variants_enabled: true,
93
- found_id_exclusions_enabled: true,
94
- price_filter_enabled: true,
95
- date_filter_enabled: true,
96
- competitor_filter_enabled: true,
97
- duplicates_filter_enabled: true,
98
- search_index_enabled: true,
99
- skip_skus_enabled: true,
100
- wattage_exclusions_enabled: true,
101
- search_exclusions_enabled: true,
102
- exclude_ignored_keys_enabled: false,
103
- }, globalScrapeOptions, }) => {
187
+ export const TOO_EXPENSIVE_MULTIPLIER = 1.15;
188
+ // const wattages = Array.from({ length: 41 }, (_, i) => (5000 + i * 500).toString())
189
+ export const filterScrapeResults = ({ scrapeResults, variant, filters, globalScrapeOptions, }) => {
104
190
  let filteredResults = scrapeResults;
105
- // if (filterOptions.exclude_linked_variants_enabled) {
106
- // filteredResults = filterLinkedElsewhereResults(filteredResults, variant.id)
107
- // }
108
- // if (filterOptions.found_id_exclusions_enabled) {
109
- // filteredResults = filterFoundProductIdExclusions(filteredResults, filters.found_id_exclusions)
110
- // }
111
- // if (filterOptions.exclude_ignored_keys_enabled) {
112
- // filteredResults = filterIgnoredResults(filteredResults)
113
- // }
114
- // if (filterOptions.price_filter_enabled) {
115
191
  filteredResults = filterPriceOutliers(filteredResults, variant.price, globalScrapeOptions);
116
- // }
117
- // if (filterOptions.date_filter_enabled) {
118
192
  filteredResults = filterDateWindow(filteredResults, filters.dayWindow);
119
- // }
120
- // if (filterOptions.competitor_filter_enabled) {
121
193
  filteredResults = filterCompetitors(filteredResults, filters.competitor_exclusions);
122
- // }
123
- // if (filterOptions.duplicates_filter_enabled) {
124
194
  filteredResults = filterDuplicateResults(filteredResults);
125
- // }
126
- // if (filterOptions.search_index_enabled) {
127
- filteredResults = handleExclusionsSearch(filteredResults, filters, variant, filterOptions);
128
- filteredResults = handleSkipSkuSearch(filteredResults, filters, variant, filterOptions);
129
- filteredResults = handleVendorExclusions(filteredResults, filters, variant, filterOptions);
130
- // filteredResults = handleIndexSearch(filteredResults, filters, variant, filterOptions)
131
- // }
195
+ filteredResults = handleExclusionsSearch(filteredResults, filters, variant);
196
+ filteredResults = handleSkipSkuSearch(filteredResults, filters, variant);
197
+ filteredResults = handleVendorExclusions(filteredResults, filters, variant);
132
198
  return filteredResults;
133
199
  };
134
- const handleIndexSearch = (dataToSearch, filters, variant, filterOptions) => {
135
- const { title, sku } = variant;
136
- function customEncoder(content) {
137
- const tokens = [];
138
- const str = content.toLowerCase();
139
- // Remove symbols from the string (keep only letters, numbers, commas, and spaces)
140
- const cleanedStr = str.replace(/[\/-]/g, ' ');
141
- const cleanedStr2 = cleanedStr.replace(/[^a-z0-9,\/\s]/gi, '');
142
- const words = cleanedStr2.split(/\s+/);
143
- for (let word of words) {
144
- tokens.push(word);
145
- }
146
- return tokens;
147
- }
148
- const index = new Index({
149
- charset: EnglishPreset,
150
- // encoder: encoder,
151
- encode: customEncoder,
152
- tokenize: 'strict',
153
- });
154
- dataToSearch.forEach((item, id) => {
155
- index.add(id, item.title);
156
- });
157
- const searchTerms = filters.match_values;
158
- let final = null;
159
- searchTerms.forEach((term) => {
160
- if (final === null) {
161
- final = index.search(term, {
162
- resolve: false,
163
- suggest: true,
164
- });
165
- }
166
- else {
167
- final = final.or({
168
- index: index,
169
- query: term,
170
- resolve: false,
171
- suggest: true,
172
- });
173
- }
174
- });
175
- final = final.and({
176
- index: index,
177
- query: sku,
178
- resolve: false,
179
- suggest: true,
180
- });
181
- const nots = [];
182
- if (filters.skip_skus.length && filterOptions.skip_skus_enabled) {
183
- const formatted = filters.skip_skus
184
- .filter((sku) => sku.toLowerCase() !== variant.sku.toLowerCase())
185
- .map((sku) => ` ${sku} `);
186
- nots.push(...formatted);
187
- }
188
- if (filters.skip_vendors.length && filterOptions.skip_vendors_enabled) {
189
- const formatted = filters.skip_vendors
190
- .filter((vendor) => vendor.toLowerCase() !== variant.vendor.toLowerCase())
191
- .map((vendor) => ` ${vendor} `);
192
- nots.push(...formatted);
193
- }
194
- const lowerCaseTitle = title.toLowerCase();
195
- const titleWithoutSku = lowerCaseTitle.replace(sku.toLowerCase(), '');
196
- const wattageTerms = Array.from(titleWithoutSku.matchAll(/\b(\d{4,5})w\b/gi)).map((match) => match[1]);
197
- const wattagesToExclude = wattages.filter((wattage) => !wattageTerms.includes(wattage));
198
- if (filterOptions.wattage_exclusions_enabled) {
199
- wattagesToExclude.forEach((wattage) => {
200
- nots.push(wattage);
201
- nots.push(` ${wattage}w `);
202
- // Push wattage with comma formatting for numbers over 999
203
- if (Number(wattage) > 999) {
204
- nots.push(Number(wattage).toLocaleString());
205
- }
206
- });
207
- }
208
- if (filters.search_exclusions.length && filterOptions.search_exclusions_enabled) {
209
- nots.push(...filters.search_exclusions);
210
- }
211
- if (filters.vendor_search_exclusions.length && filterOptions.skip_skus_enabled) {
212
- nots.push(...filters.vendor_search_exclusions.filter((sku) => sku.toLowerCase() !== variant.sku.toLowerCase()));
213
- }
214
- if (title.toLowerCase().includes('dual fuel')) {
215
- // nots.push('tri fuel', 'trifuel', 'tri-fuel')
216
- }
217
- nots.forEach((term) => {
218
- final = final.not({
219
- index: index,
220
- query: term,
221
- resolve: false,
222
- });
223
- });
224
- const result = final.resolve({ limit: 1000 });
225
- const resultsArray = [];
226
- result.forEach((i) => {
227
- resultsArray.push(dataToSearch[i]);
228
- });
229
- for (let index = 0; index < dataToSearch.length; index++) {
230
- const element = dataToSearch[index];
231
- if (!result.includes(index)) {
232
- if (!element.hide_reasons) {
233
- element.hide_reasons = [];
234
- }
235
- element.hide_reasons.push(HIDE_REASONS.SEARCH_EXCLUSION);
236
- }
237
- }
238
- return dataToSearch;
239
- };
240
- const handleVendorExclusions = (dataToSearch, filters, variant, filterOptions) => {
200
+ const handleVendorExclusions = (dataToSearch, filters, variant) => {
241
201
  if (!filters.skip_vendors || filters.skip_vendors.length === 0) {
242
202
  return dataToSearch;
243
203
  }
@@ -255,6 +215,7 @@ const handleVendorExclusions = (dataToSearch, filters, variant, filterOptions) =
255
215
  return tokens;
256
216
  }
257
217
  const index = new Index({
218
+ // @ts-ignore
258
219
  charset: EnglishPreset,
259
220
  // encoder: encoder,
260
221
  encode: customEncoder,
@@ -288,7 +249,7 @@ const handleVendorExclusions = (dataToSearch, filters, variant, filterOptions) =
288
249
  suggest: true,
289
250
  });
290
251
  const nots = [];
291
- if (filters.skip_vendors.length && filterOptions.skip_vendors_enabled) {
252
+ if (filters.skip_vendors.length > 0) {
292
253
  const formatted = filters.skip_vendors
293
254
  .filter((vendor) => vendor.toLowerCase() !== variant.vendor.toLowerCase())
294
255
  .map((vendor) => ` ${vendor} `);
@@ -317,13 +278,7 @@ const handleVendorExclusions = (dataToSearch, filters, variant, filterOptions) =
317
278
  }
318
279
  return dataToSearch;
319
280
  };
320
- const handleSkipSkuSearch = (dataToSearch, filters, variant, filterOptions) => {
321
- // if (
322
- // (!filters.skip_skus || filters.skip_skus.length === 0) &&
323
- // (!filters.vendor_search_exclusions || filters.vendor_search_exclusions.length === 0)
324
- // ) {
325
- // return dataToSearch
326
- // }
281
+ const handleSkipSkuSearch = (dataToSearch, filters, variant) => {
327
282
  const { title, sku } = variant;
328
283
  function customEncoder(content) {
329
284
  const tokens = [];
@@ -338,6 +293,7 @@ const handleSkipSkuSearch = (dataToSearch, filters, variant, filterOptions) => {
338
293
  return tokens;
339
294
  }
340
295
  const index = new Index({
296
+ // @ts-ignore
341
297
  charset: EnglishPreset,
342
298
  // encoder: encoder,
343
299
  encode: customEncoder,
@@ -399,7 +355,7 @@ const handleSkipSkuSearch = (dataToSearch, filters, variant, filterOptions) => {
399
355
  }
400
356
  return dataToSearch;
401
357
  };
402
- const handleExclusionsSearch = (dataToSearch, filters, variant, filterOptions) => {
358
+ const handleExclusionsSearch = (dataToSearch, filters, variant) => {
403
359
  if (!filters.search_exclusions || filters.search_exclusions.length === 0) {
404
360
  return dataToSearch;
405
361
  }
@@ -417,6 +373,7 @@ const handleExclusionsSearch = (dataToSearch, filters, variant, filterOptions) =
417
373
  return tokens;
418
374
  }
419
375
  const index = new Index({
376
+ // @ts-ignore
420
377
  charset: EnglishPreset,
421
378
  // encoder: encoder,
422
379
  encode: customEncoder,
@@ -474,51 +431,6 @@ const handleExclusionsSearch = (dataToSearch, filters, variant, filterOptions) =
474
431
  }
475
432
  return dataToSearch;
476
433
  };
477
- const filterLinkedElsewhereResults = (results, variantId) => {
478
- const filtered = results.filter((result) => {
479
- const linkedVariantIds = result.linked_variant_ids || [];
480
- let parsedLinkedVariantIds = linkedVariantIds;
481
- if (!Array.isArray(linkedVariantIds)) {
482
- try {
483
- parsedLinkedVariantIds = JSON.parse(linkedVariantIds);
484
- }
485
- catch {
486
- parsedLinkedVariantIds = [];
487
- }
488
- }
489
- const productLinkedElsewhere = parsedLinkedVariantIds.length > 0 && !parsedLinkedVariantIds.includes(variantId);
490
- if (productLinkedElsewhere) {
491
- return false;
492
- }
493
- return true;
494
- });
495
- return filtered;
496
- };
497
- const filterFoundProductIdExclusions = (results, found_id_exclusions) => {
498
- const filtered = results.filter((item) => {
499
- if (found_id_exclusions && found_id_exclusions.length) {
500
- if (found_id_exclusions.includes(item.found_product_id)) {
501
- return false;
502
- }
503
- }
504
- return true;
505
- });
506
- return filtered;
507
- };
508
- const filterIgnoredResults = (results) => {
509
- results.forEach((item) => {
510
- if (!item.hide_reasons) {
511
- item.hide_reasons = [];
512
- }
513
- if (item.ignore_result) {
514
- item.hide_reasons.push(HIDE_REASONS.IGNORED);
515
- }
516
- });
517
- // const filtered = results.filter((item) => {
518
- // return item.ignore_result ? false : true
519
- // })
520
- return results;
521
- };
522
434
  const filterPriceOutliers = (results, variantPrice, globalScrapeOptions) => {
523
435
  results.forEach((item) => {
524
436
  if (!item.hide_reasons) {
@@ -535,19 +447,6 @@ const filterPriceOutliers = (results, variantPrice, globalScrapeOptions) => {
535
447
  }
536
448
  });
537
449
  const filtered = results;
538
- // const filtered = results.filter((item) => {
539
- // const showMoreExpensive = showHighPriceOutliers === true
540
- // const isMoreExpensive = item.extracted_price > variantPrice * TOO_EXPENSIVE_MULTIPLIER
541
- // const showTooCheap = showLowPriceOutliers === true
542
- // const isTooCheap = item.extracted_price < variantPrice * TOO_CHEAP_MULTIPLIER
543
- // if (isMoreExpensive && !showMoreExpensive) {
544
- // return false
545
- // }
546
- // if (isTooCheap && !showTooCheap) {
547
- // return false
548
- // }
549
- // return true
550
- // })
551
450
  return filtered;
552
451
  };
553
452
  const filterDateWindow = (results, dayWindow) => {
@@ -561,12 +460,6 @@ const filterDateWindow = (results, dayWindow) => {
561
460
  item.hide_reasons.push(HIDE_REASONS.DATE_OUTLIER);
562
461
  }
563
462
  });
564
- // const filtered = results.filter((item) => {
565
- // if (!dayWindow) return true
566
- // const itemDate = new Date(item.created_at)
567
- // const variantDate = startOfDay(subDays(new Date(), Number(dayWindow) || 7))
568
- // return itemDate >= variantDate
569
- // })
570
463
  return results;
571
464
  };
572
465
  const filterCompetitors = (results, competitor_exclusions) => {
@@ -579,15 +472,6 @@ const filterCompetitors = (results, competitor_exclusions) => {
579
472
  item.hide_reasons.push(HIDE_REASONS.COMPETITOR_EXCLUSION);
580
473
  }
581
474
  });
582
- // const filtered = results.filter((item) => {
583
- // const lowerSource = item.source.toLowerCase()
584
- // for (const exclusion of competitor_exclusions) {
585
- // if (exclusion && lowerSource === exclusion.toLowerCase()) {
586
- // return false
587
- // }
588
- // }
589
- // return true
590
- // })
591
475
  return results;
592
476
  };
593
477
  const filterDuplicateResults = (results) => {
@@ -619,15 +503,7 @@ const filterDuplicateResults = (results) => {
619
503
  });
620
504
  return results;
621
505
  };
622
- export const calculateIgnoreStatus = (result, variant, result_ignore_keys) => {
623
- let ignore = false;
624
- const resultKey = `${variant.id}-${result.title}-${result.extracted_price}-${result.source}`;
625
- if (result_ignore_keys && result_ignore_keys.includes(resultKey)) {
626
- ignore = true;
627
- }
628
- if (result.details_and_offers && result.details_and_offers.includes('Out of stock online')) {
629
- ignore = true;
630
- }
506
+ export const getRefurbishedKeywords = (variant) => {
631
507
  const refurbishedKeywords = [
632
508
  'refurbished',
633
509
  'renewed',
@@ -637,19 +513,18 @@ export const calculateIgnoreStatus = (result, variant, result_ignore_keys) => {
637
513
  'scratch',
638
514
  'dent',
639
515
  'used',
640
- `${variant.sku}-R`,
641
- `${variant.sku}-R`.toLowerCase(),
642
- `${variant.sku}-R`.toUpperCase(),
643
- `${variant.sku?.toLowerCase()}-R`,
644
- `${variant.sku?.toUpperCase()}-R`,
645
516
  ];
646
- const normalizedTitle = result.title.toLowerCase().replace(/[^a-z0-9-]/g, ' ');
647
- const isRefurbished = refurbishedKeywords.some((keyword) => normalizedTitle.split(/\s+/).includes(keyword)) ||
648
- (result.details_and_offers && result.details_and_offers.includes('Pre-owned'));
649
- if (isRefurbished) {
650
- ignore = true;
517
+ if (variant?.sku) {
518
+ const skuBasedKeywords = [
519
+ `${variant.sku}-R`,
520
+ `${variant.sku}-R`.toLowerCase(),
521
+ `${variant.sku}-R`.toUpperCase(),
522
+ `${variant.sku?.toLowerCase()}-R`,
523
+ `${variant.sku?.toUpperCase()}-R`,
524
+ ];
525
+ refurbishedKeywords.push(...skuBasedKeywords);
651
526
  }
652
- return ignore;
527
+ return refurbishedKeywords;
653
528
  };
654
529
  export function calculateVisibility(hide_reasons, hide_override_reasons) {
655
530
  if (!hide_reasons || hide_reasons.length === 0) {
@@ -671,3 +546,167 @@ function getUndercutThreshold(price, undercutThresholdRanges) {
671
546
  const range = undercutThresholdRanges.find((r) => price >= r.min && price <= r.max);
672
547
  return range ? range.threshold : 0.75; // fallback default
673
548
  }
549
+ export const calculateHideReasons = (result, variant, variantScrapeOptions) => {
550
+ const hide_reasons = [];
551
+ if (variantScrapeOptions.result_ignore_keys && variantScrapeOptions.result_ignore_keys.length > 0) {
552
+ variantScrapeOptions.result_ignore_keys.forEach((key) => {
553
+ const resultKeyValues = [variant.id];
554
+ const keyValues = [];
555
+ const keyParts = JSON.parse(key.key_parts);
556
+ keyParts.forEach((part) => {
557
+ keyValues.push(key[part]);
558
+ if (part !== 'variant_id') {
559
+ resultKeyValues.push(result[part === 'price' ? 'extracted_price' : part]);
560
+ }
561
+ });
562
+ const parsedIgnoreKey = keyValues.join('-');
563
+ const resultIgnoreKey = resultKeyValues.join('-');
564
+ if (parsedIgnoreKey === resultIgnoreKey) {
565
+ key.reason === 'Ignored'
566
+ ? hide_reasons.push('Manually ignored')
567
+ : hide_reasons.push('Manually excluded');
568
+ }
569
+ });
570
+ }
571
+ if (result.brand) {
572
+ const vendor = variant.vendor ? variant.vendor.toLowerCase() : null;
573
+ const brandNameAlternates = variantScrapeOptions.brand_name_alternates;
574
+ const targetBrands = [vendor, ...(brandNameAlternates || [])].filter((b) => b).map((b) => b?.toLowerCase());
575
+ const calcBrandMatched = result.brand && result.brand !== '' ? targetBrands.includes(result.brand.toLowerCase()) : null;
576
+ if (calcBrandMatched === false) {
577
+ hide_reasons.push('Calculated Brand Mismatch');
578
+ }
579
+ }
580
+ if (result.details_and_offers && result.details_and_offers.includes('Out of stock online')) {
581
+ hide_reasons.push('Out of stock online');
582
+ }
583
+ if (result.calculated_sku && result.calculated_sku?.toLowerCase() !== variant.sku.toLowerCase()) {
584
+ hide_reasons.push('Calculated SKU Mismatch');
585
+ }
586
+ if (result.regexUnitResults && variant.regexUnitResults) {
587
+ const [regexIgnore, regexIgnoreReasons] = getRegexUnitResultsIgnore(result.regexUnitResults, variant.regexUnitResults);
588
+ if (regexIgnore) {
589
+ hide_reasons.push(...regexIgnoreReasons);
590
+ }
591
+ }
592
+ const refurbishedKeywords = getRefurbishedKeywords(variant);
593
+ const normalizedTitle = result.title.toLowerCase().replace(/[^a-z0-9-]/g, ' ');
594
+ const isRefurbished = refurbishedKeywords.some((keyword) => normalizedTitle.split(/\s+/).includes(keyword)) ||
595
+ (result.details_and_offers && result.details_and_offers.includes('Pre-owned'));
596
+ if (isRefurbished) {
597
+ hide_reasons.push('Refurbished/Used');
598
+ }
599
+ return hide_reasons;
600
+ };
601
+ export const calculateHideOverrideReasons = (result, variant) => {
602
+ const hide_override_reasons = [];
603
+ const skuRegex = new RegExp(`\\b${variant.sku}\\b`, 'gi');
604
+ if (skuRegex.test(result.title)) {
605
+ hide_override_reasons.push('SKU Match');
606
+ }
607
+ if (variant.sku.toLowerCase() === result.calculated_sku?.toLowerCase()) {
608
+ hide_override_reasons.push('Calculated SKU Match');
609
+ }
610
+ if (variant.found_product_ids && variant.found_product_ids.includes(result.found_product_id)) {
611
+ hide_override_reasons.push('Product Id Linked');
612
+ }
613
+ return hide_override_reasons;
614
+ };
615
+ function getRegexUnitResultsIgnore(resultRegexResults, variantRegexResults, criticalUnits = ['ton', 'cc', 'hp']) {
616
+ const failedUnits = [];
617
+ for (const unit in variantRegexResults) {
618
+ if (!variantRegexResults.hasOwnProperty(unit))
619
+ continue;
620
+ const variations = variantRegexResults[unit];
621
+ if (variations.length === 0)
622
+ continue;
623
+ const mostCommonVariation = variations[0];
624
+ const targetVariations = resultRegexResults[unit] || [];
625
+ if (targetVariations.length === 0)
626
+ continue;
627
+ const matchingVariation = resultRegexResults[unit].find((v) => v.normalized === mostCommonVariation.normalized);
628
+ if (!matchingVariation) {
629
+ // A unit exists in both the target and variant, but no matching variations were found
630
+ failedUnits.push(unit);
631
+ }
632
+ }
633
+ const ignoreReasons = [];
634
+ for (const criticalUnit of criticalUnits) {
635
+ if (failedUnits.includes(criticalUnit)) {
636
+ ignoreReasons.push(`Critical Spec Mismatch`);
637
+ }
638
+ }
639
+ if (ignoreReasons.length === 0) {
640
+ return [false, []];
641
+ }
642
+ else {
643
+ return [true, ignoreReasons];
644
+ }
645
+ }
646
+ export function findUnitVariations(data) {
647
+ const units = ['inch', 'cm', 'hp', 'cc', 'ton', 'lbs', 'volts', 'amp', 'ah', 'watt', 'mph', 'mile'];
648
+ const results = {
649
+ inch: [],
650
+ cm: [],
651
+ hp: [],
652
+ cc: [],
653
+ ton: [],
654
+ lbs: [],
655
+ volts: [],
656
+ amp: [],
657
+ watt: [],
658
+ mph: [],
659
+ mile: [],
660
+ ah: [],
661
+ };
662
+ units.forEach((unit) => {
663
+ const escapedUnit = unit.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
664
+ let variationsRegex;
665
+ if (unit === '"' || unit.toLowerCase() === 'inch') {
666
+ // Match numbers (integer or decimal) followed by ", ”, in, inch, inches, -in, - inch, etc.
667
+ variationsRegex = /\b\d+(\.\d+)?-?\s*(?:(\\"|\\u201d)|("|”)|in(ch(es)?)?|-\s*in(ch(es)?)?)/gi;
668
+ }
669
+ else if (unit.toLowerCase() === 'cm') {
670
+ variationsRegex = /\b\d+(\.\d+)?-?\s*(cm|centimeter(s)?)/gi;
671
+ }
672
+ else if (unit.toLowerCase() === 'volts') {
673
+ variationsRegex = /\b\d+(\.\d+)?-?\s*(v|volts|volt)/gi;
674
+ }
675
+ else if (unit.toLowerCase() === 'lbs') {
676
+ variationsRegex = /\b\d+(\.\d+)?-?\s*(lb|lbs|pounds|pound)/gi;
677
+ }
678
+ else if (unit.toLowerCase() === 'hp') {
679
+ variationsRegex = /\b\d+(\.\d+)?-?\s*(hp|horsepower|horse power)/gi;
680
+ }
681
+ else if (unit.toLowerCase() === 'mph') {
682
+ variationsRegex = /\b\d+(\.\d+)?-?\s*(mph|miles per hour|mile per hour)/gi;
683
+ }
684
+ else if (unit.toLowerCase() === 'amp') {
685
+ variationsRegex = /\b\d+(\.\d+)?-?\s*(?<!A?W?G\s*)(A\b|amp\b|amps\b|amperes\b|ampere\b)/gi;
686
+ }
687
+ else if (unit.toLowerCase() === 'ah') {
688
+ variationsRegex = /\b\d+(\.\d+)?-?\s*(ah|ampere hours|amp hour|amp hours)/gi;
689
+ }
690
+ else if (unit.toLowerCase() === 'cc') {
691
+ variationsRegex = /\b\d+(\.\d+)?-?\s*(cc|cubic centimeters|cubic centimeter)/gi;
692
+ }
693
+ else if (unit.toLowerCase() === 'ton') {
694
+ variationsRegex = /\b\d+(\.\d+)?\s*-?\s*(ton|tons)/gi;
695
+ }
696
+ else {
697
+ // Generic: number + unit, with optional dash or space
698
+ variationsRegex = new RegExp(`\\b\\d+(\\.\\d+)?\\s*(-?\\s*${escapedUnit})`, 'gi');
699
+ }
700
+ const matches = [];
701
+ const sampleText = JSON.stringify(data);
702
+ let match;
703
+ while ((match = variationsRegex.exec(sampleText)) !== null) {
704
+ matches.push({ value: match[0], source: match[0], normalized: match[0].replace(/[^\d.]/g, '') });
705
+ }
706
+ results[unit] = matches;
707
+ if (results[unit].length === 0) {
708
+ delete results[unit];
709
+ }
710
+ });
711
+ return results;
712
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@factorypure/client-helpers",
3
- "version": "1.0.18",
3
+ "version": "1.0.20",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -22,6 +22,6 @@
22
22
  "@types/date-fns": "^2.5.3",
23
23
  "date-fns": "^4.1.0",
24
24
  "flexsearch": "^0.8.212",
25
- "zod": "^4.3.5"
25
+ "zod": "^4.3.6"
26
26
  }
27
27
  }