setup custom fetcher and auth hooks

This commit is contained in:
Greg Hoskin 2021-03-27 15:54:32 -06:00
parent 753234dc51
commit ee1d8ed461
37 changed files with 299 additions and 103 deletions

View File

@ -7,3 +7,6 @@ BIGCOMMERCE_CHANNEL_ID=
SHOPIFY_STORE_DOMAIN=
SHOPIFY_STOREFRONT_ACCESS_TOKEN=
SWELL_STORE_ID=
SWELL_PUBLIC_KEY=

15
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "pwa-chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:8080",
"webRoot": "${workspaceFolder}"
}
]
}

View File

@ -1,7 +1,7 @@
{
"provider": "bigcommerce",
"provider": "swell",
"features": {
"wishlist": true,
"wishlist": false,
"customCheckout": false
}
}

View File

@ -4,7 +4,7 @@
const merge = require('deepmerge')
const PROVIDERS = ['bigcommerce', 'shopify']
const PROVIDERS = ['bigcommerce', 'shopify', 'swell']
function getProviderName() {
return process.env.BIGCOMMERCE_STOREFRONT_API_URL ? 'bigcommerce' : null

View File

@ -1,2 +1,5 @@
SHOPIFY_STORE_DOMAIN=
SHOPIFY_STOREFRONT_ACCESS_TOKEN=
NEXT_PUBLIC_SWELL_STORE_ID=
NEXT_PUBLIC_SWELL_PUBLIC_KEY=

View File

@ -22,23 +22,23 @@ if (!API_TOKEN) {
import fetchGraphqlApi from './utils/fetch-graphql-api'
export interface ShopifyConfig extends CommerceAPIConfig {}
export interface SwellConfig extends CommerceAPIConfig {}
export class Config {
private config: ShopifyConfig
private config: SwellConfig
constructor(config: ShopifyConfig) {
constructor(config: SwellConfig) {
this.config = config
}
getConfig(userConfig: Partial<ShopifyConfig> = {}) {
return Object.entries(userConfig).reduce<ShopifyConfig>(
getConfig(userConfig: Partial<SwellConfig> = {}) {
return Object.entries(userConfig).reduce<SwellConfig>(
(cfg, [key, value]) => Object.assign(cfg, { [key]: value }),
{ ...this.config }
)
}
setConfig(newConfig: Partial<ShopifyConfig>) {
setConfig(newConfig: Partial<SwellConfig>) {
Object.assign(this.config, newConfig)
}
}
@ -53,10 +53,10 @@ const config = new Config({
customerCookie: SHOPIFY_CUSTOMER_TOKEN_COOKIE,
})
export function getConfig(userConfig?: Partial<ShopifyConfig>) {
export function getConfig(userConfig?: Partial<SwellConfig>) {
return config.getConfig(userConfig)
}
export function setConfig(newConfig: Partial<ShopifyConfig>) {
export function setConfig(newConfig: Partial<SwellConfig>) {
return config.setConfig(newConfig)
}

View File

@ -1,8 +1,8 @@
import Client from 'shopify-buy'
import { ShopifyConfig } from '../index'
import { SwellConfig } from '../index'
type Options = {
config: ShopifyConfig
config: SwellConfig
}
const getAllCollections = async (options: Options) => {

View File

@ -1,5 +1,5 @@
import { Page } from '../../schema'
import { ShopifyConfig, getConfig } from '..'
import { SwellConfig, getConfig } from '..'
export type GetPageResult<T extends { page?: any } = { page?: Page }> = T
@ -15,7 +15,7 @@ async function getPage({
}: {
url?: string
variables: PageVariables
config?: ShopifyConfig
config?: SwellConfig
preview?: boolean
}): Promise<GetPageResult> {
config = getConfig(config)

View File

@ -1,5 +1,5 @@
import type { NextApiHandler, NextApiRequest, NextApiResponse } from 'next'
import { ShopifyConfig, getConfig } from '..'
import { SwellConfig, getConfig } from '..'
export type ShopifyApiHandler<
T = any,
@ -8,7 +8,7 @@ export type ShopifyApiHandler<
> = (
req: NextApiRequest,
res: NextApiResponse<ShopifyApiResponse<T>>,
config: ShopifyConfig,
config: SwellConfig,
handlers: H,
// Custom configs that may be used by a particular handler
options: Options
@ -17,7 +17,7 @@ export type ShopifyApiHandler<
export type ShopifyHandler<T = any, Body = null> = (options: {
req: NextApiRequest
res: NextApiResponse<ShopifyApiResponse<T>>
config: ShopifyConfig
config: SwellConfig
body: Body
}) => void | Promise<void>
@ -44,7 +44,7 @@ export default function createApiHandler<
operations,
options,
}: {
config?: ShopifyConfig
config?: SwellConfig
operations?: Partial<H>
options?: Options extends {} ? Partial<Options> : never
} = {}): NextApiHandler {

View File

@ -1,5 +1,5 @@
import { ProductEdge } from '../../schema'
import { ShopifyConfig } from '..'
import { SwellConfig } from '..'
const fetchAllProducts = async ({
config,
@ -8,7 +8,7 @@ const fetchAllProducts = async ({
acc = [],
cursor,
}: {
config: ShopifyConfig
config: SwellConfig
query: string
acc?: ProductEdge[]
variables?: any

View File

@ -25,7 +25,8 @@ const getErrorMessage = ({ code, message }: CustomerUserError) => {
export const handler: MutationHook<null, {}, CustomerAccessTokenCreateInput> = {
fetchOptions: {
query: createCustomerAccessTokenMutation,
query: 'account',
method: 'login',
},
async fetcher({ input: { email, password }, options, fetch }) {
if (!(email && password)) {
@ -40,9 +41,7 @@ export const handler: MutationHook<null, {}, CustomerAccessTokenCreateInput> = {
MutationCheckoutCreateArgs
>({
...options,
variables: {
input: { email, password },
},
variables: [email, password],
})
const errors = customerAccessTokenCreate?.customerUserErrors

View File

@ -9,7 +9,8 @@ export default useLogout as UseLogout<typeof handler>
export const handler: MutationHook<null> = {
fetchOptions: {
query: customerAccessTokenDeleteMutation,
query: 'account',
method: 'logout',
},
async fetcher({ options, fetch }) {
await fetch({

View File

@ -20,7 +20,8 @@ export const handler: MutationHook<
CustomerCreateInput
> = {
fetchOptions: {
query: customerCreateMutation,
query: 'account',
method: 'create',
},
async fetcher({
input: { firstName, lastName, email, password },
@ -36,23 +37,20 @@ export const handler: MutationHook<
const data = await fetch({
...options,
variables: {
input: {
firstName,
lastName,
email,
password,
},
first_name: firstName,
last_name: lastName,
email,
password,
},
})
try {
const loginData = await fetch({
query: customerAccessTokenCreateMutation,
query: 'account',
method: 'login',
variables: {
input: {
email,
password,
},
email,
password,
},
})
handleLogin(loginData)

View File

@ -18,7 +18,8 @@ export const handler: SWRHook<
{ isEmpty?: boolean }
> = {
fetchOptions: {
query: getCheckoutQuery,
query: 'cart',
method: 'get',
},
async fetcher({ input: { cartId: checkoutId }, options, fetch }) {
let checkout

View File

@ -1,5 +1,5 @@
{
"provider": "shopify",
"provider": "swell",
"features": {
"wishlist": false
}

View File

@ -1,4 +1,4 @@
import { getConfig, ShopifyConfig } from '../api'
import { getConfig, SwellConfig } from '../api'
import { PageEdge } from '../schema'
import { getAllPagesQuery } from '../utils/queries'
@ -20,7 +20,7 @@ export type Page = {
const getAllPages = async (options?: {
variables?: Variables
config: ShopifyConfig
config: SwellConfig
preview?: boolean
}): Promise<ReturnType> => {
let { config, variables = { first: 250 } } = options ?? {}

View File

@ -1,4 +1,4 @@
import { getConfig, ShopifyConfig } from '../api'
import { getConfig, SwellConfig } from '../api'
import getPageQuery from '../utils/queries/get-page-query'
import { Page } from './get-all-pages'
@ -10,7 +10,7 @@ export type GetPageResult<T extends { page?: any } = { page?: Page }> = T
const getPage = async (options: {
variables: Variables
config: ShopifyConfig
config: SwellConfig
preview?: boolean
}): Promise<GetPageResult> => {
let { config, variables } = options ?? {}

View File

@ -1,7 +1,7 @@
import getCategories, { Category } from '../utils/get-categories'
import getVendors, { Brands } from '../utils/get-vendors'
import { getConfig, ShopifyConfig } from '../api'
import { getConfig, SwellConfig } from '../api'
export type GetSiteInfoResult<
T extends { categories: any[]; brands: any[] } = {
@ -12,7 +12,7 @@ export type GetSiteInfoResult<
const getSiteInfo = async (options?: {
variables?: any
config: ShopifyConfig
config: SwellConfig
preview?: boolean
}): Promise<GetSiteInfoResult> => {
let { config } = options ?? {}

View File

@ -11,3 +11,7 @@ export const SHOPIFY_COOKIE_EXPIRE = 30
export const API_URL = `https://${STORE_DOMAIN}/api/2021-01/graphql.json`
export const API_TOKEN = process.env.NEXT_PUBLIC_SHOPIFY_STOREFRONT_ACCESS_TOKEN
export const SWELL_STORE_ID = process.env.NEXT_PUBLIC_SWELL_STORE_ID
export const SWELL_PUBLIC_KEY = process.env.NEXT_PUBLIC_SWELL_PUBLIC_KEY

View File

@ -1,4 +1,4 @@
import { getConfig, ShopifyConfig } from '../api'
import { getConfig, SwellConfig } from '../api'
import getCustomerIdQuery from '../utils/queries/get-customer-id-query'
import Cookies from 'js-cookie'
@ -7,7 +7,7 @@ async function getCustomerId({
config,
}: {
customerToken: string
config?: ShopifyConfig
config?: SwellConfig
}): Promise<number | undefined> {
config = getConfig(config)

View File

@ -1,20 +1,25 @@
import useCustomer, { UseCustomer } from '@commerce/customer/use-customer'
import { Customer } from '@commerce/types'
import { SWRHook } from '@commerce/utils/types'
import { getCustomerQuery, getCustomerToken } from '../utils'
import { normalizeCustomer } from '../utils/normalize'
// import { getCustomerQuery, getCustomerToken } from '../utils'
export default useCustomer as UseCustomer<typeof handler>
export const handler: SWRHook<Customer | null> = {
fetchOptions: {
query: getCustomerQuery,
query: 'account',
method: 'get',
},
async fetcher({ options, fetch }) {
// console.log('STORE_ID', STORE_ID, 'PUBLIC_KEY', PUBLIC_KEY);
// const data = await swell.account.get()
const data = await fetch<any | null>({
...options,
variables: { customerAccessToken: getCustomerToken() },
// variables: { customerAccessToken: getCustomerToken() },
})
return data.customer ?? null
console.log(`Customer data ${data}`)
return data ? normalizeCustomer(data) : null
},
useHook: ({ useData }) => (input) => {
return useData({
@ -25,3 +30,26 @@ export const handler: SWRHook<Customer | null> = {
})
},
}
// const handler = (): { data: Customer } => {
// const swell = getContext();
// const response = swell.account.get();
// const { firstName, lastName, email, company, customerGroupId, notes, phone,
// entityId, addressCount, attributeCount, storeCredit } = response;
// return {
// data: {
// firstName,
// lastName,
// email,
// company,
// customerGroupId,
// notes,
// phone,
// entityId,
// addressCount,
// attributeCount,
// storeCredit
// }
// }
// }
// export default handler;

View File

@ -1,18 +1,25 @@
import { Fetcher } from '@commerce/utils/types'
import { API_TOKEN, API_URL } from './const'
import { handleFetchResponse } from './utils'
import { swellConfig } from './index'
const fetcher: Fetcher = async ({ method = 'POST', variables, query }) => {
return handleFetchResponse(
await fetch(API_URL, {
method,
body: JSON.stringify({ query, variables }),
headers: {
'X-Shopify-Storefront-Access-Token': API_TOKEN!,
'Content-Type': 'application/json',
},
})
)
const fetcher: Fetcher = async ({ method = 'get', variables, query }) => {
const { swell } = swellConfig
async function callSwell() {
if (Array.isArray(variables)) {
const arg1 = variables[0]
const arg2 = variables[1]
const response = await swell[query][method](arg1, arg2)
console.log(response)
return handleFetchResponse(response)
} else {
const response = await swell[query][method](variables)
console.log(response)
return handleFetchResponse(response)
}
}
if (query) {
return await callSwell()
}
}
export default fetcher

View File

@ -1,4 +1,5 @@
import * as React from 'react'
import swell from 'swell-js'
import { ReactNode } from 'react'
import {
@ -7,30 +8,36 @@ import {
useCommerce as useCoreCommerce,
} from '@commerce'
import { shopifyProvider, ShopifyProvider } from './provider'
import { SHOPIFY_CHECKOUT_ID_COOKIE } from './const'
import { swellProvider, SwellProvider } from './provider'
import {
SHOPIFY_CHECKOUT_ID_COOKIE,
SWELL_STORE_ID,
SWELL_PUBLIC_KEY,
} from './const'
swell.init(SWELL_STORE_ID, SWELL_PUBLIC_KEY)
export { shopifyProvider }
export type { ShopifyProvider }
export { swellProvider }
export type { SwellProvider }
export const shopifyConfig: CommerceConfig = {
export const swellConfig: any = {
locale: 'en-us',
cartCookie: SHOPIFY_CHECKOUT_ID_COOKIE,
swell,
}
export type ShopifyConfig = Partial<CommerceConfig>
export type SwellConfig = Partial<CommerceConfig>
export type ShopifyProps = {
export type SwellProps = {
children?: ReactNode
locale: string
} & ShopifyConfig
} & SwellConfig
export function CommerceProvider({ children, ...config }: ShopifyProps) {
export function CommerceProvider({ children, ...config }: SwellProps) {
return (
<CoreCommerceProvider
// TODO: Fix this type
provider={shopifyProvider as any}
config={{ ...shopifyConfig, ...config }}
provider={swellProvider as any}
config={{ ...swellConfig, ...config }}
>
{children}
</CoreCommerceProvider>

View File

@ -1,10 +1,10 @@
import { CollectionEdge } from '../schema'
import { getConfig, ShopifyConfig } from '../api'
import { getConfig, SwellConfig } from '../api'
import getAllCollectionsQuery from '../utils/queries/get-all-collections-query'
const getAllCollections = async (options?: {
variables?: any
config: ShopifyConfig
config: SwellConfig
preview?: boolean
}) => {
let { config, variables = { first: 250 } } = options ?? {}

View File

@ -1,5 +1,5 @@
import { Product } from '@commerce/types'
import { getConfig, ShopifyConfig } from '../api'
import { getConfig, SwellConfig } from '../api'
import fetchAllProducts from '../api/utils/fetch-all-products'
import { ProductEdge } from '../schema'
import getAllProductsPathsQuery from '../utils/queries/get-all-products-paths-query'
@ -18,7 +18,7 @@ type ReturnType = {
const getAllProductPaths = async (options?: {
variables?: any
config?: ShopifyConfig
config?: SwellConfig
preview?: boolean
}): Promise<ReturnType> => {
let { config, variables = { first: 250 } } = options ?? {}

View File

@ -1,5 +1,5 @@
import { GraphQLFetcherResult } from '@commerce/api'
import { getConfig, ShopifyConfig } from '../api'
import { getConfig, SwellConfig } from '../api'
import { ProductEdge } from '../schema'
import { getAllProductsQuery } from '../utils/queries'
import { normalizeProduct } from '../utils/normalize'
@ -16,7 +16,7 @@ type ReturnType = {
const getAllProducts = async (options: {
variables?: Variables
config?: ShopifyConfig
config?: SwellConfig
preview?: boolean
}): Promise<ReturnType> => {
let { config, variables = { first: 250 } } = options ?? {}

View File

@ -1,5 +1,5 @@
import { GraphQLFetcherResult } from '@commerce/api'
import { getConfig, ShopifyConfig } from '../api'
import { getConfig, SwellConfig } from '../api'
import { normalizeProduct, getProductQuery } from '../utils'
type Variables = {
@ -12,7 +12,7 @@ type ReturnType = {
const getProduct = async (options: {
variables: Variables
config: ShopifyConfig
config: SwellConfig
preview?: boolean
}): Promise<ReturnType> => {
let { config, variables } = options ?? {}

View File

@ -14,7 +14,7 @@ import { handler as useSignup } from './auth/use-signup'
import fetcher from './fetcher'
export const shopifyProvider = {
export const swellProvider = {
locale: 'en-us',
cartCookie: SHOPIFY_CHECKOUT_ID_COOKIE,
storeDomain: STORE_DOMAIN,
@ -28,4 +28,4 @@ export const shopifyProvider = {
},
}
export type ShopifyProvider = typeof shopifyProvider
export type SwellProvider = typeof swellProvider

1
framework/swell/swell-js.d.ts vendored Normal file
View File

@ -0,0 +1 @@
declare module 'swell-js'

View File

@ -1,6 +1,11 @@
import * as Core from '@commerce/types'
import { CheckoutLineItem } from './schema'
export interface SwellCustomer extends Core.Customer {
first_name: string
last_name: string
}
export type ShopifyCheckout = {
id: string
webUrl: string

View File

@ -1,4 +1,4 @@
import { ShopifyConfig } from '../api'
import { SwellConfig } from '../api'
import { CollectionEdge } from '../schema'
import getSiteCollectionsQuery from './queries/get-all-collections-query'
@ -8,7 +8,7 @@ export type Category = {
path: string
}
const getCategories = async (config: ShopifyConfig): Promise<Category[]> => {
const getCategories = async (config: SwellConfig): Promise<Category[]> => {
const { data } = await config.fetch(getSiteCollectionsQuery, {
variables: {
first: 250,

View File

@ -1,4 +1,4 @@
import { ShopifyConfig } from '../api'
import { SwellConfig } from '../api'
import fetchAllProducts from '../api/utils/fetch-all-products'
import getAllProductVendors from './queries/get-all-product-vendors-query'
@ -13,7 +13,7 @@ export type BrandEdge = {
export type Brands = BrandEdge[]
const getVendors = async (config: ShopifyConfig): Promise<BrandEdge[]> => {
const getVendors = async (config: SwellConfig): Promise<BrandEdge[]> => {
const vendors = await fetchAllProducts({
config,
query: getAllProductVendors,

View File

@ -11,15 +11,16 @@ export async function getAsyncError(res: Response) {
}
const handleFetchResponse = async (res: Response) => {
if (res.ok) {
const { data, errors } = await res.json()
// if (res.ok) {
// const { data, errors } = await res.json()
if (errors && errors.length) {
throw getError(errors, res.status)
}
// if (errors && errors.length) {
// throw getError(errors, res.status)
// }
return data
}
// return data
// }
if (res) return res
throw await getAsyncError(res)
}

View File

@ -1,4 +1,5 @@
import { Product } from '@commerce/types'
import { Customer } from '@commerce/types'
import {
Product as ShopifyProduct,
@ -11,7 +12,7 @@ import {
ProductOption,
} from '../schema'
import type { Cart, LineItem } from '../types'
import type { Cart, LineItem, SwellCustomer } from '../types'
const money = ({ amount, currencyCode }: MoneyV2) => {
return {
@ -121,6 +122,15 @@ export function normalizeCart(checkout: Checkout): Cart {
}
}
export function normalizeCustomer(customer: SwellCustomer): Customer {
const { first_name: firstName, last_name: lastName } = customer
return {
...customer,
firstName,
lastName,
}
}
function normalizeLineItem({
node: { id, title, variant, quantity },
}: CheckoutLineItemEdge): LineItem {

View File

@ -42,6 +42,7 @@
"react-merge-refs": "^1.1.0",
"react-ticker": "^1.2.2",
"shopify-buy": "^2.11.0",
"swell-js": "^4.0.0-next.0",
"swr": "^0.4.0",
"tabbable": "^5.1.5",
"tailwindcss": "^2.0.3"

View File

@ -22,10 +22,10 @@
"@components/*": ["components/*"],
"@commerce": ["framework/commerce"],
"@commerce/*": ["framework/commerce/*"],
"@framework": ["framework/bigcommerce"],
"@framework/*": ["framework/bigcommerce/*"]
"@framework": ["framework/swell"],
"@framework/*": ["framework/swell/*"]
}
},
"include": ["next-env.d.ts", "**/*.d.ts", "**/*.ts", "**/*.tsx", "**/*.js"],
"exclude": ["node_modules"]
"exclude": ["node_modules", "swell-js"]
}

118
yarn.lock
View File

@ -401,6 +401,13 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@7.4.5":
version "7.4.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.5.tgz#582bb531f5f9dc67d2fcb682979894f75e253f12"
integrity sha512-TuI4qpWZP6lGOGIuGWtp9sPluqYICmbk8T/1vpSysqJxRPkudh/ofFWyqdcMsDf2s7KvDL4/YHgKyvcS3g9CJQ==
dependencies:
regenerator-runtime "^0.13.2"
"@babel/runtime@^7.0.0":
version "7.12.13"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.13.tgz#0a21452352b02542db0ffb928ac2d3ca7cb6d66d"
@ -408,6 +415,13 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.12.13", "@babel/runtime@^7.13.10":
version "7.13.10"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.13.10.tgz#47d42a57b6095f4468da440388fdbad8bebf0d7d"
integrity sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/template@^7.12.13":
version "7.12.13"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.12.13.tgz#530265be8a2589dbb37523844c5bcb55947fb327"
@ -1522,6 +1536,14 @@ array-flatten@^3.0.0:
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-3.0.0.tgz#6428ca2ee52c7b823192ec600fa3ed2f157cd541"
integrity sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==
array-includes-with-glob@^3.0.6:
version "3.0.8"
resolved "https://registry.yarnpkg.com/array-includes-with-glob/-/array-includes-with-glob-3.0.8.tgz#522a982e7913a9e6397efd3d933aa3cc61776cb2"
integrity sha512-g1XH4sJ/LMdyUSDB/9pNEC/eEO62chSTIi9I5agGHi4NI90SASER1Qe4emrTgCeaNPCAcivfi3Ba0owq6Pwo4Q==
dependencies:
"@babel/runtime" "^7.13.10"
matcher "^4.0.0"
array-union@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
@ -2542,7 +2564,7 @@ deep-is@~0.1.3:
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
deepmerge@^4.2.2:
deepmerge@4.2.2, deepmerge@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955"
integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==
@ -2914,6 +2936,11 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
escape-string-regexp@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
escodegen@^1.8.0:
version "1.14.3"
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503"
@ -3896,7 +3923,7 @@ isobject@^4.0.0:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-4.0.0.tgz#3f1c9155e73b192022a80819bacd0343711697b0"
integrity sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==
isomorphic-fetch@^3.0.0:
isomorphic-fetch@3.0.0, isomorphic-fetch@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-3.0.0.tgz#0267b005049046d2421207215d45d6a262b8b8b4"
integrity sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==
@ -4219,6 +4246,16 @@ lodash._reinterpolate@^3.0.0:
resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d"
integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=
lodash.camelcase@^4.3.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
integrity sha1-soqmKIorn8ZRA1x3EfZathkDMaY=
lodash.clonedeep@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
lodash.debounce@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af"
@ -4239,6 +4276,11 @@ lodash.isboolean@^3.0.3:
resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
integrity sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=
lodash.isdate@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.isdate/-/lodash.isdate-4.0.1.tgz#35a543673b9d76110de4114b32cc577048a7f366"
integrity sha1-NaVDZzuddhEN5BFLMsxXcEin82Y=
lodash.isinteger@^4.0.4:
version "4.0.4"
resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
@ -4269,6 +4311,11 @@ lodash.random@^3.2.0:
resolved "https://registry.yarnpkg.com/lodash.random/-/lodash.random-3.2.0.tgz#96e24e763333199130d2c9e2fd57f91703cc262d"
integrity sha1-luJOdjMzGZEw0sni/Vf5FwPMJi0=
lodash.snakecase@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz#39d714a35357147837aefd64b5dcbb16becd8f8d"
integrity sha1-OdcUo1NXFHg3rv1ktdy7Fr7Nj40=
lodash.sortby@^4.7.0:
version "4.7.0"
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
@ -4299,6 +4346,16 @@ lodash.toarray@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561"
integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE=
lodash.uniq@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=
lodash@4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
lodash@^4.17.13, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@~4.17.20:
version "4.17.20"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
@ -4445,6 +4502,13 @@ map-obj@^4.0.0:
resolved "https://registry.yarnpkg.com/map-obj/-/map-obj-4.1.0.tgz#b91221b542734b9f14256c0132c897c5d7256fd5"
integrity sha512-glc9y00wgtwcDmp7GaE/0b0OnxpNJsVf3ael/An6Fe2Q51LLwN1er6sdomLRzz5h0+yMpiYLhWYF5R7HeqVd4g==
matcher@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/matcher/-/matcher-4.0.0.tgz#a42a05a09aaed92e2d241eb91fddac689461ea51"
integrity sha512-S6x5wmcDmsDRRU/c2dkccDwQPXoFczc5+HpQ2lON8pnvHlnvHAHj5WlLVvw6n6vNyHuVugYrFohYxbS+pvFpKQ==
dependencies:
escape-string-regexp "^4.0.0"
md5.js@^1.3.4:
version "1.3.5"
resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f"
@ -4891,11 +4955,33 @@ object-inspect@^1.9.0:
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.9.0.tgz#c90521d74e1127b67266ded3394ad6116986533a"
integrity sha512-i3Bp9iTqwhaLZBxGkRfo5ZbE07BQRT7MGu8+nNgwW9ItGp1TzCTw2DLEoWwjClxBjOFI/hWljTAmYGCEwmtnOw==
object-keys-normalizer@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/object-keys-normalizer/-/object-keys-normalizer-1.0.1.tgz#db178dbba5e4c7b18b40837c8ef83365ee9348e7"
integrity sha1-2xeNu6Xkx7GLQIN8jvgzZe6TSOc=
dependencies:
lodash.camelcase "^4.3.0"
lodash.snakecase "^4.1.1"
object-keys@^1.0.12, object-keys@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
object-merge-advanced@12.0.3:
version "12.0.3"
resolved "https://registry.yarnpkg.com/object-merge-advanced/-/object-merge-advanced-12.0.3.tgz#e03c19aa33cf88da6b32187e4907b487668808d9"
integrity sha512-xQIf2Vup1rpKiHr2tQca5jyNYgT4O0kNxOfAp3ZNonm2hS+5yaJgI0Czdk/QMy52bcRwQKX3uc3H8XtAiiYfVA==
dependencies:
"@babel/runtime" "^7.12.13"
array-includes-with-glob "^3.0.6"
lodash.clonedeep "^4.5.0"
lodash.includes "^4.3.0"
lodash.isdate "^4.0.1"
lodash.isplainobject "^4.0.6"
lodash.uniq "^4.5.0"
util-nonempty "^3.0.6"
object-path@^0.11.4:
version "0.11.5"
resolved "https://registry.yarnpkg.com/object-path/-/object-path-0.11.5.tgz#d4e3cf19601a5140a55a16ad712019a9c50b577a"
@ -5755,6 +5841,11 @@ purgecss@^3.1.3:
postcss "^8.2.1"
postcss-selector-parser "^6.0.2"
qs@6.7.0:
version "6.7.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc"
integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==
querystring-es3@^0.2.0:
version "0.2.1"
resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73"
@ -5916,7 +6007,7 @@ reduce-css-calc@^2.1.8:
css-unit-converter "^1.1.1"
postcss-value-parser "^3.3.0"
regenerator-runtime@^0.13.4:
regenerator-runtime@^0.13.2, regenerator-runtime@^0.13.4:
version "0.13.7"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55"
integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==
@ -6609,6 +6700,19 @@ supports-color@^7.0.0, supports-color@^7.1.0:
dependencies:
has-flag "^4.0.0"
swell-js@^4.0.0-next.0:
version "4.0.0-next.0"
resolved "https://registry.yarnpkg.com/swell-js/-/swell-js-4.0.0-next.0.tgz#870599372e3c9eafefeafc2c63863c4032d8be6b"
integrity sha512-OQ1FLft3ruKpQw5P0TiCzs/X2Ma95+Qz+I2Xzs4KC6v+zVaFVUGNs80dQdtjfInisWoFC7iFZF2AITgellVGAg==
dependencies:
"@babel/runtime" "7.4.5"
deepmerge "4.2.2"
isomorphic-fetch "3.0.0"
lodash "4.17.21"
object-keys-normalizer "1.0.1"
object-merge-advanced "12.0.3"
qs "6.7.0"
swr@^0.4.0:
version "0.4.2"
resolved "https://registry.yarnpkg.com/swr/-/swr-0.4.2.tgz#4a9ed5e9948088af145c79d716d294cb99712a29"
@ -6982,6 +7086,14 @@ util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=
util-nonempty@^3.0.6:
version "3.0.8"
resolved "https://registry.yarnpkg.com/util-nonempty/-/util-nonempty-3.0.8.tgz#0e53820a29e2c6cdcc3ecece52bc7fdd193c9b2b"
integrity sha512-eB6dfVQWEBMT7i9EgWigvJiHUlW/iaq/Wg6pcWviwKsPWFwgprPVilZHkTAhzmXgv9LnGOLjrszm/HvIHpbeQw==
dependencies:
"@babel/runtime" "^7.13.10"
lodash.isplainobject "^4.0.6"
util@0.10.3:
version "0.10.3"
resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9"