From 8fc54664dafdfa6458345e432a53164854a05233 Mon Sep 17 00:00:00 2001 From: Michal Miszczyszyn Date: Tue, 2 May 2023 11:15:45 +0200 Subject: [PATCH] Static content done --- .graphqlrc.yml | 3 + lib/saleor/editorjs.ts | 78 + lib/saleor/generated/gql.ts | 68 +- lib/saleor/generated/graphql.ts | 1915 +++++------------ lib/saleor/generated/index.ts | 1 - lib/saleor/index.ts | 193 +- lib/saleor/queries/GetCategoryBySlug.graphql | 10 + .../queries/GetCategoryProductsBySlug.graphql | 54 + lib/saleor/queries/GetMenuBySlug.graphql | 31 +- lib/saleor/queries/GetPages.graphql | 15 + lib/saleor/queries/GetProductBySlug.graphql | 2 +- package.json | 2 - pnpm-lock.yaml | 8 +- 13 files changed, 944 insertions(+), 1436 deletions(-) create mode 100644 lib/saleor/editorjs.ts create mode 100644 lib/saleor/queries/GetCategoryBySlug.graphql create mode 100644 lib/saleor/queries/GetCategoryProductsBySlug.graphql create mode 100644 lib/saleor/queries/GetPages.graphql diff --git a/.graphqlrc.yml b/.graphqlrc.yml index 55bca518f..4b94faa59 100644 --- a/.graphqlrc.yml +++ b/.graphqlrc.yml @@ -4,11 +4,14 @@ documents: 'lib/**/*.graphql' generates: lib/saleor/generated/: preset: 'client' + presetConfig: + fragmentMasking: false config: defaultScalarType: 'unknown' useTypeImports: true dedupeFragments: true skipTypename: true + documentMode: 'string' scalars: _Any: 'unknown' Date: 'string' diff --git a/lib/saleor/editorjs.ts b/lib/saleor/editorjs.ts new file mode 100644 index 000000000..82c7dc948 --- /dev/null +++ b/lib/saleor/editorjs.ts @@ -0,0 +1,78 @@ +import { invariant } from './utils'; + +type EditorJsHeaderBlock = { + type: 'header'; + data: { text: string; level: 1 | 2 | 3 | 4 | 5 | 6 }; +}; +type EditorJsParagraphBlock = { type: 'paragraph'; data: { text: string } }; +type EditorJsListBlock = { + type: 'list'; + data: { style: 'unordered' | 'ordered'; items: string[] }; +}; + +type EditorJsBlockCommon = { id: string }; +type EditorJsBlocks = EditorJsHeaderBlock | EditorJsParagraphBlock | EditorJsListBlock; + +type EditorJsBlock = EditorJsBlocks & EditorJsBlockCommon; + +interface EditorJsResponse { + blocks: readonly EditorJsBlock[]; + time: number; + version: string; +} + +const parseEditorJson = (content: string): EditorJsResponse | null => { + try { + const data: EditorJsResponse = JSON.parse(content); + // manually validate it has more or less proper shape + invariant(data && 'blocks' in data, `Invalid shape`); + invariant(Array.isArray(data.blocks), `Invalid shape`); + invariant( + data.blocks.every((item) => 'type' in item && 'data' in item), + `Invalid shape` + ); + return data; + } catch (err) { + console.error(err); + return null; + } +}; + +export const parseEditorJsToHtml = (content: string) => { + const data = parseEditorJson(content); + if (!data) { + return ''; + } + + const html = data.blocks + .map((block) => { + switch (block.type) { + case 'header': + return header(block.data); + case 'list': + return list(block.data); + case 'paragraph': + return paragraph(block.data); + default: + console.warn(`Unknown block type: ${JSON.stringify(block)}`); + return ''; + } + }) + .join(''); + + return html; +}; + +function list(data: EditorJsListBlock['data']): string { + const el = data.style === 'ordered' ? 'ul' : 'ol'; + const items = data.items.map((item) => `
  • ${item}
  • `).join(''); + return `<${el}>${items}`; +} + +function paragraph({ text }: EditorJsParagraphBlock['data']): string { + return `

    ${text}

    `; +} + +function header({ level, text }: EditorJsHeaderBlock['data']): string { + return `${text}`; +} diff --git a/lib/saleor/generated/gql.ts b/lib/saleor/generated/gql.ts index ccbf4b8b4..4b5658c95 100644 --- a/lib/saleor/generated/gql.ts +++ b/lib/saleor/generated/gql.ts @@ -1,6 +1,5 @@ /* eslint-disable */ import * as types from './graphql'; -import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; /** * Map of all GraphQL operations in the project. @@ -15,6 +14,10 @@ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document- const documents = { 'fragment FeaturedProduct on Product {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n}': types.FeaturedProductFragmentDoc, + 'query GetCategoryBySlug($slug: String!) {\n category(slug: $slug) {\n id\n name\n slug\n description\n seoTitle\n seoDescription\n }\n}': + types.GetCategoryBySlugDocument, + 'query GetCategoryProductsBySlug($slug: String!) {\n category(slug: $slug) {\n products(channel: "default-channel", first: 100) {\n edges {\n node {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n }\n }\n }\n }\n}': + types.GetCategoryProductsBySlugDocument, 'query GetCollectionBySlug($slug: String!) {\n collection(channel: "default-channel", slug: $slug) {\n id\n name\n slug\n description\n seoTitle\n seoDescription\n }\n}': types.GetCollectionBySlugDocument, 'query GetCollectionProductsBySlug($slug: String!) {\n collection(channel: "default-channel", slug: $slug) {\n products(first: 100) {\n edges {\n node {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n }\n }\n }\n }\n}': @@ -23,11 +26,13 @@ const documents = { types.GetCollectionsDocument, 'query GetFeaturedProducts($first: Int!) {\n products(first: $first, channel: "default-channel") {\n edges {\n node {\n ...FeaturedProduct\n }\n }\n }\n}': types.GetFeaturedProductsDocument, - 'query GetMenuBySlug($slug: String!) {\n menu(slug: $slug, channel: "default-channel") {\n id\n slug\n name\n items {\n id\n name\n url\n collection {\n slug\n }\n children {\n id\n collection {\n slug\n }\n }\n }\n }\n}': - types.GetMenuBySlugDocument, + 'fragment MenuItem on MenuItem {\n id\n name\n url\n collection {\n slug\n }\n category {\n slug\n }\n page {\n slug\n }\n}\n\nquery GetMenuBySlug($slug: String!) {\n menu(slug: $slug, channel: "default-channel") {\n id\n slug\n name\n items {\n ...MenuItem\n children {\n ...MenuItem\n children {\n ...MenuItem\n children {\n ...MenuItem\n }\n }\n }\n }\n }\n}': + types.MenuItemFragmentDoc, 'query GetPageBySlug($slug: String!) {\n page(slug: $slug) {\n id\n title\n slug\n content\n seoTitle\n seoDescription\n created\n }\n}': types.GetPageBySlugDocument, - 'query GetProductBySlug($slug: String!) {\n product(slug: $slug) {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n }\n}': + 'query GetPages {\n pages(first: 10) {\n edges {\n node {\n id\n title\n slug\n content\n seoTitle\n seoDescription\n created\n }\n }\n }\n}': + types.GetPagesDocument, + 'query GetProductBySlug($slug: String!) {\n product(channel: "default-channel", slug: $slug) {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n }\n}': types.GetProductBySlugDocument, 'query SearchProducts($search: String!, $sortBy: ProductOrderField!, $sortDirection: OrderDirection!) {\n products(\n first: 100\n channel: "default-channel"\n sortBy: {field: $sortBy, direction: $sortDirection}\n filter: {search: $search}\n ) {\n edges {\n node {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n }\n }\n }\n}': types.SearchProductsDocument, @@ -37,82 +42,83 @@ const documents = { /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. - * - * - * @example - * ```ts - * const query = graphql(`query GetUser($id: ID!) { user(id: $id) { name } }`); - * ``` - * - * The query argument is unknown! - * Please regenerate the types. */ -export function graphql(source: string): unknown; - +export function graphql( + source: 'fragment FeaturedProduct on Product {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n}' +): typeof import('./graphql').FeaturedProductFragmentDoc; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: 'fragment FeaturedProduct on Product {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n}' -): (typeof documents)['fragment FeaturedProduct on Product {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n}']; + source: 'query GetCategoryBySlug($slug: String!) {\n category(slug: $slug) {\n id\n name\n slug\n description\n seoTitle\n seoDescription\n }\n}' +): typeof import('./graphql').GetCategoryBySlugDocument; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql( + source: 'query GetCategoryProductsBySlug($slug: String!) {\n category(slug: $slug) {\n products(channel: "default-channel", first: 100) {\n edges {\n node {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n }\n }\n }\n }\n}' +): typeof import('./graphql').GetCategoryProductsBySlugDocument; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( source: 'query GetCollectionBySlug($slug: String!) {\n collection(channel: "default-channel", slug: $slug) {\n id\n name\n slug\n description\n seoTitle\n seoDescription\n }\n}' -): (typeof documents)['query GetCollectionBySlug($slug: String!) {\n collection(channel: "default-channel", slug: $slug) {\n id\n name\n slug\n description\n seoTitle\n seoDescription\n }\n}']; +): typeof import('./graphql').GetCollectionBySlugDocument; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( source: 'query GetCollectionProductsBySlug($slug: String!) {\n collection(channel: "default-channel", slug: $slug) {\n products(first: 100) {\n edges {\n node {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n }\n }\n }\n }\n}' -): (typeof documents)['query GetCollectionProductsBySlug($slug: String!) {\n collection(channel: "default-channel", slug: $slug) {\n products(first: 100) {\n edges {\n node {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n }\n }\n }\n }\n}']; +): typeof import('./graphql').GetCollectionProductsBySlugDocument; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( source: 'query GetCollections {\n collections(channel: "default-channel", first: 100) {\n edges {\n node {\n id\n name\n slug\n description\n seoTitle\n seoDescription\n }\n }\n }\n}' -): (typeof documents)['query GetCollections {\n collections(channel: "default-channel", first: 100) {\n edges {\n node {\n id\n name\n slug\n description\n seoTitle\n seoDescription\n }\n }\n }\n}']; +): typeof import('./graphql').GetCollectionsDocument; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( source: 'query GetFeaturedProducts($first: Int!) {\n products(first: $first, channel: "default-channel") {\n edges {\n node {\n ...FeaturedProduct\n }\n }\n }\n}' -): (typeof documents)['query GetFeaturedProducts($first: Int!) {\n products(first: $first, channel: "default-channel") {\n edges {\n node {\n ...FeaturedProduct\n }\n }\n }\n}']; +): typeof import('./graphql').GetFeaturedProductsDocument; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: 'query GetMenuBySlug($slug: String!) {\n menu(slug: $slug, channel: "default-channel") {\n id\n slug\n name\n items {\n id\n name\n url\n collection {\n slug\n }\n children {\n id\n collection {\n slug\n }\n }\n }\n }\n}' -): (typeof documents)['query GetMenuBySlug($slug: String!) {\n menu(slug: $slug, channel: "default-channel") {\n id\n slug\n name\n items {\n id\n name\n url\n collection {\n slug\n }\n children {\n id\n collection {\n slug\n }\n }\n }\n }\n}']; + source: 'fragment MenuItem on MenuItem {\n id\n name\n url\n collection {\n slug\n }\n category {\n slug\n }\n page {\n slug\n }\n}\n\nquery GetMenuBySlug($slug: String!) {\n menu(slug: $slug, channel: "default-channel") {\n id\n slug\n name\n items {\n ...MenuItem\n children {\n ...MenuItem\n children {\n ...MenuItem\n children {\n ...MenuItem\n }\n }\n }\n }\n }\n}' +): typeof import('./graphql').MenuItemFragmentDoc; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( source: 'query GetPageBySlug($slug: String!) {\n page(slug: $slug) {\n id\n title\n slug\n content\n seoTitle\n seoDescription\n created\n }\n}' -): (typeof documents)['query GetPageBySlug($slug: String!) {\n page(slug: $slug) {\n id\n title\n slug\n content\n seoTitle\n seoDescription\n created\n }\n}']; +): typeof import('./graphql').GetPageBySlugDocument; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( - source: 'query GetProductBySlug($slug: String!) {\n product(slug: $slug) {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n }\n}' -): (typeof documents)['query GetProductBySlug($slug: String!) {\n product(slug: $slug) {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n }\n}']; + source: 'query GetPages {\n pages(first: 10) {\n edges {\n node {\n id\n title\n slug\n content\n seoTitle\n seoDescription\n created\n }\n }\n }\n}' +): typeof import('./graphql').GetPagesDocument; +/** + * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. + */ +export function graphql( + source: 'query GetProductBySlug($slug: String!) {\n product(channel: "default-channel", slug: $slug) {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n }\n}' +): typeof import('./graphql').GetProductBySlugDocument; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( source: 'query SearchProducts($search: String!, $sortBy: ProductOrderField!, $sortDirection: OrderDirection!) {\n products(\n first: 100\n channel: "default-channel"\n sortBy: {field: $sortBy, direction: $sortDirection}\n filter: {search: $search}\n ) {\n edges {\n node {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n }\n }\n }\n}' -): (typeof documents)['query SearchProducts($search: String!, $sortBy: ProductOrderField!, $sortDirection: OrderDirection!) {\n products(\n first: 100\n channel: "default-channel"\n sortBy: {field: $sortBy, direction: $sortDirection}\n filter: {search: $search}\n ) {\n edges {\n node {\n id\n slug\n name\n isAvailableForPurchase\n description\n seoTitle\n seoDescription\n pricing {\n priceRange {\n start {\n gross {\n currency\n amount\n }\n }\n stop {\n gross {\n currency\n amount\n }\n }\n }\n }\n media {\n url(size: 2160)\n type\n alt\n }\n collections {\n name\n }\n updatedAt\n variants {\n id\n name\n pricing {\n price {\n gross {\n currency\n amount\n }\n }\n }\n }\n }\n }\n }\n}']; +): typeof import('./graphql').SearchProductsDocument; /** * The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients. */ export function graphql( source: 'query GetProducts {\n products(first: 10, channel: "default-channel") {\n edges {\n node {\n name\n }\n }\n }\n}' -): (typeof documents)['query GetProducts {\n products(first: 10, channel: "default-channel") {\n edges {\n node {\n name\n }\n }\n }\n}']; +): typeof import('./graphql').GetProductsDocument; export function graphql(source: string) { return (documents as any)[source] ?? {}; } - -export type DocumentType> = - TDocumentNode extends DocumentNode ? TType : never; diff --git a/lib/saleor/generated/graphql.ts b/lib/saleor/generated/graphql.ts index 9545e57e2..a05d1c80b 100644 --- a/lib/saleor/generated/graphql.ts +++ b/lib/saleor/generated/graphql.ts @@ -1,5 +1,5 @@ /* eslint-disable */ -import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core'; +import type { DocumentTypeDecoration } from '@graphql-typed-document-node/core'; export type Maybe = T | null; export type InputMaybe = Maybe; export type Exact = { [K in keyof T]: T[K] }; @@ -24526,7 +24526,58 @@ export type FeaturedProductFragment = { name: string; pricing?: { price?: { gross: { currency: string; amount: number } } | null } | null; }> | null; -} & { ' $fragmentName'?: 'FeaturedProductFragment' }; +}; + +export type GetCategoryBySlugQueryVariables = Exact<{ + slug: Scalars['String']; +}>; + +export type GetCategoryBySlugQuery = { + category?: { + id: string; + name: string; + slug: string; + description?: string | null; + seoTitle?: string | null; + seoDescription?: string | null; + } | null; +}; + +export type GetCategoryProductsBySlugQueryVariables = Exact<{ + slug: Scalars['String']; +}>; + +export type GetCategoryProductsBySlugQuery = { + category?: { + products?: { + edges: Array<{ + node: { + id: string; + slug: string; + name: string; + isAvailableForPurchase?: boolean | null; + description?: string | null; + seoTitle?: string | null; + seoDescription?: string | null; + updatedAt: string; + pricing?: { + priceRange?: { + start?: { gross: { currency: string; amount: number } } | null; + stop?: { gross: { currency: string; amount: number } } | null; + } | null; + } | null; + media?: Array<{ url: string; type: ProductMediaType; alt: string }> | null; + collections?: Array<{ name: string }> | null; + variants?: Array<{ + id: string; + name: string; + pricing?: { price?: { gross: { currency: string; amount: number } } | null } | null; + }> | null; + }; + }>; + } | null; + } | null; +}; export type GetCollectionBySlugQueryVariables = Exact<{ slug: Scalars['String']; @@ -24603,11 +24654,42 @@ export type GetFeaturedProductsQueryVariables = Exact<{ export type GetFeaturedProductsQuery = { products?: { edges: Array<{ - node: { ' $fragmentRefs'?: { FeaturedProductFragment: FeaturedProductFragment } }; + node: { + id: string; + slug: string; + name: string; + isAvailableForPurchase?: boolean | null; + description?: string | null; + seoTitle?: string | null; + seoDescription?: string | null; + updatedAt: string; + pricing?: { + priceRange?: { + start?: { gross: { currency: string; amount: number } } | null; + stop?: { gross: { currency: string; amount: number } } | null; + } | null; + } | null; + media?: Array<{ url: string; type: ProductMediaType; alt: string }> | null; + collections?: Array<{ name: string }> | null; + variants?: Array<{ + id: string; + name: string; + pricing?: { price?: { gross: { currency: string; amount: number } } | null } | null; + }> | null; + }; }>; } | null; }; +export type MenuItemFragment = { + id: string; + name: string; + url?: string | null; + collection?: { slug: string } | null; + category?: { slug: string } | null; + page?: { slug: string } | null; +}; + export type GetMenuBySlugQueryVariables = Exact<{ slug: Scalars['String']; }>; @@ -24621,8 +24703,33 @@ export type GetMenuBySlugQuery = { id: string; name: string; url?: string | null; + children?: Array<{ + id: string; + name: string; + url?: string | null; + children?: Array<{ + id: string; + name: string; + url?: string | null; + children?: Array<{ + id: string; + name: string; + url?: string | null; + collection?: { slug: string } | null; + category?: { slug: string } | null; + page?: { slug: string } | null; + }> | null; + collection?: { slug: string } | null; + category?: { slug: string } | null; + page?: { slug: string } | null; + }> | null; + collection?: { slug: string } | null; + category?: { slug: string } | null; + page?: { slug: string } | null; + }> | null; collection?: { slug: string } | null; - children?: Array<{ id: string; collection?: { slug: string } | null }> | null; + category?: { slug: string } | null; + page?: { slug: string } | null; }> | null; } | null; }; @@ -24643,6 +24750,24 @@ export type GetPageBySlugQuery = { } | null; }; +export type GetPagesQueryVariables = Exact<{ [key: string]: never }>; + +export type GetPagesQuery = { + pages?: { + edges: Array<{ + node: { + id: string; + title: string; + slug: string; + content?: string | null; + seoTitle?: string | null; + seoDescription?: string | null; + created: string; + }; + }>; + } | null; +}; + export type GetProductBySlugQueryVariables = Exact<{ slug: Scalars['String']; }>; @@ -24713,1382 +24838,482 @@ export type GetProductsQueryVariables = Exact<{ [key: string]: never }>; export type GetProductsQuery = { products?: { edges: Array<{ node: { name: string } }> } | null }; -export const FeaturedProductFragmentDoc = { - kind: 'Document', - definitions: [ - { - kind: 'FragmentDefinition', - name: { kind: 'Name', value: 'FeaturedProduct' }, - typeCondition: { kind: 'NamedType', name: { kind: 'Name', value: 'Product' } }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'slug' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { kind: 'Field', name: { kind: 'Name', value: 'isAvailableForPurchase' } }, - { kind: 'Field', name: { kind: 'Name', value: 'description' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoTitle' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoDescription' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'pricing' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'priceRange' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'start' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'currency' } }, - { kind: 'Field', name: { kind: 'Name', value: 'amount' } } - ] - } - } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'stop' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'currency' } }, - { kind: 'Field', name: { kind: 'Name', value: 'amount' } } - ] - } - } - ] - } - } - ] - } - } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'media' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'url' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'size' }, - value: { kind: 'IntValue', value: '2160' } - } - ] - }, - { kind: 'Field', name: { kind: 'Name', value: 'type' } }, - { kind: 'Field', name: { kind: 'Name', value: 'alt' } } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'collections' }, - selectionSet: { - kind: 'SelectionSet', - selections: [{ kind: 'Field', name: { kind: 'Name', value: 'name' } }] - } - }, - { kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'variants' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'pricing' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'price' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'currency' } }, - { kind: 'Field', name: { kind: 'Name', value: 'amount' } } - ] - } - } - ] - } - } - ] - } - } - ] - } - } - ] +export class TypedDocumentString + extends String + implements DocumentTypeDecoration +{ + __apiType?: DocumentTypeDecoration['__apiType']; + + constructor(private value: string, public __meta__?: { hash: string }) { + super(value); + } + + toString(): string & DocumentTypeDecoration { + return this.value; + } +} +export const FeaturedProductFragmentDoc = new TypedDocumentString(` + fragment FeaturedProduct on Product { + id + slug + name + isAvailableForPurchase + description + seoTitle + seoDescription + pricing { + priceRange { + start { + gross { + currency + amount + } + } + stop { + gross { + currency + amount + } } } - ] -} as unknown as DocumentNode; -export const GetCollectionBySlugDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'GetCollectionBySlug' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'slug' } }, - type: { - kind: 'NonNullType', - type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } + } + media { + url(size: 2160) + type + alt + } + collections { + name + } + updatedAt + variants { + id + name + pricing { + price { + gross { + currency + amount + } + } + } + } +} + `) as unknown as TypedDocumentString; +export const MenuItemFragmentDoc = new TypedDocumentString(` + fragment MenuItem on MenuItem { + id + name + url + collection { + slug + } + category { + slug + } + page { + slug + } +} + `) as unknown as TypedDocumentString; +export const GetCategoryBySlugDocument = new TypedDocumentString(` + query GetCategoryBySlug($slug: String!) { + category(slug: $slug) { + id + name + slug + description + seoTitle + seoDescription + } +} + `) as unknown as TypedDocumentString; +export const GetCategoryProductsBySlugDocument = new TypedDocumentString(` + query GetCategoryProductsBySlug($slug: String!) { + category(slug: $slug) { + products(channel: "default-channel", first: 100) { + edges { + node { + id + slug + name + isAvailableForPurchase + description + seoTitle + seoDescription + pricing { + priceRange { + start { + gross { + currency + amount + } + } + stop { + gross { + currency + amount + } + } + } + } + media { + url(size: 2160) + type + alt + } + collections { + name + } + updatedAt + variants { + id + name + pricing { + price { + gross { + currency + amount + } + } + } } } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'collection' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'channel' }, - value: { kind: 'StringValue', value: 'default-channel', block: false } - }, - { - kind: 'Argument', - name: { kind: 'Name', value: 'slug' }, - value: { kind: 'Variable', name: { kind: 'Name', value: 'slug' } } - } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { kind: 'Field', name: { kind: 'Name', value: 'slug' } }, - { kind: 'Field', name: { kind: 'Name', value: 'description' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoTitle' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoDescription' } } - ] - } - } - ] } } - ] -} as unknown as DocumentNode; -export const GetCollectionProductsBySlugDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'GetCollectionProductsBySlug' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'slug' } }, - type: { - kind: 'NonNullType', - type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } + } +} + `) as unknown as TypedDocumentString< + GetCategoryProductsBySlugQuery, + GetCategoryProductsBySlugQueryVariables +>; +export const GetCollectionBySlugDocument = new TypedDocumentString(` + query GetCollectionBySlug($slug: String!) { + collection(channel: "default-channel", slug: $slug) { + id + name + slug + description + seoTitle + seoDescription + } +} + `) as unknown as TypedDocumentString< + GetCollectionBySlugQuery, + GetCollectionBySlugQueryVariables +>; +export const GetCollectionProductsBySlugDocument = new TypedDocumentString(` + query GetCollectionProductsBySlug($slug: String!) { + collection(channel: "default-channel", slug: $slug) { + products(first: 100) { + edges { + node { + id + slug + name + isAvailableForPurchase + description + seoTitle + seoDescription + pricing { + priceRange { + start { + gross { + currency + amount + } + } + stop { + gross { + currency + amount + } + } + } + } + media { + url(size: 2160) + type + alt + } + collections { + name + } + updatedAt + variants { + id + name + pricing { + price { + gross { + currency + amount + } + } + } } } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'collection' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'channel' }, - value: { kind: 'StringValue', value: 'default-channel', block: false } - }, - { - kind: 'Argument', - name: { kind: 'Name', value: 'slug' }, - value: { kind: 'Variable', name: { kind: 'Name', value: 'slug' } } - } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'products' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'first' }, - value: { kind: 'IntValue', value: '100' } - } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'edges' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'node' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'slug' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'isAvailableForPurchase' } - }, - { kind: 'Field', name: { kind: 'Name', value: 'description' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoTitle' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'seoDescription' } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'pricing' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'priceRange' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'start' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { - kind: 'Name', - value: 'currency' - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'amount' } - } - ] - } - } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'stop' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { - kind: 'Name', - value: 'currency' - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'amount' } - } - ] - } - } - ] - } - } - ] - } - } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'media' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'url' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'size' }, - value: { kind: 'IntValue', value: '2160' } - } - ] - }, - { kind: 'Field', name: { kind: 'Name', value: 'type' } }, - { kind: 'Field', name: { kind: 'Name', value: 'alt' } } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'collections' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'name' } } - ] - } - }, - { kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'variants' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'pricing' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'price' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { - kind: 'Name', - value: 'currency' - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'amount' } - } - ] - } - } - ] - } - } - ] - } - } - ] - } - } - ] - } - } - ] - } - } - ] - } - } - ] - } - } - ] } } - ] -} as unknown as DocumentNode< + } +} + `) as unknown as TypedDocumentString< GetCollectionProductsBySlugQuery, GetCollectionProductsBySlugQueryVariables >; -export const GetCollectionsDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'GetCollections' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'collections' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'channel' }, - value: { kind: 'StringValue', value: 'default-channel', block: false } - }, - { - kind: 'Argument', - name: { kind: 'Name', value: 'first' }, - value: { kind: 'IntValue', value: '100' } - } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'edges' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'node' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { kind: 'Field', name: { kind: 'Name', value: 'slug' } }, - { kind: 'Field', name: { kind: 'Name', value: 'description' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoTitle' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoDescription' } } - ] - } - } - ] - } - } - ] - } - } - ] +export const GetCollectionsDocument = new TypedDocumentString(` + query GetCollections { + collections(channel: "default-channel", first: 100) { + edges { + node { + id + name + slug + description + seoTitle + seoDescription } } - ] -} as unknown as DocumentNode; -export const GetFeaturedProductsDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'GetFeaturedProducts' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'first' } }, - type: { - kind: 'NonNullType', - type: { kind: 'NamedType', name: { kind: 'Name', value: 'Int' } } + } +} + `) as unknown as TypedDocumentString; +export const GetFeaturedProductsDocument = new TypedDocumentString(` + query GetFeaturedProducts($first: Int!) { + products(first: $first, channel: "default-channel") { + edges { + node { + ...FeaturedProduct + } + } + } +} + fragment FeaturedProduct on Product { + id + slug + name + isAvailableForPurchase + description + seoTitle + seoDescription + pricing { + priceRange { + start { + gross { + currency + amount + } + } + stop { + gross { + currency + amount + } + } + } + } + media { + url(size: 2160) + type + alt + } + collections { + name + } + updatedAt + variants { + id + name + pricing { + price { + gross { + currency + amount + } + } + } + } +}`) as unknown as TypedDocumentString; +export const GetMenuBySlugDocument = new TypedDocumentString(` + query GetMenuBySlug($slug: String!) { + menu(slug: $slug, channel: "default-channel") { + id + slug + name + items { + ...MenuItem + children { + ...MenuItem + children { + ...MenuItem + children { + ...MenuItem } } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'products' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'first' }, - value: { kind: 'Variable', name: { kind: 'Name', value: 'first' } } - }, - { - kind: 'Argument', - name: { kind: 'Name', value: 'channel' }, - value: { kind: 'StringValue', value: 'default-channel', block: false } - } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'edges' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'node' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'FragmentSpread', - name: { kind: 'Name', value: 'FeaturedProduct' } - } - ] - } - } - ] - } - } - ] - } - } - ] - } - }, - { - kind: 'FragmentDefinition', - name: { kind: 'Name', value: 'FeaturedProduct' }, - typeCondition: { kind: 'NamedType', name: { kind: 'Name', value: 'Product' } }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'slug' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { kind: 'Field', name: { kind: 'Name', value: 'isAvailableForPurchase' } }, - { kind: 'Field', name: { kind: 'Name', value: 'description' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoTitle' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoDescription' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'pricing' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'priceRange' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'start' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'currency' } }, - { kind: 'Field', name: { kind: 'Name', value: 'amount' } } - ] - } - } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'stop' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'currency' } }, - { kind: 'Field', name: { kind: 'Name', value: 'amount' } } - ] - } - } - ] - } - } - ] - } - } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'media' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'url' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'size' }, - value: { kind: 'IntValue', value: '2160' } - } - ] - }, - { kind: 'Field', name: { kind: 'Name', value: 'type' } }, - { kind: 'Field', name: { kind: 'Name', value: 'alt' } } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'collections' }, - selectionSet: { - kind: 'SelectionSet', - selections: [{ kind: 'Field', name: { kind: 'Name', value: 'name' } }] - } - }, - { kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'variants' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'pricing' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'price' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'currency' } }, - { kind: 'Field', name: { kind: 'Name', value: 'amount' } } - ] - } - } - ] - } - } - ] - } - } - ] - } - } - ] } } - ] -} as unknown as DocumentNode; -export const GetMenuBySlugDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'GetMenuBySlug' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'slug' } }, - type: { - kind: 'NonNullType', - type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } + } +} + fragment MenuItem on MenuItem { + id + name + url + collection { + slug + } + category { + slug + } + page { + slug + } +}`) as unknown as TypedDocumentString; +export const GetPageBySlugDocument = new TypedDocumentString(` + query GetPageBySlug($slug: String!) { + page(slug: $slug) { + id + title + slug + content + seoTitle + seoDescription + created + } +} + `) as unknown as TypedDocumentString; +export const GetPagesDocument = new TypedDocumentString(` + query GetPages { + pages(first: 10) { + edges { + node { + id + title + slug + content + seoTitle + seoDescription + created + } + } + } +} + `) as unknown as TypedDocumentString; +export const GetProductBySlugDocument = new TypedDocumentString(` + query GetProductBySlug($slug: String!) { + product(channel: "default-channel", slug: $slug) { + id + slug + name + isAvailableForPurchase + description + seoTitle + seoDescription + pricing { + priceRange { + start { + gross { + currency + amount } } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'menu' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'slug' }, - value: { kind: 'Variable', name: { kind: 'Name', value: 'slug' } } - }, - { - kind: 'Argument', - name: { kind: 'Name', value: 'channel' }, - value: { kind: 'StringValue', value: 'default-channel', block: false } - } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'slug' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'items' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { kind: 'Field', name: { kind: 'Name', value: 'url' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'collection' }, - selectionSet: { - kind: 'SelectionSet', - selections: [{ kind: 'Field', name: { kind: 'Name', value: 'slug' } }] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'children' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'collection' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'slug' } } - ] - } - } - ] - } - } - ] - } - } - ] - } - } - ] - } - } - ] -} as unknown as DocumentNode; -export const GetPageBySlugDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'GetPageBySlug' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'slug' } }, - type: { - kind: 'NonNullType', - type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } + stop { + gross { + currency + amount } } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'page' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'slug' }, - value: { kind: 'Variable', name: { kind: 'Name', value: 'slug' } } - } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'title' } }, - { kind: 'Field', name: { kind: 'Name', value: 'slug' } }, - { kind: 'Field', name: { kind: 'Name', value: 'content' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoTitle' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoDescription' } }, - { kind: 'Field', name: { kind: 'Name', value: 'created' } } - ] - } - } - ] } } - ] -} as unknown as DocumentNode; -export const GetProductBySlugDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'GetProductBySlug' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'slug' } }, - type: { - kind: 'NonNullType', - type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } + media { + url(size: 2160) + type + alt + } + collections { + name + } + updatedAt + variants { + id + name + pricing { + price { + gross { + currency + amount } } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'product' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'slug' }, - value: { kind: 'Variable', name: { kind: 'Name', value: 'slug' } } - } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'slug' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { kind: 'Field', name: { kind: 'Name', value: 'isAvailableForPurchase' } }, - { kind: 'Field', name: { kind: 'Name', value: 'description' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoTitle' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoDescription' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'pricing' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'priceRange' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'start' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'currency' } - }, - { kind: 'Field', name: { kind: 'Name', value: 'amount' } } - ] - } - } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'stop' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'currency' } - }, - { kind: 'Field', name: { kind: 'Name', value: 'amount' } } - ] - } - } - ] - } - } - ] - } - } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'media' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'url' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'size' }, - value: { kind: 'IntValue', value: '2160' } - } - ] - }, - { kind: 'Field', name: { kind: 'Name', value: 'type' } }, - { kind: 'Field', name: { kind: 'Name', value: 'alt' } } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'collections' }, - selectionSet: { - kind: 'SelectionSet', - selections: [{ kind: 'Field', name: { kind: 'Name', value: 'name' } }] - } - }, - { kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'variants' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'pricing' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'price' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'currency' } - }, - { kind: 'Field', name: { kind: 'Name', value: 'amount' } } - ] - } - } - ] - } - } - ] - } - } - ] - } - } - ] - } - } - ] } } - ] -} as unknown as DocumentNode; -export const SearchProductsDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'SearchProducts' }, - variableDefinitions: [ - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'search' } }, - type: { - kind: 'NonNullType', - type: { kind: 'NamedType', name: { kind: 'Name', value: 'String' } } - } - }, - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'sortBy' } }, - type: { - kind: 'NonNullType', - type: { kind: 'NamedType', name: { kind: 'Name', value: 'ProductOrderField' } } - } - }, - { - kind: 'VariableDefinition', - variable: { kind: 'Variable', name: { kind: 'Name', value: 'sortDirection' } }, - type: { - kind: 'NonNullType', - type: { kind: 'NamedType', name: { kind: 'Name', value: 'OrderDirection' } } + } +} + `) as unknown as TypedDocumentString; +export const SearchProductsDocument = new TypedDocumentString(` + query SearchProducts($search: String!, $sortBy: ProductOrderField!, $sortDirection: OrderDirection!) { + products( + first: 100 + channel: "default-channel" + sortBy: {field: $sortBy, direction: $sortDirection} + filter: {search: $search} + ) { + edges { + node { + id + slug + name + isAvailableForPurchase + description + seoTitle + seoDescription + pricing { + priceRange { + start { + gross { + currency + amount + } + } + stop { + gross { + currency + amount + } + } } } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'products' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'first' }, - value: { kind: 'IntValue', value: '100' } - }, - { - kind: 'Argument', - name: { kind: 'Name', value: 'channel' }, - value: { kind: 'StringValue', value: 'default-channel', block: false } - }, - { - kind: 'Argument', - name: { kind: 'Name', value: 'sortBy' }, - value: { - kind: 'ObjectValue', - fields: [ - { - kind: 'ObjectField', - name: { kind: 'Name', value: 'field' }, - value: { kind: 'Variable', name: { kind: 'Name', value: 'sortBy' } } - }, - { - kind: 'ObjectField', - name: { kind: 'Name', value: 'direction' }, - value: { kind: 'Variable', name: { kind: 'Name', value: 'sortDirection' } } - } - ] - } - }, - { - kind: 'Argument', - name: { kind: 'Name', value: 'filter' }, - value: { - kind: 'ObjectValue', - fields: [ - { - kind: 'ObjectField', - name: { kind: 'Name', value: 'search' }, - value: { kind: 'Variable', name: { kind: 'Name', value: 'search' } } - } - ] - } + media { + url(size: 2160) + type + alt + } + collections { + name + } + updatedAt + variants { + id + name + pricing { + price { + gross { + currency + amount } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'edges' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'node' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'slug' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'isAvailableForPurchase' } - }, - { kind: 'Field', name: { kind: 'Name', value: 'description' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoTitle' } }, - { kind: 'Field', name: { kind: 'Name', value: 'seoDescription' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'pricing' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'priceRange' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'start' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'currency' } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'amount' } - } - ] - } - } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'stop' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'currency' } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'amount' } - } - ] - } - } - ] - } - } - ] - } - } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'media' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'url' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'size' }, - value: { kind: 'IntValue', value: '2160' } - } - ] - }, - { kind: 'Field', name: { kind: 'Name', value: 'type' } }, - { kind: 'Field', name: { kind: 'Name', value: 'alt' } } - ] - } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'collections' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'name' } } - ] - } - }, - { kind: 'Field', name: { kind: 'Name', value: 'updatedAt' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'variants' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { kind: 'Field', name: { kind: 'Name', value: 'id' } }, - { kind: 'Field', name: { kind: 'Name', value: 'name' } }, - { - kind: 'Field', - name: { kind: 'Name', value: 'pricing' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'price' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'gross' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'currency' } - }, - { - kind: 'Field', - name: { kind: 'Name', value: 'amount' } - } - ] - } - } - ] - } - } - ] - } - } - ] - } - } - ] - } - } - ] - } - } - ] } } - ] + } } } - ] -} as unknown as DocumentNode; -export const GetProductsDocument = { - kind: 'Document', - definitions: [ - { - kind: 'OperationDefinition', - operation: 'query', - name: { kind: 'Name', value: 'GetProducts' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'products' }, - arguments: [ - { - kind: 'Argument', - name: { kind: 'Name', value: 'first' }, - value: { kind: 'IntValue', value: '10' } - }, - { - kind: 'Argument', - name: { kind: 'Name', value: 'channel' }, - value: { kind: 'StringValue', value: 'default-channel', block: false } - } - ], - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'edges' }, - selectionSet: { - kind: 'SelectionSet', - selections: [ - { - kind: 'Field', - name: { kind: 'Name', value: 'node' }, - selectionSet: { - kind: 'SelectionSet', - selections: [{ kind: 'Field', name: { kind: 'Name', value: 'name' } }] - } - } - ] - } - } - ] - } - } - ] + } +} + `) as unknown as TypedDocumentString; +export const GetProductsDocument = new TypedDocumentString(` + query GetProducts { + products(first: 10, channel: "default-channel") { + edges { + node { + name } } - ] -} as unknown as DocumentNode; + } +} + `) as unknown as TypedDocumentString; diff --git a/lib/saleor/generated/index.ts b/lib/saleor/generated/index.ts index c682b1e2f..8a12aabda 100644 --- a/lib/saleor/generated/index.ts +++ b/lib/saleor/generated/index.ts @@ -1,2 +1 @@ -export * from './fragment-masking'; export * from './gql'; diff --git a/lib/saleor/index.ts b/lib/saleor/index.ts index 784660cba..5129dd6ad 100644 --- a/lib/saleor/index.ts +++ b/lib/saleor/index.ts @@ -1,16 +1,20 @@ -import type { TypedDocumentNode } from '@graphql-typed-document-node/core'; -import { print } from 'graphql'; -import { Collection, Menu, Page, Product } from 'lib/types'; +import { Cart, Collection, Menu, Page, Product } from 'lib/types'; +import { parseEditorJsToHtml } from './editorjs'; import { + GetCategoryBySlugDocument, + GetCategoryProductsBySlugDocument, GetCollectionBySlugDocument, GetCollectionProductsBySlugDocument, GetCollectionsDocument, GetMenuBySlugDocument, GetPageBySlugDocument, + GetPagesDocument, GetProductBySlugDocument, + MenuItemFragment, OrderDirection, ProductOrderField, - SearchProductsDocument + SearchProductsDocument, + TypedDocumentString } from './generated/graphql'; import { invariant } from './utils'; @@ -28,7 +32,7 @@ export async function saleorFetch({ headers, cache = 'force-cache' }: { - query: TypedDocumentNode; + query: TypedDocumentString; variables: Variables; headers?: HeadersInit; cache?: RequestCache; @@ -42,7 +46,7 @@ export async function saleorFetch({ ...headers }, body: JSON.stringify({ - query: print(query), + query: query.toString(), ...(variables && { variables }) }), cache, @@ -138,7 +142,9 @@ export async function getProduct(handle: string): Promise { availableForSale: saleorProduct.product.isAvailableForPurchase || true, title: saleorProduct.product.name, description: saleorProduct.product.description || '', - descriptionHtml: saleorProduct.product.description || '', // @todo + descriptionHtml: saleorProduct.product.description + ? parseEditorJsToHtml(saleorProduct.product.description) + : '', options: [], // @todo priceRange: { maxVariantPrice: { @@ -174,50 +180,78 @@ export async function getProduct(handle: string): Promise { }; } -export async function getCollection(handle: string): Promise { - const saleorCollection = await saleorFetch({ - query: GetCollectionBySlugDocument, - variables: { - slug: handle - } - }); +const _getCollection = async (handle: string) => + ( + await saleorFetch({ + query: GetCollectionBySlugDocument, + variables: { + slug: handle + } + }) + ).collection; +const _getCategory = async (handle: string) => + ( + await saleorFetch({ + query: GetCategoryBySlugDocument, + variables: { + slug: handle + } + }) + ).category; - if (!saleorCollection.collection) { +export async function getCollection(handle: string): Promise { + const saleorCollection = (await _getCollection(handle)) || (await _getCategory(handle)); + + if (!saleorCollection) { throw new Error(`Collection not found: ${handle}`); } return { - handle: saleorCollection.collection.slug, - title: saleorCollection.collection.name, - description: saleorCollection.collection.description as string, + handle: saleorCollection.slug, + title: saleorCollection.name, + description: saleorCollection.description as string, seo: { - title: saleorCollection.collection.seoTitle || saleorCollection.collection.name, - description: saleorCollection.collection.seoDescription || '' + title: saleorCollection.seoTitle || saleorCollection.name, + description: saleorCollection.seoDescription || '' }, updatedAt: '', // @todo ? - path: `/search/${saleorCollection.collection.slug}` + path: `/search/${saleorCollection.slug}` }; } +const handleToSlug: Record = { + 'hidden-homepage-featured-items': 'featured', + 'hidden-homepage-carousel': 'all-products' +}; +const _getCollectionProducts = async (handle: string) => + ( + await saleorFetch({ + query: GetCollectionProductsBySlugDocument, + variables: { + slug: handleToSlug[handle] || handle + } + }) + ).collection; +const _getCategoryProducts = async (handle: string) => + ( + await saleorFetch({ + query: GetCategoryProductsBySlugDocument, + variables: { + slug: handleToSlug[handle] || handle + } + }) + ).category; + export async function getCollectionProducts(handle: string): Promise { - const handleToSlug: Record = { - 'hidden-homepage-featured-items': 'featured', - 'hidden-homepage-carousel': 'all-products' - }; + const saleorCollectionProducts = + (await _getCollectionProducts(handle)) || (await _getCategoryProducts(handle)); - const saleorCollectionProducts = await saleorFetch({ - query: GetCollectionProductsBySlugDocument, - variables: { - slug: handleToSlug[handle] || handle - } - }); - - if (!saleorCollectionProducts.collection) { + if (!saleorCollectionProducts) { throw new Error(`Collection not found: ${handle}`); } return ( - saleorCollectionProducts.collection.products?.edges.map((product) => { + saleorCollectionProducts.products?.edges.map((product) => { const images = product.node.media ?.filter((media) => media.type === 'IMAGE') @@ -236,7 +270,9 @@ export async function getCollectionProducts(handle: string): Promise availableForSale: product.node.isAvailableForPurchase || true, title: product.node.name, description: product.node.description || '', - descriptionHtml: product.node.description || '', // @todo + descriptionHtml: product.node.description + ? parseEditorJsToHtml(product.node.description) + : '', options: [], // @todo priceRange: { maxVariantPrice: { @@ -291,12 +327,47 @@ export async function getMenu(handle: string): Promise { throw new Error(`Menu not found: ${handle}`); } + const result = flattenMenuItems(saleorMenu.menu.items); + return ( - saleorMenu.menu.items?.map((item) => { - return { - path: item.url || '', // @todo handle manus without url - title: item.name - }; + result + .filter( + (menu) => + menu.path && + // manually removing empty categories + // @todo ? + menu.path !== '/search/paints' && + menu.path !== '/search/juices' && + menu.path !== '/search/alcohol' && + menu.path !== '/search/homewares' && + menu.path !== '/search/groceries' + ) + // unique by path + .filter((item1, idx, arr) => arr.findIndex((item2) => item2.path === item1.path) === idx) + .slice(0, 3) + ); +} + +type MenuItemWithChildren = MenuItemFragment & { + children?: null | undefined | MenuItemWithChildren[]; +}; +function flattenMenuItems(menuItems: null | undefined | MenuItemWithChildren[]): Menu[] { + return ( + menuItems?.flatMap((item) => { + const path = + item.url || + (item.collection + ? `/search/${item.collection.slug}` + : item.category + ? `/search/${item.category.slug}` + : ''); + return [ + { + path: path, + title: item.name + }, + ...flattenMenuItems(item.children) + ]; }) || [] ); } @@ -339,7 +410,9 @@ export async function getProducts({ availableForSale: product.node.isAvailableForPurchase || true, title: product.node.name, description: product.node.description || '', - descriptionHtml: product.node.description || '', // @todo + descriptionHtml: product.node.description + ? parseEditorJsToHtml(product.node.description) + : '', options: [], // @todo priceRange: { maxVariantPrice: { @@ -376,3 +449,41 @@ export async function getProducts({ }) || [] ); } + +export async function getPages(): Promise { + const saleorPages = await saleorFetch({ + query: GetPagesDocument, + variables: {} + }); + + return ( + saleorPages.pages?.edges.map((page) => { + return { + id: page.node.id, + title: page.node.title, + handle: page.node.slug, + body: page.node.content || '', + bodySummary: page.node.seoDescription || '', + seo: { + title: page.node.seoTitle || page.node.title, + description: page.node.seoDescription || '' + }, + createdAt: page.node.created, + updatedAt: page.node.created + }; + }) || [] + ); +} + +export async function getCart(cartId: string): Promise { + // @todo + return null; +} +export async function createCart(): Promise { + // @todo + throw new Error(`Not implemented`); +} +export async function getProductRecommendations(productId: string): Promise { + // @todo + return []; +} diff --git a/lib/saleor/queries/GetCategoryBySlug.graphql b/lib/saleor/queries/GetCategoryBySlug.graphql new file mode 100644 index 000000000..58d00127c --- /dev/null +++ b/lib/saleor/queries/GetCategoryBySlug.graphql @@ -0,0 +1,10 @@ +query GetCategoryBySlug($slug: String!) { + category(slug: $slug) { + id + name + slug + description + seoTitle + seoDescription + } +} diff --git a/lib/saleor/queries/GetCategoryProductsBySlug.graphql b/lib/saleor/queries/GetCategoryProductsBySlug.graphql new file mode 100644 index 000000000..685d6aa31 --- /dev/null +++ b/lib/saleor/queries/GetCategoryProductsBySlug.graphql @@ -0,0 +1,54 @@ +query GetCategoryProductsBySlug($slug: String!) { + category(slug: $slug) { + products(channel: "default-channel", first: 100) { + edges { + node { + id + slug + name + isAvailableForPurchase + description + seoTitle + seoDescription + pricing { + priceRange { + start { + gross { + currency + amount + } + } + stop { + gross { + currency + amount + } + } + } + } + media { + url(size: 2160) + type + alt + } + collections { + name + } + updatedAt + variants { + id + name + pricing { + price { + gross { + currency + amount + } + } + } + } + } + } + } + } +} diff --git a/lib/saleor/queries/GetMenuBySlug.graphql b/lib/saleor/queries/GetMenuBySlug.graphql index c94edde2d..27d1a38c6 100644 --- a/lib/saleor/queries/GetMenuBySlug.graphql +++ b/lib/saleor/queries/GetMenuBySlug.graphql @@ -1,19 +1,32 @@ +fragment MenuItem on MenuItem { + id + name + url + collection { + slug + } + category { + slug + } + page { + slug + } +} + query GetMenuBySlug($slug: String!) { menu(slug: $slug, channel: "default-channel") { id slug name items { - id - name - url - collection { - slug - } + ...MenuItem children { - id - collection { - slug + ...MenuItem + children { + ...MenuItem + children { + ...MenuItem + } } } } diff --git a/lib/saleor/queries/GetPages.graphql b/lib/saleor/queries/GetPages.graphql new file mode 100644 index 000000000..fd137ae29 --- /dev/null +++ b/lib/saleor/queries/GetPages.graphql @@ -0,0 +1,15 @@ +query GetPages { + pages(first: 10) { + edges { + node { + id + title + slug + content + seoTitle + seoDescription + created + } + } + } +} diff --git a/lib/saleor/queries/GetProductBySlug.graphql b/lib/saleor/queries/GetProductBySlug.graphql index ce9325d67..33df28e27 100644 --- a/lib/saleor/queries/GetProductBySlug.graphql +++ b/lib/saleor/queries/GetProductBySlug.graphql @@ -1,5 +1,5 @@ query GetProductBySlug($slug: String!) { - product(slug: $slug) { + product(channel: "default-channel", slug: $slug) { id slug name diff --git a/package.json b/package.json index 4056f0b51..757145393 100644 --- a/package.json +++ b/package.json @@ -23,12 +23,10 @@ "*": "prettier --write --ignore-unknown" }, "dependencies": { - "@graphql-typed-document-node/core": "3.2.0", "@headlessui/react": "^1.7.10", "@vercel/og": "^0.1.0", "clsx": "^1.2.1", "framer-motion": "^8.4.0", - "graphql": "16.6.0", "is-empty-iterable": "^3.0.0", "next": "13.3.1", "react": "18.2.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6ac813692..00a1be9c0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,9 +1,6 @@ lockfileVersion: '6.0' dependencies: - '@graphql-typed-document-node/core': - specifier: 3.2.0 - version: registry.npmjs.org/@graphql-typed-document-node/core@3.2.0(graphql@16.6.0) '@headlessui/react': specifier: ^1.7.10 version: 1.7.14(react-dom@18.2.0)(react@18.2.0) @@ -16,9 +13,6 @@ dependencies: framer-motion: specifier: ^8.4.0 version: 8.5.5(react-dom@18.2.0)(react@18.2.0) - graphql: - specifier: 16.6.0 - version: registry.npmjs.org/graphql@16.6.0 is-empty-iterable: specifier: ^3.0.0 version: 3.0.0 @@ -4923,6 +4917,7 @@ packages: graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 dependencies: graphql: registry.npmjs.org/graphql@16.6.0 + dev: true registry.npmjs.org/@jridgewell/gen-mapping@0.3.3: resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz} @@ -6080,6 +6075,7 @@ packages: name: graphql version: 16.6.0 engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + dev: true registry.npmjs.org/has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==, registry: https://registry.npmjs.com/, tarball: https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz}