@faststore/core 2.1.84 → 2.2.0-alpha.0

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 (211) hide show
  1. package/.turbo/turbo-build.log +9 -7
  2. package/.turbo/turbo-test.log +25 -0
  3. package/@generated/graphql/index.ts +183 -79
  4. package/@generated/graphql/persisted.json +5 -5
  5. package/@generated/graphql/schema.graphql +1053 -0
  6. package/api/index.ts +15 -0
  7. package/cms/faststore/sections.json +2 -32
  8. package/codegen.yml +2 -1
  9. package/generate.sh +71 -0
  10. package/index.ts +15 -0
  11. package/jest.config.js +6 -0
  12. package/package.json +33 -18
  13. package/src/components/ThirdPartyScripts/ThirdPartyScripts.tsx +1 -2
  14. package/src/components/cms/RenderSections.tsx +4 -5
  15. package/src/components/navigation/Navbar/Navbar.tsx +4 -3
  16. package/src/components/navigation/NavbarSlider/NavbarSlider.tsx +5 -4
  17. package/src/components/product/ProductGrid/ProductGrid.tsx +4 -3
  18. package/src/components/sections/Breadcrumb/Breadcrumb.tsx +17 -22
  19. package/src/components/sections/CrossSellingShelf/CrossSellingShelf.tsx +8 -6
  20. package/src/components/sections/Footer/Footer.tsx +2 -14
  21. package/src/components/sections/Navbar/Navbar.tsx +0 -4
  22. package/src/components/sections/ProductDetails/ProductDetails.tsx +23 -33
  23. package/src/components/sections/ProductGallery/ProductGallery.tsx +15 -26
  24. package/src/components/sections/ProductShelf/ProductShelf.tsx +1 -1
  25. package/src/components/sections/ProductTiles/ProductTiles.tsx +4 -3
  26. package/src/components/templates/ProductListingPage/ProductListing.tsx +95 -0
  27. package/src/components/templates/ProductListingPage/ProductListingPage.tsx +34 -68
  28. package/src/components/templates/SearchPage/SearchPage.tsx +81 -0
  29. package/src/components/templates/SearchPage/index.ts +2 -0
  30. package/src/components/ui/ProductGallery/ProductGallery.tsx +24 -16
  31. package/src/components/ui/ProductGallery/ProductGalleryPage.tsx +8 -7
  32. package/src/components/ui/ProductGallery/useDelayedFacets.ts +3 -3
  33. package/src/components/ui/ProductShelf/ProductShelf.tsx +3 -2
  34. package/src/customizations/GlobalOverrides.tsx +0 -2
  35. package/src/customizations/fragments/ClientProduct.ts +9 -0
  36. package/src/customizations/fragments/ClientProductGallery.ts +19 -0
  37. package/src/customizations/fragments/ClientProducts.ts +19 -0
  38. package/src/customizations/fragments/ServerCollectionPage.ts +9 -0
  39. package/src/customizations/fragments/ServerProductPage.ts +9 -0
  40. package/src/customizations/graphql/thirdParty/resolvers/index.ts +3 -0
  41. package/src/customizations/graphql/vtex/resolvers/index.ts +3 -0
  42. package/src/pages/[...slug].tsx +5 -3
  43. package/src/pages/[slug]/p.tsx +38 -18
  44. package/src/pages/s.tsx +22 -34
  45. package/src/sdk/graphql/useQuery.ts +17 -13
  46. package/src/sdk/overrides/PageProvider.tsx +78 -0
  47. package/src/sdk/product/useLocalizedVariables.ts +33 -0
  48. package/src/sdk/product/usePageProductsQuery.ts +139 -0
  49. package/src/{components/sections/ProductGallery/useGalleryQuery.ts → sdk/product/useProductGalleryQuery.ts} +12 -13
  50. package/src/sdk/product/{useProduct.ts → useProductQuery.ts} +10 -7
  51. package/src/sdk/product/useProductsPrefetch.ts +72 -0
  52. package/src/sdk/product/useProductsQuery.ts +17 -63
  53. package/src/server/generator/generateGraphQLSchemaFile.ts +3 -0
  54. package/src/server/generator/schema.ts +82 -0
  55. package/src/server/index.ts +34 -21
  56. package/src/server/options.ts +16 -0
  57. package/test/server/index.test.ts +146 -0
  58. package/.next/BUILD_ID +0 -1
  59. package/.next/build-manifest.json +0 -129
  60. package/.next/cache/.tsbuildinfo +0 -1
  61. package/.next/cache/config.json +0 -7
  62. package/.next/cache/eslint/.cache_1gneedd +0 -1
  63. package/.next/cache/next-server.js.nft.json +0 -1
  64. package/.next/cache/webpack/client-production/0.pack +0 -0
  65. package/.next/cache/webpack/client-production/index.pack +0 -0
  66. package/.next/cache/webpack/server-production/0.pack +0 -0
  67. package/.next/cache/webpack/server-production/index.pack +0 -0
  68. package/.next/export-marker.json +0 -1
  69. package/.next/images-manifest.json +0 -1
  70. package/.next/next-server.js.nft.json +0 -1
  71. package/.next/package.json +0 -1
  72. package/.next/prerender-manifest.json +0 -1
  73. package/.next/react-loadable-manifest.json +0 -44
  74. package/.next/required-server-files.json +0 -1
  75. package/.next/routes-manifest.json +0 -1
  76. package/.next/server/chunks/143.js +0 -106
  77. package/.next/server/chunks/177.js +0 -120
  78. package/.next/server/chunks/183.js +0 -94
  79. package/.next/server/chunks/184.js +0 -61
  80. package/.next/server/chunks/186.js +0 -113
  81. package/.next/server/chunks/289.js +0 -239
  82. package/.next/server/chunks/312.js +0 -697
  83. package/.next/server/chunks/350.js +0 -143
  84. package/.next/server/chunks/483.js +0 -650
  85. package/.next/server/chunks/487.js +0 -9142
  86. package/.next/server/chunks/53.js +0 -61
  87. package/.next/server/chunks/530.js +0 -626
  88. package/.next/server/chunks/576.js +0 -94
  89. package/.next/server/chunks/650.js +0 -9142
  90. package/.next/server/chunks/676.js +0 -32
  91. package/.next/server/chunks/693.js +0 -58
  92. package/.next/server/chunks/71.js +0 -1254
  93. package/.next/server/chunks/74.js +0 -4065
  94. package/.next/server/chunks/753.js +0 -509
  95. package/.next/server/chunks/779.js +0 -58
  96. package/.next/server/chunks/825.js +0 -4039
  97. package/.next/server/chunks/854.js +0 -72
  98. package/.next/server/chunks/859.js +0 -959
  99. package/.next/server/chunks/907.js +0 -1911
  100. package/.next/server/chunks/933.js +0 -517
  101. package/.next/server/chunks/98.js +0 -124
  102. package/.next/server/chunks/988.js +0 -211
  103. package/.next/server/chunks/font-manifest.json +0 -1
  104. package/.next/server/font-manifest.json +0 -1
  105. package/.next/server/middleware-build-manifest.js +0 -1
  106. package/.next/server/middleware-manifest.json +0 -6
  107. package/.next/server/middleware-react-loadable-manifest.js +0 -1
  108. package/.next/server/pages/404.js +0 -386
  109. package/.next/server/pages/404.js.nft.json +0 -1
  110. package/.next/server/pages/500.js +0 -388
  111. package/.next/server/pages/500.js.nft.json +0 -1
  112. package/.next/server/pages/[...slug].js +0 -1005
  113. package/.next/server/pages/[...slug].js.nft.json +0 -1
  114. package/.next/server/pages/[slug]/p.js +0 -2269
  115. package/.next/server/pages/[slug]/p.js.nft.json +0 -1
  116. package/.next/server/pages/_app.js +0 -280
  117. package/.next/server/pages/_app.js.nft.json +0 -1
  118. package/.next/server/pages/_document.js +0 -374
  119. package/.next/server/pages/_document.js.nft.json +0 -1
  120. package/.next/server/pages/_error.js +0 -164
  121. package/.next/server/pages/_error.js.nft.json +0 -1
  122. package/.next/server/pages/account.js +0 -363
  123. package/.next/server/pages/account.js.nft.json +0 -1
  124. package/.next/server/pages/api/graphql.js +0 -365
  125. package/.next/server/pages/api/graphql.js.nft.json +0 -1
  126. package/.next/server/pages/api/health/live.js +0 -31
  127. package/.next/server/pages/api/health/live.js.nft.json +0 -1
  128. package/.next/server/pages/api/health/ready.js +0 -31
  129. package/.next/server/pages/api/health/ready.js.nft.json +0 -1
  130. package/.next/server/pages/api/preview.js +0 -148
  131. package/.next/server/pages/api/preview.js.nft.json +0 -1
  132. package/.next/server/pages/checkout.js +0 -363
  133. package/.next/server/pages/checkout.js.nft.json +0 -1
  134. package/.next/server/pages/en-US/404.html +0 -81
  135. package/.next/server/pages/en-US/404.json +0 -1
  136. package/.next/server/pages/en-US/500.html +0 -81
  137. package/.next/server/pages/en-US/500.json +0 -1
  138. package/.next/server/pages/en-US/account.html +0 -81
  139. package/.next/server/pages/en-US/account.json +0 -1
  140. package/.next/server/pages/en-US/checkout.html +0 -81
  141. package/.next/server/pages/en-US/checkout.json +0 -1
  142. package/.next/server/pages/en-US/login.html +0 -81
  143. package/.next/server/pages/en-US/login.json +0 -1
  144. package/.next/server/pages/en-US/s.html +0 -81
  145. package/.next/server/pages/en-US/s.json +0 -1
  146. package/.next/server/pages/en-US.html +0 -81
  147. package/.next/server/pages/en-US.json +0 -1
  148. package/.next/server/pages/index.js +0 -439
  149. package/.next/server/pages/index.js.nft.json +0 -1
  150. package/.next/server/pages/login.js +0 -368
  151. package/.next/server/pages/login.js.nft.json +0 -1
  152. package/.next/server/pages/s.js +0 -466
  153. package/.next/server/pages/s.js.nft.json +0 -1
  154. package/.next/server/pages-manifest.json +0 -18
  155. package/.next/server/webpack-api-runtime.js +0 -229
  156. package/.next/server/webpack-runtime.js +0 -229
  157. package/.next/static/UFCNzAvjHLcTNmP8sQK5l/_buildManifest.js +0 -1
  158. package/.next/static/UFCNzAvjHLcTNmP8sQK5l/_ssgManifest.js +0 -1
  159. package/.next/static/chunks/143.dd8a556e6957baa1.js +0 -1
  160. package/.next/static/chunks/148.582eaa81293ee470.js +0 -1
  161. package/.next/static/chunks/238-39630714f5d70169.js +0 -1
  162. package/.next/static/chunks/243-b4f8e506d156ee41.js +0 -1
  163. package/.next/static/chunks/530.ec68de379130c11e.js +0 -1
  164. package/.next/static/chunks/548-4ee971bf7bdb3e81.js +0 -1
  165. package/.next/static/chunks/603-072c8fb73ac35775.js +0 -1
  166. package/.next/static/chunks/651.7142f31ce1e052b3.js +0 -1
  167. package/.next/static/chunks/709.7bc5a25ce30abda6.js +0 -1
  168. package/.next/static/chunks/738-a5ff304828f20cbf.js +0 -1
  169. package/.next/static/chunks/741.52f7fb873418346f.js +0 -1
  170. package/.next/static/chunks/98.97381d2021f86cd9.js +0 -1
  171. package/.next/static/chunks/988.afda042dd9ba11d1.js +0 -1
  172. package/.next/static/chunks/framework-dfd14d7ce6600b03.js +0 -1
  173. package/.next/static/chunks/main-fd466221927468fd.js +0 -1
  174. package/.next/static/chunks/pages/404-af78f7cd1d3c1f60.js +0 -1
  175. package/.next/static/chunks/pages/500-f6346ca5f9dc4fef.js +0 -1
  176. package/.next/static/chunks/pages/[...slug]-3f4e5f74ff9436ec.js +0 -1
  177. package/.next/static/chunks/pages/[slug]/p-8e20c206fb84d184.js +0 -1
  178. package/.next/static/chunks/pages/_app-895781b1c7b5bf56.js +0 -1
  179. package/.next/static/chunks/pages/_error-a7a0c1d9bfbb4f38.js +0 -1
  180. package/.next/static/chunks/pages/account-05bd79fb78365e88.js +0 -1
  181. package/.next/static/chunks/pages/checkout-c973786e68f25a39.js +0 -1
  182. package/.next/static/chunks/pages/index-73110361a184aa10.js +0 -1
  183. package/.next/static/chunks/pages/login-8deb9243376b6aa1.js +0 -1
  184. package/.next/static/chunks/pages/s-94691e1fdc9521a4.js +0 -1
  185. package/.next/static/chunks/polyfills-c67a75d1b6f99dc8.js +0 -1
  186. package/.next/static/chunks/webpack-504557a0a7373460.js +0 -1
  187. package/.next/static/css/20e4a3a45cdd65f4.css +0 -1
  188. package/.next/static/css/4b7138899cd07c63.css +0 -1
  189. package/.next/static/css/527e334fa69cf40a.css +0 -1
  190. package/.next/static/css/6e1a7434f061d0ef.css +0 -1
  191. package/.next/static/css/9e76fef1c9ca89af.css +0 -1
  192. package/.next/static/css/a2eefb25a4608343.css +0 -1
  193. package/.next/static/css/cb7d1fcea42fab9c.css +0 -1
  194. package/.next/static/css/df588bb98c0b0ca6.css +0 -1
  195. package/.next/static/css/e3b039e8f5daf95f.css +0 -1
  196. package/.next/static/css/f0e2d1b8832e935d.css +0 -1
  197. package/.next/trace +0 -80
  198. package/public/~partytown/debug/partytown-atomics.js +0 -556
  199. package/public/~partytown/debug/partytown-media.js +0 -374
  200. package/public/~partytown/debug/partytown-sandbox-sw.js +0 -543
  201. package/public/~partytown/debug/partytown-sw.js +0 -59
  202. package/public/~partytown/debug/partytown-ww-atomics.js +0 -1789
  203. package/public/~partytown/debug/partytown-ww-sw.js +0 -1781
  204. package/public/~partytown/debug/partytown.js +0 -72
  205. package/public/~partytown/partytown-atomics.js +0 -2
  206. package/public/~partytown/partytown-media.js +0 -2
  207. package/public/~partytown/partytown-sw.js +0 -2
  208. package/public/~partytown/partytown.js +0 -2
  209. package/src/components/ui/ProductGallery/usePageProducts.ts +0 -48
  210. package/src/customizations/components/overrides/ThirdPartyScripts.tsx +0 -9
  211. package/src/customizations/scripts/ThirdPartyScripts.tsx +0 -8
