@factorypure/client-helpers 1.0.25 → 1.0.27

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 CHANGED
@@ -172,6 +172,10 @@ export declare const scrapeResultsSchema: z.ZodObject<{
172
172
  calculated_sku_count: z.ZodOptional<z.ZodNull>;
173
173
  raw_sku_results: z.ZodOptional<z.ZodNull>;
174
174
  details_and_offers: z.ZodOptional<z.ZodNull>;
175
+ total: z.ZodOptional<z.ZodNull>;
176
+ extracted_total: z.ZodOptional<z.ZodNull>;
177
+ shipping: z.ZodOptional<z.ZodNull>;
178
+ extracted_shipping: z.ZodOptional<z.ZodNull>;
175
179
  parsed_results: z.ZodOptional<z.ZodNull>;
176
180
  lowest_price: z.ZodOptional<z.ZodNull>;
177
181
  highest_price: z.ZodOptional<z.ZodNull>;
@@ -188,6 +192,7 @@ export declare const immersiveScrapeResultsSchema: z.ZodObject<{
188
192
  position: z.ZodNumber;
189
193
  title: z.ZodString;
190
194
  found_product_id: z.ZodString;
195
+ type: z.ZodString;
191
196
  product_link: z.ZodString;
192
197
  immersive_product_page_token: z.ZodString;
193
198
  source: z.ZodString;
@@ -198,14 +203,14 @@ export declare const immersiveScrapeResultsSchema: z.ZodObject<{
198
203
  extracted_old_price: z.ZodNullable<z.ZodAny>;
199
204
  total: z.ZodNullable<z.ZodAny>;
200
205
  extracted_total: z.ZodNullable<z.ZodAny>;
206
+ shipping: z.ZodNullable<z.ZodAny>;
207
+ extracted_shipping: z.ZodNullable<z.ZodAny>;
201
208
  rating: z.ZodNullable<z.ZodAny>;
202
209
  reviews: z.ZodNullable<z.ZodAny>;
203
210
  details_and_offers: z.ZodNullable<z.ZodArray<z.ZodString>>;
204
211
  tag: z.ZodNullable<z.ZodAny>;
205
212
  discount: z.ZodNullable<z.ZodAny>;
206
213
  extensions: z.ZodNullable<z.ZodAny>;
207
- delivery: z.ZodNullable<z.ZodAny>;
208
- delivery_extracted: z.ZodNullable<z.ZodAny>;
209
214
  created_at: z.ZodString;
210
215
  store_id: z.ZodNumber;
211
216
  serpapi_thumbnail: z.ZodString;
package/dist/index.js CHANGED
@@ -64,6 +64,10 @@ export const scrapeResultsSchema = z.object({
64
64
  calculated_sku_count: z.null().optional(),
65
65
  raw_sku_results: z.null().optional(),
66
66
  details_and_offers: z.null().optional(),
67
+ total: z.null().optional(),
68
+ extracted_total: z.null().optional(),
69
+ shipping: z.null().optional(),
70
+ extracted_shipping: z.null().optional(),
67
71
  parsed_results: z.null().optional(),
68
72
  lowest_price: z.null().optional(),
69
73
  highest_price: z.null().optional(),
@@ -80,6 +84,7 @@ export const immersiveScrapeResultsSchema = z.object({
80
84
  position: z.number(),
81
85
  title: z.string(),
82
86
  found_product_id: z.string(),
87
+ type: z.string(),
83
88
  product_link: z.string(),
84
89
  immersive_product_page_token: z.string(),
85
90
  source: z.string(),
@@ -90,14 +95,14 @@ export const immersiveScrapeResultsSchema = z.object({
90
95
  extracted_old_price: z.nullable(z.any()),
91
96
  total: z.nullable(z.any()),
92
97
  extracted_total: z.nullable(z.any()),
98
+ shipping: z.nullable(z.any()),
99
+ extracted_shipping: z.nullable(z.any()),
93
100
  rating: z.nullable(z.any()),
94
101
  reviews: z.nullable(z.any()),
95
102
  details_and_offers: z.array(z.string()).nullable(),
96
103
  tag: z.nullable(z.any()),
97
104
  discount: z.nullable(z.any()),
98
105
  extensions: z.nullable(z.any()),
99
- delivery: z.nullable(z.any()),
100
- delivery_extracted: z.nullable(z.any()),
101
106
  created_at: z.string(),
102
107
  store_id: z.number(),
103
108
  serpapi_thumbnail: z.string(),
@@ -198,78 +203,30 @@ export const filterScrapeResults = ({ scrapeResults, variant, filters, globalScr
198
203
  return filteredResults;
199
204
  };
200
205
  const handleVendorExclusions = (dataToSearch, filters, variant) => {
201
- if (!filters.skip_vendors || filters.skip_vendors.length === 0) {
202
- return dataToSearch;
203
- }
204
- const { title, sku } = variant;
205
- function customEncoder(content) {
206
- const tokens = [];
207
- const str = content.toLowerCase();
208
- // Remove symbols from the string (keep only letters, numbers, commas, and spaces)
209
- const cleanedStr = str.replace(/[\/-]/g, ' ');
210
- const cleanedStr2 = cleanedStr.replace(/[^a-z0-9,\/\s]/gi, '');
211
- const words = cleanedStr2.split(/\s+/);
212
- for (let word of words) {
213
- tokens.push(word);
214
- }
215
- return tokens;
216
- }
217
- const index = new Index({
218
- // @ts-ignore
219
- charset: EnglishPreset,
220
- // encoder: encoder,
221
- encode: customEncoder,
222
- tokenize: 'strict',
223
- });
224
- dataToSearch.forEach((item, id) => {
225
- index.add(id, item.title);
226
- });
227
- const searchTerms = filters.match_values;
228
- let final = null;
229
- searchTerms.forEach((term) => {
230
- if (final === null) {
231
- final = index.search(term, {
232
- resolve: false,
233
- suggest: true,
234
- });
235
- }
236
- else {
237
- final = final.or({
238
- index: index,
239
- query: term,
240
- resolve: false,
241
- suggest: true,
242
- });
243
- }
244
- });
245
- final = final.and({
246
- index: index,
247
- query: sku,
248
- resolve: false,
249
- suggest: true,
250
- });
206
+ // Build exclusion list
251
207
  const nots = [];
252
- if (filters.skip_vendors.length > 0) {
253
- const formatted = filters.skip_vendors
254
- .filter((vendor) => vendor.toLowerCase() !== variant.vendor.toLowerCase())
255
- .map((vendor) => ` ${vendor} `);
256
- nots.push(...formatted);
257
- }
258
- nots.forEach((term) => {
259
- final = final.not({
260
- index: index,
261
- query: term,
262
- resolve: false,
208
+ const formatted = filters.skip_vendors
209
+ .filter((s) => s.toLowerCase() !== variant.vendor.toLowerCase())
210
+ .map((s) => `${s}`);
211
+ nots.push(...formatted);
212
+ // Find matching indices based on search criteria
213
+ const matchingIndices = [];
214
+ dataToSearch.forEach((item, index) => {
215
+ // NOT logic: Check if none of the exclusion terms match
216
+ const hasExclusion = nots.some((sku) => {
217
+ const escaped = sku.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
218
+ const matchRegex = new RegExp(`(?: |\/|\&|\=|"|'|\`)${escaped}(?: |\/|\&|\=|"|'|\`)`, 'gi');
219
+ const matches = item.title.match(matchRegex);
220
+ return matches && matches.length > 0;
263
221
  });
222
+ if (!hasExclusion) {
223
+ matchingIndices.push(index);
224
+ }
264
225
  });
265
- const result = final.resolve({ limit: 1000 });
266
- const resultsArray = [];
267
- result.forEach((i) => {
268
- resultsArray.push(dataToSearch[i]);
269
- });
226
+ // Mark items that don't match with hide reason
270
227
  for (let index = 0; index < dataToSearch.length; index++) {
271
228
  const element = dataToSearch[index];
272
- if (!result.includes(index)) {
229
+ if (!matchingIndices.includes(index)) {
273
230
  if (!element.hide_reasons) {
274
231
  element.hide_reasons = [];
275
232
  }
@@ -279,74 +236,30 @@ const handleVendorExclusions = (dataToSearch, filters, variant) => {
279
236
  return dataToSearch;
280
237
  };
281
238
  const handleSkipSkuSearch = (dataToSearch, filters, variant) => {
282
- const { title, sku } = variant;
283
- function customEncoder(content) {
284
- const tokens = [];
285
- const str = content.toLowerCase();
286
- // Remove symbols from the string (keep only letters, numbers, commas, and spaces)
287
- const cleanedStr = str.replace(/[\/-]/g, ' ');
288
- const cleanedStr2 = cleanedStr.replace(/[^a-z0-9,\/\s]/gi, '');
289
- const words = cleanedStr2.split(/\s+/);
290
- for (let word of words) {
291
- tokens.push(word);
292
- }
293
- return tokens;
294
- }
295
- const index = new Index({
296
- // @ts-ignore
297
- charset: EnglishPreset,
298
- // encoder: encoder,
299
- encode: customEncoder,
300
- tokenize: 'strict',
301
- });
302
- dataToSearch.forEach((item, id) => {
303
- index.add(id, item.title);
304
- });
305
- const searchTerms = filters.match_values;
306
- let final = null;
307
- searchTerms.forEach((term) => {
308
- if (final === null) {
309
- final = index.search(term, {
310
- resolve: false,
311
- suggest: true,
312
- });
313
- }
314
- else {
315
- final = final.or({
316
- index: index,
317
- query: term,
318
- resolve: false,
319
- suggest: true,
320
- });
321
- }
322
- });
323
- final = final.and({
324
- index: index,
325
- query: sku,
326
- resolve: false,
327
- suggest: true,
328
- });
239
+ // Build exclusion list
329
240
  const nots = [];
330
- const formatted = filters.skip_skus
331
- .filter((sku) => sku.toLowerCase() !== variant.sku.toLowerCase())
332
- .map((sku) => ` ${sku} `);
241
+ const formatted = filters.skip_skus.filter((s) => s.toLowerCase() !== variant.sku.toLowerCase()).map((s) => `${s}`);
333
242
  nots.push(...formatted);
334
- nots.push(...filters.vendor_search_exclusions.filter((sku) => sku.toLowerCase() !== variant.sku.toLowerCase()));
335
- nots.forEach((term) => {
336
- final = final.not({
337
- index: index,
338
- query: term,
339
- resolve: false,
243
+ nots.push(...filters.vendor_search_exclusions.filter((s) => s.toLowerCase() !== variant.sku.toLowerCase()));
244
+ // Find matching indices based on search criteria
245
+ const matchingIndices = [];
246
+ dataToSearch.forEach((item, index) => {
247
+ // NOT logic: Check if none of the exclusion terms match
248
+ const hasExclusion = nots.some((sku) => {
249
+ const escapedSku = sku.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
250
+ // 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
251
+ const skuRegex = new RegExp(`(?: |\/|\&|\=|"|'|\`)${escapedSku}(?: |\/|\&|\=|"|'|\`)`, 'gi');
252
+ const skuMatches = item.title.match(skuRegex);
253
+ return skuMatches && skuMatches.length > 0;
340
254
  });
255
+ if (!hasExclusion) {
256
+ matchingIndices.push(index);
257
+ }
341
258
  });
342
- const result = final.resolve({ limit: 1000 });
343
- const resultsArray = [];
344
- result.forEach((i) => {
345
- resultsArray.push(dataToSearch[i]);
346
- });
259
+ // Mark items that don't match with hide reason
347
260
  for (let index = 0; index < dataToSearch.length; index++) {
348
261
  const element = dataToSearch[index];
349
- if (!result.includes(index)) {
262
+ if (!matchingIndices.includes(index)) {
350
263
  if (!element.hide_reasons) {
351
264
  element.hide_reasons = [];
352
265
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@factorypure/client-helpers",
3
- "version": "1.0.25",
3
+ "version": "1.0.27",
4
4
  "description": "",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",