@faststore/api 1.9.7 → 1.9.11

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 (37) hide show
  1. package/CHANGELOG.md +525 -1697
  2. package/README.md +5 -2
  3. package/dist/__generated__/schema.d.ts +72 -41
  4. package/dist/api.cjs.development.js +270 -210
  5. package/dist/api.cjs.development.js.map +1 -1
  6. package/dist/api.cjs.production.min.js +1 -1
  7. package/dist/api.cjs.production.min.js.map +1 -1
  8. package/dist/api.esm.js +270 -210
  9. package/dist/api.esm.js.map +1 -1
  10. package/dist/index.d.ts +4 -2
  11. package/dist/platforms/vtex/clients/search/index.d.ts +2 -1
  12. package/dist/platforms/vtex/clients/search/types/FacetSearchResult.d.ts +8 -8
  13. package/dist/platforms/vtex/index.d.ts +7 -3
  14. package/dist/platforms/vtex/resolvers/faceValue.d.ts +3 -0
  15. package/dist/platforms/vtex/resolvers/facet.d.ts +3 -1
  16. package/dist/platforms/vtex/utils/facets.d.ts +1 -0
  17. package/package.json +3 -2
  18. package/src/__generated__/schema.ts +75 -41
  19. package/src/platforms/vtex/clients/search/index.ts +9 -1
  20. package/src/platforms/vtex/clients/search/types/FacetSearchResult.ts +9 -8
  21. package/src/platforms/vtex/index.ts +26 -16
  22. package/src/platforms/vtex/resolvers/faceValue.ts +12 -0
  23. package/src/platforms/vtex/resolvers/facet.ts +66 -5
  24. package/src/platforms/vtex/resolvers/offer.ts +1 -1
  25. package/src/platforms/vtex/resolvers/searchResult.ts +9 -26
  26. package/src/platforms/vtex/utils/facets.ts +18 -0
  27. package/src/typeDefs/cart.graphql +1 -1
  28. package/src/typeDefs/collection.graphql +12 -0
  29. package/src/typeDefs/facet.graphql +28 -6
  30. package/src/typeDefs/mutation.graphql +2 -2
  31. package/src/typeDefs/order.graphql +1 -1
  32. package/src/typeDefs/pageInfo.graphql +5 -5
  33. package/src/typeDefs/query.graphql +59 -23
  34. package/src/typeDefs/session.graphql +4 -4
  35. package/src/typeDefs/status.graphql +1 -1
  36. package/dist/platforms/vtex/resolvers/facetValue.d.ts +0 -5
  37. package/src/platforms/vtex/resolvers/facetValue.ts +0 -12
package/dist/index.d.ts CHANGED
@@ -51,8 +51,10 @@ export declare const getResolvers: (options: Options) => {
51
51
  description?: string | undefined;
52
52
  canonical?: string | undefined;
53
53
  }, unknown, any>>;