@@ -0,0 +1,72 @@
1
+ import { gql } from '@faststore/graphql-utils'
2
+ import { useSearch } from '@faststore/sdk'
3
+ import { ClientProductsQueryQueryVariables } from '@generated/graphql'
4
+ import { useEffect, useCallback } from 'react'
5
+ import type { QueryOptions } from '../graphql/useQuery'
6
+ import { useSWRConfig } from 'swr'
7
+ import { prefetchQuery } from '../graphql/prefetchQuery'
8
+ import { useLocalizedVariables } from './useLocalizedVariables'
9
+
10
+ export const query = gql`
11
+ query ClientProductsQuery(
12
+ $first: Int!
13
+ $after: String
14
+ $sort: StoreSort!
15
+ $term: String!
16
+ $selectedFacets: [IStoreSelectedFacet!]!
17
+ ) {
18
+ ...ClientProducts
19
+ search(
20
+ first: $first
21
+ after: $after
22
+ sort: $sort
23
+ term: $term
24
+ selectedFacets: $selectedFacets
25
+ ) {
26
+ products {
27
+ pageInfo {
28
+ totalCount
29
+ }
30
+ edges {
31
+ node {
32
+ ...ProductSummary_product
33
+ }
34
+ }
35
+ }
36
+ }
37
+ }
38
+ `
39
+
40
+ export const useProductsQueryPrefetch = (
41
+ variables: ClientProductsQueryQueryVariables,
42
+ options?: QueryOptions
43
+ ) => {
44
+ const localizedVariables = useLocalizedVariables(variables)
45
+ const { cache } = useSWRConfig()
46
+
47
+ return useCallback(
48
+ () => prefetchQuery(query, localizedVariables, { cache, ...options }),
49
+ [localizedVariables, cache, options]
50
+ )
51
+ }
52
+
53
+ export const useProductsPrefetch = (page: number | null) => {
54
+ const {
55
+ itemsPerPage,
56
+ state: { sort, term, selectedFacets },
57
+ } = useSearch()
58
+
59
+ const prefetch = useProductsQueryPrefetch({
60
+ first: itemsPerPage,
61
+ after: (itemsPerPage * (page ?? 0)).toString(),
62
+ sort,
63
+ term: term ?? '',
64
+ selectedFacets,
65
+ })
66
+
67
+ useEffect(() => {
68
+ if (page !== null) {
69
+ prefetch()
70
+ }
71
+ }, [page, prefetch])
72
+ }
@@ -1,26 +1,23 @@
1
1
  import { gql } from '@faststore/graphql-utils'
2
- import { useCallback, useMemo } from 'react'
3
- import { useSWRConfig } from 'swr'
4
2
 
5
- import { ITEMS_PER_SECTION } from 'src/constants'
6
3
  import type {
7
- ProductsQueryQuery,
8
- ProductsQueryQueryVariables,
4
+ ClientProductsQueryQuery,
5
+ ClientProductsQueryQueryVariables,
9
6
  } from '@generated/graphql'
10
7
 
11
- import { prefetchQuery } from '../graphql/prefetchQuery'
12
- import { useQuery } from '../graphql/useQuery'
13
- import { useSession } from '../session'
14
8
  import type { QueryOptions } from '../graphql/useQuery'
9
+ import { useQuery } from '../graphql/useQuery'
10
+ import { useLocalizedVariables } from './useLocalizedVariables'
15
11
 
16
12
  export const query = gql`
17
- query ProductsQuery(
13
+ query ClientProductsQuery(
18
14
  $first: Int!
19
15
  $after: String
20
16
  $sort: StoreSort!
21
17
  $term: String!
22
18
  $selectedFacets: [IStoreSelectedFacet!]!
23
19
  ) {
20
+ ...ClientProducts
24
21
  search(
25
22
  first: $first
26
23
  after: $after
@@ -42,66 +39,23 @@ export const query = gql`
42
39
  }
