Update Vendure provider to latest API changes (#352)

Relates to #349
This commit is contained in:
Michael Bromley
2021-06-02 16:46:38 +02:00
committed by GitHub
parent a98c95d447
commit 0e804d09f9
81 changed files with 1265 additions and 698 deletions

View File

@@ -0,0 +1,67 @@
export type HasParent = { id: string; parent?: { id: string } | null }
export type TreeNode<T extends HasParent> = T & {
children: Array<TreeNode<T>>
expanded: boolean
}
export type RootNode<T extends HasParent> = {
id?: string
children: Array<TreeNode<T>>
}
export function arrayToTree<T extends HasParent>(
nodes: T[],
currentState?: RootNode<T>
): RootNode<T> {
const topLevelNodes: Array<TreeNode<T>> = []
const mappedArr: { [id: string]: TreeNode<T> } = {}
const currentStateMap = treeToMap(currentState)
// First map the nodes of the array to an object -> create a hash table.
for (const node of nodes) {
mappedArr[node.id] = { ...(node as any), children: [] }
}
for (const id of nodes.map((n) => n.id)) {
if (mappedArr.hasOwnProperty(id)) {
const mappedElem = mappedArr[id]
mappedElem.expanded = currentStateMap.get(id)?.expanded ?? false
const parent = mappedElem.parent
if (!parent) {
continue
}
// If the element is not at the root level, add it to its parent array of children.
const parentIsRoot = !mappedArr[parent.id]
if (!parentIsRoot) {
if (mappedArr[parent.id]) {
mappedArr[parent.id].children.push(mappedElem)
} else {
mappedArr[parent.id] = { children: [mappedElem] } as any
}
} else {
topLevelNodes.push(mappedElem)
}
}
}
// tslint:disable-next-line:no-non-null-assertion
const rootId = topLevelNodes.length ? topLevelNodes[0].parent!.id : undefined
return { id: rootId, children: topLevelNodes }
}
/**
* Converts an existing tree (as generated by the arrayToTree function) into a flat
* Map. This is used to persist certain states (e.g. `expanded`) when re-building the
* tree.
*/
function treeToMap<T extends HasParent>(
tree?: RootNode<T>
): Map<string, TreeNode<T>> {
const nodeMap = new Map<string, TreeNode<T>>()
function visit(node: TreeNode<T>) {
nodeMap.set(node.id, node)
node.children.forEach(visit)
}
if (tree) {
visit(tree as TreeNode<T>)
}
return nodeMap
}

View File

@@ -0,0 +1,44 @@
export const cartFragment = /* GraphQL */ `
fragment Cart on Order {
id
code
createdAt
totalQuantity
subTotal
subTotalWithTax
total
totalWithTax
currencyCode
customer {
id
}
lines {
id
quantity
linePriceWithTax
discountedLinePriceWithTax
unitPriceWithTax
discountedUnitPriceWithTax
featuredAsset {
id
preview
}
discounts {
description
amount
}
productVariant {
id
name
sku
price
priceWithTax
stockLevel
product {
slug
}
productId
}
}
}
`

View File

@@ -0,0 +1,24 @@
export const searchResultFragment = /* GraphQL */ `
fragment SearchResult on SearchResult {
productId
productName
description
description
slug
sku
currencyCode
productAsset {
id
preview
}
priceWithTax {
... on SinglePrice {
value
}
... on PriceRange {
min
max
}
}
}
`

View File

@@ -0,0 +1,15 @@
import { cartFragment } from '../fragments/cart-fragment'
export const addItemToOrderMutation = /* GraphQL */ `
mutation addItemToOrder($variantId: ID!, $quantity: Int!) {
addItemToOrder(productVariantId: $variantId, quantity: $quantity) {
__typename
...Cart
... on ErrorResult {
errorCode
message
}
}
}
${cartFragment}
`

View File

@@ -0,0 +1,15 @@
import { cartFragment } from '../fragments/cart-fragment'
export const adjustOrderLineMutation = /* GraphQL */ `
mutation adjustOrderLine($orderLineId: ID!, $quantity: Int!) {
adjustOrderLine(orderLineId: $orderLineId, quantity: $quantity) {
__typename
...Cart
... on ErrorResult {
errorCode
message
}
}
}
${cartFragment}
`

View File

@@ -0,0 +1,14 @@
export const loginMutation = /* GraphQL */ `
mutation login($username: String!, $password: String!) {
login(username: $username, password: $password) {
__typename
... on CurrentUser {
id
}
... on ErrorResult {
errorCode
message
}
}
}
`

View File

@@ -0,0 +1,7 @@
export const logoutMutation = /* GraphQL */ `
mutation logout {
logout {
success
}
}
`

View File

@@ -0,0 +1,15 @@
import { cartFragment } from '../fragments/cart-fragment'
export const removeOrderLineMutation = /* GraphQL */ `
mutation removeOrderLine($orderLineId: ID!) {
removeOrderLine(orderLineId: $orderLineId) {
__typename
...Cart
... on ErrorResult {
errorCode
message
}
}
}
${cartFragment}
`

View File

@@ -0,0 +1,14 @@
export const signupMutation = /* GraphQL */ `
mutation signup($input: RegisterCustomerInput!) {
registerCustomerAccount(input: $input) {
__typename
... on Success {
success
}
... on ErrorResult {
errorCode
message
}
}
}
`

View File

@@ -0,0 +1,56 @@
import { Product } from '@commerce/types/product'
import { Cart } from '@commerce/types/cart'
import { CartFragment, SearchResultFragment } from '../schema'
export function normalizeSearchResult(item: SearchResultFragment): Product {
return {
id: item.productId,
name: item.productName,
description: item.description,
slug: item.slug,
path: item.slug,
images: [{ url: item.productAsset?.preview + '?w=800&mode=crop' || '' }],
variants: [],
price: {
value: (item.priceWithTax as any).min / 100,
currencyCode: item.currencyCode,
},
options: [],
sku: item.sku,
}
}
export function normalizeCart(order: CartFragment): Cart {
return {
id: order.id.toString(),
createdAt: order.createdAt,
taxesIncluded: true,
lineItemsSubtotalPrice: order.subTotalWithTax / 100,
currency: { code: order.currencyCode },
subtotalPrice: order.subTotalWithTax / 100,
totalPrice: order.totalWithTax / 100,
customerId: order.customer?.id,
lineItems: order.lines?.map((l) => ({
id: l.id,
name: l.productVariant.name,
quantity: l.quantity,
url: l.productVariant.product.slug,
variantId: l.productVariant.id,
productId: l.productVariant.productId,
images: [{ url: l.featuredAsset?.preview + '?preset=thumb' || '' }],
discounts: l.discounts.map((d) => ({ value: d.amount / 100 })),
path: '',
variant: {
id: l.productVariant.id,
name: l.productVariant.name,
sku: l.productVariant.sku,
price: l.discountedUnitPriceWithTax / 100,
listPrice: l.unitPriceWithTax / 100,
image: {
url: l.featuredAsset?.preview + '?preset=thumb' || '',
},
requiresShipping: true,
},
})),
}
}

View File

@@ -0,0 +1,10 @@
export const activeCustomerQuery = /* GraphQL */ `
query activeCustomer {
activeCustomer {
id
firstName
lastName
emailAddress
}
}
`

View File

@@ -0,0 +1,9 @@
export const getAllProductPathsQuery = /* GraphQL */ `
query getAllProductPaths($first: Int = 100) {
products(options: { take: $first }) {
items {
slug
}
}
}
`

View File

@@ -0,0 +1,12 @@
import { searchResultFragment } from '../fragments/search-result-fragment'
export const getAllProductsQuery = /* GraphQL */ `
query getAllProducts($input: SearchInput!) {
search(input: $input) {
items {
...SearchResult
}
}
}
${searchResultFragment}
`

View File

@@ -0,0 +1,10 @@
import { cartFragment } from '../fragments/cart-fragment'
export const getCartQuery = /* GraphQL */ `
query activeOrder {
activeOrder {
...Cart
}
}
${cartFragment}
`

View File

@@ -0,0 +1,21 @@
export const getCollectionsQuery = /* GraphQL */ `
query getCollections {
collections {
items {
id
name
description
slug
productVariants {
totalItems
}
parent {
id
}
children {
id
}
}
}
}
`

View File

@@ -0,0 +1,41 @@
export const getProductQuery = /* GraphQL */ `
query getProduct($slug: String!) {
product(slug: $slug) {
id
name
slug
description
assets {
id
preview
name
}
variants {
id
priceWithTax
currencyCode
options {
id
name
code
groupId
group {
id
options {
name
}
}
}
}
optionGroups {
id
code
name
options {
id
name
}
}
}
}
`

View File

@@ -0,0 +1,13 @@
import { searchResultFragment } from '../fragments/search-result-fragment'
export const searchQuery = /* GraphQL */ `
query search($input: SearchInput!) {
search(input: $input) {
items {
...SearchResult
}
totalItems
}
}
${searchResultFragment}
`