54
- StoreFacet: Record<string, import("./platforms/vtex").Resolver<import("./platforms/vtex/clients/search/types/FacetSearchResult").Facet, unknown, any>>;
55
- StoreFacetValue: Record<string, import("./platforms/vtex").Resolver<import("./platforms/vtex/clients/search/types/FacetSearchResult").FacetValue, unknown, any>>;
54
+ StoreFacet: Record<string, import("./platforms/vtex").Resolver<import("./platforms/vtex/clients/search/types/FacetSearchResult").Facet<import("./platforms/vtex/clients/search/types/FacetSearchResult").FacetValueBoolean | import("./platforms/vtex/clients/search/types/FacetSearchResult").FacetValueRange>, unknown, any>>;
55
+ StoreFacetBoolean: Record<string, import("./platforms/vtex").Resolver<import("./platforms/vtex/clients/search/types/FacetSearchResult").Facet<import("./platforms/vtex/clients/search/types/FacetSearchResult").FacetValueBoolean>, unknown, any>>;
56
+ StoreFacetRange: Record<string, import("./platforms/vtex").Resolver<import("./platforms/vtex/clients/search/types/FacetSearchResult").Facet<import("./platforms/vtex/clients/search/types/FacetSearchResult").FacetValueRange>, unknown, any>>;
57
+ StoreFacetValueBoolean: Record<string, import("./platforms/vtex").Resolver<import("./platforms/vtex/clients/search/types/FacetSearchResult").FacetValueBoolean, unknown, any>>;
56
58
  StoreOffer: Record<string, import("./platforms/vtex").Resolver<import("./platforms/vtex/utils/enhanceCommercialOffer").EnhancedCommercialOffer<import("./platforms/vtex/clients/search/types/ProductSearchResult").Seller, import("./platforms/vtex/clients/search/types/ProductSearchResult").Item & {
57
59
  isVariantOf: import("./platforms/vtex/clients/search/types/ProductSearchResult").Product;
58
60
  } & {
@@ -1,6 +1,6 @@
1
1
  import type { Context, Options } from '../../index';
2
2
  import type { SelectedFacet } from '../../utils/facets';
3
- import type { FacetSearchResult } from './types/FacetSearchResult';
3
+ import type { Facet, FacetValueBoolean, FacetSearchResult } from './types/FacetSearchResult';
4
4
  import type { ProductSearchResult, Suggestion } from './types/ProductSearchResult';
5
5
  export declare type Sort = 'price:desc' | 'price:asc' | 'orders:desc' | 'name:desc' | 'name:asc' | 'release:desc' | 'discount:desc' | '';
6
6
  export interface SearchArgs {
@@ -17,6 +17,7 @@ export interface ProductLocator {
17
17
  field: 'id' | 'slug';
18
18
  value: string;
19
19
  }
20
+ export declare const isFacetBoolean: (facet: Facet) => facet is Facet<FacetValueBoolean>;
20
21
  export declare const IntelligentSearch: ({ account, environment, hideUnavailableItems }: Options, ctx: Context) => {
21
22
  facets: (args: Omit<SearchArgs, 'type'>) => Promise<FacetSearchResult>;
22
23
  products: (args: Omit<SearchArgs, 'type'>) => Promise<ProductSearchResult>;
@@ -3,26 +3,26 @@ export interface FacetSearchResult {
3
3
  facets: Facet[];
4
4
  breadcrumb: Breadcrumb;
5
5
  }
6
- export interface Facet {
6
+ export interface Facet<T = FacetValueBoolean | FacetValueRange> {
7
7
  type: FilterType;
8
8
  name: string;
9
9
  hidden: boolean;
10
- values: FacetValue[];
10
+ values: T[];
11
11
  quantity?: number;
12
- key?: string;
12
+ key: string;
13
13
  }
14
- export interface FacetValue {
14
+ export interface FacetValueBoolean {
15
15
  quantity: number;
16
16
  name: string;
17
17
  key: string;
18
18
  value: string;
19
- selected?: boolean;
20
- range?: {
19
+ selected: boolean;
20
+ }
21
+ export interface FacetValueRange {
22
+ range: {
21
23
  from: number;
22
24
  to: number;
23
25
  };
24
- children?: FacetValue[];
25
- id?: string;
26
26
  }
27
27
  interface Breadcrumb {
28
28
  href: string;
@@ -1,3 +1,4 @@
1
+ import type { SearchArgs } from './clients/search';
1
2
  import type { Loaders } from './loaders';
2
3
  import type { Clients } from './clients';
3
4
  import type { Channel } from './utils/channel';
@@ -26,6 +27,7 @@ export interface Context {
26
27
  channel: Required<Channel>;
27
28
  locale: string;
28
29
  flags: FeatureFlags;
30
+ searchArgs?: Omit<SearchArgs, 'type'>;
29
31
  };
30
32
  headers: Record<string, string>;
31
33
  }
@@ -79,8 +81,10 @@ export declare const getResolvers: (_: Options) => {
79
81
  description?: string | undefined;
80
82
  canonical?: string | undefined;
81
83
  }, unknown, any>>;
82
- StoreFacet: Record<string, Resolver<import("./clients/search/types/FacetSearchResult").Facet, unknown, any>>;
83
- StoreFacetValue: Record<string, Resolver<import("./clients/search/types/FacetSearchResult").FacetValue, unknown, any>>;
84
+ StoreFacet: Record<string, Resolver<import("./clients/search/types/FacetSearchResult").Facet<import("./clients/search/types/FacetSearchResult").FacetValueBoolean | import("./clients/search/types/FacetSearchResult").FacetValueRange>, unknown, any>>;
85
+ StoreFacetBoolean: Record<string, Resolver<import("./clients/search/types/FacetSearchResult").Facet<import("./clients/search/types/FacetSearchResult").FacetValueBoolean>, unknown, any>>;
86
+ StoreFacetRange: Record<string, Resolver<import("./clients/search/types/FacetSearchResult").Facet<import("./clients/search/types/FacetSearchResult").FacetValueRange>, unknown, any>>;
87
+ StoreFacetValueBoolean: Record<string, Resolver<import("./clients/search/types/FacetSearchResult").FacetValueBoolean, unknown, any>>;
84
88
  StoreOffer: Record<string, Resolver<import("./utils/enhanceCommercialOffer").EnhancedCommercialOffer<import("./clients/search/types/ProductSearchResult").Seller, import("./clients/search/types/ProductSearchResult").Item & {
85
89
  isVariantOf: import("./clients/search/types/ProductSearchResult").Product;
86
90
  } & {
@@ -95,7 +99,7 @@ export declare const getResolvers: (_: Options) => {
95
99
  } & {
96
100
  attachmentsValues?: import("./clients/commerce/types/OrderForm").Attachment[] | undefined;
97
101
  }, unknown, any>>;
98
- StoreSearchResult: Record<string, Resolver<Pick<import("./clients/search").SearchArgs, "hideUnavailableItems" | "query" | "page" | "count" | "sort" | "selectedFacets" | "fuzzy">, unknown, any>>;
102
+ StoreSearchResult: Record<string, Resolver<Pick<SearchArgs, "hideUnavailableItems" | "query" | "page" | "count" | "sort" | "selectedFacets" | "fuzzy">, unknown, any>>;
99
103
  StorePropertyValue: Record<string, Resolver<import("../..").IStorePropertyValue, unknown, any>>;
100
104
  ObjectOrString: import("graphql").GraphQLScalarType;
101
105
  Query: {
@@ -0,0 +1,3 @@
1
+ import type { Resolver } from '..';
2
+ import type { FacetValueBoolean } from '../clients/search/types/FacetSearchResult';
3
+ export declare const StoreFacetValueBoolean: Record<string, Resolver<FacetValueBoolean>>;
@@ -1,5 +1,7 @@
1
+ import type { FacetValueBoolean, Facet, FacetValueRange } from '../clients/search/types/FacetSearchResult';
1
2
  import type { Resolver } from '..';
2
- import type { Facet } from '../clients/search/types/FacetSearchResult';
3
3
  declare type Root = Facet;
4
4
  export declare const StoreFacet: Record<string, Resolver<Root>>;
5
+ export declare const StoreFacetBoolean: Record<string, Resolver<Facet<FacetValueBoolean>>>;
6
+ export declare const StoreFacetRange: Record<string, Resolver<Facet<FacetValueRange>>>;
5
7
  export {};
@@ -13,6 +13,7 @@ export declare const transformSelectedFacet: ({ key, value }: SelectedFacet) =>
13
13
  key: string;
14
14
  value: string;
15
15
  };
16
+ export declare const parseRange: (range: string) => [number, number] | null;
16
17
  export declare const findSlug: (facets?: SelectedFacet[] | null | undefined) => string | null;
17
18
  export declare const findSkuId: (facets?: SelectedFacet[] | null | undefined) => string | null;
18
19
  export declare const findLocale: (facets?: SelectedFacet[] | null | undefined) => string | null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faststore/api",
3
- "version": "1.9.7",
3
+ "version": "1.9.11",
4
4
  "license": "MIT",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -17,6 +17,7 @@
17
17
  "develop": "tsdx watch --entry ./local/server.ts --target node --onSuccess \"node ./dist\"",
18
18
  "develop:no-server": "concurrently \"yarn generate -w\" \"tsdx watch\"",
19
19
  "build": "graphql-codegen --config codegen.yml && tsdx build",
20
+ "lint": "eslint src/**/*.ts",
20
21
  "test": "tsdx test",
21
22
  "generate": "graphql-codegen --config codegen.yml"
22
23
  },
@@ -44,5 +45,5 @@
44
45
  "peerDependencies": {
45
46
  "graphql": "^15.6.0"
46
47
  },
47
- "gitHead": "a0c8cbd82dc0d83b4ca9f186fd974e09a2bbd768"
48
+ "gitHead": "78e4520e4588669f0f3382ccd441737b98c57d11"
48
49
  }
@@ -19,9 +19,9 @@ export type IStoreCart = {
19
19
  };
20
20
 
21
21
  export type IStoreCurrency = {
22
- /** Currency code, e.g: USD */
22
+ /** Currency code (e.g: USD). */
23
23
  code: Scalars['String'];
24
- /** Currency symbol, e.g: $ */
24
+ /** Currency symbol (e.g: $). */
25
25
  symbol: Scalars['String'];
26
26
  };
27
27
 
@@ -47,7 +47,7 @@ export type IStoreOffer = {
47
47
  seller: IStoreOrganization;
48
48
  };
49
49
 
50
- /** Offer input. */
50
+ /** Order input. */
51
51
  export type IStoreOrder = {
52
52
  /** Array with information on each accepted offer. */
53
53
  acceptedOffer: Array<IStoreOffer>;
@@ -96,9 +96,11 @@ export type IStorePropertyValue = {
96
96
  valueReference: Scalars['String'];
97
97
  };
98
98
 
99
- /** Selected facet input. */
99
+ /** Selected search facet input. */
100
100
  export type IStoreSelectedFacet = {
101
+ /** Selected search facet key. */
101
102
  key: Scalars['String'];
103
+ /** Selected search facet value. */
102
104
  value: Scalars['String'];
103
105
  };
104
106
 
@@ -120,9 +122,9 @@ export type IStoreSession = {
120
122
 
121
123
  export type Mutation = {
122
124
  __typename?: 'Mutation';
123
- /** Returns the order if anything has changed in it, or `null` if the order is valid. */
125
+ /** Checks for changes between the cart presented in the UI and the cart stored in the ecommerce platform. If changes are detected, it returns the cart stored on the platform. Otherwise, it returns `null`. */
124
126
  validateCart?: Maybe<StoreCart>;
125
- /** Validate session information. */
127
+ /** Updates a web session with the specified values. */
126
128
  validateSession?: Maybe<StoreSession>;
127
129
  };
128
130
 
@@ -139,15 +141,15 @@ export type MutationValidateSessionArgs = {
139
141
 
140
142
  export type Query = {
141
143
  __typename?: 'Query';
142
- /** All collections query. */
144
+ /** Returns information about all collections. */
143
145
  allCollections: StoreCollectionConnection;
144
- /** All products query. */
146
+ /** Returns information about all products. */
145
147
  allProducts: StoreProductConnection;
146
- /** Collection query. */
148
+ /** Returns the details of a collection based on the collection slug. */
147
149
  collection: StoreCollection;
148
- /** Product query. */
150
+ /** Returns the details of a product based on the specified locator. */
149
151
  product: StoreProduct;
150
- /** Search query. */
152
+ /** Returns the result of a product, facet, or suggestion search. */
151
153
  search: StoreSearchResult;
152
154
  };
153
155
 
@@ -241,7 +243,7 @@ export type StoreCart = {
241
243
  /** Shopping cart message. */
242
244
  export type StoreCartMessage = {
243
245
  __typename?: 'StoreCartMessage';
244
- /** Shopping cart message status, which can be `INFO`, `WARNING` OR `ERROR`. */
246
+ /** Shopping cart message status, which can be `INFO`, `WARNING` or `ERROR`. */
245
247
  status: StoreStatus;
246
248
  /** Shopping cart message text. */
247
249
  text: Scalars['String'];
@@ -264,21 +266,21 @@ export type StoreCollection = {
264
266
  type: StoreCollectionType;
265
267
  };
266
268
 
267
- /** Collection connection pagination information. */
269
+ /** Collection connections, including pagination information and collections returned by the query. */
268
270
  export type StoreCollectionConnection = {
269
271
  __typename?: 'StoreCollectionConnection';
270
- /** Array with collection connection page edges. */
272
+ /** Array with collection connection page edges, each containing a collection and a corresponding cursor.. */
271
273
  edges: Array<StoreCollectionEdge>;
272
- /** Collection connection page information. */
274
+ /** Collection pagination information. */
273
275
  pageInfo: StorePageInfo;
274
276
  };
275
277
 
276
- /** Collection pagination edge. */
278
+ /** Each collection edge contains a `node`, with product collection information, and a `cursor`, that can be used as a reference for pagination. */
277
279
  export type StoreCollectionEdge = {
278
280
  __typename?: 'StoreCollectionEdge';
279
- /** Collection pagination cursor. */
281
+ /** Collection cursor. Used as pagination reference. */
280
282
  cursor: Scalars['String'];
281
- /** Collection pagination node. */
283
+ /** Each collection node contains the information of a product collection returned by the query. */
282
284
  node: StoreCollection;
283
285
  };
284
286
 
@@ -300,43 +302,61 @@ export type StoreCollectionMeta = {
300
302
 
301
303
  /** Product collection type. Possible values are `Department`, `Category`, `Brand` or `Cluster`. */
302
304
  export const enum StoreCollectionType {
305
+ /** Product brand. */
303
306
  Brand = 'Brand',
307
+ /** Second level of product categorization. */
304
308
  Category = 'Category',
309
+ /** Product cluster. */
305
310
  Cluster = 'Cluster',
311
+ /** First level of product categorization. */
306
312
  Department = 'Department'
307
313
  };
308
314
 
309
315
  /** Currency information. */
310
316
  export type StoreCurrency = {
311
317
  __typename?: 'StoreCurrency';
312
- /** Currency code, e.g: USD */
318
+ /** Currency code (e.g: USD). */
313
319
  code: Scalars['String'];
314
- /** Currency symbol, e.g: $ */
320
+ /** Currency symbol (e.g: $). */
315
321
  symbol: Scalars['String'];
316
322
  };
317
323
 
318
- /** Search facet information. */
319
- export type StoreFacet = {
320
- __typename?: 'StoreFacet';
324
+ export type StoreFacet = StoreFacetBoolean | StoreFacetRange;
325
+
326
+ /** Search facet boolean information. */
327
+ export type StoreFacetBoolean = {
328
+ __typename?: 'StoreFacetBoolean';
329
+ /** Facet key. */
330
+ key: Scalars['String'];
331
+ /** Facet label. */
332
+ label: Scalars['String'];
333
+ /** Array with information on each facet value. */
334
+ values: Array<StoreFacetValueBoolean>;
335
+ };
336
+
337
+ /** Search facet range information. */
338
+ export type StoreFacetRange = {
339
+ __typename?: 'StoreFacetRange';
321
340
  /** Facet key. */
322
341
  key: Scalars['String'];
323
342
  /** Facet label. */
324
343
  label: Scalars['String'];
325
- /** Facet type. Possible values are `BOOLEAN` and `RANGE`. */
326
- type: StoreFacetType;
344
+ max: StoreFacetValueRange;
327
345
  /** Array with information on each facet value. */
328
- values: Array<StoreFacetValue>;
346
+ min: StoreFacetValueRange;
329
347
  };
330
348
 
331
349
  /** Search facet type. */
332
350
  export const enum StoreFacetType {
351
+ /** Indicates boolean search facet. */
333
352
  Boolean = 'BOOLEAN',
353
+ /** Indicates range type search facet. */
334
354
  Range = 'RANGE'
335
355
  };
336
356
 
337
357
  /** Information of a specific facet value. */
338
- export type StoreFacetValue = {
339
- __typename?: 'StoreFacetValue';
358
+ export type StoreFacetValueBoolean = {
359
+ __typename?: 'StoreFacetValueBoolean';
340
360
  /** Facet value label. */
341
361
  label: Scalars['String'];
342
362
  /** Number of items with this facet. */
@@ -347,6 +367,12 @@ export type StoreFacetValue = {
347
367
  value: Scalars['String'];
348
368
  };
349
369
 
370
+ export type StoreFacetValueRange = {
371
+ __typename?: 'StoreFacetValueRange';
372
+ absolute: Scalars['Float'];
373
+ selected: Scalars['Float'];
374
+ };
375
+
350
376
  /** Image. */
351
377
  export type StoreImage = {
352
378
  __typename?: 'StoreImage';
@@ -408,16 +434,16 @@ export type StoreOrganization = {
408
434
  identifier: Scalars['String'];
409
435
  };
410
436
 
411
- /** Page information. */
437
+ /** Whenever you make a query that allows for pagination, such as `allProducts` or `allCollections`, you can check `StorePageInfo` to learn more about the complete set of items and use it to paginate your queries. */
412
438
  export type StorePageInfo = {
413
439
  __typename?: 'StorePageInfo';
414
- /** Page cursor end. */
440
+ /** Cursor corresponding to the last possible item. */
415
441
  endCursor: Scalars['String'];
416
- /** Indicates whether next page exists. */
442
+ /** Indicates whether there is at least one more page with items after the ones returned in the current query. */
417
443
  hasNextPage: Scalars['Boolean'];
418
- /** Indicates whether previous page exists. */
444
+ /** Indicates whether there is at least one more page with items before the ones returned in the current query. */
419
445
  hasPreviousPage: Scalars['Boolean'];
420
- /** Page cursor start. */
446
+ /** Cursor corresponding to the first possible item. */
421
447
  startCursor: Scalars['String'];
422
448
  /** Total number of items (products or collections), not pages. */
423
449
  totalCount: Scalars['Int'];
@@ -471,21 +497,21 @@ export type StoreProduct = {
471
497
  slug: Scalars['String'];
472
498
  };
473
499
 
474
- /** Product connection pagination information. */
500
+ /** Product connections, including pagination information and products returned by the query. */
475
501
  export type StoreProductConnection = {
476
502
  __typename?: 'StoreProductConnection';
477
- /** Array with product connection page edges. */
503
+ /** Array with product connection edges, each containing a product and a corresponding cursor. */
478
504
  edges: Array<StoreProductEdge>;
479
- /** Product connection page information. */
505
+ /** Product pagination information. */
480
506
  pageInfo: StorePageInfo;
481
507
  };
482
508
 
483
- /** Product pagination edge. */
509
+ /** Each product edge contains a `node`, with product information, and a `cursor`, that can be used as a reference for pagination. */
484
510
  export type StoreProductEdge = {
485
511
  __typename?: 'StoreProductEdge';
486
- /** Product pagination cursor. */
512
+ /** Product cursor. Used as pagination reference. */
487
513
  cursor: Scalars['String'];
488
- /** Product pagination node. */
514
+ /** Each product node contains the information of a product returned by the query. */
489
515
  node: StoreProduct;
490
516
  };
491
517
 
@@ -574,19 +600,27 @@ export type StoreSession = {
574
600
  postalCode?: Maybe<Scalars['String']>;
575
601
  };
576
602
 
577
- /** Product sorting options used in search. */
603
+ /** Product search results sorting options. */
578
604
  export const enum StoreSort {
605
+ /** Sort by discount value, from highest to lowest. */
579
606
  DiscountDesc = 'discount_desc',
607
+ /** Sort by name, in alphabetical order. */
580
608
  NameAsc = 'name_asc',
609
+ /** Sort by name, in reverse alphabetical order. */
581
610
  NameDesc = 'name_desc',
611
+ /** Sort by orders, from highest to lowest. */
582
612
  OrdersDesc = 'orders_desc',
613
+ /** Sort by price, from lowest to highest. */
583
614
  PriceAsc = 'price_asc',
615
+ /** Sort by price, from highest to lowest. */
584
616
  PriceDesc = 'price_desc',
617
+ /** Sort by release date, from highest to lowest. */
585
618
  ReleaseDesc = 'release_desc',
619
+ /** Sort by product score, from highest to lowest. */
586
620
  ScoreDesc = 'score_desc'
587
621
  };
588
622
 
589
- /** Status used to indicate type of message. For instance, in shopping cart messages. */
623
+ /** Status used to indicate a message type. For instance, a shopping cart informative or error message. */
590
624
  export const enum StoreStatus {
591
625
  Error = 'ERROR',
592
626
  Info = 'INFO',
@@ -2,7 +2,11 @@ import { fetchAPI } from '../fetch'
2
2
  import type { IStoreSelectedFacet } from '../../../../__generated__/schema'
3
3
  import type { Context, Options } from '../../index'
4
4
  import type { SelectedFacet } from '../../utils/facets'
5
- import type { FacetSearchResult } from './types/FacetSearchResult'
5
+ import type {
6
+ Facet,
7
+ FacetValueBoolean,
8
+ FacetSearchResult,
9
+ } from './types/FacetSearchResult'
6
10
  import type {
7
11
  ProductSearchResult,
8
12
  Suggestion,
@@ -38,6 +42,10 @@ const POLICY_KEY = 'trade-policy'
38
42
  const REGION_KEY = 'region-id'
39
43
  const CHANNEL_KEYS = new Set([POLICY_KEY, REGION_KEY])
40
44
 
45
+ export const isFacetBoolean = (
46
+ facet: Facet
47
+ ): facet is Facet<FacetValueBoolean> => facet.type === 'TEXT'
48
+
41
49
  export const IntelligentSearch = (
42
50
  { account, environment, hideUnavailableItems }: Options,
43
51
  ctx: Context
@@ -4,27 +4,28 @@ export interface FacetSearchResult {
4
4
  breadcrumb: Breadcrumb
5
5
  }
6
6
 
7
- export interface Facet {
7
+ export interface Facet<T = FacetValueBoolean | FacetValueRange> {
8
8
  type: FilterType
9
9
  name: string
10
10
  hidden: boolean
11
- values: FacetValue[]
11
+ values: T[]
12
12
  quantity?: number
13
- key?: string
13
+ key: string
14
14
  }
15
15
 
16
- export interface FacetValue {
16
+ export interface FacetValueBoolean {
17
17
  quantity: number
18
18
  name: string
19
19
  key: string
20
20
  value: string
21
- selected?: boolean
22
- range?: {
21
+ selected: boolean
22
+ }
23
+
24
+ export interface FacetValueRange {
25
+ range: {
23
26
  from: number
24
27
  to: number
25
28
  }
26
- children?: FacetValue[]
27
- id?: string
28
29
  }
29
30
 
30
31
  interface Breadcrumb {
@@ -1,24 +1,29 @@
1
1
  import { getClients } from './clients'
2
+ import type { SearchArgs } from './clients/search'
2
3
  import { getLoaders } from './loaders'
3
4
  import { StoreAggregateOffer } from './resolvers/aggregateOffer'
4
5
  import { StoreAggregateRating } from './resolvers/aggregateRating'
5
6
  import { StoreCollection } from './resolvers/collection'
6
- import { StoreFacet } from './resolvers/facet'
7
- import { StoreFacetValue } from './resolvers/facetValue'
7
+ import {
8
+ StoreFacet,
9
+ StoreFacetBoolean,
10
+ StoreFacetRange,
11
+ } from './resolvers/facet'
12
+ import { StoreFacetValueBoolean } from './resolvers/faceValue'
8
13
  import { Mutation } from './resolvers/mutation'
14
+ import { ObjectOrString } from './resolvers/objectOrString'
9
15
  import { StoreOffer } from './resolvers/offer'
10
16
  import { StoreProduct } from './resolvers/product'
11
17
  import { StoreProductGroup } from './resolvers/productGroup'
18
+ import { StorePropertyValue } from './resolvers/propertyValue'
12
19
  import { Query } from './resolvers/query'
13
20
  import { StoreReview } from './resolvers/review'
14
21
  import { StoreSearchResult } from './resolvers/searchResult'
15
22
  import { StoreSeo } from './resolvers/seo'
16
- import { ObjectOrString } from './resolvers/objectOrString'
17
- import { StorePropertyValue } from './resolvers/propertyValue'
23
+ import ChannelMarshal from './utils/channel'
18
24
  import type { Loaders } from './loaders'
19
25
  import type { Clients } from './clients'
20
26
  import type { Channel } from './utils/channel'
21
- import ChannelMarshal from './utils/channel'
22
27
 
23
28
  export interface Options {
24
29
  platform: 'vtex'
@@ -48,6 +53,7 @@ export interface Context {
48
53
  channel: Required<Channel>
49
54
  locale: string
50
55
  flags: FeatureFlags
56
+ searchArgs?: Omit<SearchArgs, 'type'>
51
57
  }
52
58
  headers: Record<string, string>
53
59
  }
@@ -65,7 +71,9 @@ const Resolvers = {
65
71
  StoreProduct,
66
72
  StoreSeo,
67
73
  StoreFacet,
68
- StoreFacetValue,
74
+ StoreFacetBoolean,
75
+ StoreFacetRange,
76
+ StoreFacetValueBoolean,
69
77
  StoreOffer,
70
78
  StoreAggregateRating,
71
79
  StoreReview,
@@ -77,16 +85,18 @@ const Resolvers = {
77
85
  Mutation,
78
86
  }
79
87
 
80
- export const getContextFactory = (options: Options) => (ctx: any): Context => {
81
- ctx.storage = {
82
- channel: ChannelMarshal.parse(options.channel),
83
- flags: options.flags ?? {},
84
- locale: options.locale,
85
- }
86
- ctx.clients = getClients(options, ctx)
87
- ctx.loaders = getLoaders(options, ctx)
88
+ export const getContextFactory =
89
+ (options: Options) =>
90
+ (ctx: any): Context => {
91
+ ctx.storage = {
92
+ channel: ChannelMarshal.parse(options.channel),
93
+ flags: options.flags ?? {},
94
+ locale: options.locale,
95
+ }
96
+ ctx.clients = getClients(options, ctx)
97
+ ctx.loaders = getLoaders(options, ctx)
88
98
 
89
- return ctx
90
- }
99
+ return ctx
100
+ }
91
101
 
92
102
  export const getResolvers = (_: Options) => Resolvers
@@ -0,0 +1,12 @@
1
+ import type { Resolver } from '..'
2
+ import type { FacetValueBoolean } from '../clients/search/types/FacetSearchResult'
3
+
4
+ export const StoreFacetValueBoolean: Record<
5
+ string,
6
+ Resolver<FacetValueBoolean>
7
+ > = {
8
+ value: ({ value }) => value,
9
+ label: ({ name }) => name || 'unknown',
10
+ selected: ({ selected }) => selected,
11
+ quantity: ({ quantity }) => quantity,
12
+ }
@@ -1,11 +1,72 @@
1
+ import { parseRange } from '../utils/facets'
2
+ import { min } from '../utils/orderStatistics'
3
+ import type {
4
+ FacetValueBoolean,
5
+ Facet,
6
+ FacetValueRange,
7
+ } from '../clients/search/types/FacetSearchResult'
1
8
  import type { Resolver } from '..'
2
- import type { Facet } from '../clients/search/types/FacetSearchResult'
3
9
 
4
10
  type Root = Facet
5
11
 
6
12
  export const StoreFacet: Record<string, Resolver<Root>> = {
7
- key: ({ key }) => key ?? '',
8
- label: ({ name }) => name ?? 'unknown',
9
- values: ({ values }) => values,
10
- type: ({ type }) => (type === 'TEXT' ? 'BOOLEAN' : 'RANGE'),
13
+ __resolveType: ({ type }) =>
14
+ type === 'TEXT' ? 'StoreFacetBoolean' : 'StoreFacetRange',
15
+ }
16
+
17
+ export const StoreFacetBoolean: Record<
18
+ string,
19
+ Resolver<Facet<FacetValueBoolean>>
20
+ > = {
21
+ key: ({ key }) => key,
22
+ label: ({ name }) => name,
23
+ values: ({ values }) => values.sort((a, b) => a.name.localeCompare(b.name)),
24
+ }
25
+
26
+ export const StoreFacetRange: Record<
27
+ string,
28
+ Resolver<Facet<FacetValueRange>>
29
+ > = {
30
+ key: ({ key }) => key,
31
+ label: ({ name }) => name,
32
+ min: ({ values, key }, _, { storage: { searchArgs } }) => {
33
+ /**
34
+ * Fetch the selected range the user queried.
35
+ *
36
+ * This is necessary because, differently from boolean facets, Search API does
37
+ * not return the selected values, making us have to implement it in here
38
+ */
39
+ const selectedRange = parseRange(
40
+ searchArgs?.selectedFacets?.find((facet) => facet.key === key)?.value ??
41
+ ''
42
+ )
43
+
44
+ const facet = min(values, (a, b) => a.range.from - b.range.from)
45
+ const globalMin = facet?.range.from ?? 0
46
+
47
+ return {
48
+ selected: selectedRange?.[0] ?? globalMin,
49
+ absolute: globalMin,
50
+ }
51
+ },
52
+ max: ({ values, key }, _, { storage: { searchArgs } }) => {
53
+ /**
54
+ * Fetch the selected range the user queried.
55
+ *
56
+ * This is necessary because, differently from boolean facets, Search API does
57
+ * not return the selected values, making us have to implement it in here
58
+ */
59
+ const selectedRange = parseRange(
60
+ searchArgs?.selectedFacets?.find((facet) => facet.key === key)?.value ??
61
+ ''
62
+ )
63
+
64
+ const facet = min(values, (a, b) => b.range.to - a.range.to)
65
+ const globalMax = facet?.range.to ?? 0
66
+
67
+ return {
68
+ selected: selectedRange?.[1] ?? globalMax,
69
+ absolute: globalMax,
70
+ }
71
+ },
11
72
  }