43
40
  `
44
41
 
45
- const toArray = <T>(x: T[] | T | undefined) =>
46
- Array.isArray(x) ? x : x ? [x] : []
47
-
48
- export const useLocalizedVariables = ({
49
- first,
50
- after,
51
- sort,
52
- term,
53
- selectedFacets,
54
- }: Partial<ProductsQueryQueryVariables>) => {
55
- const { channel, locale } = useSession()
56
-
57
- return useMemo(() => {
58
- const facets = toArray(selectedFacets)
59
-
60
- return {
61
- first: first ?? ITEMS_PER_SECTION,
62
- after: after ?? '0',
63
- sort: sort ?? ('score_desc' as const),
64
- term: term ?? '',
65
- selectedFacets: [
66
- ...facets,
67
- { key: 'channel', value: channel ?? '' },
68
- { key: 'locale', value: locale },
69
- ],
70
- }
71
- }, [selectedFacets, first, after, sort, term, channel, locale])
72
- }
73
-
74
42
  /**
75
- * Use this hook for fetching a list of products, like in search results and shelves
43
+ * Use this hook for fetching a list of products, like shelves and tiles
76
44
  */
77
45
  export const useProductsQuery = (
78
- variables: Partial<ProductsQueryQueryVariables>,
46
+ variables: Partial<ClientProductsQueryQueryVariables>,
79
47
  options?: QueryOptions
80
48
  ) => {
81
49
  const localizedVariables = useLocalizedVariables(variables)
82
50
 
83
- const { data } = useQuery<ProductsQueryQuery, ProductsQueryQueryVariables>(
84
- query,
85
- localizedVariables,
86
- {
87
- fallbackData: null,
88
- suspense: true,
89
- ...options,
90
- }
91
- )
92
-
93
- return data?.search?.products
94
- }
95
-
96
- export const useProductsQueryPrefetch = (
97
- variables: ProductsQueryQueryVariables,
98
- options?: QueryOptions
99
- ) => {
100
- const localizedVariables = useLocalizedVariables(variables)
101
- const { cache } = useSWRConfig()
51
+ const { data } = useQuery<
52
+ ClientProductsQueryQuery,
53
+ ClientProductsQueryQueryVariables
54
+ >(query, localizedVariables, {
55
+ fallbackData: null,
56
+ suspense: true,
57
+ ...options,
58
+ })
102
59
 
103
- return useCallback(
104
- () => prefetchQuery(query, localizedVariables, { cache, ...options }),
105
- [localizedVariables, cache, options]
106
- )
60
+ return data
107
61
  }
@@ -0,0 +1,3 @@
1
+ import { writeGraphqlSchemaFile, getMergedSchema } from './schema'
2
+
3
+ writeGraphqlSchemaFile(getMergedSchema())
@@ -0,0 +1,82 @@
1
+ import { writeFileSync } from 'fs-extra'
2
+ import { getSchema, getTypeDefs } from '@faststore/api'
3
+ import { printSchemaWithDirectives } from '@graphql-tools/utils'
4
+ import { loadFilesSync } from '@graphql-tools/load-files'
5
+ import { mergeTypeDefs } from '@graphql-tools/merge'
6
+ import { buildASTSchema } from 'graphql'
7
+ import type { GraphQLSchema } from 'graphql'
8
+ import type { TypeSource } from '@graphql-tools/utils'
9
+
10
+ import { apiOptions } from '../options'
11
+
12
+ export function getTypeDefsFromFolder(
13
+ customPath: string | string[]
14
+ ): TypeSource {
15
+ const basePath = ['src', 'customizations', 'graphql']
16
+
17
+ const pathArray = Array.isArray(customPath) ? customPath : [customPath]
18
+
19
+ return (
20
+ loadFilesSync([...basePath, ...pathArray, 'typeDefs'], {
21
+ extensions: ['graphql'],
22
+ }) ??
23
+ loadFilesSync([...basePath, ...pathArray, 'typedefs'], {
24
+ extensions: ['graphql'],
25
+ })
26
+ )
27
+ }
28
+
29
+ export function getCustomSchema(typeDefs: TypeSource[]) {
30
+ try {
31
+ const mergedTypeDefs = mergeTypeDefs(typeDefs)
32
+
33
+ const schema = buildASTSchema(mergedTypeDefs)
34
+
35
+ return schema
36
+ } catch (e) {
37
+ console.error(
38
+ 'An error occurred while attempting to merge the GraphQL Schema Extensions. Check the custom typeDefs and resolvers located in the "customizations/graphql/" directory. The changes since the last successful schema merge will be ignored.'
39
+ )
40
+
41
+ throw e
42
+ }
43
+ }
44
+
45
+ export function getNativeTypeDefs() {
46
+ return getTypeDefs() as TypeSource
47
+ }
48
+
49
+ export function getVTEXExtensionsTypeDefs() {
50
+ return getTypeDefsFromFolder('vtex')
51
+ }
52
+
53
+ export function getThirdPartyExtensionsTypeDefs() {
54
+ return getTypeDefsFromFolder('thirdParty')
55
+ }
56
+
57
+ export const nativeApiSchema = getSchema(apiOptions)
58
+
59
+ // Schema with no resolvers - used to generate schema.graphql file
60
+ export const getMergedSchema = (): GraphQLSchema =>
61
+ getCustomSchema(
62
+ [
63
+ getNativeTypeDefs(),
64
+ getVTEXExtensionsTypeDefs(),
65
+ getThirdPartyExtensionsTypeDefs(),
66
+ ].filter(Boolean)
67
+ )
68
+
69
+ export function writeGraphqlSchemaFile(apiSchema: GraphQLSchema) {
70
+ try {
71
+ writeFileSync(
72
+ [process.cwd(), '@generated', 'graphql', 'schema.graphql'].join('/'),
73
+ printSchemaWithDirectives(apiSchema)
74
+ )
75
+
76
+ console.log('Schema GraphQL file generated successfully')
77
+ } catch (e) {
78
+ console.error('An error occurred while generating the GraphQL schema file')
79
+
80
+ throw e
81
+ }
82
+ }
@@ -1,20 +1,32 @@
1
1
  /* eslint-disable react-hooks/rules-of-hooks */
2
+ import path from 'path'
2
3
  import type { FormatErrorHandler } from '@envelop/core'
3
4
  import {
4
5
  envelop,
5
- useAsyncSchema,
6
+ useSchema,
6
7
  useExtendContext,
7
8
  useMaskedErrors,
8
9
  } from '@envelop/core'
9
10
  import { useGraphQlJit } from '@envelop/graphql-jit'
10
11
  import { useParserCache } from '@envelop/parser-cache'
11
12
  import { useValidationCache } from '@envelop/validation-cache'
12
- import { getContextFactory, getSchema, isFastStoreError } from '@faststore/api'
13
+ import type { CacheControl, Maybe } from '@faststore/api'
14
+ import {
15
+ getContextFactory,
16
+ getResolvers,
17
+ isFastStoreError,
18
+ } from '@faststore/api'
13
19
  import { GraphQLError } from 'graphql'
14
- import type { Maybe, Options as APIOptions, CacheControl } from '@faststore/api'
20
+ import { makeExecutableSchema } from '@graphql-tools/schema'
21
+ import { loadFilesSync } from '@graphql-tools/load-files'
22
+ import type { TypeSource } from '@graphql-tools/utils'
15
23
 
16
24
  import persisted from '../../@generated/graphql/persisted.json'
17
- import storeConfig from '../../faststore.config'
25
+
26
+ import vtexExtensionsResolvers from '../customizations/graphql/vtex/resolvers'
27
+ import thirdPartyResolvers from '../customizations/graphql/thirdParty/resolvers'
28
+
29
+ import { apiOptions } from './options'
18
30
 
19
31
  interface ExecuteOptions<V = Record<string, unknown>> {
20
32
  operationName: string
@@ -24,21 +36,6 @@ interface ExecuteOptions<V = Record<string, unknown>> {
24
36
 
25
37
  const persistedQueries = new Map(Object.entries(persisted))
26
38
 
27
- const apiOptions: APIOptions = {
28
- platform: storeConfig.platform as APIOptions['platform'],
29
- account: storeConfig.api.storeId,
30
- environment: storeConfig.api.environment as APIOptions['environment'],
31
- hideUnavailableItems: storeConfig.api.hideUnavailableItems,
32
- incrementAddress: storeConfig.api.incrementAddress,
33
- channel: storeConfig.session.channel,
34
- locale: storeConfig.session.locale,
35
- flags: {
36
- enableOrderFormSync: true,
37
- },
38
- }
39
-
40
- export const apiSchema = getSchema(apiOptions)
41
-
42
39
  const apiContextFactory = getContextFactory(apiOptions)
43
40
 
44
41
  const formatError: FormatErrorHandler = (err) => {
@@ -51,10 +48,26 @@ const formatError: FormatErrorHandler = (err) => {
51
48
  return new GraphQLError('Sorry, something went wrong.')
52
49
  }
53
50
 
54
- const getEnvelop = async () =>
51
+ function loadGeneratedSchema(): TypeSource {
52
+ return loadFilesSync(path.join(process.cwd(), '@generated', 'graphql'), {
53
+ extensions: ['graphql'],
54
+ })
55
+ }
56
+
57
+ function getFinalAPISchema() {
58
+ const generatedSchema = loadGeneratedSchema()
59
+ const nativeResolvers = getResolvers(apiOptions)
60
+
61
+ return makeExecutableSchema({
62
+ typeDefs: generatedSchema,
63
+ resolvers: [nativeResolvers, vtexExtensionsResolvers, thirdPartyResolvers],
64
+ })
65
+ }
66
+
67
+ export const getEnvelop = async () =>
55
68
  envelop({
56
69
  plugins: [
57
- useAsyncSchema(apiSchema),
70
+ useSchema(getFinalAPISchema()),
58
71
  useExtendContext(apiContextFactory),
59
72
  useMaskedErrors({ formatError }),
60
73
  useGraphQlJit(),
@@ -0,0 +1,16 @@
1
+ import type { Options as APIOptions } from '@faststore/api'
2
+
3
+ import storeConfig from '../../faststore.config'
4
+
5
+ export const apiOptions: APIOptions = {
6
+ platform: storeConfig.platform as APIOptions['platform'],
7
+ account: storeConfig.api.storeId,
8
+ environment: storeConfig.api.environment as APIOptions['environment'],
9
+ hideUnavailableItems: storeConfig.api.hideUnavailableItems,
10
+ incrementAddress: storeConfig.api.incrementAddress,
11
+ channel: storeConfig.session.channel,
12
+ locale: storeConfig.session.locale,
13
+ flags: {
14
+ enableOrderFormSync: true,
15
+ },
16
+ }
@@ -0,0 +1,146 @@
1
+ import { assertValidSchema } from 'graphql'
2
+
3
+ import { execute, getEnvelop } from '../../src/server'
4
+ import {
5
+ getTypeDefsFromFolder,
6
+ getMergedSchema,
7
+ } from '../../src/server/generator/schema'
8
+ import storeConfig from '../../faststore.config'
9
+
10
+ const TYPES = [
11
+ 'StoreAggregateOffer',
12
+ 'StoreAggregateRating',
13
+ 'StoreAuthor',
14
+ 'StoreBrand',
15
+ 'StoreListItem',
16
+ 'StoreBreadcrumbList',
17
+ 'StoreCartMessage',
18
+ 'StoreCart',
19
+ 'IStoreCart',
20
+ 'StoreCollectionType',
21
+ 'StoreCollectionFacet',
22
+ 'StoreCollectionMeta',
23
+ 'StoreCollection',
24
+ 'StoreFacet',
25
+ 'StoreFacetRange',
26
+ 'StoreFacetBoolean',
27
+ 'StoreFacetValueRange',
28
+ 'StoreFacetValueBoolean',
29
+ 'StoreImage',
30
+ 'IStoreImage',
31
+ 'StoreOffer',
32
+ 'IStoreOffer',
33
+ 'StoreOrder',
34
+ 'IStoreOrder',
35
+ 'StoreOrganization',
36
+ 'IStoreOrganization',
37
+ 'StorePageInfo',
38
+ 'StoreProduct',
39
+ 'IStoreProduct',
40
+ 'StoreProductGroup',
41
+ 'StorePropertyValue',
42
+ 'StoreProductEdge',
43
+ 'StoreProductConnection',
44
+ 'StoreCollectionEdge',
45
+ 'StoreCollectionConnection',
46
+ 'StoreSort',
47
+ 'IStoreSelectedFacet',
48
+ 'StoreSearchResult',
49
+ 'StoreReviewRating',
50
+ 'StoreReview',
51
+ 'StoreSeo',
52
+ 'StoreStatus',
53
+ 'IShippingItem',
54
+ 'ShippingData',
55
+ 'LogisticsItem',
56
+ 'LogisticsInfo',
57
+ 'ShippingSLA',
58
+ 'DeliveryIds',
59
+ 'PickupStoreInfo',
60
+ 'PickupAddress',
61
+ 'MessageInfo',
62
+ 'MessageFields',
63
+ ]
64
+
65
+ const QUERIES = [
66
+ 'product',
67
+ 'collection',
68
+ 'search',
69
+ 'allProducts',
70
+ 'allCollections',
71
+ 'shipping',
72
+ 'redirect',
73
+ 'sellers',
74
+ ]
75
+
76
+ const MUTATIONS = ['validateCart', 'validateSession', 'subscribeToNewsletter']
77
+
78
+ describe('FastStore GraphQL Layer', () => {
79
+ describe('@faststore/api', () => {
80
+ const nativeSchema = getMergedSchema()
81
+
82
+ it('should return a valid GraphQL schema', async () => {
83
+ // `assertValidSchema()` will throw an error if the schema is invalid, and
84
+ // return nothing if it is valid. That's why we're checking for `undefined`.
85
+ expect(assertValidSchema(nativeSchema)).toBeUndefined()
86
+ })
87
+
88
+ it('should return a valid GraphQL schema contain all expected types', async () => {
89
+ TYPES.forEach((typeName) => {
90
+ expect(nativeSchema.getType(typeName)).toBeDefined()
91
+ })
92
+ })
93
+
94
+ it('should return a valid GraphQL schema contain all expected queries', async () => {
95
+ const queryFields = nativeSchema.getQueryType()?.getFields() ?? {}
96
+
97
+ expect(Object.keys(queryFields)).toEqual(QUERIES)
98
+ })
99
+
100
+ it('should return a valid GraphQL schema contain all expected mutations', async () => {
101
+ const mutationFields = nativeSchema.getMutationType()?.getFields() ?? {}
102
+
103
+ expect(Object.keys(mutationFields)).toEqual(MUTATIONS)
104
+ })
105
+ })
106
+
107
+ describe('VTEX API Extension', () => {
108
+ it('getTypeDefsFromFolder function should return an Array', () => {
109
+ const typeDefs = getTypeDefsFromFolder('vtex')
110
+ expect(typeDefs).toBeInstanceOf(Array)
111
+ })
112
+ })
113
+
114
+ describe('Third Party API Extension', () => {
115
+ it('getTypeDefsFromFolder function should return an Array', () => {
116
+ const typeDefs = getTypeDefsFromFolder('thirdParty')
117
+ expect(typeDefs).toBeInstanceOf(Array)
118
+ })
119
+ })
120
+
121
+ describe('Final Schema after merging', () => {
122
+ it('should return a valid merged GraphQL schema', async () => {
123
+ const schema = getMergedSchema()
124
+
125
+ // `assertValidSchema()` will throw an error if the schema is invalid, and
126
+ // return nothing if it is valid. That's why we're checking for `undefined`.
127
+ expect(assertValidSchema(schema)).toBeUndefined()
128
+ })
129
+ })
130
+
131
+ describe('Envelop', () => {
132
+ it('should exist with its plugins', async () => {
133
+ const envelop = await getEnvelop()
134
+ expect(envelop).toBeDefined()
135
+ expect(envelop._plugins).toHaveLength(6)
136
+ })
137
+
138
+ it('should handle options and execute', async () => {
139
+ const result = await execute({
140
+ variables: { slug: storeConfig.cypress.pages.collection.slice(1) },
141
+ operationName: 'ServerCollectionPageQuery',
142
+ })
143
+ expect(result.data).toBeDefined()
144
+ })
145
+ })
146
+ })
package/.next/BUILD_ID DELETED
@@ -1 +0,0 @@
1
- UFCNzAvjHLcTNmP8sQK5l
@@ -1,129 +0,0 @@
1
- {
2
- "polyfillFiles": [
3
- "static/chunks/polyfills-c67a75d1b6f99dc8.js"
4
- ],
5
- "devFiles": [],
6
- "ampDevFiles": [],
7
- "lowPriorityFiles": [
8
- "static/UFCNzAvjHLcTNmP8sQK5l/_buildManifest.js",
9
- "static/UFCNzAvjHLcTNmP8sQK5l/_ssgManifest.js"
10
- ],
11
- "rootMainFiles": [],
12
- "pages": {
13
- "/": [
14
- "static/chunks/webpack-504557a0a7373460.js",
15
- "static/chunks/framework-dfd14d7ce6600b03.js",
16
- "static/chunks/main-fd466221927468fd.js",
17
- "static/chunks/738-a5ff304828f20cbf.js",
18
- "static/chunks/548-4ee971bf7bdb3e81.js",
19
- "static/css/e3b039e8f5daf95f.css",
20
- "static/chunks/243-b4f8e506d156ee41.js",
21
- "static/css/20e4a3a45cdd65f4.css",
22
- "static/chunks/238-39630714f5d70169.js",
23
- "static/css/a2eefb25a4608343.css",
24
- "static/chunks/pages/index-73110361a184aa10.js"
25
- ],
26
- "/404": [
27
- "static/chunks/webpack-504557a0a7373460.js",
28
- "static/chunks/framework-dfd14d7ce6600b03.js",
29
- "static/chunks/main-fd466221927468fd.js",
30
- "static/chunks/738-a5ff304828f20cbf.js",
31
- "static/css/e3b039e8f5daf95f.css",
32
- "static/chunks/243-b4f8e506d156ee41.js",
33
- "static/css/df588bb98c0b0ca6.css",
34
- "static/chunks/pages/404-af78f7cd1d3c1f60.js"
35
- ],
36
- "/500": [
37
- "static/chunks/webpack-504557a0a7373460.js",
38
- "static/chunks/framework-dfd14d7ce6600b03.js",
39
- "static/chunks/main-fd466221927468fd.js",
40
- "static/chunks/738-a5ff304828f20cbf.js",
41
- "static/css/e3b039e8f5daf95f.css",
42
- "static/chunks/243-b4f8e506d156ee41.js",
43
- "static/css/df588bb98c0b0ca6.css",
44
- "static/chunks/pages/500-f6346ca5f9dc4fef.js"
45
- ],
46
- "/[...slug]": [
47
- "static/chunks/webpack-504557a0a7373460.js",
48
- "static/chunks/framework-dfd14d7ce6600b03.js",
49
- "static/chunks/main-fd466221927468fd.js",
50
- "static/chunks/738-a5ff304828f20cbf.js",
51
- "static/chunks/548-4ee971bf7bdb3e81.js",
52
- "static/css/e3b039e8f5daf95f.css",
53
- "static/chunks/243-b4f8e506d156ee41.js",
54
- "static/css/20e4a3a45cdd65f4.css",
55
- "static/chunks/238-39630714f5d70169.js",
56
- "static/css/f0e2d1b8832e935d.css",
57
- "static/chunks/603-072c8fb73ac35775.js",
58
- "static/css/a2eefb25a4608343.css",
59
- "static/css/527e334fa69cf40a.css",
60
- "static/chunks/pages/[...slug]-3f4e5f74ff9436ec.js"
61
- ],
62
- "/[slug]/p": [
63
- "static/chunks/webpack-504557a0a7373460.js",
64
- "static/chunks/framework-dfd14d7ce6600b03.js",
65
- "static/chunks/main-fd466221927468fd.js",
66
- "static/chunks/738-a5ff304828f20cbf.js",
67
- "static/chunks/548-4ee971bf7bdb3e81.js",
68
- "static/css/e3b039e8f5daf95f.css",
69
- "static/chunks/243-b4f8e506d156ee41.js",
70
- "static/css/20e4a3a45cdd65f4.css",
71
- "static/chunks/238-39630714f5d70169.js",
72
- "static/css/4b7138899cd07c63.css",
73
- "static/chunks/pages/[slug]/p-8e20c206fb84d184.js"
74
- ],
75
- "/_app": [
76
- "static/chunks/webpack-504557a0a7373460.js",
77
- "static/chunks/framework-dfd14d7ce6600b03.js",
78
- "static/chunks/main-fd466221927468fd.js",
79
- "static/css/9e76fef1c9ca89af.css",
80
- "static/chunks/pages/_app-895781b1c7b5bf56.js"
81
- ],
82
- "/_error": [
83
- "static/chunks/webpack-504557a0a7373460.js",
84
- "static/chunks/framework-dfd14d7ce6600b03.js",
85
- "static/chunks/main-fd466221927468fd.js",
86
- "static/chunks/pages/_error-a7a0c1d9bfbb4f38.js"
87
- ],
88
- "/account": [
89
- "static/chunks/webpack-504557a0a7373460.js",
90
- "static/chunks/framework-dfd14d7ce6600b03.js",
91
- "static/chunks/main-fd466221927468fd.js",
92
- "static/chunks/738-a5ff304828f20cbf.js",
93
- "static/css/e3b039e8f5daf95f.css",
94
- "static/chunks/243-b4f8e506d156ee41.js",
95
- "static/chunks/pages/account-05bd79fb78365e88.js"
96
- ],
97
- "/checkout": [
98
- "static/chunks/webpack-504557a0a7373460.js",
99
- "static/chunks/framework-dfd14d7ce6600b03.js",
100
- "static/chunks/main-fd466221927468fd.js",
101
- "static/chunks/738-a5ff304828f20cbf.js",
102
- "static/css/e3b039e8f5daf95f.css",
103
- "static/chunks/243-b4f8e506d156ee41.js",
104
- "static/chunks/pages/checkout-c973786e68f25a39.js"
105
- ],
106
- "/login": [
107
- "static/chunks/webpack-504557a0a7373460.js",
108
- "static/chunks/framework-dfd14d7ce6600b03.js",
109
- "static/chunks/main-fd466221927468fd.js",
110
- "static/chunks/738-a5ff304828f20cbf.js",
111
- "static/css/e3b039e8f5daf95f.css",
112
- "static/chunks/243-b4f8e506d156ee41.js",
113
- "static/css/df588bb98c0b0ca6.css",
114
- "static/chunks/pages/login-8deb9243376b6aa1.js"
115
- ],
116
- "/s": [
117
- "static/chunks/webpack-504557a0a7373460.js",
118
- "static/chunks/framework-dfd14d7ce6600b03.js",
119
- "static/chunks/main-fd466221927468fd.js",
120
- "static/chunks/738-a5ff304828f20cbf.js",
121
- "static/css/e3b039e8f5daf95f.css",
122
- "static/chunks/243-b4f8e506d156ee41.js",
123
- "static/css/f0e2d1b8832e935d.css",
124
- "static/chunks/603-072c8fb73ac35775.js",
125
- "static/chunks/pages/s-94691e1fdc9521a4.js"
126
- ]
127
- },
128
- "ampFirstPages": []
129
- }