diff --git a/components/auth/SignUpView.tsx b/components/auth/SignUpView.tsx index b72b7037f..1b619828b 100644 --- a/components/auth/SignUpView.tsx +++ b/components/auth/SignUpView.tsx @@ -34,8 +34,8 @@ const SignUpView: FC = () => { setMessage('') await signup({ email, - // firstName, - // lastName, + firstName, + lastName, password, }) setLoading(false) diff --git a/components/product/ProductView/ProductView.tsx b/components/product/ProductView/ProductView.tsx index 0797d2a3b..2a7fccb10 100644 --- a/components/product/ProductView/ProductView.tsx +++ b/components/product/ProductView/ProductView.tsx @@ -120,8 +120,7 @@ const ProductView: FC = ({ product }) => { { diff --git a/framework/saleor/api/endpoints/cart.ts b/framework/saleor/api/endpoints/cart.ts new file mode 100644 index 000000000..d09c976c3 --- /dev/null +++ b/framework/saleor/api/endpoints/cart.ts @@ -0,0 +1 @@ +export default function (_commerce: any) {} diff --git a/framework/saleor/api/endpoints/catalog/products.ts b/framework/saleor/api/endpoints/catalog/products.ts new file mode 100644 index 000000000..d09c976c3 --- /dev/null +++ b/framework/saleor/api/endpoints/catalog/products.ts @@ -0,0 +1 @@ +export default function (_commerce: any) {} diff --git a/framework/saleor/api/endpoints/checkout/index.ts b/framework/saleor/api/endpoints/checkout/index.ts new file mode 100644 index 000000000..f15672435 --- /dev/null +++ b/framework/saleor/api/endpoints/checkout/index.ts @@ -0,0 +1,57 @@ +import { CommerceAPI, GetAPISchema, createEndpoint } from '@commerce/api' +import checkoutEndpoint from '@commerce/api/endpoints/checkout' +import { CheckoutSchema } from '@commerce/types/checkout' + +export type CheckoutAPI = GetAPISchema + +export type CheckoutEndpoint = CheckoutAPI['endpoint'] + +const checkout: CheckoutEndpoint['handlers']['checkout'] = async ({ + req, + res, + config, +}) => { + try { + const html = ` + + + + + + Checkout + + +
+ + + +

Checkout not yet implemented :(

+

+ See #64 +

+
+ + + ` + + res.status(200) + res.setHeader('Content-Type', 'text/html') + res.write(html) + res.end() + } catch (error) { + console.error(error) + + const message = 'An unexpected error ocurred' + + res.status(500).json({ data: null, errors: [{ message }] }) + } +} + +export const handlers: CheckoutEndpoint['handlers'] = { checkout } + +const checkoutApi = createEndpoint({ + handler: checkoutEndpoint, + handlers, +}) + +export default checkoutApi diff --git a/framework/saleor/api/endpoints/customer.ts b/framework/saleor/api/endpoints/customer.ts new file mode 100644 index 000000000..d09c976c3 --- /dev/null +++ b/framework/saleor/api/endpoints/customer.ts @@ -0,0 +1 @@ +export default function (_commerce: any) {} diff --git a/framework/saleor/api/endpoints/login.ts b/framework/saleor/api/endpoints/login.ts new file mode 100644 index 000000000..d09c976c3 --- /dev/null +++ b/framework/saleor/api/endpoints/login.ts @@ -0,0 +1 @@ +export default function (_commerce: any) {} diff --git a/framework/saleor/api/endpoints/logout.ts b/framework/saleor/api/endpoints/logout.ts new file mode 100644 index 000000000..d09c976c3 --- /dev/null +++ b/framework/saleor/api/endpoints/logout.ts @@ -0,0 +1 @@ +export default function (_commerce: any) {} diff --git a/framework/saleor/api/endpoints/signup.ts b/framework/saleor/api/endpoints/signup.ts new file mode 100644 index 000000000..d09c976c3 --- /dev/null +++ b/framework/saleor/api/endpoints/signup.ts @@ -0,0 +1 @@ +export default function (_commerce: any) {} diff --git a/framework/saleor/api/endpoints/wishlist.ts b/framework/saleor/api/endpoints/wishlist.ts new file mode 100644 index 000000000..d09c976c3 --- /dev/null +++ b/framework/saleor/api/endpoints/wishlist.ts @@ -0,0 +1 @@ +export default function (_commerce: any) {} diff --git a/framework/saleor/api/index.ts b/framework/saleor/api/index.ts index b3b938401..5ae5f3a8a 100644 --- a/framework/saleor/api/index.ts +++ b/framework/saleor/api/index.ts @@ -16,26 +16,7 @@ export interface SaleorConfig extends CommerceAPIConfig { storeChannel: string } -export class Config { - private config: SaleorConfig - - constructor(config: SaleorConfig) { - this.config = config - } - - getConfig(userConfig: Partial = {}) { - return Object.entries(userConfig).reduce( - (cfg, [key, value]) => Object.assign(cfg, { [key]: value }), - { ...this.config } - ) - } - - setConfig(newConfig: Partial) { - Object.assign(this.config, newConfig) - } -} - -const config = new Config({ +const config: SaleorConfig = { locale: 'en-US', commerceUrl: Const.API_URL, apiToken: Const.SALEOR_TOKEN, @@ -44,12 +25,25 @@ const config = new Config({ fetch: fetchGraphqlApi, customerCookie: '', storeChannel: Const.API_CHANNEL, -}) - -export function getConfig(userConfig?: Partial) { - return config.getConfig(userConfig) } -export function setConfig(newConfig: Partial) { - return config.setConfig(newConfig) +import { + CommerceAPI, + getCommerceApi as commerceApi, +} from '@commerce/api' + +import * as operations from './operations' + +export interface ShopifyConfig extends CommerceAPIConfig {} + +export const provider = { config, operations } + +export type Provider = typeof provider + +export type SaleorAPI

= CommerceAPI

+ +export function getCommerceApi

( + customProvider: P = provider as any +): SaleorAPI

{ + return commerceApi(customProvider) } diff --git a/framework/saleor/api/operations/get-all-pages.ts b/framework/saleor/api/operations/get-all-pages.ts new file mode 100644 index 000000000..f3ed54e27 --- /dev/null +++ b/framework/saleor/api/operations/get-all-pages.ts @@ -0,0 +1,50 @@ +import type { OperationContext } from '@commerce/api/operations' + +import { QueryPagesArgs, PageCountableEdge } from '../../schema' +import type { SaleorConfig, Provider } from '..' +import * as Query from '../../utils/queries' + +export type Page = any + + export type GetAllPagesResult< + T extends { pages: any[] } = { pages: Page[] } + > = T + +export default function getAllPagesOperation({ + commerce, +}: OperationContext) { + + async function getAllPages({ + query = Query.PageMany, + config, + variables, + }: { + url?: string + config?: Partial + variables?: QueryPagesArgs + preview?: boolean + query?: string + } = {}): Promise { + const { fetch, locale, locales = ['en-US'] } = commerce.getConfig(config) + + const { data } = await fetch(query, { variables }, + { + ...(locale && { + headers: { + 'Accept-Language': locale, + }, + }), + } + ) + + const pages = data.pages?.edges?.map(({ node: { title: name, slug, ...node } }: PageCountableEdge) => ({ + ...node, + url: `/${locale}/${slug}`, + name, + })) + + return { pages } + } + + return getAllPages +} diff --git a/framework/saleor/api/operations/get-all-product-paths.ts b/framework/saleor/api/operations/get-all-product-paths.ts new file mode 100644 index 000000000..43ce7de94 --- /dev/null +++ b/framework/saleor/api/operations/get-all-product-paths.ts @@ -0,0 +1,46 @@ +import type { OperationContext } from '@commerce/api/operations' +import { + GetAllProductPathsQuery, + GetAllProductPathsQueryVariables, + ProductCountableEdge, +} from '../../schema' +import type { ShopifyConfig, Provider, SaleorConfig } from '..' + +import { getAllProductsPathsQuery } from '../../utils/queries' +import fetchAllProducts from '../utils/fetch-all-products' + +export type GetAllProductPathsResult = { + products: Array<{ path: string }> +} + +export default function getAllProductPathsOperation({ + commerce, +}: OperationContext) { + + async function getAllProductPaths({ + query, + config, + variables, + }: { + query?: string + config?: SaleorConfig + variables?: any + } = {}): Promise { + config = commerce.getConfig(config) + + const products = await fetchAllProducts({ + config, + query: getAllProductsPathsQuery, + variables, + }) + + return { + products: products?.map(({ node: { slug } }: ProductCountableEdge) => ({ + path: `/${slug}`, + })), + } + + } + + return getAllProductPaths +} diff --git a/framework/saleor/api/operations/get-all-products.ts b/framework/saleor/api/operations/get-all-products.ts new file mode 100644 index 000000000..575581491 --- /dev/null +++ b/framework/saleor/api/operations/get-all-products.ts @@ -0,0 +1,50 @@ +import type { OperationContext } from '@commerce/api/operations' +import { Product } from '@commerce/types/product' + +import { ProductCountableEdge } from '../../schema' +import type { Provider, SaleorConfig } from '..' +import { normalizeProduct } from '../../utils' + +import * as Query from '../../utils/queries' + +type ReturnType = { + products: Product[] +} + +export default function getAllProductsOperation({ + commerce, +}: OperationContext) { + async function getAllProducts({ + query = Query.ProductMany, + variables, + config, + }: { + query?: string + variables?: any + config?: Partial + preview?: boolean + featured?: boolean + } = {}): Promise { + const { fetch, locale } = commerce.getConfig(config) + + const { data } = await fetch( + query, + { variables }, + { + ...(locale && { + headers: { + 'Accept-Language': locale, + }, + }), + } + ) + + const products = data.products?.edges?.map(({ node: p }: ProductCountableEdge) => normalizeProduct(p)) ?? [] + + return { + products, + } + } + + return getAllProducts +} diff --git a/framework/saleor/api/operations/get-page.ts b/framework/saleor/api/operations/get-page.ts new file mode 100644 index 000000000..af2d5b8e6 --- /dev/null +++ b/framework/saleor/api/operations/get-page.ts @@ -0,0 +1,51 @@ +import type { OperationContext } from '@commerce/api/operations' +import type { Provider, SaleorConfig } from '..' +import { QueryPageArgs } from '../../schema' + +import * as Query from '../../utils/queries' + +export type Page = any + + export type GetPageResult = T + +export default function getPageOperation({ + commerce, +}: OperationContext) { + + async function getPage({ + query = Query.PageOne, + variables, + config, + }: { + query?: string + variables: QueryPageArgs, + config?: Partial + preview?: boolean + }): Promise { + const { fetch, locale = 'en-US' } = commerce.getConfig(config) + + const { + data: { page }, + } = await fetch(query, { variables }, + { + ...(locale && { + headers: { + 'Accept-Language': locale, + }, + }), + } + ) + + return { + page: page + ? { + ...page, + name: page.title, + url: `/${locale}/${page.slug}`, + } + : null, + } + } + + return getPage +} diff --git a/framework/saleor/api/operations/get-product.ts b/framework/saleor/api/operations/get-product.ts new file mode 100644 index 000000000..85fca934a --- /dev/null +++ b/framework/saleor/api/operations/get-product.ts @@ -0,0 +1,46 @@ +import type { OperationContext } from '@commerce/api/operations' +import { normalizeProduct, } from '../../utils' +import type { Provider, SaleorConfig } from '..' + +import * as Query from '../../utils/queries' + +type Variables = { + slug: string +} + +type ReturnType = { + product: any +} + +export default function getProductOperation({ + commerce, +}: OperationContext) { + async function getProduct({ + query = Query.ProductOneBySlug, + variables, + config: cfg, + }: { + query?: string + variables: Variables + config?: Partial + preview?: boolean + }): Promise { + const { fetch, locale } = commerce.getConfig(cfg) + + const { data } = await fetch(query, { variables }, + { + ...(locale && { + headers: { + 'Accept-Language': locale, + }, + }), + } + ) + + return { + product: data?.product ? normalizeProduct(data.product) : null, + } + } + + return getProduct +} diff --git a/framework/saleor/api/operations/get-site-info.ts b/framework/saleor/api/operations/get-site-info.ts new file mode 100644 index 000000000..eca0f2246 --- /dev/null +++ b/framework/saleor/api/operations/get-site-info.ts @@ -0,0 +1,35 @@ +import type { OperationContext } from '@commerce/api/operations' +import { Category } from '@commerce/types/site' +import type { SaleorConfig, Provider } from '..' + +import { getCategories, getVendors } from '../../utils' + +interface GetSiteInfoResult { + categories: Category[] + brands: any[] +} + +export default function getSiteInfoOperation({ commerce }: OperationContext) { + async function getSiteInfo({ + query, + config, + variables, + }: { + query?: string + config?: Partial + preview?: boolean + variables?: any + } = {}): Promise { + const cfg = commerce.getConfig(config) + + const categories = await getCategories(cfg) + const brands = await getVendors(cfg) + + return { + categories, + brands, + } + } + + return getSiteInfo +} diff --git a/framework/saleor/api/operations/index.ts b/framework/saleor/api/operations/index.ts new file mode 100644 index 000000000..7872a20b6 --- /dev/null +++ b/framework/saleor/api/operations/index.ts @@ -0,0 +1,7 @@ +export { default as getAllPages } from './get-all-pages' +export { default as getPage } from './get-page' +export { default as getAllProducts } from './get-all-products' +export { default as getAllProductPaths } from './get-all-product-paths' +export { default as getProduct } from './get-product' +export { default as getSiteInfo } from './get-site-info' +export { default as login } from './login' diff --git a/framework/saleor/api/operations/login.ts b/framework/saleor/api/operations/login.ts new file mode 100644 index 000000000..ca680b82c --- /dev/null +++ b/framework/saleor/api/operations/login.ts @@ -0,0 +1,42 @@ +import type { ServerResponse } from 'http' +import type { OperationContext } from '@commerce/api/operations' +import type { Provider, SaleorConfig } from '..' +import { + throwUserErrors, +} from '../../utils' + +import * as Mutation from '../../utils/mutations' + +export default function loginOperation({ + commerce, +}: OperationContext) { + async function login({ + query = Mutation.SessionCreate, + variables, + config, + }: { + query?: string + variables: any + res: ServerResponse + config?: SaleorConfig + }): Promise { + config = commerce.getConfig(config) + + const { data: { customerAccessTokenCreate } } = await config.fetch(query, { variables }) + + throwUserErrors(customerAccessTokenCreate?.customerUserErrors) + + const customerAccessToken = customerAccessTokenCreate?.customerAccessToken + const accessToken = customerAccessToken?.accessToken + + // if (accessToken) { + // setCustomerToken(accessToken) + // } + + return { + result: customerAccessToken?.accessToken, + } + } + + return login +} diff --git a/framework/saleor/api/utils/create-api-handler.ts b/framework/saleor/api/utils/create-api-handler.ts deleted file mode 100644 index 73aab4b37..000000000 --- a/framework/saleor/api/utils/create-api-handler.ts +++ /dev/null @@ -1,50 +0,0 @@ -import type { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' -import { SaleorConfig, getConfig } from '..' - -export type SaleorApiHandler = ( - req: NextApiRequest, - res: NextApiResponse>, - config: SaleorConfig, - handlers: H, - // Custom configs that may be used by a particular handler - options: Options -) => void | Promise - -export type SaleorHandler = (options: { - req: NextApiRequest - res: NextApiResponse> - config: SaleorConfig - body: Body -}) => void | Promise - -export type SaleorHandlers = { - [k: string]: SaleorHandler -} - -export type SaleorApiResponse = { - data: T | null - errors?: { message: string; code?: string }[] -} - -export default function createApiHandler( - handler: SaleorApiHandler, - handlers: H, - defaultOptions: Options -) { - return function getApiHandler({ - config, - operations, - options, - }: { - config?: SaleorConfig - operations?: Partial - options?: Options extends {} ? Partial : never - } = {}): NextApiHandler { - const ops = { ...operations, ...handlers } - const opts = { ...defaultOptions, ...options } - - return function apiHandler(req, res) { - return handler(req, res, getConfig(config), ops, opts) - } - } -} diff --git a/framework/saleor/api/utils/fetch-graphql-api.ts b/framework/saleor/api/utils/fetch-graphql-api.ts index 465eacba7..71199d661 100644 --- a/framework/saleor/api/utils/fetch-graphql-api.ts +++ b/framework/saleor/api/utils/fetch-graphql-api.ts @@ -3,12 +3,11 @@ import fetch from './fetch' import { API_URL } from '../../const' import { getError } from '../../utils/handle-fetch-response' -import { getConfig } from '..' +import { getCommerceApi } from '..' import { getToken } from '@framework/utils' const fetchGraphqlApi: GraphQLFetcher = async (query: string, { variables } = {}, fetchOptions) => { - // FIXME @zaiste follow the bigcommerce example - const config = getConfig() + const config = getCommerceApi().getConfig() const token = getToken() const res = await fetch(API_URL!, { diff --git a/framework/saleor/auth/use-login.tsx b/framework/saleor/auth/use-login.tsx index 333b48694..2a31c932b 100644 --- a/framework/saleor/auth/use-login.tsx +++ b/framework/saleor/auth/use-login.tsx @@ -7,10 +7,11 @@ import * as mutation from '../utils/mutations' import { Mutation, MutationTokenCreateArgs } from '../schema' import useLogin, { UseLogin } from '@commerce/auth/use-login' import { setCSRFToken, setToken, throwUserErrors, checkoutAttach, getCheckoutId } from '../utils' +import { LoginHook } from '@commerce/types/login' export default useLogin as UseLogin -export const handler: MutationHook = { +export const handler: MutationHook = { fetchOptions: { query: mutation.SessionCreate, }, diff --git a/framework/saleor/auth/use-logout.tsx b/framework/saleor/auth/use-logout.tsx index e48d7290f..fe75df84b 100644 --- a/framework/saleor/auth/use-logout.tsx +++ b/framework/saleor/auth/use-logout.tsx @@ -4,10 +4,11 @@ import useLogout, { UseLogout } from '@commerce/auth/use-logout' import useCustomer from '../customer/use-customer' import * as mutation from '../utils/mutations' import { setCSRFToken, setToken, setCheckoutToken } from '../utils/customer-token' +import { LogoutHook } from '@commerce/types/logout' export default useLogout as UseLogout -export const handler: MutationHook = { +export const handler: MutationHook = { fetchOptions: { query: mutation.SessionDestroy, }, diff --git a/framework/saleor/auth/use-signup.tsx b/framework/saleor/auth/use-signup.tsx index d042425c0..d9e91b468 100644 --- a/framework/saleor/auth/use-signup.tsx +++ b/framework/saleor/auth/use-signup.tsx @@ -7,10 +7,11 @@ import { AccountRegisterInput, Mutation, MutationAccountRegisterArgs } from '../ import * as mutation from '../utils/mutations' import { handleAutomaticLogin, throwUserErrors } from '../utils' +import { SignupHook } from '@commerce/types/signup' export default useSignup as UseSignup -export const handler: MutationHook = { +export const handler: MutationHook = { fetchOptions: { query: mutation.AccountCreate, }, @@ -27,6 +28,8 @@ export const handler: MutationHook -export const handler: MutationHook = { +export const handler: MutationHook = { fetchOptions: { query: mutation.CheckoutLineAdd }, async fetcher({ input: item, options, fetch }) { if (item.quantity && (!Number.isInteger(item.quantity) || item.quantity! < 1)) { diff --git a/framework/saleor/cart/use-cart.tsx b/framework/saleor/cart/use-cart.tsx index 1f2890d60..ab80ea395 100644 --- a/framework/saleor/cart/use-cart.tsx +++ b/framework/saleor/cart/use-cart.tsx @@ -1,14 +1,14 @@ import { useMemo } from 'react' -import useCommerceCart, { FetchCartInput, UseCart } from '@commerce/cart/use-cart' +import useCommerceCart, { UseCart } from '@commerce/cart/use-cart' -import { Cart } from '../types' import { SWRHook } from '@commerce/utils/types' import { checkoutCreate, checkoutToCart, getCheckoutId } from '../utils' import * as query from '../utils/queries' +import { GetCartHook } from '@commerce/types/cart' export default useCommerceCart as UseCart -export const handler: SWRHook = { +export const handler: SWRHook = { fetchOptions: { query: query.CheckoutOne, }, diff --git a/framework/saleor/cart/use-remove-item.tsx b/framework/saleor/cart/use-remove-item.tsx index 35cafaba0..81f9c122f 100644 --- a/framework/saleor/cart/use-remove-item.tsx +++ b/framework/saleor/cart/use-remove-item.tsx @@ -1,25 +1,17 @@ import { useCallback } from 'react' -import type { MutationHookContext, HookFetcherContext } from '@commerce/utils/types' -import { RemoveCartItemBody } from '@commerce/types' -import { ValidationError } from '@commerce/utils/errors' -import useRemoveItem, { RemoveItemInput as RemoveItemInputBase, UseRemoveItem } from '@commerce/cart/use-remove-item' +import type { MutationHookContext, HookFetcherContext, MutationHook } from '@commerce/utils/types' +import useRemoveItem, { UseRemoveItem } from '@commerce/cart/use-remove-item' import useCart from './use-cart' import * as mutation from '../utils/mutations' import { getCheckoutId, checkoutToCart } from '../utils' -import { Cart, LineItem } from '../types' import { Mutation, MutationCheckoutLineDeleteArgs } from '../schema' - -export type RemoveItemFn = T extends LineItem - ? (input?: RemoveItemInput) => Promise - : (input: RemoveItemInput) => Promise - -export type RemoveItemInput = T extends LineItem ? Partial : RemoveItemInputBase +import { LineItem, RemoveItemHook } from '../types/cart' export default useRemoveItem as UseRemoveItem export const handler = { fetchOptions: { query: mutation.CheckoutLineDelete }, - async fetcher({ input: { itemId }, options, fetch }: HookFetcherContext) { + async fetcher({ input: { itemId }, options, fetch }: HookFetcherContext) { const data = await fetch({ ...options, variables: { @@ -29,25 +21,19 @@ export const handler = { }) return checkoutToCart(data.checkoutLineDelete) }, - useHook: - ({ fetch }: MutationHookContext) => - (ctx: { item?: T } = {}) => { - const { item } = ctx + useHook: ({ fetch }: MutationHookContext) => < + T extends LineItem | undefined = undefined + > () => { const { mutate } = useCart() - const removeItem: RemoveItemFn = async (input) => { - const itemId = input?.id ?? item?.id - if (!itemId) { - throw new ValidationError({ - message: 'Invalid input used for this operation', - }) - } + return useCallback( + async function removeItem(input) { + const data = await fetch({ input: { itemId: input.id } }) + await mutate(data, false) - const data = await fetch({ input: { itemId } }) - await mutate(data, false) - return data - } - - return useCallback(removeItem as RemoveItemFn, [fetch, mutate]) + return data + }, + [fetch, mutate] + ); }, } diff --git a/framework/saleor/cart/use-update-item.tsx b/framework/saleor/cart/use-update-item.tsx index ae9f7f039..361ae5cdf 100644 --- a/framework/saleor/cart/use-update-item.tsx +++ b/framework/saleor/cart/use-update-item.tsx @@ -2,26 +2,32 @@ import { useCallback } from 'react' import debounce from 'lodash.debounce' import type { HookFetcherContext, MutationHookContext } from '@commerce/utils/types' import { ValidationError } from '@commerce/utils/errors' -import useUpdateItem, { UpdateItemInput as UpdateItemInputBase, UseUpdateItem } from '@commerce/cart/use-update-item' +import useUpdateItem, { UseUpdateItem } from '@commerce/cart/use-update-item' import useCart from './use-cart' import { handler as removeItemHandler } from './use-remove-item' -import type { Cart, LineItem, UpdateCartItemBody } from '../types' +import type { LineItem } from '../types' import { checkoutToCart } from '../utils' import { getCheckoutId } from '../utils' import { Mutation, MutationCheckoutLinesUpdateArgs } from '../schema' import * as mutation from '../utils/mutations' -export type UpdateItemInput = T extends LineItem - ? Partial> - : UpdateItemInputBase +import type { UpdateItemHook } from '../types/cart' + +export type UpdateItemActionInput = T extends LineItem + ? Partial + : UpdateItemHook['actionInput'] export default useUpdateItem as UseUpdateItem export const handler = { fetchOptions: { query: mutation.CheckoutLineUpdate }, - async fetcher({ input: { itemId, item }, options, fetch }: HookFetcherContext) { + async fetcher({ + input: { itemId, item }, + options, + fetch + }: HookFetcherContext) { if (Number.isInteger(item.quantity)) { // Also allow the update hook to remove an item if the quantity is lower than 1 if (item.quantity! < 1) { @@ -53,8 +59,7 @@ export const handler = { return checkoutToCart(checkoutLinesUpdate) }, - useHook: - ({ fetch }: MutationHookContext) => + useHook: ({ fetch }: MutationHookContext) => ( ctx: { item?: T @@ -65,7 +70,7 @@ export const handler = { const { mutate } = useCart() as any return useCallback( - debounce(async (input: UpdateItemInput) => { + debounce(async (input: UpdateItemActionInput) => { const itemId = input.id ?? item?.id const productId = input.productId ?? item?.productId const variantId = input.productId ?? item?.variantId diff --git a/framework/saleor/common/get-all-pages.ts b/framework/saleor/common/get-all-pages.ts deleted file mode 100644 index 69c460a0d..000000000 --- a/framework/saleor/common/get-all-pages.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { getConfig, SaleorConfig } from '../api' -import { PageCountableEdge } from '../schema' -import * as query from '../utils/queries' - -type Variables = { - first?: number -} - -type ReturnType = { - pages: Page[] -} - -export type Page = { - id: string - name: string - url: string - sort_order?: number - body: string -} - -const getAllPages = async (options?: { - variables?: Variables - config: SaleorConfig - preview?: boolean -}): Promise => { - let { config, variables = { first: 100 } } = options ?? {} - config = getConfig(config) - const { locale } = config - const { data } = await config.fetch(query.PageMany, { variables }) - - const pages = data.pages?.edges?.map(({ node: { title: name, slug, ...node } }: PageCountableEdge) => ({ - ...node, - url: `/${locale}/${slug}`, - name, - })) - - return { pages } -} - -export default getAllPages diff --git a/framework/saleor/common/get-page.ts b/framework/saleor/common/get-page.ts deleted file mode 100644 index 003504010..000000000 --- a/framework/saleor/common/get-page.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { getConfig, SaleorConfig } from '../api' -import { Page } from './get-all-pages' - -import * as query from '../utils/queries' - -type Variables = { - id: string -} - -export type GetPageResult = T - -const getPage = async (options: { - variables: Variables - config: SaleorConfig - preview?: boolean -}): Promise => { - let { config, variables } = options ?? {} - - config = getConfig(config) - const { locale } = config - - const { data } = await config.fetch(query.PageOne, { variables }) - const page = data.page - - return { - page: page - ? { - ...page, - name: page.title, - url: `/${locale}/${page.slug}`, - } - : null, - } -} - -export default getPage diff --git a/framework/saleor/common/get-site-info.ts b/framework/saleor/common/get-site-info.ts deleted file mode 100644 index 439fe385f..000000000 --- a/framework/saleor/common/get-site-info.ts +++ /dev/null @@ -1,31 +0,0 @@ -import getCategories, { Category } from '../utils/get-categories' -import getVendors, { Brands } from '../utils/get-vendors' - -import { getConfig, SaleorConfig } from '../api' - -export type GetSiteInfoResult< - T extends { categories: any[]; brands: any[] } = { - categories: Category[] - brands: Brands - } -> = T - -const getSiteInfo = async (options?: { - variables?: any - config: SaleorConfig - preview?: boolean -}): Promise => { - let { config } = options ?? {} - - config = getConfig(config) - - const categories = await getCategories(config) - const brands = await getVendors(config) - - return { - categories, - brands, - } -} - -export default getSiteInfo diff --git a/framework/saleor/customer/get-customer-id.ts b/framework/saleor/customer/get-customer-id.ts deleted file mode 100644 index 97bde3905..000000000 --- a/framework/saleor/customer/get-customer-id.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { getConfig, SaleorConfig } from '../api' -import * as query from '../utils/queries' -import Cookies from 'js-cookie' - -async function getCustomerId({ - customerToken: customerAccesToken, - config, -}: { - customerToken: string - config?: SaleorConfig -}): Promise { - config = getConfig(config) - - const { data } = await config.fetch(query.CustomerOne, { - variables: { - customerAccesToken: customerAccesToken || Cookies.get(config.customerCookie), - }, - }) - - return data.customer?.id -} - -export default getCustomerId diff --git a/framework/saleor/customer/use-customer.tsx b/framework/saleor/customer/use-customer.tsx index a84c3d593..1e0e63d5a 100644 --- a/framework/saleor/customer/use-customer.tsx +++ b/framework/saleor/customer/use-customer.tsx @@ -1,12 +1,12 @@ import useCustomer, { UseCustomer } from '@commerce/customer/use-customer' -import { Customer } from '@commerce/types' +import { CustomerHook } from '@commerce/types/customer' import { SWRHook } from '@commerce/utils/types' import * as query from '../utils/queries' export default useCustomer as UseCustomer -export const handler: SWRHook = { +export const handler: SWRHook = { fetchOptions: { query: query.CustomerCurrent, }, diff --git a/framework/saleor/product/get-all-collections.ts b/framework/saleor/product/get-all-collections.ts deleted file mode 100644 index 3b1ae9410..000000000 --- a/framework/saleor/product/get-all-collections.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { CollectionCountableEdge } from '../schema' -import { getConfig, SaleorConfig } from '../api' -import * as query from '../utils/queries' - -const getAllCollections = async (options?: { variables?: any; config: SaleorConfig; preview?: boolean }) => { - let { config, variables = { first: 100 } } = options ?? {} - config = getConfig(config) - - const { data } = await config.fetch(query.CollectionMany, { variables }) - const edges = data.collections?.edges ?? [] - - const categories = edges.map(({ node: { id: entityId, name, slug } }: CollectionCountableEdge) => ({ - entityId, - name, - path: `/${slug}`, - })) - - return { - categories, - } -} - -export default getAllCollections diff --git a/framework/saleor/product/get-all-product-paths.ts b/framework/saleor/product/get-all-product-paths.ts deleted file mode 100644 index e2c289561..000000000 --- a/framework/saleor/product/get-all-product-paths.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { getConfig, SaleorConfig } from '../api' -import fetchAllProducts from '../api/utils/fetch-all-products' -import { ProductCountableEdge } from '../schema' -import { getAllProductsPathsQuery } from '../utils/queries' - -type ProductPath = { - path: string -} - -export type ProductPathNode = { - node: ProductPath -} - -type ReturnType = { - products: ProductPathNode[] -} - -const getAllProductPaths = async (options?: { - variables?: any - config?: SaleorConfig - preview?: boolean -}): Promise => { - let { config, variables = { first: 100 } } = options ?? {} - config = getConfig(config) - - const products = await fetchAllProducts({ - config, - query: getAllProductsPathsQuery, - variables, - }) - - return { - products: products?.map(({ node: { slug } }: ProductCountableEdge) => ({ - node: { - path: `/${slug}`, - }, - })), - } -} - -export default getAllProductPaths diff --git a/framework/saleor/product/get-all-products.ts b/framework/saleor/product/get-all-products.ts deleted file mode 100644 index c2c5fe811..000000000 --- a/framework/saleor/product/get-all-products.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { GraphQLFetcherResult } from '@commerce/api' -import { Product } from '@commerce/types' - -import { getConfig, SaleorConfig } from '../api' -import { ProductCountableEdge } from '../schema' -import { normalizeProduct } from '../utils/normalize' - -import * as query from '../utils/queries' - -type Variables = { - first?: number - field?: string -} - -type ReturnType = { - products: Product[] -} - -const getAllProducts = async (options: { - variables?: Variables - config?: SaleorConfig - preview?: boolean - featured?: boolean -}): Promise => { - let { config, variables = { first: 100 }, featured } = options ?? {} - config = getConfig(config) - - if (featured) { - const { data }: GraphQLFetcherResult = await config.fetch(query.CollectionOne, { - variables: { ...variables, categoryId: 'Q29sbGVjdGlvbjoxOQ==' }, - }) - - debugger - - const products = data.collection.products?.edges?.map(({ node: p }: ProductCountableEdge) => normalizeProduct(p)) ?? [] - - return { - products, - } - - } else { - const { data }: GraphQLFetcherResult = await config.fetch(query.ProductMany, { - variables, - }) - - const products = data.products?.edges?.map(({ node: p }: ProductCountableEdge) => normalizeProduct(p)) ?? [] - - return { - products, - } - } -} - -export default getAllProducts diff --git a/framework/saleor/product/get-product.ts b/framework/saleor/product/get-product.ts deleted file mode 100644 index e45aea19c..000000000 --- a/framework/saleor/product/get-product.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { GraphQLFetcherResult } from '@commerce/api' -import { getConfig, SaleorConfig } from '../api' -import { normalizeProduct } from '../utils' -import * as query from '../utils/queries' - -type Variables = { - slug: string -} - -type ReturnType = { - product: any -} - -const getProduct = async (options: { - variables: Variables - config: SaleorConfig - preview?: boolean -}): Promise => { - let { config, variables } = options ?? {} - config = getConfig(config) - - const { data }: GraphQLFetcherResult = await config.fetch(query.ProductOneBySlug, { variables }) - - return { - product: data?.product ? normalizeProduct(data.product) : null, - } -} - -export default getProduct diff --git a/framework/saleor/product/use-search.tsx b/framework/saleor/product/use-search.tsx index 7a1aa1594..cc763c4b7 100644 --- a/framework/saleor/product/use-search.tsx +++ b/framework/saleor/product/use-search.tsx @@ -1,18 +1,19 @@ import { SWRHook } from '@commerce/utils/types' -import { Product } from '@commerce/types' +import { Product } from '@commerce/types/product' import useSearch, { UseSearch } from '@commerce/product/use-search' import { ProductCountableEdge } from '../schema' import { getSearchVariables, normalizeProduct } from '../utils' import * as query from '../utils/queries' +import { SearchProductsHook } from '@commerce/types/product' export default useSearch as UseSearch export type SearchProductsInput = { search?: string - categoryId?: string - brandId?: string + categoryId?: string | number + brandId?: string | number sort?: string } @@ -21,7 +22,7 @@ export type SearchProductsData = { found: boolean } -export const handler: SWRHook = { +export const handler: SWRHook = { fetchOptions: { query: query.ProductMany, }, diff --git a/framework/saleor/types.ts b/framework/saleor/types.ts index 746a3217b..2025b8898 100644 --- a/framework/saleor/types.ts +++ b/framework/saleor/types.ts @@ -1,4 +1,4 @@ -import * as Core from '@commerce/types' +import type { Cart as CoreCart } from '@commerce/types' import { CheckoutLine } from './schema' export type SaleorCheckout = { @@ -7,10 +7,10 @@ export type SaleorCheckout = { lineItems: CheckoutLine[] } -export type Cart = Core.Cart & { +export type Cart = CoreCart.Cart & { lineItems: LineItem[] } -export interface LineItem extends Core.LineItem { +export interface LineItem extends CoreCart.LineItem { options?: any[] } @@ -23,21 +23,21 @@ export type OptionSelections = { option_value: number | string } -export type CartItemBody = Core.CartItemBody & { +export type CartItemBody = CoreCart.CartItemBody & { productId: string // The product id is always required for BC optionSelections?: OptionSelections } -export type GetCartHandlerBody = Core.GetCartHandlerBody +// export type GetCartHandlerBody = CoreCart.GetCartHandlerBody -export type AddCartItemBody = Core.AddCartItemBody +// export type AddCartItemBody = Core.AddCartItemBody -export type AddCartItemHandlerBody = Core.AddCartItemHandlerBody +// export type AddCartItemHandlerBody = Core.AddCartItemHandlerBody -export type UpdateCartItemBody = Core.UpdateCartItemBody +// export type UpdateCartItemBody = Core.UpdateCartItemBody -export type UpdateCartItemHandlerBody = Core.UpdateCartItemHandlerBody +// export type UpdateCartItemHandlerBody = Core.UpdateCartItemHandlerBody -export type RemoveCartItemBody = Core.RemoveCartItemBody +// export type RemoveCartItemBody = Core.RemoveCartItemBody -export type RemoveCartItemHandlerBody = Core.RemoveCartItemHandlerBody +// export type RemoveCartItemHandlerBody = Core.RemoveCartItemHandlerBody diff --git a/framework/saleor/types/cart.ts b/framework/saleor/types/cart.ts new file mode 100644 index 000000000..1f4ba61df --- /dev/null +++ b/framework/saleor/types/cart.ts @@ -0,0 +1,32 @@ +import * as Core from '@commerce/types/cart' + +export * from '@commerce/types/cart' + +export type SaleorCart = {} + +/** + * Extend core cart types + */ + +export type Cart = Core.Cart & { + lineItems: Core.LineItem[] + url?: string +} + +export type CartTypes = Core.CartTypes + +export type CartHooks = Core.CartHooks + +export type GetCartHook = CartHooks['getCart'] +export type AddItemHook = CartHooks['addItem'] +export type UpdateItemHook = CartHooks['updateItem'] +export type RemoveItemHook = CartHooks['removeItem'] + +export type CartSchema = Core.CartSchema + +export type CartHandlers = Core.CartHandlers + +export type GetCartHandler = CartHandlers['getCart'] +export type AddItemHandler = CartHandlers['addItem'] +export type UpdateItemHandler = CartHandlers['updateItem'] +export type RemoveItemHandler = CartHandlers['removeItem'] diff --git a/framework/saleor/utils/get-categories.ts b/framework/saleor/utils/get-categories.ts index 04402c2ae..990c0a404 100644 --- a/framework/saleor/utils/get-categories.ts +++ b/framework/saleor/utils/get-categories.ts @@ -1,13 +1,8 @@ +import { Category } from '@commerce/types/site' import { SaleorConfig } from '../api' import { CollectionCountableEdge } from '../schema' import * as query from './queries' -export type Category = { - entityId: string - name: string - path: string -} - const getCategories = async (config: SaleorConfig): Promise => { const { data } = await config.fetch(query.CollectionMany, { variables: { @@ -16,9 +11,10 @@ const getCategories = async (config: SaleorConfig): Promise => { }) return ( - data.collections?.edges?.map(({ node: { id: entityId, name, slug } }: CollectionCountableEdge) => ({ - entityId, + data.collections?.edges?.map(({ node: { id, name, slug } }: CollectionCountableEdge) => ({ + id, name, + slug, path: `/${slug}`, })) ?? [] ) diff --git a/framework/saleor/utils/normalize.ts b/framework/saleor/utils/normalize.ts index 91188a65a..a7e13a92e 100644 --- a/framework/saleor/utils/normalize.ts +++ b/framework/saleor/utils/normalize.ts @@ -1,4 +1,4 @@ -import { Product } from '@commerce/types' +import { Product } from '@commerce/types/product' import { Product as SaleorProduct, Checkout, CheckoutLine, Money, ProductVariant } from '../schema' @@ -120,7 +120,7 @@ function normalizeLineItem({ id, variant, quantity }: CheckoutLine): LineItem { sku: variant?.sku ?? '', name: variant?.name!, image: { - url: variant?.media![0].url ?? placeholderImg, + url: variant?.media![0] ? variant?.media![0].url : placeholderImg, }, requiresShipping: false, price: variant?.pricing?.price?.gross.amount!, diff --git a/package.json b/package.json index b8cbc0121..5034d7e0c 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,7 @@ "postcss-flexbugs-fixes": "^5.0.2", "postcss-preset-env": "^6.7.0", "prettier": "^2.3.0", - "typescript": "^4.2.4" + "typescript": "4.2.4" }, "husky": { "hooks": { diff --git a/yarn.lock b/yarn.lock index 5d9029897..9dbfca574 100644 --- a/yarn.lock +++ b/yarn.lock @@ -921,25 +921,25 @@ resolved "https://registry.yarnpkg.com/@next/react-refresh-utils/-/react-refresh-utils-10.0.9-canary.5.tgz#5ece6594ec08b48bc319d8f171d9c46a7beb04ba" integrity sha512-47Y2GO+PezgJF4t41/VOEmIpUe66bbzbh/jO+doldwoPiLPxrSfOMpAnlJLpm5keHquBJMCIQbwDtmSpNvPkTg== -"@nodelib/fs.scandir@2.1.4": - version "2.1.4" - resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69" - integrity sha512-33g3pMJk3bg5nXbL/+CY6I2eJDzZAni49PfJnL5fghPTggPvBd/pFNSgJsdAgWptuFu7qq/ERvOYFlhvsLTCKA== +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== dependencies: - "@nodelib/fs.stat" "2.0.4" + "@nodelib/fs.stat" "2.0.5" run-parallel "^1.1.9" -"@nodelib/fs.stat@2.0.4", "@nodelib/fs.stat@^2.0.2": - version "2.0.4" - resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz#a3f2dd61bab43b8db8fa108a121cfffe4c676655" - integrity sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q== +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== "@nodelib/fs.walk@^1.2.3": - version "1.2.6" - resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.6.tgz#cce9396b30aa5afe9e3756608f5831adcb53d063" - integrity sha512-8Broas6vTtW4GIXTAHDoE32hnN2M5ykgCpWGbuXHQ15vEMqr23pB76e/GZcYsZCHALv50ktd24qhEyKr6wBtow== + version "1.2.7" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.7.tgz#94c23db18ee4653e129abd26fb06f870ac9e1ee2" + integrity sha512-BTIhocbPBSrRmHxOAJFtR18oLhxTtAFDAvL8hY1S3iU8k+E60W/YFs4jrixGzQjMpF4qPXxIQHcjVD9dz1C2QA== dependencies: - "@nodelib/fs.scandir" "2.1.4" + "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" "@opentelemetry/api@0.14.0": @@ -1081,21 +1081,16 @@ dependencies: "@types/node" "*" -"@types/node@*": - version "15.3.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-15.3.1.tgz#23a06b87eedb524016616e886b116b8fdcb180af" - integrity sha512-weaeiP4UF4XgF++3rpQhpIJWsCTS4QJw5gvBhQu6cFIxTwyxWIe3xbnrY/o2lTCQ0lsdb8YIUDUvLR4Vuz5rbw== +"@types/node@*", "@types/node@^15.6.1": + version "15.12.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-15.12.1.tgz#9b60797dee1895383a725f828a869c86c6caa5c2" + integrity sha512-zyxJM8I1c9q5sRMtVF+zdd13Jt6RU4r4qfhTd7lQubyThvLfx6yYekWSQjGCGV2Tkecgxnlpl/DNlb6Hg+dmEw== "@types/node@10.12.18": version "10.12.18" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== -"@types/node@^15.6.1": - version "15.6.1" - resolved "https://registry.yarnpkg.com/@types/node/-/node-15.6.1.tgz#32d43390d5c62c5b6ec486a9bc9c59544de39a08" - integrity sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA== - "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" @@ -1107,9 +1102,9 @@ integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== "@types/react@^17.0.8": - version "17.0.8" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.8.tgz#fe76e3ba0fbb5602704110fd1e3035cf394778e3" - integrity sha512-3sx4c0PbXujrYAKwXxNONXUtRp9C+hE2di0IuxFyf5BELD+B+AXL8G7QrmSKhVwKZDbv0igiAjQAMhXj8Yg3aw== + version "17.0.9" + resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.9.tgz#1147fb520024a62c9b3841f5cb4db89b73ddb87f" + integrity sha512-2Cw7FvevpJxQrCb+k5t6GH1KIvmadj5uBbjPaLlJB/nZWUj56e1ZqcD6zsoMFB47MsJUTFl9RJ132A7hb3QFJA== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" @@ -1766,15 +1761,10 @@ camelcase@^5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== -caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001173, caniuse-lite@^1.0.30001179, caniuse-lite@^1.0.30001219: - version "1.0.30001228" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001228.tgz#bfdc5942cd3326fa51ee0b42fbef4da9d492a7fa" - integrity sha512-QQmLOGJ3DEgokHbMSA8cj2a+geXqmnpyOFT0lhQV6P3/YOJvGDEwoedcwxEQ30gJIwIIunHIicunJ2rzK5gB2A== - -caniuse-lite@^1.0.30001230: - version "1.0.30001231" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001231.tgz#6c1f9b49fc27cc368b894e64b9b28b39ef80603b" - integrity sha512-WAFFv31GgU4DiwNAy77qMo3nNyycEhH3ikcCVHvkQpPe/fO8Tb2aRYzss8kgyLQBm8mJ7OryW4X6Y4vsBCIqag== +caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001173, caniuse-lite@^1.0.30001179, caniuse-lite@^1.0.30001219, caniuse-lite@^1.0.30001230: + version "1.0.30001234" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001234.tgz#8fc2e709e3b0679d7af7f073a1c661155c39b975" + integrity sha512-a3gjUVKkmwLdNysa1xkUAwN2VfJUJyVW47rsi3aCbkRCtbHAfo+rOsCqVw29G6coQ8gzAPb5XBXwiGHwme3isA== capital-case@^1.0.4: version "1.0.4" @@ -2584,9 +2574,9 @@ ecdsa-sig-formatter@1.0.11: safe-buffer "^5.0.1" electron-to-chromium@^1.3.634, electron-to-chromium@^1.3.723: - version "1.3.734" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.734.tgz#c8d318a4eb27509190cf3a08870dbcbf06c74dcb" - integrity sha512-iQF2mjPZ6zNNq45kbJ6MYZYCBNdv2JpGiJC/lVx4tGJWi9MNg73KkL9sWGN4X4I/CP2SBLWsT8nPADZZpAHIyw== + version "1.3.749" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.749.tgz#0ecebc529ceb49dd2a7c838ae425236644c3439a" + integrity sha512-F+v2zxZgw/fMwPz/VUGIggG4ZndDsYy0vlpthi3tjmDZlcfbhN5mYW0evXUsBr2sUtuDANFtle410A9u/sd/4A== elegant-spinner@^1.0.1: version "1.0.1" @@ -2672,9 +2662,9 @@ error-ex@^1.3.1: is-arrayish "^0.2.1" es-abstract@^1.18.0-next.1: - version "1.18.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.0.tgz#ab80b359eecb7ede4c298000390bc5ac3ec7b5a4" - integrity sha512-LJzK7MrQa8TS0ja2w3YNLzUgJCGPdPOV1yVvezjNnS89D+VR08+Szt2mz3YB2Dck/+w5tfIq/RoUAFqJJGM2yw== + version "1.18.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.18.3.tgz#25c4c3380a27aa203c44b2b685bba94da31b63e0" + integrity sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw== dependencies: call-bind "^1.0.2" es-to-primitive "^1.2.1" @@ -2684,14 +2674,14 @@ es-abstract@^1.18.0-next.1: has-symbols "^1.0.2" is-callable "^1.2.3" is-negative-zero "^2.0.1" - is-regex "^1.1.2" - is-string "^1.0.5" - object-inspect "^1.9.0" + is-regex "^1.1.3" + is-string "^1.0.6" + object-inspect "^1.10.3" object-keys "^1.1.1" object.assign "^4.1.2" string.prototype.trimend "^1.0.4" string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.0" + unbox-primitive "^1.0.1" es-to-primitive@^1.2.1: version "1.2.1" @@ -2778,9 +2768,9 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: safe-buffer "^5.1.1" execa@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-5.0.1.tgz#aee63b871c9b2cb56bc9addcd3c70a785c6bf0d1" - integrity sha512-4hFTjFbFzQa3aCLobpbPJR/U+VoL1wdV5ozOWjeet0AWDeYr9UFGM1eUFWHX+VtOWFq4p0xXUXfW1YxUaP4fpw== + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== dependencies: cross-spawn "^7.0.3" get-stream "^6.0.0" @@ -3150,9 +3140,9 @@ graphql-tag@^2.11.0: tslib "^2.1.0" graphql-ws@^4.4.1: - version "4.7.0" - resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-4.7.0.tgz#b323fbf35a3736eed85dac24c0054d6d10c93e62" - integrity sha512-Md8SsmC9ZlsogFPd3Ot8HbIAAqsHh8Xoq7j4AmcIat1Bh6k91tjVyQvA0Au1/BolXSYq+RDvib6rATU2Hcf1Xw== + version "4.8.0" + resolved "https://registry.yarnpkg.com/graphql-ws/-/graphql-ws-4.8.0.tgz#4b0a82fa1ad00a3baa1cae980032dcaaad08b339" + integrity sha512-0jk0c7GPfAlQfA7xZ4CKlLvFF4JBPYbczIHIXl/tk/fXoCLzmrmwQ/HNwOoOHfFMS3usbD1nt77k67pgXx2BYQ== graphql@^15.5.0: version "15.5.0" @@ -3559,7 +3549,7 @@ is-promise@^2.1.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== -is-regex@^1.1.2: +is-regex@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.3.tgz#d029f9aff6448b93ebbe3f33dac71511fdcbef9f" integrity sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ== @@ -3594,7 +3584,7 @@ is-stream@^2.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== -is-string@^1.0.5: +is-string@^1.0.5, is-string@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.6.tgz#3fe5d5992fb0d93404f32584d4b0179a71b54a5f" integrity sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w== @@ -4208,17 +4198,17 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.47.0: - version "1.47.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.47.0.tgz#8cb313e59965d3c05cfbf898915a267af46a335c" - integrity sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw== +mime-db@1.48.0: + version "1.48.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.48.0.tgz#e35b31045dd7eada3aaad537ed88a33afbef2d1d" + integrity sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ== mime-types@^2.1.12: - version "2.1.30" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.30.tgz#6e7be8b4c479825f85ed6326695db73f9305d62d" - integrity sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg== + version "2.1.31" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.31.tgz#a00d76b74317c61f9c2db2218b8e9f8e9c5c9e6b" + integrity sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg== dependencies: - mime-db "1.47.0" + mime-db "1.48.0" mime@^2.3.1: version "2.5.2" @@ -4512,7 +4502,7 @@ object-hash@^2.1.1: resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5" integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw== -object-inspect@^1.9.0: +object-inspect@^1.10.3: version "1.10.3" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.3.tgz#c2aa7d2d09f50c99375704f7a0adf24c5782d369" integrity sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw== @@ -5210,16 +5200,7 @@ postcss@^7.0.14, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.32, postcss@^7.0. source-map "^0.6.1" supports-color "^6.1.0" -postcss@^8.1.6, postcss@^8.1.7, postcss@^8.2.1: - version "8.2.15" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.2.15.tgz#9e66ccf07292817d226fc315cbbf9bc148fbca65" - integrity sha512-2zO3b26eJD/8rb106Qu2o7Qgg52ND5HPjcyQiK2B98O388h43A448LCslC0dI2P97wCAQRJsFvwTRcXxTKds+Q== - dependencies: - colorette "^1.2.2" - nanoid "^3.1.23" - source-map "^0.6.1" - -postcss@^8.3.0: +postcss@^8.1.6, postcss@^8.1.7, postcss@^8.2.1, postcss@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.0.tgz#b1a713f6172ca427e3f05ef1303de8b65683325f" integrity sha512-+ogXpdAjWGa+fdYY5BQ96V/6tAo+TdSSIMP5huJBIygdWwKtVoB5JWZ7yUd4xZ8r+8Kvvx4nyg/PQ071H4UtcQ== @@ -5258,9 +5239,9 @@ prepend-http@^2.0.0: integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= prettier@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.0.tgz#b6a5bf1284026ae640f17f7ff5658a7567fc0d18" - integrity sha512-kXtO4s0Lz/DW/IJ9QdWhAf7/NmPWQXkFr/r/WkR3vyI+0v8amTDxiaQSLzs8NBlytfLWX/7uQUMIW677yLKl4w== + version "2.3.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.3.1.tgz#76903c3f8c4449bc9ac597acefa24dc5ad4cbea6" + integrity sha512-p+vNbgpLjif/+D+DwAZAbndtRrR0md0MwfmOVN9N+2RgyACMT+7tfaRnT+WDPkqnuVwleyuBIG2XBxKDme3hPA== pretty-hrtime@^1.0.3: version "1.0.3" @@ -6151,9 +6132,9 @@ tabbable@^5.2.0: integrity sha512-0uyt8wbP0P3T4rrsfYg/5Rg3cIJ8Shl1RJ54QMqYxm1TLdWqJD1u6+RQjr2Lor3wmfT7JRHkirIwy99ydBsyPg== tailwindcss@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-2.1.2.tgz#29402bf73a445faedd03df6d3b177e7b52b7c4a1" - integrity sha512-T5t+wwd+/hsOyRw2HJuFuv0LTUm3MUdHm2DJ94GPVgzqwPPFa9XxX0KlwLWupUuiOUj6uiKURCzYPHFcuPch/w== + version "2.1.4" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-2.1.4.tgz#ee8a1b8ccc140db61960b6738f968a8a1c4cd1f8" + integrity sha512-fh1KImDLg6se/Suaelju/5oFbqq1b0ntagmGLu0aG9LlnNPGHgO1n/4E57CbKcCtyz/VYnvVXUiWmfyfBBZQ6g== dependencies: "@fullhuman/postcss-purgecss" "^3.1.3" bytes "^3.0.0" @@ -6350,12 +6331,17 @@ type-fest@^0.7.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.7.1.tgz#8dda65feaf03ed78f0a3f9678f1869147f7c5c48" integrity sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg== +typescript@4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.2.4.tgz#8610b59747de028fda898a8aef0e103f156d0961" + integrity sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg== + typescript@^3.9.5, typescript@^3.9.7: version "3.9.9" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.9.tgz#e69905c54bc0681d0518bd4d587cc6f2d0b1a674" integrity sha512-kdMjTiekY+z/ubJCATUPlRDl39vXYiMV9iyeMuEuXZh2we6zz80uovNN2WlAxmmdE/Z/YQe+EbOEXB5RHEED3w== -typescript@^4.2.3, typescript@^4.2.4: +typescript@^4.2.3: version "4.3.2" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.2.tgz#399ab18aac45802d6f2498de5054fcbbe716a805" integrity sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw== @@ -6365,7 +6351,7 @@ ua-parser-js@^0.7.18: resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.28.tgz#8ba04e653f35ce210239c64661685bf9121dec31" integrity sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g== -unbox-primitive@^1.0.0: +unbox-primitive@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==