({
+ handler: checkoutEndpoint,
+ handlers
+});
+
+export default checkoutApi;
diff --git a/lib/spree/api/endpoints/customer/address.ts b/lib/spree/api/endpoints/customer/address.ts
new file mode 100644
index 000000000..491bf0ac9
--- /dev/null
+++ b/lib/spree/api/endpoints/customer/address.ts
@@ -0,0 +1 @@
+export default function noopApi(...args: any[]): void {}
diff --git a/lib/spree/api/endpoints/customer/card.ts b/lib/spree/api/endpoints/customer/card.ts
new file mode 100644
index 000000000..491bf0ac9
--- /dev/null
+++ b/lib/spree/api/endpoints/customer/card.ts
@@ -0,0 +1 @@
+export default function noopApi(...args: any[]): void {}
diff --git a/lib/spree/api/endpoints/customer/index.ts b/lib/spree/api/endpoints/customer/index.ts
new file mode 100644
index 000000000..491bf0ac9
--- /dev/null
+++ b/lib/spree/api/endpoints/customer/index.ts
@@ -0,0 +1 @@
+export default function noopApi(...args: any[]): void {}
diff --git a/lib/spree/api/endpoints/login/index.ts b/lib/spree/api/endpoints/login/index.ts
new file mode 100644
index 000000000..491bf0ac9
--- /dev/null
+++ b/lib/spree/api/endpoints/login/index.ts
@@ -0,0 +1 @@
+export default function noopApi(...args: any[]): void {}
diff --git a/lib/spree/api/endpoints/logout/index.ts b/lib/spree/api/endpoints/logout/index.ts
new file mode 100644
index 000000000..491bf0ac9
--- /dev/null
+++ b/lib/spree/api/endpoints/logout/index.ts
@@ -0,0 +1 @@
+export default function noopApi(...args: any[]): void {}
diff --git a/lib/spree/api/endpoints/signup/index.ts b/lib/spree/api/endpoints/signup/index.ts
new file mode 100644
index 000000000..491bf0ac9
--- /dev/null
+++ b/lib/spree/api/endpoints/signup/index.ts
@@ -0,0 +1 @@
+export default function noopApi(...args: any[]): void {}
diff --git a/lib/spree/api/endpoints/wishlist/index.tsx b/lib/spree/api/endpoints/wishlist/index.tsx
new file mode 100644
index 000000000..491bf0ac9
--- /dev/null
+++ b/lib/spree/api/endpoints/wishlist/index.tsx
@@ -0,0 +1 @@
+export default function noopApi(...args: any[]): void {}
diff --git a/lib/spree/api/index.ts b/lib/spree/api/index.ts
new file mode 100644
index 000000000..f34260992
--- /dev/null
+++ b/lib/spree/api/index.ts
@@ -0,0 +1,48 @@
+import type { CommerceAPI, CommerceAPIConfig } from '@commerce/api';
+import { getCommerceApi as commerceApi } from '@commerce/api';
+import createApiFetch from './utils/create-api-fetch';
+
+import getAllPages from './operations/get-all-pages';
+import getPage from './operations/get-page';
+import getSiteInfo from './operations/get-site-info';
+import getCustomerWishlist from './operations/get-customer-wishlist';
+import getAllProductPaths from './operations/get-all-product-paths';
+import getAllProducts from './operations/get-all-products';
+import getProduct from './operations/get-product';
+import getAllTaxons from './operations/get-all-taxons';
+import getProducts from './operations/get-products';
+
+export interface SpreeApiConfig extends CommerceAPIConfig {}
+
+const config: SpreeApiConfig = {
+ commerceUrl: '',
+ apiToken: '',
+ cartCookie: '',
+ customerCookie: '',
+ cartCookieMaxAge: 2592000,
+ fetch: createApiFetch(() => getCommerceApi().getConfig())
+};
+
+const operations = {
+ getAllPages,
+ getPage,
+ getSiteInfo,
+ getCustomerWishlist,
+ getAllProductPaths,
+ getAllProducts,
+ getProduct,
+ getAllTaxons,
+ getProducts
+};
+
+export const provider = { config, operations };
+
+export type SpreeApiProvider = typeof provider;
+
+export type SpreeApi = CommerceAPI
;
+
+export function getCommerceApi
(
+ customProvider: P = provider as any
+): SpreeApi
{
+ return commerceApi(customProvider);
+}
diff --git a/lib/spree/api/operations/get-all-pages.ts b/lib/spree/api/operations/get-all-pages.ts
new file mode 100644
index 000000000..2bbaf35e5
--- /dev/null
+++ b/lib/spree/api/operations/get-all-pages.ts
@@ -0,0 +1,72 @@
+import type { OperationContext, OperationOptions } from '@commerce/api/operations';
+import type { GetAllPagesOperation, Page } from '@commerce/types/page';
+import { requireConfigValue } from '../../isomorphic-config';
+import normalizePage from '../../utils/normalizations/normalize-page';
+import type { IPages } from '@spree/storefront-api-v2-sdk/types/interfaces/Page';
+import type { SpreeSdkVariables } from '../../types';
+import type { SpreeApiConfig, SpreeApiProvider } from '../index';
+
+export default function getAllPagesOperation({ commerce }: OperationContext) {
+ async function getAllPages(options?: {
+ config?: Partial;
+ preview?: boolean;
+ }): Promise;
+
+ async function getAllPages(
+ opts: {
+ config?: Partial;
+ preview?: boolean;
+ } & OperationOptions
+ ): Promise;
+
+ async function getAllPages({
+ config: userConfig,
+ preview,
+ query,
+ url
+ }: {
+ url?: string;
+ config?: Partial;
+ preview?: boolean;
+ query?: string;
+ } = {}): Promise {
+ console.info(
+ 'getAllPages called. Configuration: ',
+ 'query: ',
+ query,
+ 'userConfig: ',
+ userConfig,
+ 'preview: ',
+ preview,
+ 'url: ',
+ url
+ );
+
+ const config = commerce.getConfig(userConfig);
+ const { fetch: apiFetch } = config;
+
+ const variables: SpreeSdkVariables = {
+ methodPath: 'pages.list',
+ arguments: [
+ {
+ per_page: 500,
+ filter: {
+ locale_eq: config.locale || (requireConfigValue('defaultLocale') as string)
+ }
+ }
+ ]
+ };
+
+ const { data: spreeSuccessResponse } = await apiFetch('__UNUSED__', {
+ variables
+ });
+
+ const normalizedPages: Page[] = spreeSuccessResponse.data.map((spreePage) =>
+ normalizePage(spreeSuccessResponse, spreePage, config.locales || [])
+ );
+
+ return { pages: normalizedPages };
+ }
+
+ return getAllPages;
+}
diff --git a/lib/spree/api/operations/get-all-product-paths.ts b/lib/spree/api/operations/get-all-product-paths.ts
new file mode 100644
index 000000000..391724315
--- /dev/null
+++ b/lib/spree/api/operations/get-all-product-paths.ts
@@ -0,0 +1,91 @@
+import type { OperationContext, OperationOptions } from '@commerce/api/operations';
+import type { Product } from '@commerce/types/product';
+import type { GetAllProductPathsOperation } from '@commerce/types/product';
+import { requireConfigValue } from '../../isomorphic-config';
+import type { IProductsSlugs, SpreeSdkVariables } from '../../types';
+import getProductPath from '../../utils/get-product-path';
+import type { SpreeApiConfig, SpreeApiProvider } from '..';
+
+const imagesSize = requireConfigValue('imagesSize') as string;
+const imagesQuality = requireConfigValue('imagesQuality') as number;
+
+export default function getAllProductPathsOperation({
+ commerce
+}: OperationContext) {
+ async function getAllProductPaths(opts?: {
+ variables?: T['variables'];
+ config?: Partial;
+ }): Promise;
+
+ async function getAllProductPaths(
+ opts: {
+ variables?: T['variables'];
+ config?: Partial;
+ } & OperationOptions
+ ): Promise;
+
+ async function getAllProductPaths({
+ query,
+ variables: getAllProductPathsVariables = {},
+ config: userConfig
+ }: {
+ query?: string;
+ variables?: T['variables'];
+ config?: Partial;
+ } = {}): Promise {
+ console.info(
+ 'getAllProductPaths called. Configuration: ',
+ 'query: ',
+ query,
+ 'getAllProductPathsVariables: ',
+ getAllProductPathsVariables,
+ 'config: ',
+ userConfig
+ );
+
+ const productsCount = requireConfigValue('lastUpdatedProductsPrerenderCount');
+
+ if (productsCount === 0) {
+ return {
+ products: []
+ };
+ }
+
+ const variables: SpreeSdkVariables = {
+ methodPath: 'products.list',
+ arguments: [
+ {},
+ {
+ fields: {
+ product: 'slug'
+ },
+ per_page: productsCount,
+ image_transformation: {
+ quality: imagesQuality,
+ size: imagesSize
+ }
+ }
+ ]
+ };
+
+ const config = commerce.getConfig(userConfig);
+ const { fetch: apiFetch } = config; // TODO: Send config.locale to Spree.
+
+ const { data: spreeSuccessResponse } = await apiFetch(
+ '__UNUSED__',
+ {
+ variables
+ }
+ );
+
+ const normalizedProductsPaths: Pick[] = spreeSuccessResponse.data.map(
+ (spreeProduct) => ({
+ path: getProductPath(spreeProduct)
+ })
+ );
+
+ return { products: normalizedProductsPaths };
+ }
+
+ return getAllProductPaths;
+}
diff --git a/lib/spree/api/operations/get-all-products.ts b/lib/spree/api/operations/get-all-products.ts
new file mode 100644
index 000000000..3bdd722e2
--- /dev/null
+++ b/lib/spree/api/operations/get-all-products.ts
@@ -0,0 +1,84 @@
+import type { Product } from '@commerce/types/product';
+import type { GetAllProductsOperation } from '@commerce/types/product';
+import type { OperationContext, OperationOptions } from '@commerce/api/operations';
+import type { IProducts } from '@spree/storefront-api-v2-sdk/types/interfaces/Product';
+import type { SpreeApiConfig, SpreeApiProvider } from '../index';
+import type { SpreeSdkVariables } from '../../types';
+import normalizeProduct from '../../utils/normalizations/normalize-product';
+import { requireConfigValue } from '../../isomorphic-config';
+
+const imagesSize = requireConfigValue('imagesSize') as string;
+const imagesQuality = requireConfigValue('imagesQuality') as number;
+
+export default function getAllProductsOperation({ commerce }: OperationContext) {
+ async function getAllProducts(opts?: {
+ variables?: T['variables'];
+ config?: Partial;
+ preview?: boolean;
+ }): Promise;
+
+ async function getAllProducts(
+ opts: {
+ variables?: T['variables'];
+ config?: Partial;
+ preview?: boolean;
+ } & OperationOptions
+ ): Promise;
+
+ async function getAllProducts({
+ variables: getAllProductsVariables = {},
+ config: userConfig
+ }: {
+ variables?: T['variables'];
+ config?: Partial;
+ } = {}): Promise<{ products: Product[] }> {
+ console.info(
+ 'getAllProducts called. Configuration: ',
+ 'getAllProductsVariables: ',
+ getAllProductsVariables,
+ 'config: ',
+ userConfig
+ );
+
+ const defaultProductsTaxonomyId = requireConfigValue('allProductsTaxonomyId') as string | false;
+
+ const first = getAllProductsVariables.first;
+ const filter = !defaultProductsTaxonomyId
+ ? {}
+ : { filter: { taxons: defaultProductsTaxonomyId }, sort: '-updated_at' };
+
+ const variables: SpreeSdkVariables = {
+ methodPath: 'products.list',
+ arguments: [
+ {},
+ {
+ include: 'primary_variant,variants,images,option_types,variants.option_values',
+ per_page: first,
+ ...filter,
+ image_transformation: {
+ quality: imagesQuality,
+ size: imagesSize
+ }
+ }
+ ]
+ };
+
+ const config = commerce.getConfig(userConfig);
+ const { fetch: apiFetch } = config; // TODO: Send config.locale to Spree.
+
+ const { data: spreeSuccessResponse } = await apiFetch(
+ '__UNUSED__',
+ {
+ variables
+ }
+ );
+
+ const normalizedProducts: Product[] = spreeSuccessResponse.data.map((spreeProduct) =>
+ normalizeProduct(spreeSuccessResponse, spreeProduct)
+ );
+
+ return { products: normalizedProducts };
+ }
+
+ return getAllProducts;
+}
diff --git a/lib/spree/api/operations/get-all-taxons.ts b/lib/spree/api/operations/get-all-taxons.ts
new file mode 100644
index 000000000..2fff9df42
--- /dev/null
+++ b/lib/spree/api/operations/get-all-taxons.ts
@@ -0,0 +1,63 @@
+import _ from 'lodash';
+import type { ITaxons, TaxonAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/Taxon';
+import type { SpreeSdkVariables } from '../../types';
+
+const taxonsSort = (spreeTaxon1: TaxonAttr, spreeTaxon2: TaxonAttr): number => {
+ const { left: left1, right: right1 } = spreeTaxon1.attributes;
+ const { left: left2, right: right2 } = spreeTaxon2.attributes;
+
+ if (right1 < left2) {
+ return -1;
+ }
+
+ if (right2 < left1) {
+ return 1;
+ }
+
+ return 0;
+};
+
+const buildTaxonsTree = (taxons: TaxonAttr[], parentId: string | number): TaxonAttr[] => {
+ const children = _.chain(taxons)
+ .filter((item) => {
+ const relationships = item.relationships || {};
+ return parentId === _.get(relationships, 'parent.data.id');
+ })
+ .sort(taxonsSort)
+ .value();
+
+ return children.map((child) => ({
+ id: child.id,
+ name: child.attributes.name,
+ type: child.type,
+ position: child.attributes.position,
+ children: buildTaxonsTree(taxons, child.id)
+ }));
+};
+
+export default function getAllTaxonsOperation({ commerce, locale }) {
+ async function getAllTaxons(options = {}) {
+ const { config: userConfig } = options;
+
+ const config = commerce.getConfig(userConfig);
+
+ const { fetch: apiFetch } = config;
+
+ const variables: SpreeSdkVariables = {
+ methodPath: 'taxons.list',
+ arguments: [
+ {
+ locale: config.locale
+ }
+ ]
+ };
+
+ const { data: spreeSuccessResponse } = await apiFetch('__UNUSED__', { variables });
+
+ const normalizedTaxons = buildTaxonsTree(spreeSuccessResponse.data, '1');
+
+ return { taxons: normalizedTaxons };
+ }
+
+ return getAllTaxons;
+}
diff --git a/lib/spree/api/operations/get-customer-wishlist.ts b/lib/spree/api/operations/get-customer-wishlist.ts
new file mode 100644
index 000000000..f417bf0c3
--- /dev/null
+++ b/lib/spree/api/operations/get-customer-wishlist.ts
@@ -0,0 +1,6 @@
+export default function getCustomerWishlistOperation() {
+ function getCustomerWishlist(): any {
+ return { wishlist: {} };
+ }
+ return getCustomerWishlist;
+}
diff --git a/lib/spree/api/operations/get-page.ts b/lib/spree/api/operations/get-page.ts
new file mode 100644
index 000000000..fa00ffb42
--- /dev/null
+++ b/lib/spree/api/operations/get-page.ts
@@ -0,0 +1,73 @@
+import type { OperationContext, OperationOptions } from '@commerce/api/operations';
+import type { GetPageOperation } from '@commerce/types/page';
+import type { SpreeSdkVariables } from '../../types';
+import type { SpreeApiConfig, SpreeApiProvider } from '..';
+import type { IPage } from '@spree/storefront-api-v2-sdk/types/interfaces/Page';
+import normalizePage from '../../utils/normalizations/normalize-page';
+
+export type Page = any;
+export type GetPageResult = { page?: Page };
+
+export type PageVariables = {
+ id: number;
+};
+
+export default function getPageOperation({ commerce }: OperationContext) {
+ async function getPage(opts: {
+ variables: T['variables'];
+ config?: Partial;
+ preview?: boolean;
+ }): Promise;
+
+ async function getPage(
+ opts: {
+ variables: T['variables'];
+ config?: Partial;
+ preview?: boolean;
+ } & OperationOptions
+ ): Promise;
+
+ async function getPage({
+ url,
+ config: userConfig,
+ preview,
+ variables: getPageVariables
+ }: {
+ url?: string;
+ variables: T['variables'];
+ config?: Partial;
+ preview?: boolean;
+ }): Promise {
+ console.info(
+ 'getPage called. Configuration: ',
+ 'userConfig: ',
+ userConfig,
+ 'preview: ',
+ preview,
+ 'url: ',
+ url
+ );
+
+ const config = commerce.getConfig(userConfig);
+ const { fetch: apiFetch } = config;
+
+ const variables: SpreeSdkVariables = {
+ methodPath: 'pages.show',
+ arguments: [getPageVariables.id]
+ };
+
+ const { data: spreeSuccessResponse } = await apiFetch('__UNUSED__', {
+ variables
+ });
+
+ const normalizedPage: Page = normalizePage(
+ spreeSuccessResponse,
+ spreeSuccessResponse.data,
+ config.locales || []
+ );
+
+ return { page: normalizedPage };
+ }
+
+ return getPage;
+}
diff --git a/lib/spree/api/operations/get-product.ts b/lib/spree/api/operations/get-product.ts
new file mode 100644
index 000000000..bc415329f
--- /dev/null
+++ b/lib/spree/api/operations/get-product.ts
@@ -0,0 +1,81 @@
+import type { SpreeApiConfig, SpreeApiProvider } from '../index';
+import type { GetProductOperation } from '@commerce/types/product';
+import type { OperationContext, OperationOptions } from '@commerce/api/operations';
+import type { IProduct } from '@spree/storefront-api-v2-sdk/types/interfaces/Product';
+import type { SpreeSdkVariables } from '../../types';
+import MissingSlugVariableError from '../../errors/MissingSlugVariableError';
+import normalizeProduct from '../../utils/normalizations/normalize-product';
+import { requireConfigValue } from '../../isomorphic-config';
+
+const imagesSize = requireConfigValue('imagesSize') as string;
+const imagesQuality = requireConfigValue('imagesQuality') as number;
+
+export default function getProductOperation({ commerce }: OperationContext) {
+ async function getProduct(opts: {
+ variables: T['variables'];
+ config?: Partial;
+ preview?: boolean;
+ }): Promise;
+
+ async function getProduct(
+ opts: {
+ variables: T['variables'];
+ config?: Partial;
+ preview?: boolean;
+ } & OperationOptions
+ ): Promise;
+
+ async function getProduct({
+ query = '',
+ variables: getProductVariables,
+ config: userConfig
+ }: {
+ query?: string;
+ variables?: T['variables'];
+ config?: Partial;
+ preview?: boolean;
+ }): Promise {
+ console.log(
+ 'getProduct called. Configuration: ',
+ 'getProductVariables: ',
+ getProductVariables,
+ 'config: ',
+ userConfig
+ );
+
+ if (!getProductVariables?.slug) {
+ throw new MissingSlugVariableError();
+ }
+
+ const variables: SpreeSdkVariables = {
+ methodPath: 'products.show',
+ arguments: [
+ getProductVariables.slug,
+ {},
+ {
+ include: 'primary_variant,variants,images,option_types,variants.option_values',
+ image_transformation: {
+ quality: imagesQuality,
+ size: imagesSize
+ }
+ }
+ ]
+ };
+
+ const config = commerce.getConfig(userConfig);
+ const { fetch: apiFetch } = config; // TODO: Send config.locale to Spree.
+
+ const { data: spreeSuccessResponse } = await apiFetch(
+ '__UNUSED__',
+ {
+ variables
+ }
+ );
+
+ return {
+ product: normalizeProduct(spreeSuccessResponse, spreeSuccessResponse.data)
+ };
+ }
+
+ return getProduct;
+}
diff --git a/lib/spree/api/operations/get-products.js b/lib/spree/api/operations/get-products.js
new file mode 100644
index 000000000..d39c66144
--- /dev/null
+++ b/lib/spree/api/operations/get-products.js
@@ -0,0 +1,37 @@
+import normalizeProduct from '../../utils/normalizations/normalize-product';
+import { requireConfigValue } from '../../isomorphic-config';
+
+const imagesSize = requireConfigValue('imagesSize');
+const imagesQuality = requireConfigValue('imagesQuality');
+
+export default function getProductsOperation({ commerce }) {
+ async function getProducts({ taxons = [], config: userConfig } = {}) {
+ const filter = { filter: { taxons: taxons.join(',') }, sort: '-updated_at' };
+
+ const variables = {
+ methodPath: 'products.list',
+ arguments: [
+ {
+ include: 'primary_variant,variants,images,option_types,variants.option_values',
+ per_page: 100,
+ ...filter,
+ image_transformation: {
+ quality: imagesQuality,
+ size: imagesSize
+ }
+ }
+ ]
+ };
+
+ const config = commerce.getConfig(userConfig);
+ const { fetch: apiFetch } = config;
+ const { data: spreeSuccessResponse } = await apiFetch('__UNUSED__', { variables });
+ const normalizedProducts = spreeSuccessResponse.data.map((spreeProduct) =>
+ normalizeProduct(spreeSuccessResponse, spreeProduct)
+ );
+
+ return { products: normalizedProducts };
+ }
+
+ return getProducts;
+}
diff --git a/lib/spree/api/operations/get-site-info.ts b/lib/spree/api/operations/get-site-info.ts
new file mode 100644
index 000000000..94c1142ff
--- /dev/null
+++ b/lib/spree/api/operations/get-site-info.ts
@@ -0,0 +1,120 @@
+import type { OperationContext, OperationOptions } from '@commerce/api/operations';
+import type { Category, GetSiteInfoOperation } from '@commerce/types/site';
+import type { ITaxons, TaxonAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/Taxon';
+import { requireConfigValue } from '../../isomorphic-config';
+import type { SpreeSdkVariables } from '../../types';
+import type { SpreeApiConfig, SpreeApiProvider } from '..';
+
+const taxonsSort = (spreeTaxon1: TaxonAttr, spreeTaxon2: TaxonAttr): number => {
+ const { left: left1, right: right1 } = spreeTaxon1.attributes;
+ const { left: left2, right: right2 } = spreeTaxon2.attributes;
+
+ if (right1 < left2) {
+ return -1;
+ }
+
+ if (right2 < left1) {
+ return 1;
+ }
+
+ return 0;
+};
+
+export type GetSiteInfoResult<
+ T extends { categories: any[]; brands: any[] } = {
+ categories: Category[];
+ brands: any[];
+ }
+> = T;
+
+export default function getSiteInfoOperation({ commerce }: OperationContext) {
+ async function getSiteInfo(opts?: {
+ config?: Partial;
+ preview?: boolean;
+ }): Promise;
+
+ async function getSiteInfo(
+ opts: {
+ config?: Partial;
+ preview?: boolean;
+ } & OperationOptions
+ ): Promise;
+
+ async function getSiteInfo({
+ query,
+ variables: getSiteInfoVariables = {},
+ config: userConfig
+ }: {
+ query?: string;
+ variables?: any;
+ config?: Partial;
+ preview?: boolean;
+ } = {}): Promise {
+ console.info(
+ 'getSiteInfo called. Configuration: ',
+ 'query: ',
+ query,
+ 'getSiteInfoVariables ',
+ getSiteInfoVariables,
+ 'config: ',
+ userConfig
+ );
+
+ const createVariables = (parentPermalink: string): SpreeSdkVariables => ({
+ methodPath: 'taxons.list',
+ arguments: [
+ {
+ filter: {
+ parent_permalink: parentPermalink
+ }
+ }
+ ]
+ });
+
+ const config = commerce.getConfig(userConfig);
+ const { fetch: apiFetch } = config; // TODO: Send config.locale to Spree.
+
+ const { data: spreeCategoriesSuccessResponse } = await apiFetch(
+ '__UNUSED__',
+ {
+ variables: createVariables(requireConfigValue('categoriesTaxonomyPermalink') as string)
+ }
+ );
+
+ const { data: spreeBrandsSuccessResponse } = await apiFetch(
+ '__UNUSED__',
+ {
+ variables: createVariables(requireConfigValue('brandsTaxonomyPermalink') as string)
+ }
+ );
+
+ const normalizedCategories: GetSiteInfoOperation['data']['categories'] =
+ spreeCategoriesSuccessResponse.data.sort(taxonsSort).map((spreeTaxon: TaxonAttr) => {
+ return {
+ id: spreeTaxon.id,
+ name: spreeTaxon.attributes.name,
+ slug: spreeTaxon.id,
+ path: spreeTaxon.id
+ };
+ });
+
+ const normalizedBrands: GetSiteInfoOperation['data']['brands'] = spreeBrandsSuccessResponse.data
+ .sort(taxonsSort)
+ .map((spreeTaxon: TaxonAttr) => {
+ return {
+ node: {
+ entityId: spreeTaxon.id,
+ path: `brands/${spreeTaxon.id}`,
+ name: spreeTaxon.attributes.name
+ }
+ };
+ });
+
+ return {
+ categories: normalizedCategories,
+ brands: normalizedBrands
+ };
+ }
+
+ return getSiteInfo;
+}
diff --git a/lib/spree/api/operations/index.ts b/lib/spree/api/operations/index.ts
new file mode 100644
index 000000000..cffc30af8
--- /dev/null
+++ b/lib/spree/api/operations/index.ts
@@ -0,0 +1,8 @@
+export { default as getPage } from './get-page';
+export { default as getSiteInfo } from './get-site-info';
+export { default as getAllPages } from './get-all-pages';
+export { default as getProduct } from './get-product';
+export { default as getAllProducts } from './get-all-products';
+export { default as getAllProductPaths } from './get-all-product-paths';
+export { default as getAllTaxons } from './get-all-taxons';
+export { default as getProducts } from './get-products';
diff --git a/lib/spree/api/utils/create-api-fetch.ts b/lib/spree/api/utils/create-api-fetch.ts
new file mode 100644
index 000000000..1336cebc8
--- /dev/null
+++ b/lib/spree/api/utils/create-api-fetch.ts
@@ -0,0 +1,74 @@
+import { SpreeApiConfig } from '..';
+import { errors, makeClient } from '@spree/storefront-api-v2-sdk';
+import { requireConfigValue } from '../../isomorphic-config';
+import convertSpreeErrorToGraphQlError from '../../utils/convert-spree-error-to-graph-ql-error';
+import type { ResultResponse } from '@spree/storefront-api-v2-sdk/types/interfaces/ResultResponse';
+import getSpreeSdkMethodFromEndpointPath from '../../utils/get-spree-sdk-method-from-endpoint-path';
+import SpreeSdkMethodFromEndpointPathError from '../../errors/SpreeSdkMethodFromEndpointPathError';
+import { GraphQLFetcher, GraphQLFetcherResult } from '@commerce/api';
+import createCustomizedFetchFetcher, {
+ fetchResponseKey
+} from '../../utils/create-customized-fetch-fetcher';
+import fetch, { Request } from 'node-fetch';
+import type { SpreeSdkResponseWithRawResponse } from '../../types';
+
+export type CreateApiFetch = (
+ getConfig: () => SpreeApiConfig
+) => GraphQLFetcher, any>;
+
+// TODO: GraphQLFetcher, any> should be GraphQLFetcher, SpreeSdkVariables>.
+// But CommerceAPIConfig['fetch'] cannot be extended from Variables = any to SpreeSdkVariables.
+
+const createApiFetch: CreateApiFetch = (_getConfig) => {
+ const client = makeClient({
+ host: requireConfigValue('apiHost') as string,
+ createFetcher: (fetcherOptions) => {
+ return createCustomizedFetchFetcher({
+ fetch,
+ requestConstructor: Request,
+ ...fetcherOptions
+ });
+ }
+ });
+
+ return async (url, queryData = {}, fetchOptions = {}) => {
+ console.log(
+ 'apiFetch called. query = ',
+ 'url = ',
+ url,
+ 'queryData = ',
+ queryData,
+ 'fetchOptions = ',
+ fetchOptions
+ );
+
+ const { variables } = queryData;
+
+ if (!variables) {
+ throw new SpreeSdkMethodFromEndpointPathError(`Required SpreeSdkVariables not provided.`);
+ }
+
+ const storeResponse: ResultResponse =
+ await getSpreeSdkMethodFromEndpointPath(client, variables.methodPath)(...variables.arguments);
+
+ if (storeResponse.isSuccess()) {
+ const data = storeResponse.success();
+ const rawFetchResponse = data[fetchResponseKey];
+
+ return {
+ data,
+ res: rawFetchResponse
+ };
+ }
+
+ const storeResponseError = storeResponse.fail();
+
+ if (storeResponseError instanceof errors.SpreeError) {
+ throw convertSpreeErrorToGraphQlError(storeResponseError);
+ }
+
+ throw storeResponseError;
+ };
+};
+
+export default createApiFetch;
diff --git a/lib/spree/api/utils/fetch.ts b/lib/spree/api/utils/fetch.ts
new file mode 100644
index 000000000..70407fd0c
--- /dev/null
+++ b/lib/spree/api/utils/fetch.ts
@@ -0,0 +1,3 @@
+import vercelFetch from '@vercel/fetch';
+
+export default vercelFetch();
diff --git a/lib/spree/auth/index.ts b/lib/spree/auth/index.ts
new file mode 100644
index 000000000..41c664eec
--- /dev/null
+++ b/lib/spree/auth/index.ts
@@ -0,0 +1,3 @@
+export { default as useLogin } from './use-login';
+export { default as useLogout } from './use-logout';
+export { default as useSignup } from './use-signup';
diff --git a/lib/spree/auth/use-login.tsx b/lib/spree/auth/use-login.tsx
new file mode 100644
index 000000000..ce71f97f9
--- /dev/null
+++ b/lib/spree/auth/use-login.tsx
@@ -0,0 +1,81 @@
+import { useCallback } from 'react';
+import type { MutationHook } from '@commerce/utils/types';
+import useLogin, { UseLogin } from '@commerce/auth/use-login';
+import type { LoginHook } from '@commerce/types/login';
+import type { AuthTokenAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/Authentication';
+import { FetcherError, ValidationError } from '@commerce/utils/errors';
+import useCustomer from '../customer/use-customer';
+import useCart from '../cart/use-cart';
+import useWishlist from '../wishlist/use-wishlist';
+import login from '../utils/login';
+
+export default useLogin as UseLogin;
+
+export const handler: MutationHook = {
+ // Provide fetchOptions for SWR cache key
+ fetchOptions: {
+ url: 'authentication',
+ query: 'getToken'
+ },
+ async fetcher({ input, options, fetch }) {
+ console.info(
+ 'useLogin fetcher called. Configuration: ',
+ 'input: ',
+ input,
+ 'options: ',
+ options
+ );
+
+ const { email, password } = input;
+
+ if (!email || !password) {
+ throw new ValidationError({
+ message: 'Email and password need to be provided.'
+ });
+ }
+
+ const getTokenParameters: AuthTokenAttr = {
+ username: email,
+ password
+ };
+
+ try {
+ await login(fetch, getTokenParameters, false);
+
+ return null;
+ } catch (getTokenError) {
+ if (getTokenError instanceof FetcherError && getTokenError.status === 400) {
+ // Change the error message to be more user friendly.
+ throw new FetcherError({
+ status: getTokenError.status,
+ message: 'The email or password is invalid.',
+ code: getTokenError.code
+ });
+ }
+
+ throw getTokenError;
+ }
+ },
+ useHook: ({ fetch }) => {
+ const useWrappedHook: ReturnType['useHook']> = () => {
+ const customer = useCustomer();
+ const cart = useCart();
+ const wishlist = useWishlist();
+
+ return useCallback(
+ async function login(input) {
+ const data = await fetch({ input });
+
+ await customer.revalidate();
+ await cart.revalidate();
+ await wishlist.revalidate();
+
+ return data;
+ },
+ [customer, cart, wishlist]
+ );
+ };
+
+ return useWrappedHook;
+ }
+};
diff --git a/lib/spree/auth/use-logout.tsx b/lib/spree/auth/use-logout.tsx
new file mode 100644
index 000000000..90e0f3ba0
--- /dev/null
+++ b/lib/spree/auth/use-logout.tsx
@@ -0,0 +1,79 @@
+import { MutationHook } from '@commerce/utils/types';
+import useLogout, { UseLogout } from '@commerce/auth/use-logout';
+import type { LogoutHook } from '@commerce/types/logout';
+import { useCallback } from 'react';
+import useCustomer from '../customer/use-customer';
+import useCart from '../cart/use-cart';
+import useWishlist from '../wishlist/use-wishlist';
+import {
+ ensureUserTokenResponse,
+ removeUserTokenResponse
+} from '../utils/tokens/user-token-response';
+import revokeUserTokens from '../utils/tokens/revoke-user-tokens';
+import TokensNotRejectedError from '../errors/TokensNotRejectedError';
+
+export default useLogout as UseLogout;
+
+export const handler: MutationHook = {
+ // Provide fetchOptions for SWR cache key
+ fetchOptions: {
+ url: 'authentication',
+ query: 'revokeToken'
+ },
+ async fetcher({ input, options, fetch }) {
+ console.info(
+ 'useLogout fetcher called. Configuration: ',
+ 'input: ',
+ input,
+ 'options: ',
+ options
+ );
+
+ const userToken = ensureUserTokenResponse();
+
+ if (userToken) {
+ try {
+ // Revoke any tokens associated with the logged in user.
+ await revokeUserTokens(fetch, {
+ accessToken: userToken.access_token,
+ refreshToken: userToken.refresh_token
+ });
+ } catch (revokeUserTokenError) {
+ // Squash token revocation errors and rethrow anything else.
+ if (!(revokeUserTokenError instanceof TokensNotRejectedError)) {
+ throw revokeUserTokenError;
+ }
+ }
+
+ // Whether token revocation succeeded or not, remove them from local storage.
+ removeUserTokenResponse();
+ }
+
+ return null;
+ },
+ useHook: ({ fetch }) => {
+ const useWrappedHook: ReturnType['useHook']> = () => {
+ const customer = useCustomer({
+ swrOptions: { isPaused: () => true }
+ });
+ const cart = useCart({
+ swrOptions: { isPaused: () => true }
+ });
+ const wishlist = useWishlist({
+ swrOptions: { isPaused: () => true }
+ });
+
+ return useCallback(async () => {
+ const data = await fetch();
+
+ await customer.mutate(null, false);
+ await cart.mutate(null, false);
+ await wishlist.mutate(null, false);
+
+ return data;
+ }, [customer, cart, wishlist]);
+ };
+
+ return useWrappedHook;
+ }
+};
diff --git a/lib/spree/auth/use-signup.tsx b/lib/spree/auth/use-signup.tsx
new file mode 100644
index 000000000..c97080668
--- /dev/null
+++ b/lib/spree/auth/use-signup.tsx
@@ -0,0 +1,94 @@
+import { useCallback } from 'react';
+import type { GraphQLFetcherResult } from '@commerce/api';
+import type { MutationHook } from '@commerce/utils/types';
+import useSignup, { UseSignup } from '@commerce/auth/use-signup';
+import type { SignupHook } from '@commerce/types/signup';
+import { ValidationError } from '@commerce/utils/errors';
+import type { IAccount } from '@spree/storefront-api-v2-sdk/types/interfaces/Account';
+import type { AuthTokenAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/Authentication';
+import useCustomer from '../customer/use-customer';
+import useCart from '../cart/use-cart';
+import useWishlist from '../wishlist/use-wishlist';
+import login from '../utils/login';
+import { requireConfigValue } from '../isomorphic-config';
+
+export default useSignup as UseSignup;
+
+export const handler: MutationHook = {
+ // Provide fetchOptions for SWR cache key
+ fetchOptions: {
+ url: 'account',
+ query: 'create'
+ },
+ async fetcher({ input, options, fetch }) {
+ console.info(
+ 'useSignup fetcher called. Configuration: ',
+ 'input: ',
+ input,
+ 'options: ',
+ options
+ );
+
+ const { email, password } = input;
+
+ if (!email || !password) {
+ throw new ValidationError({
+ message: 'Email and password need to be provided.'
+ });
+ }
+
+ // TODO: Replace any with specific type from Spree SDK
+ // once it's added to the SDK.
+ const createAccountParameters: any = {
+ user: {
+ email,
+ password,
+ // The stock NJC interface doesn't have a
+ // password confirmation field, so just copy password.
+ passwordConfirmation: password
+ }
+ };
+
+ // Create the user account.
+ await fetch>({
+ variables: {
+ methodPath: 'account.create',
+ arguments: [createAccountParameters]
+ }
+ });
+
+ const getTokenParameters: AuthTokenAttr = {
+ username: email,
+ password
+ };
+
+ // Login immediately after the account is created.
+ if (requireConfigValue('loginAfterSignup')) {
+ await login(fetch, getTokenParameters, true);
+ }
+
+ return null;
+ },
+ useHook: ({ fetch }) => {
+ const useWrappedHook: ReturnType['useHook']> = () => {
+ const customer = useCustomer();
+ const cart = useCart();
+ const wishlist = useWishlist();
+
+ return useCallback(
+ async (input) => {
+ const data = await fetch({ input });
+
+ await customer.revalidate();
+ await cart.revalidate();
+ await wishlist.revalidate();
+
+ return data;
+ },
+ [customer, cart, wishlist]
+ );
+ };
+
+ return useWrappedHook;
+ }
+};
diff --git a/lib/spree/cart/index.ts b/lib/spree/cart/index.ts
new file mode 100644
index 000000000..ce8557363
--- /dev/null
+++ b/lib/spree/cart/index.ts
@@ -0,0 +1,4 @@
+export { default as useCart } from './use-cart';
+export { default as useAddItem } from './use-add-item';
+export { default as useRemoveItem } from './use-remove-item';
+export { default as useUpdateItem } from './use-update-item';
diff --git a/lib/spree/cart/use-add-item.tsx b/lib/spree/cart/use-add-item.tsx
new file mode 100644
index 000000000..80c4108ec
--- /dev/null
+++ b/lib/spree/cart/use-add-item.tsx
@@ -0,0 +1,109 @@
+import useAddItem from '@commerce/cart/use-add-item';
+import type { UseAddItem } from '@commerce/cart/use-add-item';
+import type { MutationHook } from '@commerce/utils/types';
+import { useCallback } from 'react';
+import useCart from './use-cart';
+import type { AddItemHook } from '@commerce/types/cart';
+import normalizeCart from '../utils/normalizations/normalize-cart';
+import type { GraphQLFetcherResult } from '@commerce/api';
+import type { IOrder } from '@spree/storefront-api-v2-sdk/types/interfaces/Order';
+import type { IToken } from '@spree/storefront-api-v2-sdk/types/interfaces/Token';
+import type { AddItem } from '@spree/storefront-api-v2-sdk/types/interfaces/endpoints/CartClass';
+import { setCartToken } from '../utils/tokens/cart-token';
+import ensureIToken from '../utils/tokens/ensure-itoken';
+import createEmptyCart from '../utils/create-empty-cart';
+import { FetcherError } from '@commerce/utils/errors';
+import isLoggedIn from '../utils/tokens/is-logged-in';
+
+export default useAddItem as UseAddItem;
+
+export const handler: MutationHook = {
+ // Provide fetchOptions for SWR cache key
+ fetchOptions: {
+ url: 'cart',
+ query: 'addItem'
+ },
+ async fetcher({ input, options, fetch }) {
+ console.info(
+ 'useAddItem fetcher called. Configuration: ',
+ 'input: ',
+ input,
+ 'options: ',
+ options
+ );
+
+ const { quantity, productId, variantId } = input;
+
+ const safeQuantity = quantity ?? 1;
+
+ let token: IToken | undefined = ensureIToken();
+
+ const addItemParameters: AddItem = {
+ variant_id: variantId,
+ quantity: safeQuantity,
+ include: [
+ 'line_items',
+ 'line_items.variant',
+ 'line_items.variant.product',
+ 'line_items.variant.product.images',
+ 'line_items.variant.images',
+ 'line_items.variant.option_values',
+ 'line_items.variant.product.option_types'
+ ].join(',')
+ };
+
+ if (!token) {
+ const { data: spreeCartCreateSuccessResponse } = await createEmptyCart(fetch);
+
+ setCartToken(spreeCartCreateSuccessResponse.data.attributes.token);
+ token = ensureIToken();
+ }
+
+ try {
+ const { data: spreeSuccessResponse } = await fetch>({
+ variables: {
+ methodPath: 'cart.addItem',
+ arguments: [token, addItemParameters]
+ }
+ });
+
+ return normalizeCart(spreeSuccessResponse, spreeSuccessResponse.data);
+ } catch (addItemError) {
+ if (addItemError instanceof FetcherError && addItemError.status === 404) {
+ const { data: spreeRetroactiveCartCreateSuccessResponse } = await createEmptyCart(fetch);
+
+ if (!isLoggedIn()) {
+ setCartToken(spreeRetroactiveCartCreateSuccessResponse.data.attributes.token);
+ }
+
+ // Return an empty cart. The user has to add the item again.
+ // This is going to be a rare situation.
+
+ return normalizeCart(
+ spreeRetroactiveCartCreateSuccessResponse,
+ spreeRetroactiveCartCreateSuccessResponse.data
+ );
+ }
+
+ throw addItemError;
+ }
+ },
+ useHook: ({ fetch }) => {
+ const useWrappedHook: ReturnType['useHook']> = () => {
+ const { mutate } = useCart();
+
+ return useCallback(
+ async (input) => {
+ const data = await fetch({ input });
+
+ await mutate(data, false);
+
+ return data;
+ },
+ [mutate]
+ );
+ };
+
+ return useWrappedHook;
+ }
+};
diff --git a/lib/spree/cart/use-cart.tsx b/lib/spree/cart/use-cart.tsx
new file mode 100644
index 000000000..ed0d51061
--- /dev/null
+++ b/lib/spree/cart/use-cart.tsx
@@ -0,0 +1,108 @@
+import { useMemo } from 'react';
+import type { SWRHook } from '@commerce/utils/types';
+import useCart from '@commerce/cart/use-cart';
+import type { UseCart } from '@commerce/cart/use-cart';
+import type { GetCartHook } from '@commerce/types/cart';
+import normalizeCart from '../utils/normalizations/normalize-cart';
+import type { GraphQLFetcherResult } from '@commerce/api';
+import type { IOrder } from '@spree/storefront-api-v2-sdk/types/interfaces/Order';
+import type { IToken } from '@spree/storefront-api-v2-sdk/types/interfaces/Token';
+import { FetcherError } from '@commerce/utils/errors';
+import { setCartToken } from '../utils/tokens/cart-token';
+import ensureIToken from '../utils/tokens/ensure-itoken';
+import isLoggedIn from '../utils/tokens/is-logged-in';
+import createEmptyCart from '../utils/create-empty-cart';
+import { requireConfigValue } from '../isomorphic-config';
+
+const imagesSize = requireConfigValue('imagesSize') as string;
+const imagesQuality = requireConfigValue('imagesQuality') as number;
+
+export default useCart as UseCart;
+
+// This handler avoids calling /api/cart.
+// There doesn't seem to be a good reason to call it.
+// So far, only @framework/bigcommerce uses it.
+export const handler: SWRHook = {
+ // Provide fetchOptions for SWR cache key
+ fetchOptions: {
+ url: 'cart',
+ query: 'show'
+ },
+ async fetcher({ input, options, fetch }) {
+ console.info('useCart fetcher called. Configuration: ', 'input: ', input, 'options: ', options);
+
+ let spreeCartResponse: IOrder | null;
+
+ const token: IToken | undefined = ensureIToken();
+
+ if (!token) {
+ spreeCartResponse = null;
+ } else {
+ try {
+ const { data: spreeCartShowSuccessResponse } = await fetch>({
+ variables: {
+ methodPath: 'cart.show',
+ arguments: [
+ token,
+ {
+ include: [
+ 'line_items',
+ 'line_items.variant',
+ 'line_items.variant.product',
+ 'line_items.variant.product.images',
+ 'line_items.variant.images',
+ 'line_items.variant.option_values',
+ 'line_items.variant.product.option_types'
+ ].join(','),
+ image_transformation: {
+ quality: imagesQuality,
+ size: imagesSize
+ }
+ }
+ ]
+ }
+ });
+
+ spreeCartResponse = spreeCartShowSuccessResponse;
+ } catch (fetchCartError) {
+ if (!(fetchCartError instanceof FetcherError) || fetchCartError.status !== 404) {
+ throw fetchCartError;
+ }
+
+ spreeCartResponse = null;
+ }
+ }
+
+ if (!spreeCartResponse || spreeCartResponse?.data.attributes.completed_at) {
+ const { data: spreeCartCreateSuccessResponse } = await createEmptyCart(fetch);
+
+ spreeCartResponse = spreeCartCreateSuccessResponse;
+
+ if (!isLoggedIn()) {
+ setCartToken(spreeCartResponse.data.attributes.token);
+ }
+ }
+
+ return normalizeCart(spreeCartResponse, spreeCartResponse.data);
+ },
+ useHook: ({ useData }) => {
+ const useWrappedHook: ReturnType['useHook']> = (input) => {
+ const response = useData({
+ swrOptions: { revalidateOnFocus: false, ...input?.swrOptions }
+ });
+
+ return useMemo(() => {
+ return Object.create(response, {
+ isEmpty: {
+ get() {
+ return (response.data?.lineItems.length ?? 0) === 0;
+ },
+ enumerable: true
+ }
+ });
+ }, [response]);
+ };
+
+ return useWrappedHook;
+ }
+};
diff --git a/lib/spree/cart/use-remove-item.tsx b/lib/spree/cart/use-remove-item.tsx
new file mode 100644
index 000000000..bdc8fc5ca
--- /dev/null
+++ b/lib/spree/cart/use-remove-item.tsx
@@ -0,0 +1,107 @@
+import type { MutationHook } from '@commerce/utils/types';
+import useRemoveItem from '@commerce/cart/use-remove-item';
+import type { UseRemoveItem } from '@commerce/cart/use-remove-item';
+import type { RemoveItemHook } from '@commerce/types/cart';
+import useCart from './use-cart';
+import { useCallback } from 'react';
+import normalizeCart from '../utils/normalizations/normalize-cart';
+import type { IOrder } from '@spree/storefront-api-v2-sdk/types/interfaces/Order';
+import type { GraphQLFetcherResult } from '@commerce/api';
+import type { IQuery } from '@spree/storefront-api-v2-sdk/types/interfaces/Query';
+import type { IToken } from '@spree/storefront-api-v2-sdk/types/interfaces/Token';
+import ensureIToken from '../utils/tokens/ensure-itoken';
+import createEmptyCart from '../utils/create-empty-cart';
+import { setCartToken } from '../utils/tokens/cart-token';
+import { FetcherError } from '@commerce/utils/errors';
+import isLoggedIn from '../utils/tokens/is-logged-in';
+
+export default useRemoveItem as UseRemoveItem;
+
+export const handler: MutationHook = {
+ // Provide fetchOptions for SWR cache key
+ fetchOptions: {
+ url: 'cart',
+ query: 'removeItem'
+ },
+ async fetcher({ input, options, fetch }) {
+ console.info(
+ 'useRemoveItem fetcher called. Configuration: ',
+ 'input: ',
+ input,
+ 'options: ',
+ options
+ );
+
+ const { itemId: lineItemId } = input;
+
+ let token: IToken | undefined = ensureIToken();
+
+ if (!token) {
+ const { data: spreeCartCreateSuccessResponse } = await createEmptyCart(fetch);
+
+ setCartToken(spreeCartCreateSuccessResponse.data.attributes.token);
+ token = ensureIToken();
+ }
+
+ const removeItemParameters: IQuery = {
+ include: [
+ 'line_items',
+ 'line_items.variant',
+ 'line_items.variant.product',
+ 'line_items.variant.product.images',
+ 'line_items.variant.images',
+ 'line_items.variant.option_values',
+ 'line_items.variant.product.option_types'
+ ].join(',')
+ };
+
+ try {
+ const { data: spreeSuccessResponse } = await fetch>({
+ variables: {
+ methodPath: 'cart.removeItem',
+ arguments: [token, lineItemId, removeItemParameters]
+ }
+ });
+
+ return normalizeCart(spreeSuccessResponse, spreeSuccessResponse.data);
+ } catch (removeItemError) {
+ if (removeItemError instanceof FetcherError && removeItemError.status === 404) {
+ const { data: spreeRetroactiveCartCreateSuccessResponse } = await createEmptyCart(fetch);
+
+ if (!isLoggedIn()) {
+ setCartToken(spreeRetroactiveCartCreateSuccessResponse.data.attributes.token);
+ }
+
+ // Return an empty cart. This is going to be a rare situation.
+
+ return normalizeCart(
+ spreeRetroactiveCartCreateSuccessResponse,
+ spreeRetroactiveCartCreateSuccessResponse.data
+ );
+ }
+
+ throw removeItemError;
+ }
+ },
+ useHook: ({ fetch }) => {
+ const useWrappedHook: ReturnType['useHook']> = () => {
+ const { mutate } = useCart();
+
+ return useCallback(
+ async (input) => {
+ const data = await fetch({ input: { itemId: input.id } });
+
+ // Upon calling cart.removeItem, Spree returns the old version of the cart,
+ // with the already removed line item. Invalidate the useCart mutation
+ // to fetch the cart again.
+ await mutate(data, true);
+
+ return data;
+ },
+ [mutate]
+ );
+ };
+
+ return useWrappedHook;
+ }
+};
diff --git a/lib/spree/cart/use-update-item.tsx b/lib/spree/cart/use-update-item.tsx
new file mode 100644
index 000000000..b53c762ce
--- /dev/null
+++ b/lib/spree/cart/use-update-item.tsx
@@ -0,0 +1,134 @@
+import type { MutationHook } from '@commerce/utils/types';
+import useUpdateItem, { UseUpdateItem } from '@commerce/cart/use-update-item';
+import type { UpdateItemHook } from '@commerce/types/cart';
+import useCart from './use-cart';
+import { useMemo } from 'react';
+import { FetcherError, ValidationError } from '@commerce/utils/errors';
+import type { IToken } from '@spree/storefront-api-v2-sdk/types/interfaces/Token';
+import type { SetQuantity } from '@spree/storefront-api-v2-sdk/types/interfaces/endpoints/CartClass';
+import type { GraphQLFetcherResult } from '@commerce/api';
+import type { IOrder } from '@spree/storefront-api-v2-sdk/types/interfaces/Order';
+import normalizeCart from '../utils/normalizations/normalize-cart';
+import debounce from 'lodash.debounce';
+import ensureIToken from '../utils/tokens/ensure-itoken';
+import createEmptyCart from '../utils/create-empty-cart';
+import { setCartToken } from '../utils/tokens/cart-token';
+import isLoggedIn from '../utils/tokens/is-logged-in';
+
+export default useUpdateItem as UseUpdateItem;
+
+export const handler: MutationHook = {
+ // Provide fetchOptions for SWR cache key
+ fetchOptions: {
+ url: 'cart',
+ query: 'setQuantity'
+ },
+ async fetcher({ input, options, fetch }) {
+ console.info(
+ 'useRemoveItem fetcher called. Configuration: ',
+ 'input: ',
+ input,
+ 'options: ',
+ options
+ );
+
+ const { itemId, item } = input;
+
+ if (!item.quantity) {
+ throw new ValidationError({
+ message: 'Line item quantity needs to be provided.'
+ });
+ }
+
+ let token: IToken | undefined = ensureIToken();
+
+ if (!token) {
+ const { data: spreeCartCreateSuccessResponse } = await createEmptyCart(fetch);
+
+ setCartToken(spreeCartCreateSuccessResponse.data.attributes.token);
+ token = ensureIToken();
+ }
+
+ try {
+ const setQuantityParameters: SetQuantity = {
+ line_item_id: itemId,
+ quantity: item.quantity,
+ include: [
+ 'line_items',
+ 'line_items.variant',
+ 'line_items.variant.product',
+ 'line_items.variant.product.images',
+ 'line_items.variant.images',
+ 'line_items.variant.option_values',
+ 'line_items.variant.product.option_types'
+ ].join(',')
+ };
+
+ const { data: spreeSuccessResponse } = await fetch>({
+ variables: {
+ methodPath: 'cart.setQuantity',
+ arguments: [token, setQuantityParameters]
+ }
+ });
+
+ return normalizeCart(spreeSuccessResponse, spreeSuccessResponse.data);
+ } catch (updateItemError) {
+ if (updateItemError instanceof FetcherError && updateItemError.status === 404) {
+ const { data: spreeRetroactiveCartCreateSuccessResponse } = await createEmptyCart(fetch);
+
+ if (!isLoggedIn()) {
+ setCartToken(spreeRetroactiveCartCreateSuccessResponse.data.attributes.token);
+ }
+
+ // Return an empty cart. The user has to update the item again.
+ // This is going to be a rare situation.
+
+ return normalizeCart(
+ spreeRetroactiveCartCreateSuccessResponse,
+ spreeRetroactiveCartCreateSuccessResponse.data
+ );
+ }
+
+ throw updateItemError;
+ }
+ },
+ useHook: ({ fetch }) => {
+ const useWrappedHook: ReturnType['useHook']> = (context) => {
+ const { mutate } = useCart();
+
+ return useMemo(
+ () =>
+ debounce(async (input: UpdateItemHook['actionInput']) => {
+ const itemId = context?.item?.id;
+ const productId = input.productId ?? context?.item?.productId;
+ const variantId = input.variantId ?? context?.item?.variantId;
+ const quantity = input.quantity;
+
+ if (!itemId || !productId || !variantId) {
+ throw new ValidationError({
+ message: 'Invalid input used for this operation'
+ });
+ }
+
+ const data = await fetch({
+ input: {
+ item: {
+ productId,
+ variantId,
+ quantity
+ },
+ itemId
+ }
+ });
+
+ await mutate(data, false);
+
+ return data;
+ }, context?.wait ?? 500),
+ [mutate, context]
+ );
+ };
+
+ return useWrappedHook;
+ }
+};
diff --git a/lib/spree/checkout/use-checkout.tsx b/lib/spree/checkout/use-checkout.tsx
new file mode 100644
index 000000000..738fddac3
--- /dev/null
+++ b/lib/spree/checkout/use-checkout.tsx
@@ -0,0 +1,17 @@
+import { SWRHook } from '@commerce/utils/types';
+import useCheckout, { UseCheckout } from '@commerce/checkout/use-checkout';
+
+export default useCheckout as UseCheckout;
+
+export const handler: SWRHook = {
+ // Provide fetchOptions for SWR cache key
+ fetchOptions: {
+ // TODO: Revise url and query
+ url: 'checkout',
+ query: 'show'
+ },
+ async fetcher({ input, options, fetch }) {},
+ useHook:
+ ({ useData }) =>
+ async (input) => ({})
+};
diff --git a/lib/spree/commerce.config.json b/lib/spree/commerce.config.json
new file mode 100644
index 000000000..6f8399fb5
--- /dev/null
+++ b/lib/spree/commerce.config.json
@@ -0,0 +1,10 @@
+{
+ "provider": "spree",
+ "features": {
+ "wishlist": true,
+ "cart": true,
+ "search": true,
+ "customerAuth": true,
+ "customCheckout": false
+ }
+}
diff --git a/lib/spree/customer/address/use-add-item.tsx b/lib/spree/customer/address/use-add-item.tsx
new file mode 100644
index 000000000..06bda6a27
--- /dev/null
+++ b/lib/spree/customer/address/use-add-item.tsx
@@ -0,0 +1,18 @@
+import useAddItem from '@commerce/customer/address/use-add-item';
+import type { UseAddItem } from '@commerce/customer/address/use-add-item';
+import type { MutationHook } from '@commerce/utils/types';
+
+export default useAddItem as UseAddItem;
+
+export const handler: MutationHook = {
+ // Provide fetchOptions for SWR cache key
+ fetchOptions: {
+ url: 'account',
+ query: 'createAddress'
+ },
+ async fetcher({ input, options, fetch }) {},
+ useHook:
+ ({ fetch }) =>
+ () =>
+ async () => ({})
+};
diff --git a/lib/spree/customer/card/use-add-item.tsx b/lib/spree/customer/card/use-add-item.tsx
new file mode 100644
index 000000000..1b05a4bed
--- /dev/null
+++ b/lib/spree/customer/card/use-add-item.tsx
@@ -0,0 +1,19 @@
+import useAddItem from '@commerce/customer/address/use-add-item';
+import type { UseAddItem } from '@commerce/customer/address/use-add-item';
+import type { MutationHook } from '@commerce/utils/types';
+
+export default useAddItem as UseAddItem;
+
+export const handler: MutationHook = {
+ // Provide fetchOptions for SWR cache key
+ fetchOptions: {
+ // TODO: Revise url and query
+ url: 'checkout',
+ query: 'addPayment'
+ },
+ async fetcher({ input, options, fetch }) {},
+ useHook:
+ ({ fetch }) =>
+ () =>
+ async () => ({})
+};
diff --git a/lib/spree/customer/index.ts b/lib/spree/customer/index.ts
new file mode 100644
index 000000000..8410d6ad4
--- /dev/null
+++ b/lib/spree/customer/index.ts
@@ -0,0 +1 @@
+export { default as useCustomer } from './use-customer';
diff --git a/lib/spree/customer/use-customer.tsx b/lib/spree/customer/use-customer.tsx
new file mode 100644
index 000000000..d9fe6028e
--- /dev/null
+++ b/lib/spree/customer/use-customer.tsx
@@ -0,0 +1,75 @@
+import type { SWRHook } from '@commerce/utils/types';
+import useCustomer from '@commerce/customer/use-customer';
+import type { UseCustomer } from '@commerce/customer/use-customer';
+import type { CustomerHook } from '@commerce/types/customer';
+import type { IToken } from '@spree/storefront-api-v2-sdk/types/interfaces/Token';
+import type { GraphQLFetcherResult } from '@commerce/api';
+import type { IAccount } from '@spree/storefront-api-v2-sdk/types/interfaces/Account';
+import { FetcherError } from '@commerce/utils/errors';
+import normalizeUser from '../utils/normalizations/normalize-user';
+import isLoggedIn from '../utils/tokens/is-logged-in';
+import ensureIToken from '../utils/tokens/ensure-itoken';
+
+export default useCustomer as UseCustomer;
+
+export const handler: SWRHook = {
+ // Provide fetchOptions for SWR cache key
+ fetchOptions: {
+ url: 'account',
+ query: 'get'
+ },
+ async fetcher({ input, options, fetch }) {
+ console.info(
+ 'useCustomer fetcher called. Configuration: ',
+ 'input: ',
+ input,
+ 'options: ',
+ options
+ );
+
+ if (!isLoggedIn()) {
+ return null;
+ }
+
+ const token: IToken | undefined = ensureIToken();
+
+ if (!token) {
+ return null;
+ }
+
+ try {
+ const { data: spreeAccountInfoSuccessResponse } = await fetch>(
+ {
+ variables: {
+ methodPath: 'account.accountInfo',
+ arguments: [token]
+ }
+ }
+ );
+
+ const spreeUser = spreeAccountInfoSuccessResponse.data;
+
+ const normalizedUser = normalizeUser(spreeAccountInfoSuccessResponse, spreeUser);
+
+ return normalizedUser;
+ } catch (fetchUserError) {
+ if (!(fetchUserError instanceof FetcherError) || fetchUserError.status !== 404) {
+ throw fetchUserError;
+ }
+
+ return null;
+ }
+ },
+ useHook: ({ useData }) => {
+ const useWrappedHook: ReturnType['useHook']> = (input) => {
+ return useData({
+ swrOptions: {
+ revalidateOnFocus: false,
+ ...input?.swrOptions
+ }
+ });
+ };
+
+ return useWrappedHook;
+ }
+};
diff --git a/lib/spree/errors/AccessTokenError.ts b/lib/spree/errors/AccessTokenError.ts
new file mode 100644
index 000000000..4c79c0be8
--- /dev/null
+++ b/lib/spree/errors/AccessTokenError.ts
@@ -0,0 +1 @@
+export default class AccessTokenError extends Error {}
diff --git a/lib/spree/errors/MisconfigurationError.ts b/lib/spree/errors/MisconfigurationError.ts
new file mode 100644
index 000000000..0717ae404
--- /dev/null
+++ b/lib/spree/errors/MisconfigurationError.ts
@@ -0,0 +1 @@
+export default class MisconfigurationError extends Error {}
diff --git a/lib/spree/errors/MissingConfigurationValueError.ts b/lib/spree/errors/MissingConfigurationValueError.ts
new file mode 100644
index 000000000..02b497bf1
--- /dev/null
+++ b/lib/spree/errors/MissingConfigurationValueError.ts
@@ -0,0 +1 @@
+export default class MissingConfigurationValueError extends Error {}
diff --git a/lib/spree/errors/MissingLineItemVariantError.ts b/lib/spree/errors/MissingLineItemVariantError.ts
new file mode 100644
index 000000000..d9bee0803
--- /dev/null
+++ b/lib/spree/errors/MissingLineItemVariantError.ts
@@ -0,0 +1 @@
+export default class MissingLineItemVariantError extends Error {}
diff --git a/lib/spree/errors/MissingOptionValueError.ts b/lib/spree/errors/MissingOptionValueError.ts
new file mode 100644
index 000000000..04457ac5e
--- /dev/null
+++ b/lib/spree/errors/MissingOptionValueError.ts
@@ -0,0 +1 @@
+export default class MissingOptionValueError extends Error {}
diff --git a/lib/spree/errors/MissingPrimaryVariantError.ts b/lib/spree/errors/MissingPrimaryVariantError.ts
new file mode 100644
index 000000000..f9af41b03
--- /dev/null
+++ b/lib/spree/errors/MissingPrimaryVariantError.ts
@@ -0,0 +1 @@
+export default class MissingPrimaryVariantError extends Error {}
diff --git a/lib/spree/errors/MissingProductError.ts b/lib/spree/errors/MissingProductError.ts
new file mode 100644
index 000000000..3098be689
--- /dev/null
+++ b/lib/spree/errors/MissingProductError.ts
@@ -0,0 +1 @@
+export default class MissingProductError extends Error {}
diff --git a/lib/spree/errors/MissingSlugVariableError.ts b/lib/spree/errors/MissingSlugVariableError.ts
new file mode 100644
index 000000000..09b9d2e20
--- /dev/null
+++ b/lib/spree/errors/MissingSlugVariableError.ts
@@ -0,0 +1 @@
+export default class MissingSlugVariableError extends Error {}
diff --git a/lib/spree/errors/MissingVariantError.ts b/lib/spree/errors/MissingVariantError.ts
new file mode 100644
index 000000000..5ed9e0ed2
--- /dev/null
+++ b/lib/spree/errors/MissingVariantError.ts
@@ -0,0 +1 @@
+export default class MissingVariantError extends Error {}
diff --git a/lib/spree/errors/RefreshTokenError.ts b/lib/spree/errors/RefreshTokenError.ts
new file mode 100644
index 000000000..a79365bbb
--- /dev/null
+++ b/lib/spree/errors/RefreshTokenError.ts
@@ -0,0 +1 @@
+export default class RefreshTokenError extends Error {}
diff --git a/lib/spree/errors/SpreeResponseContentError.ts b/lib/spree/errors/SpreeResponseContentError.ts
new file mode 100644
index 000000000..19c10cf2e
--- /dev/null
+++ b/lib/spree/errors/SpreeResponseContentError.ts
@@ -0,0 +1 @@
+export default class SpreeResponseContentError extends Error {}
diff --git a/lib/spree/errors/SpreeSdkMethodFromEndpointPathError.ts b/lib/spree/errors/SpreeSdkMethodFromEndpointPathError.ts
new file mode 100644
index 000000000..bf15aada0
--- /dev/null
+++ b/lib/spree/errors/SpreeSdkMethodFromEndpointPathError.ts
@@ -0,0 +1 @@
+export default class SpreeSdkMethodFromEndpointPathError extends Error {}
diff --git a/lib/spree/errors/TokensNotRejectedError.ts b/lib/spree/errors/TokensNotRejectedError.ts
new file mode 100644
index 000000000..245f66414
--- /dev/null
+++ b/lib/spree/errors/TokensNotRejectedError.ts
@@ -0,0 +1 @@
+export default class TokensNotRejectedError extends Error {}
diff --git a/lib/spree/errors/UserTokenResponseParseError.ts b/lib/spree/errors/UserTokenResponseParseError.ts
new file mode 100644
index 000000000..9631971c1
--- /dev/null
+++ b/lib/spree/errors/UserTokenResponseParseError.ts
@@ -0,0 +1 @@
+export default class UserTokenResponseParseError extends Error {}
diff --git a/lib/spree/index.tsx b/lib/spree/index.tsx
new file mode 100644
index 000000000..dc6bc1ccb
--- /dev/null
+++ b/lib/spree/index.tsx
@@ -0,0 +1,9 @@
+const createAxiosFetcher = require('@spree/axios-fetcher/dist/server/index').default;
+import { makeClient } from '@spree/storefront-api-v2-sdk/dist/client';
+
+const spreeClient = makeClient({
+ host: 'http://localhost:3000',
+ createFetcher: createAxiosFetcher
+});
+
+export default spreeClient;
diff --git a/lib/spree/next.config.js b/lib/spree/next.config.js
new file mode 100644
index 000000000..90e720888
--- /dev/null
+++ b/lib/spree/next.config.js
@@ -0,0 +1,16 @@
+const commerce = require('./commerce.config.json');
+
+module.exports = {
+ commerce,
+ images: {
+ domains: [process.env.NEXT_PUBLIC_SPREE_ALLOWED_IMAGE_DOMAIN]
+ },
+ rewrites() {
+ return [
+ {
+ source: '/checkout',
+ destination: '/api/checkout'
+ }
+ ];
+ }
+};
diff --git a/lib/spree/product/index.ts b/lib/spree/product/index.ts
new file mode 100644
index 000000000..6c5a2d91d
--- /dev/null
+++ b/lib/spree/product/index.ts
@@ -0,0 +1,2 @@
+export { default as usePrice } from './use-price';
+export { default as useSearch } from './use-search';
diff --git a/lib/spree/product/use-price.tsx b/lib/spree/product/use-price.tsx
new file mode 100644
index 000000000..63b587cb0
--- /dev/null
+++ b/lib/spree/product/use-price.tsx
@@ -0,0 +1,2 @@
+export * from '@commerce/product/use-price';
+export { default } from '@commerce/product/use-price';
diff --git a/lib/spree/product/use-search.tsx b/lib/spree/product/use-search.tsx
new file mode 100644
index 000000000..e1ca4d887
--- /dev/null
+++ b/lib/spree/product/use-search.tsx
@@ -0,0 +1,96 @@
+import type { SWRHook } from '@commerce/utils/types';
+import useSearch from '@commerce/product/use-search';
+import type { Product, SearchProductsHook } from '@commerce/types/product';
+import type { UseSearch } from '@commerce/product/use-search';
+import normalizeProduct from '../utils/normalizations/normalize-product';
+import type { GraphQLFetcherResult } from '@commerce/api';
+import { IProducts } from '@spree/storefront-api-v2-sdk/types/interfaces/Product';
+import { requireConfigValue } from '../isomorphic-config';
+
+const imagesSize = requireConfigValue('imagesSize') as string;
+const imagesQuality = requireConfigValue('imagesQuality') as number;
+
+const nextToSpreeSortMap: { [key: string]: string } = {
+ 'trending-desc': 'available_on',
+ 'latest-desc': 'updated_at',
+ 'price-asc': 'price',
+ 'price-desc': '-price'
+};
+
+export const handler: SWRHook = {
+ // Provide fetchOptions for SWR cache key
+ fetchOptions: {
+ url: 'products',
+ query: 'list'
+ },
+ async fetcher({ input, options, fetch }) {
+ // This method is only needed if the options need to be modified before calling the generic fetcher (created in createFetcher).
+
+ console.info(
+ 'useSearch fetcher called. Configuration: ',
+ 'input: ',
+ input,
+ 'options: ',
+ options
+ );
+
+ const taxons = [input.categoryId, input.brandId].filter(Boolean);
+
+ const filter = {
+ filter: {
+ ...(taxons.length > 0 ? { taxons: taxons.join(',') } : {}),
+ ...(input.search ? { name: input.search } : {})
+ }
+ };
+
+ const sort = input.sort ? { sort: nextToSpreeSortMap[input.sort] } : {};
+
+ const { data: spreeSuccessResponse } = await fetch>({
+ variables: {
+ methodPath: 'products.list',
+ arguments: [
+ {},
+ {
+ include: 'primary_variant,variants,images,option_types,variants.option_values',
+ per_page: 50,
+ ...filter,
+ ...sort,
+ image_transformation: {
+ quality: imagesQuality,
+ size: imagesSize
+ }
+ }
+ ]
+ }
+ });
+
+ const normalizedProducts: Product[] = spreeSuccessResponse.data.map((spreeProduct) =>
+ normalizeProduct(spreeSuccessResponse, spreeProduct)
+ );
+
+ const found = spreeSuccessResponse.data.length > 0;
+
+ return { products: normalizedProducts, found };
+ },
+ useHook: ({ useData }) => {
+ const useWrappedHook: ReturnType['useHook']> = (input = {}) => {
+ return useData({
+ input: [
+ ['search', input.search],
+ ['categoryId', input.categoryId],
+ ['brandId', input.brandId],
+ ['sort', input.sort]
+ ],
+ swrOptions: {
+ revalidateOnFocus: false,
+ // revalidateOnFocus: false means do not fetch products again when website is refocused in the web browser.
+ ...input.swrOptions
+ }
+ });
+ };
+
+ return useWrappedHook;
+ }
+};
+
+export default useSearch as UseSearch;
diff --git a/lib/spree/provider.ts b/lib/spree/provider.ts
new file mode 100644
index 000000000..91ed5f6ea
--- /dev/null
+++ b/lib/spree/provider.ts
@@ -0,0 +1,35 @@
+import fetcher from './fetcher';
+import { handler as useCart } from './cart/use-cart';
+import { handler as useAddItem } from './cart/use-add-item';
+import { handler as useUpdateItem } from './cart/use-update-item';
+import { handler as useRemoveItem } from './cart/use-remove-item';
+import { handler as useCustomer } from './customer/use-customer';
+import { handler as useSearch } from './product/use-search';
+import { handler as useLogin } from './auth/use-login';
+import { handler as useLogout } from './auth/use-logout';
+import { handler as useSignup } from './auth/use-signup';
+import { handler as useCheckout } from './checkout/use-checkout';
+import { handler as useWishlist } from './wishlist/use-wishlist';
+import { handler as useWishlistAddItem } from './wishlist/use-add-item';
+import { handler as useWishlistRemoveItem } from './wishlist/use-remove-item';
+import { requireConfigValue } from './isomorphic-config';
+
+const spreeProvider = {
+ locale: requireConfigValue('defaultLocale') as string,
+ cartCookie: requireConfigValue('cartCookieName') as string,
+ fetcher,
+ cart: { useCart, useAddItem, useUpdateItem, useRemoveItem },
+ customer: { useCustomer },
+ products: { useSearch },
+ auth: { useLogin, useLogout, useSignup },
+ checkout: { useCheckout },
+ wishlist: {
+ useWishlist,
+ useAddItem: useWishlistAddItem,
+ useRemoveItem: useWishlistRemoveItem
+ }
+};
+
+export { spreeProvider };
+
+export type SpreeProvider = typeof spreeProvider;
diff --git a/lib/spree/types/index.ts b/lib/spree/types/index.ts
new file mode 100644
index 000000000..9ea74c282
--- /dev/null
+++ b/lib/spree/types/index.ts
@@ -0,0 +1,166 @@
+import type { fetchResponseKey } from '../utils/create-customized-fetch-fetcher';
+import type {
+ JsonApiDocument,
+ JsonApiListResponse,
+ JsonApiSingleResponse
+} from '@spree/storefront-api-v2-sdk/types/interfaces/JsonApi';
+import type { ResultResponse } from '@spree/storefront-api-v2-sdk/types/interfaces/ResultResponse';
+import type { Response } from '@vercel/fetch';
+import type { ProductOption, Product } from '@commerce/types/product';
+import type {
+ AddItemHook,
+ RemoveItemHook,
+ WishlistItemBody,
+ WishlistTypes
+} from '@commerce/types/wishlist';
+
+export type UnknownObjectValues = Record;
+
+export type NonUndefined = T extends undefined ? never : T;
+
+export type ValueOf = T[keyof T];
+
+export type SpreeSdkResponse = JsonApiSingleResponse | JsonApiListResponse;
+
+export type SpreeSdkResponseWithRawResponse = SpreeSdkResponse & {
+ [fetchResponseKey]: Response;
+};
+
+export type SpreeSdkResultResponseSuccessType = SpreeSdkResponseWithRawResponse;
+
+export type SpreeSdkMethodReturnType<
+ ResultResponseSuccessType extends
+ SpreeSdkResultResponseSuccessType = SpreeSdkResultResponseSuccessType
+> = Promise>;
+
+export type SpreeSdkMethod<
+ ResultResponseSuccessType extends
+ SpreeSdkResultResponseSuccessType = SpreeSdkResultResponseSuccessType
+> = (...args: any[]) => SpreeSdkMethodReturnType;
+
+export type SpreeSdkVariables = {
+ methodPath: string;
+ arguments: any[];
+};
+
+export type FetcherVariables = SpreeSdkVariables & {
+ refreshExpiredAccessToken: boolean;
+ replayUnauthorizedRequest: boolean;
+};
+
+export interface ImageStyle {
+ url: string;
+ width: string;
+ height: string;
+ size: string;
+}
+
+export interface SpreeProductImage extends JsonApiDocument {
+ attributes: {
+ position: number;
+ alt: string;
+ original_url: string;
+ transformed_url: string | null;
+ styles: ImageStyle[];
+ };
+}
+
+export interface OptionTypeAttr extends JsonApiDocument {
+ attributes: {
+ name: string;
+ presentation: string;
+ position: number;
+ created_at: string;
+ updated_at: string;
+ filterable: boolean;
+ };
+}
+
+export interface LineItemAttr extends JsonApiDocument {
+ attributes: {
+ name: string;
+ quantity: number;
+ slug: string;
+ options_text: string;
+ price: string;
+ currency: string;
+ display_price: string;
+ total: string;
+ display_total: string;
+ adjustment_total: string;
+ display_adjustment_total: string;
+ additional_tax_total: string;
+ display_additional_tax_total: string;
+ discounted_amount: string;
+ display_discounted_amount: string;
+ pre_tax_amount: string;
+ display_pre_tax_amount: string;
+ promo_total: string;
+ display_promo_total: string;
+ included_tax_total: string;
+ display_inluded_tax_total: string;
+ };
+}
+
+export interface VariantAttr extends JsonApiDocument {
+ attributes: {
+ sku: string;
+ price: string;
+ currency: string;
+ display_price: string;
+ weight: string;
+ height: string;
+ width: string;
+ depth: string;
+ is_master: boolean;
+ options_text: string;
+ purchasable: boolean;
+ in_stock: boolean;
+ backorderable: boolean;
+ };
+}
+
+export interface ProductSlugAttr extends JsonApiDocument {
+ attributes: {
+ slug: string;
+ };
+}
+export interface IProductsSlugs extends JsonApiListResponse {
+ data: ProductSlugAttr[];
+}
+
+export type ExpandedProductOption = ProductOption & { position: number };
+
+export type UserOAuthTokens = {
+ refreshToken: string;
+ accessToken: string;
+};
+
+// TODO: ExplicitCommerceWishlist is a temporary type
+// derived from tsx views. It will be removed once
+// Wishlist in @commerce/types/wishlist is updated
+// to a more specific type than `any`.
+export type ExplicitCommerceWishlist = {
+ id: string;
+ token: string;
+ items: {
+ id: string;
+ product_id: number;
+ variant_id: number;
+ product: Product;
+ }[];
+};
+
+export type ExplicitWishlistAddItemHook = AddItemHook<
+ WishlistTypes & {
+ wishlist: ExplicitCommerceWishlist;
+ itemBody: WishlistItemBody & {
+ wishlistToken?: string;
+ };
+ }
+>;
+
+export type ExplicitWishlistRemoveItemHook = RemoveItemHook & {
+ fetcherInput: { wishlistToken?: string };
+ body: { wishlistToken?: string };
+};
diff --git a/lib/spree/utils/convert-spree-error-to-graph-ql-error.ts b/lib/spree/utils/convert-spree-error-to-graph-ql-error.ts
new file mode 100644
index 000000000..4103d1c63
--- /dev/null
+++ b/lib/spree/utils/convert-spree-error-to-graph-ql-error.ts
@@ -0,0 +1,50 @@
+import { FetcherError } from '@commerce/utils/errors';
+import { errors } from '@spree/storefront-api-v2-sdk';
+
+const convertSpreeErrorToGraphQlError = (error: errors.SpreeError): FetcherError => {
+ if (error instanceof errors.ExpandedSpreeError) {
+ // Assuming error.errors[key] is a list of strings.
+
+ if ('base' in error.errors) {
+ const baseErrorMessage = error.errors.base as unknown as string;
+
+ return new FetcherError({
+ status: error.serverResponse.status,
+ message: baseErrorMessage
+ });
+ }
+
+ const fetcherErrors = Object.keys(error.errors).map((sdkErrorKey) => {
+ const errors = error.errors[sdkErrorKey] as string[];
+
+ // Naively assume sdkErrorKey is a label. Capitalize it for a better
+ // out-of-the-box experience.
+ const capitalizedSdkErrorKey = sdkErrorKey.replace(/^\w/, (firstChar) =>
+ firstChar.toUpperCase()
+ );
+
+ return {
+ message: `${capitalizedSdkErrorKey} ${errors.join(', ')}`
+ };
+ });
+
+ return new FetcherError({
+ status: error.serverResponse.status,
+ errors: fetcherErrors
+ });
+ }
+
+ if (error instanceof errors.BasicSpreeError) {
+ return new FetcherError({
+ status: error.serverResponse.status,
+ message: error.summary
+ });
+ }
+
+ return new FetcherError({
+ status: error.serverResponse.status,
+ message: error.message
+ });
+};
+
+export default convertSpreeErrorToGraphQlError;
diff --git a/lib/spree/utils/create-customized-fetch-fetcher.ts b/lib/spree/utils/create-customized-fetch-fetcher.ts
new file mode 100644
index 000000000..f49fdbe83
--- /dev/null
+++ b/lib/spree/utils/create-customized-fetch-fetcher.ts
@@ -0,0 +1,96 @@
+import { errors, request as spreeSdkRequestHelpers } from '@spree/storefront-api-v2-sdk';
+import type { CreateCustomizedFetchFetcher } from '@spree/storefront-api-v2-sdk/types/interfaces/CreateCustomizedFetchFetcher';
+import isJsonContentType from './is-json-content-type';
+
+export const fetchResponseKey = Symbol('fetch-response-key');
+
+const createCustomizedFetchFetcher: CreateCustomizedFetchFetcher = (fetcherOptions) => {
+ const { FetchError } = errors;
+ const sharedHeaders = {
+ 'Content-Type': 'application/json'
+ };
+
+ const { host, fetch, requestConstructor } = fetcherOptions;
+
+ return {
+ fetch: async (fetchOptions) => {
+ // This fetcher always returns request equal null,
+ // because @vercel/fetch doesn't accept a Request object as argument
+ // and it's not used by NJC anyway.
+ try {
+ const { url, params, method, headers, responseParsing } = fetchOptions;
+ const absoluteUrl = new URL(url, host);
+ let payload;
+
+ switch (method.toUpperCase()) {
+ case 'PUT':
+ case 'POST':
+ case 'DELETE':
+ case 'PATCH':
+ payload = { body: JSON.stringify(params) };
+ break;
+ default:
+ payload = null;
+ absoluteUrl.search = spreeSdkRequestHelpers.objectToQuerystring(params);
+ }
+
+ const request: Request = new requestConstructor(absoluteUrl.toString(), {
+ method: method.toUpperCase(),
+ headers: { ...sharedHeaders, ...headers },
+ ...payload
+ });
+
+ try {
+ const response: Response = await fetch(request);
+ const responseContentType = response.headers.get('content-type');
+ let data;
+
+ if (responseParsing === 'automatic') {
+ if (responseContentType && isJsonContentType(responseContentType)) {
+ data = await response.json();
+ } else {
+ data = await response.text();
+ }
+ } else if (responseParsing === 'text') {
+ data = await response.text();
+ } else if (responseParsing === 'json') {
+ data = await response.json();
+ } else if (responseParsing === 'stream') {
+ data = await response.body;
+ }
+
+ if (!response.ok) {
+ // Use the "traditional" approach and reject non 2xx responses.
+ throw new FetchError(response, request, data);
+ }
+
+ data[fetchResponseKey] = response;
+
+ return { data };
+ } catch (error) {
+ if (error instanceof FetchError) {
+ throw error;
+ }
+
+ if (!(error instanceof Error)) {
+ throw error;
+ }
+
+ throw new FetchError(null, request, null, error.message);
+ }
+ } catch (error) {
+ if (error instanceof FetchError) {
+ throw error;
+ }
+
+ if (!(error instanceof Error)) {
+ throw error;
+ }
+
+ throw new FetchError(null, null, null, error.message);
+ }
+ }
+ };
+};
+
+export default createCustomizedFetchFetcher;
diff --git a/lib/spree/utils/create-empty-cart.ts b/lib/spree/utils/create-empty-cart.ts
new file mode 100644
index 000000000..968346380
--- /dev/null
+++ b/lib/spree/utils/create-empty-cart.ts
@@ -0,0 +1,22 @@
+import type { GraphQLFetcherResult } from '@commerce/api';
+import type { HookFetcherContext } from '@commerce/utils/types';
+import type { IOrder } from '@spree/storefront-api-v2-sdk/types/interfaces/Order';
+import type { IToken } from '@spree/storefront-api-v2-sdk/types/interfaces/Token';
+import ensureIToken from './tokens/ensure-itoken';
+
+const createEmptyCart = (
+ fetch: HookFetcherContext<{
+ data: any;
+ }>['fetch']
+): Promise> => {
+ const token: IToken | undefined = ensureIToken();
+
+ return fetch>({
+ variables: {
+ methodPath: 'cart.create',
+ arguments: [token]
+ }
+ });
+};
+
+export default createEmptyCart;
diff --git a/lib/spree/utils/create-get-absolute-image-url.ts b/lib/spree/utils/create-get-absolute-image-url.ts
new file mode 100644
index 000000000..2a4955a94
--- /dev/null
+++ b/lib/spree/utils/create-get-absolute-image-url.ts
@@ -0,0 +1,22 @@
+import { SpreeProductImage } from '../types';
+import getImageUrl from './get-image-url';
+
+const createGetAbsoluteImageUrl =
+ (host: string, useOriginalImageSize: boolean = true) =>
+ (image: SpreeProductImage, minWidth: number, minHeight: number): string | null => {
+ let url;
+
+ if (useOriginalImageSize) {
+ url = image.attributes.transformed_url || null;
+ } else {
+ url = getImageUrl(image, minWidth, minHeight);
+ }
+
+ if (url === null) {
+ return null;
+ }
+
+ return `${host}${url}`;
+ };
+
+export default createGetAbsoluteImageUrl;
diff --git a/lib/spree/utils/expand-options.ts b/lib/spree/utils/expand-options.ts
new file mode 100644
index 000000000..5bc18591b
--- /dev/null
+++ b/lib/spree/utils/expand-options.ts
@@ -0,0 +1,102 @@
+import type { ProductOptionValues } from '@commerce/types/product';
+import type {
+ JsonApiDocument,
+ JsonApiResponse
+} from '@spree/storefront-api-v2-sdk/types/interfaces/JsonApi';
+import { jsonApi } from '@spree/storefront-api-v2-sdk';
+import type { RelationType } from '@spree/storefront-api-v2-sdk/types/interfaces/Relationships';
+import SpreeResponseContentError from '../errors/SpreeResponseContentError';
+import type { OptionTypeAttr, ExpandedProductOption } from '../types';
+import sortOptionsByPosition from '../utils/sort-option-types';
+
+const isColorProductOption = (productOption: ExpandedProductOption) => {
+ return productOption.displayName === 'Color';
+};
+
+const expandOptions = (
+ spreeSuccessResponse: JsonApiResponse,
+ spreeOptionValue: JsonApiDocument,
+ accumulatedOptions: ExpandedProductOption[]
+): ExpandedProductOption[] => {
+ const spreeOptionTypeIdentifier = spreeOptionValue.relationships.option_type.data as RelationType;
+
+ const existingOptionIndex = accumulatedOptions.findIndex(
+ (option) => option.id == spreeOptionTypeIdentifier.id
+ );
+
+ let option: ExpandedProductOption;
+
+ if (existingOptionIndex === -1) {
+ const spreeOptionType = jsonApi.findDocument(
+ spreeSuccessResponse,
+ spreeOptionTypeIdentifier
+ );
+
+ if (!spreeOptionType) {
+ throw new SpreeResponseContentError(
+ `Option type with id ${spreeOptionTypeIdentifier.id} not found.`
+ );
+ }
+
+ option = {
+ __typename: 'MultipleChoiceOption',
+ id: spreeOptionType.id,
+ displayName: spreeOptionType.attributes.presentation,
+ position: spreeOptionType.attributes.position,
+ values: []
+ };
+ } else {
+ const existingOption = accumulatedOptions[existingOptionIndex];
+
+ option = existingOption;
+ }
+
+ let optionValue: ProductOptionValues;
+
+ const label = isColorProductOption(option)
+ ? spreeOptionValue.attributes.name
+ : spreeOptionValue.attributes.presentation;
+
+ const productOptionValueExists = option.values.some(
+ (optionValue: ProductOptionValues) => optionValue.label === label
+ );
+
+ if (!productOptionValueExists) {
+ if (isColorProductOption(option)) {
+ optionValue = {
+ label,
+ hexColors: [spreeOptionValue.attributes.presentation]
+ };
+ } else {
+ optionValue = {
+ label
+ };
+ }
+
+ if (existingOptionIndex === -1) {
+ return [
+ ...accumulatedOptions,
+ {
+ ...option,
+ values: [optionValue]
+ }
+ ];
+ }
+
+ const expandedOptionValues = [...option.values, optionValue];
+ const expandedOptions = [...accumulatedOptions];
+
+ expandedOptions[existingOptionIndex] = {
+ ...option,
+ values: expandedOptionValues
+ };
+
+ const sortedOptions = sortOptionsByPosition(expandedOptions);
+
+ return sortedOptions;
+ }
+
+ return accumulatedOptions;
+};
+
+export default expandOptions;
diff --git a/lib/spree/utils/force-isomorphic-config-values.ts b/lib/spree/utils/force-isomorphic-config-values.ts
new file mode 100644
index 000000000..322d0d787
--- /dev/null
+++ b/lib/spree/utils/force-isomorphic-config-values.ts
@@ -0,0 +1,42 @@
+import type { NonUndefined, UnknownObjectValues } from '../types';
+import MisconfigurationError from '../errors/MisconfigurationError';
+import isServer from './is-server';
+
+const generateMisconfigurationErrorMessage = (keys: Array) =>
+ `${keys.join(', ')} must have a value before running the Framework.`;
+
+const forceIsomorphicConfigValues = <
+ X extends keyof T,
+ T extends UnknownObjectValues,
+ H extends Record>
+>(
+ config: T,
+ requiredServerKeys: string[],
+ requiredPublicKeys: X[]
+) => {
+ if (isServer) {
+ const missingServerConfigValues = requiredServerKeys.filter(
+ (requiredServerKey) => typeof config[requiredServerKey] === 'undefined'
+ );
+
+ if (missingServerConfigValues.length > 0) {
+ throw new MisconfigurationError(
+ generateMisconfigurationErrorMessage(missingServerConfigValues)
+ );
+ }
+ }
+
+ const missingPublicConfigValues = requiredPublicKeys.filter(
+ (requiredPublicKey) => typeof config[requiredPublicKey] === 'undefined'
+ );
+
+ if (missingPublicConfigValues.length > 0) {
+ throw new MisconfigurationError(
+ generateMisconfigurationErrorMessage(missingPublicConfigValues)
+ );
+ }
+
+ return config as T & H;
+};
+
+export default forceIsomorphicConfigValues;
diff --git a/lib/spree/utils/get-image-url.ts b/lib/spree/utils/get-image-url.ts
new file mode 100644
index 000000000..76f5a561c
--- /dev/null
+++ b/lib/spree/utils/get-image-url.ts
@@ -0,0 +1,38 @@
+// Based on https://github.com/spark-solutions/spree2vuestorefront/blob/d88d85ae1bcd2ec99b13b81cd2e3c25600a0216e/src/utils/index.ts
+
+import type { ImageStyle, SpreeProductImage } from '../types';
+
+const getImageUrl = (image: SpreeProductImage, minWidth: number, _: number): string | null => {
+ // every image is still resized in vue-storefront-api, no matter what getImageUrl returns
+ if (image) {
+ const {
+ attributes: { styles }
+ } = image;
+ const bestStyleIndex = styles.reduce(
+ (bSIndex: number | null, style: ImageStyle, styleIndex: number) => {
+ // assuming all images are the same dimensions, just scaled
+ if (bSIndex === null) {
+ return 0;
+ }
+ const bestStyle = styles[bSIndex];
+ const widthDiff = +bestStyle.width - minWidth;
+ const minWidthDiff = +style.width - minWidth;
+ if (widthDiff < 0 && minWidthDiff > 0) {
+ return styleIndex;
+ }
+ if (widthDiff > 0 && minWidthDiff < 0) {
+ return bSIndex;
+ }
+ return Math.abs(widthDiff) < Math.abs(minWidthDiff) ? bSIndex : styleIndex;
+ },
+ null
+ );
+
+ if (bestStyleIndex !== null) {
+ return styles[bestStyleIndex].url;
+ }
+ }
+ return null;
+};
+
+export default getImageUrl;
diff --git a/lib/spree/utils/get-media-gallery.ts b/lib/spree/utils/get-media-gallery.ts
new file mode 100644
index 000000000..91e2ddb7a
--- /dev/null
+++ b/lib/spree/utils/get-media-gallery.ts
@@ -0,0 +1,21 @@
+// Based on https://github.com/spark-solutions/spree2vuestorefront/blob/d88d85ae1bcd2ec99b13b81cd2e3c25600a0216e/src/utils/index.ts
+
+import type { ProductImage } from '@commerce/types/product';
+import type { SpreeProductImage } from '../types';
+
+const getMediaGallery = (
+ images: SpreeProductImage[],
+ getImageUrl: (image: SpreeProductImage, minWidth: number, minHeight: number) => string | null
+) => {
+ return images.reduce((productImages, _, imageIndex) => {
+ const url = getImageUrl(images[imageIndex], 800, 800);
+
+ if (url) {
+ return [...productImages, { url }];
+ }
+
+ return productImages;
+ }, []);
+};
+
+export default getMediaGallery;
diff --git a/lib/spree/utils/get-product-path.ts b/lib/spree/utils/get-product-path.ts
new file mode 100644
index 000000000..12c27f52c
--- /dev/null
+++ b/lib/spree/utils/get-product-path.ts
@@ -0,0 +1,7 @@
+import type { ProductSlugAttr } from '../types';
+
+const getProductPath = (partialSpreeProduct: ProductSlugAttr) => {
+ return `/${partialSpreeProduct.attributes.slug}`;
+};
+
+export default getProductPath;
diff --git a/lib/spree/utils/get-spree-sdk-method-from-endpoint-path.ts b/lib/spree/utils/get-spree-sdk-method-from-endpoint-path.ts
new file mode 100644
index 000000000..98744cc21
--- /dev/null
+++ b/lib/spree/utils/get-spree-sdk-method-from-endpoint-path.ts
@@ -0,0 +1,50 @@
+import type { Client } from '@spree/storefront-api-v2-sdk';
+import SpreeSdkMethodFromEndpointPathError from '../errors/SpreeSdkMethodFromEndpointPathError';
+import type { SpreeSdkMethod, SpreeSdkResultResponseSuccessType } from '../types';
+
+const getSpreeSdkMethodFromEndpointPath = <
+ ExactSpreeSdkClientType extends Client,
+ ResultResponseSuccessType extends
+ SpreeSdkResultResponseSuccessType = SpreeSdkResultResponseSuccessType
+>(
+ client: ExactSpreeSdkClientType,
+ path: string
+): SpreeSdkMethod => {
+ const pathParts = path.split('.');
+ const reachedPath: string[] = [];
+ let node = >client;
+
+ console.log(`Looking for ${path} in Spree Sdk.`);
+
+ while (reachedPath.length < pathParts.length - 1) {
+ const checkedPathPart = pathParts[reachedPath.length];
+ const checkedNode = node[checkedPathPart];
+
+ console.log(`Checking part ${checkedPathPart}.`);
+
+ if (typeof checkedNode !== 'object') {
+ throw new SpreeSdkMethodFromEndpointPathError(
+ `Couldn't reach ${path}. Farthest path reached was: ${reachedPath.join('.')}.`
+ );
+ }
+
+ if (checkedNode === null) {
+ throw new SpreeSdkMethodFromEndpointPathError(`Path ${path} doesn't exist.`);
+ }
+
+ node = >checkedNode;
+ reachedPath.push(checkedPathPart);
+ }
+
+ const foundEndpointMethod = node[pathParts[reachedPath.length]];
+
+ if (reachedPath.length !== pathParts.length - 1 || typeof foundEndpointMethod !== 'function') {
+ throw new SpreeSdkMethodFromEndpointPathError(
+ `Couldn't reach ${path}. Farthest path reached was: ${reachedPath.join('.')}.`
+ );
+ }
+
+ return foundEndpointMethod.bind(node);
+};
+
+export default getSpreeSdkMethodFromEndpointPath;
diff --git a/lib/spree/utils/handle-token-errors.ts b/lib/spree/utils/handle-token-errors.ts
new file mode 100644
index 000000000..49f1b6935
--- /dev/null
+++ b/lib/spree/utils/handle-token-errors.ts
@@ -0,0 +1,14 @@
+import AccessTokenError from '../errors/AccessTokenError';
+import RefreshTokenError from '../errors/RefreshTokenError';
+
+const handleTokenErrors = (error: unknown, action: () => void): boolean => {
+ if (error instanceof AccessTokenError || error instanceof RefreshTokenError) {
+ action();
+
+ return true;
+ }
+
+ return false;
+};
+
+export default handleTokenErrors;
diff --git a/lib/spree/utils/is-json-content-type.ts b/lib/spree/utils/is-json-content-type.ts
new file mode 100644
index 000000000..020407c67
--- /dev/null
+++ b/lib/spree/utils/is-json-content-type.ts
@@ -0,0 +1,4 @@
+const isJsonContentType = (contentType: string): boolean =>
+ contentType.includes('application/json') || contentType.includes('application/vnd.api+json');
+
+export default isJsonContentType;
diff --git a/lib/spree/utils/is-server.ts b/lib/spree/utils/is-server.ts
new file mode 100644
index 000000000..246d8b700
--- /dev/null
+++ b/lib/spree/utils/is-server.ts
@@ -0,0 +1 @@
+export default typeof window === 'undefined';
diff --git a/lib/spree/utils/login.ts b/lib/spree/utils/login.ts
new file mode 100644
index 000000000..8cce71b0a
--- /dev/null
+++ b/lib/spree/utils/login.ts
@@ -0,0 +1,53 @@
+import type { GraphQLFetcherResult } from '@commerce/api';
+import type { HookFetcherContext } from '@commerce/utils/types';
+import type { AuthTokenAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/Authentication';
+import type { AssociateCart } from '@spree/storefront-api-v2-sdk/types/interfaces/endpoints/CartClass';
+import type { IOrder } from '@spree/storefront-api-v2-sdk/types/interfaces/Order';
+import type { IOAuthToken, IToken } from '@spree/storefront-api-v2-sdk/types/interfaces/Token';
+import { getCartToken, removeCartToken } from './tokens/cart-token';
+import { setUserTokenResponse } from './tokens/user-token-response';
+
+const login = async (
+ fetch: HookFetcherContext<{
+ data: any;
+ }>['fetch'],
+ getTokenParameters: AuthTokenAttr,
+ associateGuestCart: boolean
+): Promise => {
+ const { data: spreeGetTokenSuccessResponse } = await fetch>({
+ variables: {
+ methodPath: 'authentication.getToken',
+ arguments: [getTokenParameters]
+ }
+ });
+
+ setUserTokenResponse(spreeGetTokenSuccessResponse);
+
+ if (associateGuestCart) {
+ const cartToken = getCartToken();
+
+ if (cartToken) {
+ // If the user had a cart as guest still use its contents
+ // after logging in.
+ const accessToken = spreeGetTokenSuccessResponse.access_token;
+ const token: IToken = { bearerToken: accessToken };
+
+ const associateGuestCartParameters: AssociateCart = {
+ guest_order_token: cartToken
+ };
+
+ await fetch>({
+ variables: {
+ methodPath: 'cart.associateGuestCart',
+ arguments: [token, associateGuestCartParameters]
+ }
+ });
+
+ // We no longer need the guest cart token, so let's remove it.
+ }
+ }
+
+ removeCartToken();
+};
+
+export default login;
diff --git a/lib/spree/utils/normalizations/normalize-cart.ts b/lib/spree/utils/normalizations/normalize-cart.ts
new file mode 100644
index 000000000..95248edf6
--- /dev/null
+++ b/lib/spree/utils/normalizations/normalize-cart.ts
@@ -0,0 +1,191 @@
+import type { Cart, LineItem, ProductVariant, SelectedOption } from '@commerce/types/cart';
+import MissingLineItemVariantError from '../../errors/MissingLineItemVariantError';
+import { requireConfigValue } from '../../isomorphic-config';
+import type { OrderAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/Order';
+import type { ProductAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/Product';
+import type { Image } from '@commerce/types/common';
+import { jsonApi } from '@spree/storefront-api-v2-sdk';
+import createGetAbsoluteImageUrl from '../create-get-absolute-image-url';
+import getMediaGallery from '../get-media-gallery';
+import type {
+ LineItemAttr,
+ OptionTypeAttr,
+ SpreeProductImage,
+ SpreeSdkResponse,
+ VariantAttr
+} from '../../types';
+
+const placeholderImage = requireConfigValue('lineItemPlaceholderImageUrl') as string | false;
+
+const isColorProductOption = (productOptionType: OptionTypeAttr) => {
+ return productOptionType.attributes.presentation === 'Color';
+};
+
+const normalizeVariant = (
+ spreeSuccessResponse: SpreeSdkResponse,
+ spreeVariant: VariantAttr
+): ProductVariant => {
+ const spreeProduct = jsonApi.findSingleRelationshipDocument(
+ spreeSuccessResponse,
+ spreeVariant,
+ 'product'
+ );
+
+ if (spreeProduct === null) {
+ throw new MissingLineItemVariantError(
+ `Couldn't find product for variant with id ${spreeVariant.id}.`
+ );
+ }
+
+ const spreeVariantImageRecords = jsonApi.findRelationshipDocuments(
+ spreeSuccessResponse,
+ spreeVariant,
+ 'images'
+ );
+
+ let lineItemImage;
+
+ const variantImage = getMediaGallery(
+ spreeVariantImageRecords,
+ createGetAbsoluteImageUrl(requireConfigValue('imageHost') as string)
+ )[0];
+
+ if (variantImage) {
+ lineItemImage = variantImage;
+ } else {
+ const spreeProductImageRecords = jsonApi.findRelationshipDocuments(
+ spreeSuccessResponse,
+ spreeProduct,
+ 'images'
+ );
+
+ const productImage = getMediaGallery(
+ spreeProductImageRecords,
+ createGetAbsoluteImageUrl(requireConfigValue('imageHost') as string)
+ )[0];
+
+ lineItemImage = productImage;
+ }
+
+ const image: Image =
+ lineItemImage ?? (placeholderImage === false ? undefined : { url: placeholderImage });
+
+ return {
+ id: spreeVariant.id,
+ sku: spreeVariant.attributes.sku,
+ name: spreeProduct.attributes.name,
+ requiresShipping: true,
+ price: parseFloat(spreeVariant.attributes.price),
+ listPrice: parseFloat(spreeVariant.attributes.price),
+ image,
+ isInStock: spreeVariant.attributes.in_stock,
+ availableForSale: spreeVariant.attributes.purchasable,
+ ...(spreeVariant.attributes.weight === '0.0'
+ ? {}
+ : {
+ weight: {
+ value: parseFloat(spreeVariant.attributes.weight),
+ unit: 'KILOGRAMS'
+ }
+ })
+ // TODO: Add height, width and depth when Measurement type allows distance measurements.
+ };
+};
+
+const normalizeLineItem = (
+ spreeSuccessResponse: SpreeSdkResponse,
+ spreeLineItem: LineItemAttr
+): LineItem => {
+ const variant = jsonApi.findSingleRelationshipDocument(
+ spreeSuccessResponse,
+ spreeLineItem,
+ 'variant'
+ );
+
+ if (variant === null) {
+ throw new MissingLineItemVariantError(
+ `Couldn't find variant for line item with id ${spreeLineItem.id}.`
+ );
+ }
+
+ const product = jsonApi.findSingleRelationshipDocument(
+ spreeSuccessResponse,
+ variant,
+ 'product'
+ );
+
+ if (product === null) {
+ throw new MissingLineItemVariantError(
+ `Couldn't find product for variant with id ${variant.id}.`
+ );
+ }
+
+ // CartItem.tsx expects path without a '/' prefix unlike pages/product/[slug].tsx and others.
+ const path = `${product.attributes.slug}`;
+
+ const spreeOptionValues = jsonApi.findRelationshipDocuments(
+ spreeSuccessResponse,
+ variant,
+ 'option_values'
+ );
+
+ const options: SelectedOption[] = spreeOptionValues.map((spreeOptionValue) => {
+ const spreeOptionType = jsonApi.findSingleRelationshipDocument(
+ spreeSuccessResponse,
+ spreeOptionValue,
+ 'option_type'
+ );
+
+ if (spreeOptionType === null) {
+ throw new MissingLineItemVariantError(
+ `Couldn't find option type of option value with id ${spreeOptionValue.id}.`
+ );
+ }
+
+ const label = isColorProductOption(spreeOptionType)
+ ? spreeOptionValue.attributes.name
+ : spreeOptionValue.attributes.presentation;
+
+ return {
+ id: spreeOptionValue.id,
+ name: spreeOptionType.attributes.presentation,
+ value: label
+ };
+ });
+
+ return {
+ id: spreeLineItem.id,
+ variantId: variant.id,
+ productId: product.id,
+ name: spreeLineItem.attributes.name,
+ quantity: spreeLineItem.attributes.quantity,
+ discounts: [], // TODO: Implement when the template starts displaying them.
+ path,
+ variant: normalizeVariant(spreeSuccessResponse, variant),
+ options
+ };
+};
+
+const normalizeCart = (spreeSuccessResponse: SpreeSdkResponse, spreeCart: OrderAttr): Cart => {
+ const lineItems = jsonApi
+ .findRelationshipDocuments(spreeSuccessResponse, spreeCart, 'line_items')
+ .map((lineItem) => normalizeLineItem(spreeSuccessResponse, lineItem));
+
+ return {
+ id: spreeCart.id,
+ createdAt: spreeCart.attributes.created_at.toString(),
+ currency: { code: spreeCart.attributes.currency },
+ taxesIncluded: true,
+ lineItems,
+ lineItemsSubtotalPrice: parseFloat(spreeCart.attributes.item_total),
+ subtotalPrice: parseFloat(spreeCart.attributes.item_total),
+ totalPrice: parseFloat(spreeCart.attributes.total),
+ customerId: spreeCart.attributes.token,
+ email: spreeCart.attributes.email,
+ discounts: [] // TODO: Implement when the template starts displaying them.
+ };
+};
+
+export { normalizeLineItem };
+
+export default normalizeCart;
diff --git a/lib/spree/utils/normalizations/normalize-page.ts b/lib/spree/utils/normalizations/normalize-page.ts
new file mode 100644
index 000000000..c257bacc1
--- /dev/null
+++ b/lib/spree/utils/normalizations/normalize-page.ts
@@ -0,0 +1,42 @@
+import { Page } from '@commerce/types/page';
+import type { PageAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/Page';
+import { SpreeSdkResponse } from '../../types';
+
+const normalizePage = (
+ _spreeSuccessResponse: SpreeSdkResponse,
+ spreePage: PageAttr,
+ commerceLocales: string[]
+): Page => {
+ // If the locale returned by Spree is not available, search
+ // for a similar one.
+
+ const spreeLocale = spreePage.attributes.locale;
+ let usedCommerceLocale: string;
+
+ if (commerceLocales.includes(spreeLocale)) {
+ usedCommerceLocale = spreeLocale;
+ } else {
+ const genericSpreeLocale = spreeLocale.split('-')[0];
+
+ const foundExactGenericLocale = commerceLocales.includes(genericSpreeLocale);
+
+ if (foundExactGenericLocale) {
+ usedCommerceLocale = genericSpreeLocale;
+ } else {
+ const foundSimilarLocale = commerceLocales.find((locale) => {
+ return locale.split('-')[0] === genericSpreeLocale;
+ });
+
+ usedCommerceLocale = foundSimilarLocale || spreeLocale;
+ }
+ }
+
+ return {
+ id: spreePage.id,
+ name: spreePage.attributes.title,
+ url: `/${usedCommerceLocale}/${spreePage.attributes.slug}`,
+ body: spreePage.attributes.content
+ };
+};
+
+export default normalizePage;
diff --git a/lib/spree/utils/normalizations/normalize-product.ts b/lib/spree/utils/normalizations/normalize-product.ts
new file mode 100644
index 000000000..716980aa1
--- /dev/null
+++ b/lib/spree/utils/normalizations/normalize-product.ts
@@ -0,0 +1,196 @@
+import type { Product, ProductImage, ProductPrice, ProductVariant } from '@commerce/types/product';
+import type { ProductAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/Product';
+import type { RelationType } from '@spree/storefront-api-v2-sdk/types/interfaces/Relationships';
+import { jsonApi } from '@spree/storefront-api-v2-sdk';
+import { JsonApiDocument } from '@spree/storefront-api-v2-sdk/types/interfaces/JsonApi';
+import { requireConfigValue } from '../../isomorphic-config';
+import createGetAbsoluteImageUrl from '../create-get-absolute-image-url';
+import expandOptions from '../expand-options';
+import getMediaGallery from '../get-media-gallery';
+import getProductPath from '../get-product-path';
+import MissingPrimaryVariantError from '../../errors/MissingPrimaryVariantError';
+import MissingOptionValueError from '../../errors/MissingOptionValueError';
+import type { ExpandedProductOption, SpreeSdkResponse, VariantAttr } from '../../types';
+
+const placeholderImage = requireConfigValue('productPlaceholderImageUrl') as string | false;
+
+const imagesOptionFilter = requireConfigValue('imagesOptionFilter') as string | false;
+
+const normalizeProduct = (
+ spreeSuccessResponse: SpreeSdkResponse,
+ spreeProduct: ProductAttr
+): Product => {
+ const spreePrimaryVariant = jsonApi.findSingleRelationshipDocument(
+ spreeSuccessResponse,
+ spreeProduct,
+ 'primary_variant'
+ );
+
+ if (spreePrimaryVariant === null) {
+ throw new MissingPrimaryVariantError(
+ `Couldn't find primary variant for product with id ${spreeProduct.id}.`
+ );
+ }
+
+ const sku = spreePrimaryVariant.attributes.sku;
+
+ const price: ProductPrice = {
+ value: parseFloat(spreeProduct.attributes.price),
+ currencyCode: spreeProduct.attributes.currency
+ };
+
+ const hasNonMasterVariants =
+ (spreeProduct.relationships.variants.data as RelationType[]).length > 1;
+
+ const showOptions =
+ (requireConfigValue('showSingleVariantOptions') as boolean) || hasNonMasterVariants;
+
+ let options: ExpandedProductOption[] = [];
+
+ const spreeVariantRecords = jsonApi.findRelationshipDocuments(
+ spreeSuccessResponse,
+ spreeProduct,
+ 'variants'
+ );
+
+ // Use variants with option values if available. Fall back to
+ // Spree primary_variant if no explicit variants are present.
+ const spreeOptionsVariantsOrPrimary =
+ spreeVariantRecords.length === 0 ? [spreePrimaryVariant] : spreeVariantRecords;
+
+ const variants: ProductVariant[] = spreeOptionsVariantsOrPrimary.map((spreeVariantRecord) => {
+ let variantOptions: ExpandedProductOption[] = [];
+
+ if (showOptions) {
+ const spreeOptionValues = jsonApi.findRelationshipDocuments(
+ spreeSuccessResponse,
+ spreeVariantRecord,
+ 'option_values'
+ );
+
+ // Only include options which are used by variants.
+
+ spreeOptionValues.forEach((spreeOptionValue) => {
+ variantOptions = expandOptions(spreeSuccessResponse, spreeOptionValue, variantOptions);
+
+ options = expandOptions(spreeSuccessResponse, spreeOptionValue, options);
+ });
+ }
+
+ return {
+ id: spreeVariantRecord.id,
+ options: variantOptions
+ };
+ });
+
+ const spreePrimaryVariantImageRecords = jsonApi.findRelationshipDocuments(
+ spreeSuccessResponse,
+ spreePrimaryVariant,
+ 'images'
+ );
+
+ let spreeVariantImageRecords: JsonApiDocument[];
+
+ if (imagesOptionFilter === false) {
+ spreeVariantImageRecords = spreeVariantRecords.reduce(
+ (accumulatedImageRecords, spreeVariantRecord) => {
+ return [
+ ...accumulatedImageRecords,
+ ...jsonApi.findRelationshipDocuments(spreeSuccessResponse, spreeVariantRecord, 'images')
+ ];
+ },
+ []
+ );
+ } else {
+ const spreeOptionTypes = jsonApi.findRelationshipDocuments(
+ spreeSuccessResponse,
+ spreeProduct,
+ 'option_types'
+ );
+
+ const imagesFilterOptionType = spreeOptionTypes.find(
+ (spreeOptionType) => spreeOptionType.attributes.name === imagesOptionFilter
+ );
+
+ if (!imagesFilterOptionType) {
+ console.warn(
+ `Couldn't find option type having name ${imagesOptionFilter} for product with id ${spreeProduct.id}.` +
+ ' Showing no images for this product.'
+ );
+
+ spreeVariantImageRecords = [];
+ } else {
+ const imagesOptionTypeFilterId = imagesFilterOptionType.id;
+ const includedOptionValuesImagesIds: string[] = [];
+
+ spreeVariantImageRecords = spreeVariantRecords.reduce(
+ (accumulatedImageRecords, spreeVariantRecord) => {
+ const spreeVariantOptionValuesIdentifiers: RelationType[] =
+ spreeVariantRecord.relationships.option_values.data;
+
+ const spreeOptionValueOfFilterTypeIdentifier = spreeVariantOptionValuesIdentifiers.find(
+ (spreeVariantOptionValuesIdentifier: RelationType) =>
+ imagesFilterOptionType.relationships.option_values.data.some(
+ (filterOptionTypeValueIdentifier: RelationType) =>
+ filterOptionTypeValueIdentifier.id === spreeVariantOptionValuesIdentifier.id
+ )
+ );
+
+ if (!spreeOptionValueOfFilterTypeIdentifier) {
+ throw new MissingOptionValueError(
+ `Couldn't find option value related to option type with id ${imagesOptionTypeFilterId}.`
+ );
+ }
+
+ const optionValueImagesAlreadyIncluded = includedOptionValuesImagesIds.includes(
+ spreeOptionValueOfFilterTypeIdentifier.id
+ );
+
+ if (optionValueImagesAlreadyIncluded) {
+ return accumulatedImageRecords;
+ }
+
+ includedOptionValuesImagesIds.push(spreeOptionValueOfFilterTypeIdentifier.id);
+
+ return [
+ ...accumulatedImageRecords,
+ ...jsonApi.findRelationshipDocuments(spreeSuccessResponse, spreeVariantRecord, 'images')
+ ];
+ },
+ []
+ );
+ }
+ }
+
+ const spreeImageRecords = [...spreePrimaryVariantImageRecords, ...spreeVariantImageRecords];
+
+ const productImages = getMediaGallery(
+ spreeImageRecords,
+ createGetAbsoluteImageUrl(requireConfigValue('imageHost') as string)
+ );
+
+ const images: ProductImage[] =
+ productImages.length === 0
+ ? placeholderImage === false
+ ? []
+ : [{ url: placeholderImage }]
+ : productImages;
+
+ const slug = spreeProduct.attributes.slug;
+ const path = getProductPath(spreeProduct);
+
+ return {
+ id: spreeProduct.id,
+ name: spreeProduct.attributes.name,
+ description: spreeProduct.attributes.description,
+ images,
+ variants,
+ options,
+ price,
+ slug,
+ path,
+ sku
+ };
+};
+
+export default normalizeProduct;
diff --git a/lib/spree/utils/normalizations/normalize-user.ts b/lib/spree/utils/normalizations/normalize-user.ts
new file mode 100644
index 000000000..246936152
--- /dev/null
+++ b/lib/spree/utils/normalizations/normalize-user.ts
@@ -0,0 +1,16 @@
+import type { Customer } from '@commerce/types/customer';
+import type { AccountAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/Account';
+import type { SpreeSdkResponse } from '../../types';
+
+const normalizeUser = (
+ _spreeSuccessResponse: SpreeSdkResponse,
+ spreeUser: AccountAttr
+): Customer => {
+ const email = spreeUser.attributes.email;
+
+ return {
+ email
+ };
+};
+
+export default normalizeUser;
diff --git a/lib/spree/utils/normalizations/normalize-wishlist.ts b/lib/spree/utils/normalizations/normalize-wishlist.ts
new file mode 100644
index 000000000..15a73ef4f
--- /dev/null
+++ b/lib/spree/utils/normalizations/normalize-wishlist.ts
@@ -0,0 +1,60 @@
+import MissingProductError from '../../errors/MissingProductError';
+import MissingVariantError from '../../errors/MissingVariantError';
+import { jsonApi } from '@spree/storefront-api-v2-sdk';
+import type { ProductAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/Product';
+import type { WishedItemAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/WishedItem';
+import type { WishlistAttr } from '@spree/storefront-api-v2-sdk/types/interfaces/Wishlist';
+import type { ExplicitCommerceWishlist, SpreeSdkResponse, VariantAttr } from '../../types';
+import normalizeProduct from './normalize-product';
+
+const normalizeWishlist = (
+ spreeSuccessResponse: SpreeSdkResponse,
+ spreeWishlist: WishlistAttr
+): ExplicitCommerceWishlist => {
+ const spreeWishedItems = jsonApi.findRelationshipDocuments(
+ spreeSuccessResponse,
+ spreeWishlist,
+ 'wished_items'
+ );
+
+ const items: ExplicitCommerceWishlist['items'] = spreeWishedItems.map((spreeWishedItem) => {
+ const spreeWishedVariant = jsonApi.findSingleRelationshipDocument(
+ spreeSuccessResponse,
+ spreeWishedItem,
+ 'variant'
+ );
+
+ if (spreeWishedVariant === null) {
+ throw new MissingVariantError(
+ `Couldn't find variant for wished item with id ${spreeWishedItem.id}.`
+ );
+ }
+
+ const spreeWishedProduct = jsonApi.findSingleRelationshipDocument(
+ spreeSuccessResponse,
+ spreeWishedVariant,
+ 'product'
+ );
+
+ if (spreeWishedProduct === null) {
+ throw new MissingProductError(
+ `Couldn't find product for variant with id ${spreeWishedVariant.id}.`
+ );
+ }
+
+ return {
+ id: spreeWishedItem.id,
+ product_id: parseInt(spreeWishedProduct.id, 10),
+ variant_id: parseInt(spreeWishedVariant.id, 10),
+ product: normalizeProduct(spreeSuccessResponse, spreeWishedProduct)
+ };
+ });
+
+ return {
+ id: spreeWishlist.id,
+ token: spreeWishlist.attributes.token,
+ items
+ };
+};
+
+export default normalizeWishlist;
diff --git a/lib/spree/utils/require-config.ts b/lib/spree/utils/require-config.ts
new file mode 100644
index 000000000..2d0072b63
--- /dev/null
+++ b/lib/spree/utils/require-config.ts
@@ -0,0 +1,14 @@
+import MissingConfigurationValueError from '../errors/MissingConfigurationValueError';
+import type { NonUndefined, ValueOf } from '../types';
+
+const requireConfig = (isomorphicConfig: T, key: keyof T) => {
+ const valueUnderKey = isomorphicConfig[key];
+
+ if (typeof valueUnderKey === 'undefined') {
+ throw new MissingConfigurationValueError(`Value for configuration key ${key} was undefined.`);
+ }
+
+ return valueUnderKey as NonUndefined>;
+};
+
+export default requireConfig;
diff --git a/lib/spree/utils/sort-option-types.ts b/lib/spree/utils/sort-option-types.ts
new file mode 100644
index 000000000..99e05ac02
--- /dev/null
+++ b/lib/spree/utils/sort-option-types.ts
@@ -0,0 +1,9 @@
+import type { ExpandedProductOption } from '../types';
+
+const sortOptionsByPosition = (options: ExpandedProductOption[]): ExpandedProductOption[] => {
+ return options.sort((firstOption, secondOption) => {
+ return firstOption.position - secondOption.position;
+ });
+};
+
+export default sortOptionsByPosition;
diff --git a/lib/spree/utils/tokens/cart-token.ts b/lib/spree/utils/tokens/cart-token.ts
new file mode 100644
index 000000000..596d6ea27
--- /dev/null
+++ b/lib/spree/utils/tokens/cart-token.ts
@@ -0,0 +1,16 @@
+import { requireConfigValue } from '../../isomorphic-config';
+import Cookies from 'js-cookie';
+
+export const getCartToken = () => Cookies.get(requireConfigValue('cartCookieName') as string);
+
+export const setCartToken = (cartToken: string) => {
+ const cookieOptions = {
+ expires: requireConfigValue('cartCookieExpire') as number
+ };
+
+ Cookies.set(requireConfigValue('cartCookieName') as string, cartToken, cookieOptions);
+};
+
+export const removeCartToken = () => {
+ Cookies.remove(requireConfigValue('cartCookieName') as string);
+};
diff --git a/lib/spree/utils/tokens/ensure-fresh-user-access-token.ts b/lib/spree/utils/tokens/ensure-fresh-user-access-token.ts
new file mode 100644
index 000000000..a2483ad1f
--- /dev/null
+++ b/lib/spree/utils/tokens/ensure-fresh-user-access-token.ts
@@ -0,0 +1,49 @@
+import { SpreeSdkResponseWithRawResponse } from '../../types';
+import type { Client } from '@spree/storefront-api-v2-sdk';
+import type { IOAuthToken } from '@spree/storefront-api-v2-sdk/types/interfaces/Token';
+import getSpreeSdkMethodFromEndpointPath from '../get-spree-sdk-method-from-endpoint-path';
+import {
+ ensureUserTokenResponse,
+ removeUserTokenResponse,
+ setUserTokenResponse
+} from './user-token-response';
+import AccessTokenError from '../../errors/AccessTokenError';
+
+/**
+ * If the user has a saved access token, make sure it's not expired
+ * If it is expired, attempt to refresh it.
+ */
+const ensureFreshUserAccessToken = async (client: Client): Promise => {
+ const userTokenResponse = ensureUserTokenResponse();
+
+ if (!userTokenResponse) {
+ // There's no user token or it has an invalid format.
+ return;
+ }
+
+ const isAccessTokenExpired =
+ (userTokenResponse.created_at + userTokenResponse.expires_in) * 1000 < Date.now();
+
+ if (!isAccessTokenExpired) {
+ return;
+ }
+
+ const spreeRefreshAccessTokenSdkMethod = getSpreeSdkMethodFromEndpointPath<
+ Client,
+ SpreeSdkResponseWithRawResponse & IOAuthToken
+ >(client, 'authentication.refreshToken');
+
+ const spreeRefreshAccessTokenResponse = await spreeRefreshAccessTokenSdkMethod({
+ refresh_token: userTokenResponse.refresh_token
+ });
+
+ if (spreeRefreshAccessTokenResponse.isFail()) {
+ removeUserTokenResponse();
+
+ throw new AccessTokenError('Could not refresh access token.');
+ }
+
+ setUserTokenResponse(spreeRefreshAccessTokenResponse.success());
+};
+
+export default ensureFreshUserAccessToken;
diff --git a/lib/spree/utils/tokens/ensure-itoken.ts b/lib/spree/utils/tokens/ensure-itoken.ts
new file mode 100644
index 000000000..df412f53f
--- /dev/null
+++ b/lib/spree/utils/tokens/ensure-itoken.ts
@@ -0,0 +1,25 @@
+import type { IToken } from '@spree/storefront-api-v2-sdk/types/interfaces/Token';
+import { getCartToken } from './cart-token';
+import { ensureUserTokenResponse } from './user-token-response';
+
+const ensureIToken = (): IToken | undefined => {
+ const userTokenResponse = ensureUserTokenResponse();
+
+ if (userTokenResponse) {
+ return {
+ bearerToken: userTokenResponse.access_token
+ };
+ }
+
+ const cartToken = getCartToken();
+
+ if (cartToken) {
+ return {
+ orderToken: cartToken
+ };
+ }
+
+ return undefined;
+};
+
+export default ensureIToken;
diff --git a/lib/spree/utils/tokens/is-logged-in.ts b/lib/spree/utils/tokens/is-logged-in.ts
new file mode 100644
index 000000000..214aef4df
--- /dev/null
+++ b/lib/spree/utils/tokens/is-logged-in.ts
@@ -0,0 +1,9 @@
+import { ensureUserTokenResponse } from './user-token-response';
+
+const isLoggedIn = (): boolean => {
+ const userTokenResponse = ensureUserTokenResponse();
+
+ return !!userTokenResponse;
+};
+
+export default isLoggedIn;
diff --git a/lib/spree/utils/tokens/revoke-user-tokens.ts b/lib/spree/utils/tokens/revoke-user-tokens.ts
new file mode 100644
index 000000000..de2510a91
--- /dev/null
+++ b/lib/spree/utils/tokens/revoke-user-tokens.ts
@@ -0,0 +1,45 @@
+import type { GraphQLFetcherResult } from '@commerce/api';
+import type { HookFetcherContext } from '@commerce/utils/types';
+import TokensNotRejectedError from '../../errors/TokensNotRejectedError';
+import type { UserOAuthTokens } from '../../types';
+import type { EmptyObjectResponse } from '@spree/storefront-api-v2-sdk/types/interfaces/EmptyObject';
+
+const revokeUserTokens = async (
+ fetch: HookFetcherContext<{
+ data: any;
+ }>['fetch'],
+ userTokens: UserOAuthTokens
+): Promise => {
+ const spreeRevokeTokensResponses = await Promise.allSettled([
+ fetch>({
+ variables: {
+ methodPath: 'authentication.revokeToken',
+ arguments: [
+ {
+ token: userTokens.refreshToken
+ }
+ ]
+ }
+ }),
+ fetch>({
+ variables: {
+ methodPath: 'authentication.revokeToken',
+ arguments: [
+ {
+ token: userTokens.accessToken
+ }
+ ]
+ }
+ })
+ ]);
+
+ const anyRejected = spreeRevokeTokensResponses.some((response) => response.status === 'rejected');
+
+ if (anyRejected) {
+ throw new TokensNotRejectedError('Some tokens could not be rejected in Spree.');
+ }
+
+ return undefined;
+};
+
+export default revokeUserTokens;
diff --git a/lib/spree/utils/tokens/user-token-response.ts b/lib/spree/utils/tokens/user-token-response.ts
new file mode 100644
index 000000000..516ecf89f
--- /dev/null
+++ b/lib/spree/utils/tokens/user-token-response.ts
@@ -0,0 +1,50 @@
+import { requireConfigValue } from '../../isomorphic-config';
+import Cookies from 'js-cookie';
+import type { IOAuthToken } from '@spree/storefront-api-v2-sdk/types/interfaces/Token';
+import UserTokenResponseParseError from '../../errors/UserTokenResponseParseError';
+
+export const getUserTokenResponse = (): IOAuthToken | undefined => {
+ const stringifiedToken = Cookies.get(requireConfigValue('userCookieName') as string);
+
+ if (!stringifiedToken) {
+ return undefined;
+ }
+
+ try {
+ const token: IOAuthToken = JSON.parse(stringifiedToken);
+
+ return token;
+ } catch (parseError) {
+ throw new UserTokenResponseParseError('Could not parse stored user token response.');
+ }
+};
+
+/**
+ * Retrieves the saved user token response. If the response fails json parsing,
+ * removes the saved token and returns @type {undefined} instead.
+ */
+export const ensureUserTokenResponse = (): IOAuthToken | undefined => {
+ try {
+ return getUserTokenResponse();
+ } catch (error) {
+ if (error instanceof UserTokenResponseParseError) {
+ removeUserTokenResponse();
+
+ return undefined;
+ }
+
+ throw error;
+ }
+};
+
+export const setUserTokenResponse = (token: IOAuthToken) => {
+ const cookieOptions = {
+ expires: requireConfigValue('userCookieExpire') as number
+ };
+
+ Cookies.set(requireConfigValue('userCookieName') as string, JSON.stringify(token), cookieOptions);
+};
+
+export const removeUserTokenResponse = () => {
+ Cookies.remove(requireConfigValue('userCookieName') as string);
+};
diff --git a/lib/spree/utils/validations/validate-all-products-taxonomy-id.ts b/lib/spree/utils/validations/validate-all-products-taxonomy-id.ts
new file mode 100644
index 000000000..392ae4a7e
--- /dev/null
+++ b/lib/spree/utils/validations/validate-all-products-taxonomy-id.ts
@@ -0,0 +1,13 @@
+const validateAllProductsTaxonomyId = (taxonomyId: unknown): string | false => {
+ if (!taxonomyId || taxonomyId === 'false') {
+ return false;
+ }
+
+ if (typeof taxonomyId === 'string') {
+ return taxonomyId;
+ }
+
+ throw new TypeError('taxonomyId must be a string or falsy.');
+};
+
+export default validateAllProductsTaxonomyId;
diff --git a/lib/spree/utils/validations/validate-cookie-expire.ts b/lib/spree/utils/validations/validate-cookie-expire.ts
new file mode 100644
index 000000000..54daf50ad
--- /dev/null
+++ b/lib/spree/utils/validations/validate-cookie-expire.ts
@@ -0,0 +1,19 @@
+const validateCookieExpire = (expire: unknown): number => {
+ let expireInteger: number;
+
+ if (typeof expire === 'string') {
+ expireInteger = parseFloat(expire);
+ } else if (typeof expire === 'number') {
+ expireInteger = expire;
+ } else {
+ throw new TypeError('expire must be a string containing a number or an integer.');
+ }
+
+ if (expireInteger < 0) {
+ throw new RangeError('expire must be non-negative.');
+ }
+
+ return expireInteger;
+};
+
+export default validateCookieExpire;
diff --git a/lib/spree/utils/validations/validate-images-option-filter.ts b/lib/spree/utils/validations/validate-images-option-filter.ts
new file mode 100644
index 000000000..4e0083947
--- /dev/null
+++ b/lib/spree/utils/validations/validate-images-option-filter.ts
@@ -0,0 +1,13 @@
+const validateImagesOptionFilter = (optionTypeNameOrFalse: unknown): string | false => {
+ if (!optionTypeNameOrFalse || optionTypeNameOrFalse === 'false') {
+ return false;
+ }
+
+ if (typeof optionTypeNameOrFalse === 'string') {
+ return optionTypeNameOrFalse;
+ }
+
+ throw new TypeError('optionTypeNameOrFalse must be a string or falsy.');
+};
+
+export default validateImagesOptionFilter;
diff --git a/lib/spree/utils/validations/validate-images-quality.ts b/lib/spree/utils/validations/validate-images-quality.ts
new file mode 100644
index 000000000..7eb5181e8
--- /dev/null
+++ b/lib/spree/utils/validations/validate-images-quality.ts
@@ -0,0 +1,19 @@
+const validateImagesQuality = (quality: unknown): number => {
+ let quality_level: number;
+
+ if (typeof quality === 'string') {
+ quality_level = parseInt(quality);
+ } else if (typeof quality === 'number') {
+ quality_level = quality;
+ } else {
+ throw new TypeError('prerenderCount count must be a string containing a number or an integer.');
+ }
+
+ if (quality_level === NaN) {
+ throw new TypeError('prerenderCount count must be a string containing a number or an integer.');
+ }
+
+ return quality_level;
+};
+
+export default validateImagesQuality;
diff --git a/lib/spree/utils/validations/validate-images-size.ts b/lib/spree/utils/validations/validate-images-size.ts
new file mode 100644
index 000000000..501027c08
--- /dev/null
+++ b/lib/spree/utils/validations/validate-images-size.ts
@@ -0,0 +1,13 @@
+const validateImagesSize = (size: unknown): string => {
+ if (typeof size !== 'string') {
+ throw new TypeError('size must be a string.');
+ }
+
+ if (!size.includes('x') || size.split('x').length != 2) {
+ throw new Error("size must have two numbers separated with an 'x'");
+ }
+
+ return size;
+};
+
+export default validateImagesSize;
diff --git a/lib/spree/utils/validations/validate-placeholder-image-url.ts b/lib/spree/utils/validations/validate-placeholder-image-url.ts
new file mode 100644
index 000000000..e42ba64bd
--- /dev/null
+++ b/lib/spree/utils/validations/validate-placeholder-image-url.ts
@@ -0,0 +1,13 @@
+const validatePlaceholderImageUrl = (placeholderUrlOrFalse: unknown): string | false => {
+ if (!placeholderUrlOrFalse || placeholderUrlOrFalse === 'false') {
+ return false;
+ }
+
+ if (typeof placeholderUrlOrFalse === 'string') {
+ return placeholderUrlOrFalse;
+ }
+
+ throw new TypeError('placeholderUrlOrFalse must be a string or falsy.');
+};
+
+export default validatePlaceholderImageUrl;
diff --git a/lib/spree/utils/validations/validate-products-prerender-count.ts b/lib/spree/utils/validations/validate-products-prerender-count.ts
new file mode 100644
index 000000000..533d42473
--- /dev/null
+++ b/lib/spree/utils/validations/validate-products-prerender-count.ts
@@ -0,0 +1,19 @@
+const validateProductsPrerenderCount = (prerenderCount: unknown): number => {
+ let prerenderCountInteger: number;
+
+ if (typeof prerenderCount === 'string') {
+ prerenderCountInteger = parseInt(prerenderCount);
+ } else if (typeof prerenderCount === 'number') {
+ prerenderCountInteger = prerenderCount;
+ } else {
+ throw new TypeError('prerenderCount count must be a string containing a number or an integer.');
+ }
+
+ if (prerenderCountInteger < 0) {
+ throw new RangeError('prerenderCount must be non-negative.');
+ }
+
+ return prerenderCountInteger;
+};
+
+export default validateProductsPrerenderCount;
diff --git a/lib/spree/wishlist/index.ts b/lib/spree/wishlist/index.ts
new file mode 100644
index 000000000..79b8a0b94
--- /dev/null
+++ b/lib/spree/wishlist/index.ts
@@ -0,0 +1,3 @@
+export { default as useAddItem } from './use-add-item';
+export { default as useWishlist } from './use-wishlist';
+export { default as useRemoveItem } from './use-remove-item';
diff --git a/lib/spree/wishlist/use-add-item.tsx b/lib/spree/wishlist/use-add-item.tsx
new file mode 100644
index 000000000..cce3d1401
--- /dev/null
+++ b/lib/spree/wishlist/use-add-item.tsx
@@ -0,0 +1,86 @@
+import { useCallback } from 'react';
+import type { MutationHook } from '@commerce/utils/types';
+import useAddItem from '@commerce/wishlist/use-add-item';
+import type { UseAddItem } from '@commerce/wishlist/use-add-item';
+import useWishlist from './use-wishlist';
+import type { ExplicitWishlistAddItemHook } from '../types';
+import type {
+ WishedItem,
+ WishlistsAddWishedItem
+} from '@spree/storefront-api-v2-sdk/types/interfaces/WishedItem';
+import type { GraphQLFetcherResult } from '@commerce/api';
+import ensureIToken from '../utils/tokens/ensure-itoken';
+import type { IToken } from '@spree/storefront-api-v2-sdk/types/interfaces/Token';
+import type { AddItemHook } from '@commerce/types/wishlist';
+import isLoggedIn from '../utils/tokens/is-logged-in';
+
+export default useAddItem as UseAddItem;
+
+export const handler: MutationHook = {
+ fetchOptions: {
+ url: 'wishlists',
+ query: 'addWishedItem'
+ },
+ async fetcher({ input, options, fetch }) {
+ console.info(
+ 'useAddItem (wishlist) fetcher called. Configuration: ',
+ 'input: ',
+ input,
+ 'options: ',
+ options
+ );
+
+ const {
+ item: { productId, variantId, wishlistToken }
+ } = input;
+
+ if (!isLoggedIn() || !wishlistToken) {
+ return null;
+ }
+
+ let token: IToken | undefined = ensureIToken();
+
+ const addItemParameters: WishlistsAddWishedItem = {
+ variant_id: `${variantId}`,
+ quantity: 1
+ };
+
+ await fetch>({
+ variables: {
+ methodPath: 'wishlists.addWishedItem',
+ arguments: [token, wishlistToken, addItemParameters]
+ }
+ });
+
+ return null;
+ },
+ useHook: ({ fetch }) => {
+ const useWrappedHook: ReturnType['useHook']> = () => {
+ const wishlist = useWishlist();
+
+ return useCallback(
+ async (item) => {
+ if (!wishlist.data) {
+ return null;
+ }
+
+ const data = await fetch({
+ input: {
+ item: {
+ ...item,
+ wishlistToken: wishlist.data.token
+ }
+ }
+ });
+
+ await wishlist.revalidate();
+
+ return data;
+ },
+ [wishlist]
+ );
+ };
+
+ return useWrappedHook;
+ }
+};
diff --git a/lib/spree/wishlist/use-remove-item.tsx b/lib/spree/wishlist/use-remove-item.tsx
new file mode 100644
index 000000000..e66b1d849
--- /dev/null
+++ b/lib/spree/wishlist/use-remove-item.tsx
@@ -0,0 +1,75 @@
+import { useCallback } from 'react';
+import type { MutationHook } from '@commerce/utils/types';
+import useRemoveItem from '@commerce/wishlist/use-remove-item';
+import type { UseRemoveItem } from '@commerce/wishlist/use-remove-item';
+import useWishlist from './use-wishlist';
+import type { ExplicitWishlistRemoveItemHook } from '../types';
+import isLoggedIn from '../utils/tokens/is-logged-in';
+import ensureIToken from '../utils/tokens/ensure-itoken';
+import type { IToken } from '@spree/storefront-api-v2-sdk/types/interfaces/Token';
+import type { GraphQLFetcherResult } from '@commerce/api';
+import type { WishedItem } from '@spree/storefront-api-v2-sdk/types/interfaces/WishedItem';
+
+export default useRemoveItem as UseRemoveItem;
+
+export const handler: MutationHook = {
+ fetchOptions: {
+ url: 'wishlists',
+ query: 'removeWishedItem'
+ },
+ async fetcher({ input, options, fetch }) {
+ console.info(
+ 'useRemoveItem (wishlist) fetcher called. Configuration: ',
+ 'input: ',
+ input,
+ 'options: ',
+ options
+ );
+
+ const { itemId, wishlistToken } = input;
+
+ if (!isLoggedIn() || !wishlistToken) {
+ return null;
+ }
+
+ let token: IToken | undefined = ensureIToken();
+
+ await fetch>({
+ variables: {
+ methodPath: 'wishlists.removeWishedItem',
+ arguments: [token, wishlistToken, itemId]
+ }
+ });
+
+ return null;
+ },
+ useHook: ({ fetch }) => {
+ const useWrappedHook: ReturnType<
+ MutationHook['useHook']
+ > = () => {
+ const wishlist = useWishlist();
+
+ return useCallback(
+ async (input) => {
+ if (!wishlist.data) {
+ return null;
+ }
+
+ const data = await fetch({
+ input: {
+ itemId: `${input.id}`,
+ wishlistToken: wishlist.data.token
+ }
+ });
+
+ await wishlist.revalidate();
+
+ return data;
+ },
+ [wishlist]
+ );
+ };
+
+ return useWrappedHook;
+ }
+};
diff --git a/lib/spree/wishlist/use-wishlist.tsx b/lib/spree/wishlist/use-wishlist.tsx
new file mode 100644
index 000000000..4c94c8bbb
--- /dev/null
+++ b/lib/spree/wishlist/use-wishlist.tsx
@@ -0,0 +1,91 @@
+import { useMemo } from 'react';
+import type { SWRHook } from '@commerce/utils/types';
+import useWishlist from '@commerce/wishlist/use-wishlist';
+import type { UseWishlist } from '@commerce/wishlist/use-wishlist';
+import type { GetWishlistHook } from '@commerce/types/wishlist';
+import type { IToken } from '@spree/storefront-api-v2-sdk/types/interfaces/Token';
+import type { GraphQLFetcherResult } from '@commerce/api';
+import type { Wishlist } from '@spree/storefront-api-v2-sdk/types/interfaces/Wishlist';
+import ensureIToken from '../utils/tokens/ensure-itoken';
+import normalizeWishlist from '../utils/normalizations/normalize-wishlist';
+import isLoggedIn from '../utils/tokens/is-logged-in';
+
+export default useWishlist as UseWishlist;
+
+export const handler: SWRHook = {
+ // Provide fetchOptions for SWR cache key
+ fetchOptions: {
+ url: 'wishlists',
+ query: 'default'
+ },
+ async fetcher({ input, options, fetch }) {
+ console.info(
+ 'useWishlist fetcher called. Configuration: ',
+ 'input: ',
+ input,
+ 'options: ',
+ options
+ );
+
+ if (!isLoggedIn()) {
+ return null;
+ }
+
+ // TODO: Optimize with includeProducts.
+
+ const token: IToken | undefined = ensureIToken();
+
+ const { data: spreeWishlistsDefaultSuccessResponse } = await fetch<
+ GraphQLFetcherResult
+ >({
+ variables: {
+ methodPath: 'wishlists.default',
+ arguments: [
+ token,
+ {
+ include: [
+ 'wished_items',
+ 'wished_items.variant',
+ 'wished_items.variant.product',
+ 'wished_items.variant.product.primary_variant',
+ 'wished_items.variant.product.images',
+ 'wished_items.variant.product.option_types',
+ 'wished_items.variant.product.variants',
+ 'wished_items.variant.product.variants.option_values'
+ ].join(',')
+ }
+ ]
+ }
+ });
+
+ return normalizeWishlist(
+ spreeWishlistsDefaultSuccessResponse,
+ spreeWishlistsDefaultSuccessResponse.data
+ );
+ },
+ useHook: ({ useData }) => {
+ const useWrappedHook: ReturnType['useHook']> = (input) => {
+ const response = useData({
+ swrOptions: {
+ revalidateOnFocus: false,
+ ...input?.swrOptions
+ }
+ });
+
+ return useMemo(
+ () =>
+ Object.create(response, {
+ isEmpty: {
+ get() {
+ return (response.data?.items?.length || 0) <= 0;
+ },
+ enumerable: true
+ }
+ }),
+ [response]
+ );
+ };
+
+ return useWrappedHook;
+ }
+};
diff --git a/next.config.js b/next.config.js
index 8bab35c40..ce04f5a91 100644
--- a/next.config.js
+++ b/next.config.js
@@ -1,5 +1,5 @@
/** @type {import('next').NextConfig} */
-module.exports = {
+const baseConfig = {
eslint: {
// Disabling on production builds because we're running checks on PRs via GitHub Actions.
ignoreDuringBuilds: true
@@ -24,3 +24,7 @@ module.exports = {
];
}
};
+
+const spreeConfig = require('./lib/spree/next.config.js');
+
+module.exports = { ...baseConfig, ...spreeConfig };
diff --git a/package.json b/package.json
index 711a9a38b..76880cdbe 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,7 @@
"pnpm": ">=8"
},
"scripts": {
- "dev": "next dev --turbo",
+ "dev": "next dev -p 4000 --turbo",
"build": "next build",
"start": "next start",
"lint": "next lint",
@@ -24,6 +24,9 @@
"dependencies": {
"@headlessui/react": "^1.7.19",
"@heroicons/react": "^2.1.3",
+ "@spree/axios-fetcher": "^1.0.0",
+ "@spree/storefront-api-v2-sdk": "^6.0.6",
+ "axios": "^1.7.1",
"clsx": "^2.1.0",
"geist": "^1.3.0",
"next": "14.2.2",
diff --git a/tsconfig.json b/tsconfig.json
index 6cd05f98a..14ac13ac8 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -15,6 +15,9 @@
"jsx": "preserve",
"incremental": true,
"baseUrl": ".",
+ "paths": {
+ "@commerce/*": ["lib/spree/*"]
+ },
"noUncheckedIndexedAccess": true,
"plugins": [
{
diff --git a/yarn.lock b/yarn.lock
new file mode 100644
index 000000000..a542e52dc
--- /dev/null
+++ b/yarn.lock
@@ -0,0 +1,3465 @@
+# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
+# yarn lockfile v1
+
+
+"@alloc/quick-lru@^5.2.0":
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/@alloc/quick-lru/-/quick-lru-5.2.0.tgz#7bf68b20c0a350f936915fcae06f58e32007ce30"
+ integrity sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==
+
+"@babel/code-frame@^7.0.0":
+ version "7.24.2"
+ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae"
+ integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==
+ dependencies:
+ "@babel/highlight" "^7.24.2"
+ picocolors "^1.0.0"
+
+"@babel/helper-validator-identifier@^7.22.20", "@babel/helper-validator-identifier@^7.24.5":
+ version "7.24.5"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz#918b1a7fa23056603506370089bd990d8720db62"
+ integrity sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==
+
+"@babel/highlight@^7.24.2":
+ version "7.24.5"
+ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.5.tgz#bc0613f98e1dd0720e99b2a9ee3760194a704b6e"
+ integrity sha512-8lLmua6AVh/8SLJRRVD6V8p73Hir9w5mJrhE+IPpILG31KKlI9iz5zmBYKcWPS59qSfgP9RaSBQSHHE81WKuEw==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.24.5"
+ chalk "^2.4.2"
+ js-tokens "^4.0.0"
+ picocolors "^1.0.0"
+
+"@babel/runtime@^7.23.2":
+ version "7.24.5"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.5.tgz#230946857c053a36ccc66e1dd03b17dd0c4ed02c"
+ integrity sha512-Nms86NXrsaeU9vbBJKni6gXiEXZ4CVpYVzEjDH9Sb8vmZ3UljyA1GSOJl/6LGPO8EHLuSF9H+IxNXHPX8QHJ4g==
+ dependencies:
+ regenerator-runtime "^0.14.0"
+
+"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
+ integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==
+ dependencies:
+ eslint-visitor-keys "^3.3.0"
+
+"@eslint-community/regexpp@^4.6.1":
+ version "4.10.0"
+ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63"
+ integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==
+
+"@eslint/eslintrc@^2.1.4":
+ version "2.1.4"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad"
+ integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==
+ dependencies:
+ ajv "^6.12.4"
+ debug "^4.3.2"
+ espree "^9.6.0"
+ globals "^13.19.0"
+ ignore "^5.2.0"
+ import-fresh "^3.2.1"
+ js-yaml "^4.1.0"
+ minimatch "^3.1.2"
+ strip-json-comments "^3.1.1"
+
+"@eslint/js@8.57.0":
+ version "8.57.0"
+ resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f"
+ integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==
+
+"@headlessui/react@^1.7.19":
+ version "1.7.19"
+ resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.7.19.tgz#91c78cf5fcb254f4a0ebe96936d48421caf75f40"
+ integrity sha512-Ll+8q3OlMJfJbAKM/+/Y2q6PPYbryqNTXDbryx7SXLIDamkF6iQFbriYHga0dY44PvDhvvBWCx1Xj4U5+G4hOw==
+ dependencies:
+ "@tanstack/react-virtual" "^3.0.0-beta.60"
+ client-only "^0.0.1"
+
+"@heroicons/react@^2.1.3":
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/@heroicons/react/-/react-2.1.3.tgz#78a2a7f504a7370283d07eabcddc7fec04f503db"
+ integrity sha512-fEcPfo4oN345SoqdlCDdSa4ivjaKbk0jTd+oubcgNxnNgAfzysfwWfQUr+51wigiWHQQRiZNd1Ao0M5Y3M2EGg==
+
+"@humanwhocodes/config-array@^0.11.14":
+ version "0.11.14"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b"
+ integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==
+ dependencies:
+ "@humanwhocodes/object-schema" "^2.0.2"
+ debug "^4.3.1"
+ minimatch "^3.0.5"
+
+"@humanwhocodes/module-importer@^1.0.1":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
+ integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
+
+"@humanwhocodes/object-schema@^2.0.2":
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3"
+ integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==
+
+"@isaacs/cliui@^8.0.2":
+ version "8.0.2"
+ resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550"
+ integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==
+ dependencies:
+ string-width "^5.1.2"
+ string-width-cjs "npm:string-width@^4.2.0"
+ strip-ansi "^7.0.1"
+ strip-ansi-cjs "npm:strip-ansi@^6.0.1"
+ wrap-ansi "^8.1.0"
+ wrap-ansi-cjs "npm:wrap-ansi@^7.0.0"
+
+"@jridgewell/gen-mapping@^0.3.2":
+ version "0.3.5"
+ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36"
+ integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==
+ dependencies:
+ "@jridgewell/set-array" "^1.2.1"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+ "@jridgewell/trace-mapping" "^0.3.24"
+
+"@jridgewell/resolve-uri@^3.1.0":
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
+ integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
+
+"@jridgewell/set-array@^1.2.1":
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280"
+ integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==
+
+"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14":
+ version "1.4.15"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
+ integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+
+"@jridgewell/trace-mapping@^0.3.24":
+ version "0.3.25"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
+ integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.1.0"
+ "@jridgewell/sourcemap-codec" "^1.4.14"
+
+"@next/env@14.2.2":
+ version "14.2.2"
+ resolved "https://registry.yarnpkg.com/@next/env/-/env-14.2.2.tgz#6c36fe0b04a22ea78bd60a645ae77d53cd16d3ca"
+ integrity sha512-sk72qRfM1Q90XZWYRoJKu/UWlTgihrASiYw/scb15u+tyzcze3bOuJ/UV6TBOQEeUaxOkRqGeuGUdiiuxc5oqw==
+
+"@next/eslint-plugin-next@14.2.3":
+ version "14.2.3"
+ resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.3.tgz#287ad8620e7061ba01e8d3313d464db6d217b6df"
+ integrity sha512-L3oDricIIjgj1AVnRdRor21gI7mShlSwU/1ZGHmqM3LzHhXXhdkrfeNY5zif25Bi5Dd7fiJHsbhoZCHfXYvlAw==
+ dependencies:
+ glob "10.3.10"
+
+"@next/swc-darwin-arm64@14.2.2":
+ version "14.2.2"
+ resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.2.tgz#55e395b0db6dd5ea2dc92818260ff3a399f1a056"
+ integrity sha512-3iPgMhzbalizGwHNFUcGnDhFPSgVBHQ8aqSTAMxB5BvJG0oYrDf1WOJZlbXBgunOEj/8KMVbejEur/FpvFsgFQ==
+
+"@next/swc-darwin-x64@14.2.2":
+ version "14.2.2"
+ resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.2.tgz#f96fb65510be798c03b0432129792c6ac8885bc8"
+ integrity sha512-x7Afi/jt0ZBRUZHTi49yyej4o8znfIMHO4RvThuoc0P+uli8Jd99y5GKjxoYunPKsXL09xBXEM1+OQy2xEL0Ag==
+
+"@next/swc-linux-arm64-gnu@14.2.2":
+ version "14.2.2"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.2.tgz#443f0d4ab9d1aa4338e40f77ca4e182d60e88448"
+ integrity sha512-zbfPtkk7L41ODMJwSp5VbmPozPmMMQrzAc0HAUomVeVIIwlDGs/UCqLJvLNDt4jpWgc21SjjyIn762lNGrMaUA==
+
+"@next/swc-linux-arm64-musl@14.2.2":
+ version "14.2.2"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.2.tgz#182c00b3d2f3ed4eaacdd385d07b230252c64de9"
+ integrity sha512-wPbS3pI/JU16rm3XdLvvTmlsmm1nd+sBa2ohXgBZcShX4TgOjD4R+RqHKlI1cjo/jDZKXt6OxmcU0Iys0OC/yg==
+
+"@next/swc-linux-x64-gnu@14.2.2":
+ version "14.2.2"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.2.tgz#e826a08085dcc61685ff42884ad4032e71ac154f"
+ integrity sha512-NqWOHqqq8iC9tuHvZxjQ2tX+jWy2X9y8NX2mcB4sj2bIccuCxbIZrU/ThFPZZPauygajZuVQ6zediejQHwZHwQ==
+
+"@next/swc-linux-x64-musl@14.2.2":
+ version "14.2.2"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.2.tgz#42f921ca6d93fdfb2b13de70cd8a44ba5526b318"
+ integrity sha512-lGepHhwb9sGhCcU7999+iK1ZZT+6rrIoVg40MP7DZski9GIZP80wORSbt5kJzh9v2x2ev2lxC6VgwMQT0PcgTA==
+
+"@next/swc-win32-arm64-msvc@14.2.2":
+ version "14.2.2"
+ resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.2.tgz#9c8f60da8e3882c4c66f21747abf944a627d05ff"
+ integrity sha512-TZSh/48SfcLEQ4rD25VVn2kdIgUWmMflRX3OiyPwGNXn3NiyPqhqei/BaqCYXViIQ+6QsG9R0C8LftMqy8JPMA==
+
+"@next/swc-win32-ia32-msvc@14.2.2":
+ version "14.2.2"
+ resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.2.tgz#fdb0b5f74e6dc0dcb34b7f7d24775ad034d915e8"
+ integrity sha512-M0tBVNMEBJN2ZNQWlcekMn6pvLria7Sa2Fai5znm7CCJz4pP3lrvlSxhKdkCerk0D9E0bqx5yAo3o2Q7RrD4gA==
+
+"@next/swc-win32-x64-msvc@14.2.2":
+ version "14.2.2"
+ resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.2.tgz#95cc0dad2c7ac5177fa6eeab070dccfa30532353"
+ integrity sha512-a/20E/wtTJZ3Ykv3f/8F0l7TtgQa2LWHU2oNB9bsu0VjqGuGGHmm/q6waoUNQYTVPYrrlxxaHjJcDV6aiSTt/w==
+
+"@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.5"
+ run-parallel "^1.1.9"
+
+"@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", "@nodelib/fs.walk@^1.2.8":
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a"
+ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==
+ dependencies:
+ "@nodelib/fs.scandir" "2.1.5"
+ fastq "^1.6.0"
+
+"@pkgjs/parseargs@^0.11.0":
+ version "0.11.0"
+ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
+ integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
+
+"@rushstack/eslint-patch@^1.3.3":
+ version "1.10.3"
+ resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz#391d528054f758f81e53210f1a1eebcf1a8b1d20"
+ integrity sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg==
+
+"@spree/axios-fetcher@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@spree/axios-fetcher/-/axios-fetcher-1.0.0.tgz#d990ed38ee8bc33706f196a797f90117f8bd4d6d"
+ integrity sha512-mflTBxdhiYAlVvHqZnzsDOs2w4e3CDIUTa4SvK6X9jZy7VhWhPocS9u8Zo8nsLm77kus2oeq3jcZljbEJEbEhw==
+
+"@spree/storefront-api-v2-sdk@^6.0.6":
+ version "6.0.6"
+ resolved "https://registry.yarnpkg.com/@spree/storefront-api-v2-sdk/-/storefront-api-v2-sdk-6.0.6.tgz#e6b4a847e6409474bfb0f2fbf50308f6570475b6"
+ integrity sha512-22y90GmxJyIxaXKPmUB/jjMTnlw405B/CIy8jA8ZW9ox2afJTPw6w2Q3tn3pL/M7t/p+IlLIf4jBkoD2oVUSMg==
+
+"@swc/counter@^0.1.3":
+ version "0.1.3"
+ resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9"
+ integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==
+
+"@swc/helpers@0.5.5":
+ version "0.5.5"
+ resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.5.tgz#12689df71bfc9b21c4f4ca00ae55f2f16c8b77c0"
+ integrity sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==
+ dependencies:
+ "@swc/counter" "^0.1.3"
+ tslib "^2.4.0"
+
+"@tailwindcss/container-queries@^0.1.1":
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/@tailwindcss/container-queries/-/container-queries-0.1.1.tgz#9a759ce2cb8736a4c6a0cb93aeb740573a731974"
+ integrity sha512-p18dswChx6WnTSaJCSGx6lTmrGzNNvm2FtXmiO6AuA1V4U5REyoqwmT6kgAsIMdjo07QdAfYXHJ4hnMtfHzWgA==
+
+"@tailwindcss/typography@^0.5.12":
+ version "0.5.13"
+ resolved "https://registry.yarnpkg.com/@tailwindcss/typography/-/typography-0.5.13.tgz#cd788a4fa4d0ca2506e242d512f377b22c1f7932"
+ integrity sha512-ADGcJ8dX21dVVHIwTRgzrcunY6YY9uSlAHHGVKvkA+vLc5qLwEszvKts40lx7z0qc4clpjclwLeK5rVCV2P/uw==
+ dependencies:
+ lodash.castarray "^4.4.0"
+ lodash.isplainobject "^4.0.6"
+ lodash.merge "^4.6.2"
+ postcss-selector-parser "6.0.10"
+
+"@tanstack/react-virtual@^3.0.0-beta.60":
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/@tanstack/react-virtual/-/react-virtual-3.5.0.tgz#873b5b77cf78af563a4a11e6251ed51ee8868132"
+ integrity sha512-rtvo7KwuIvqK9zb0VZ5IL7fiJAEnG+0EiFZz8FUOs+2mhGqdGmjKIaT1XU7Zq0eFqL0jonLlhbayJI/J2SA/Bw==
+ dependencies:
+ "@tanstack/virtual-core" "3.5.0"
+
+"@tanstack/virtual-core@3.5.0":
+ version "3.5.0"
+ resolved "https://registry.yarnpkg.com/@tanstack/virtual-core/-/virtual-core-3.5.0.tgz#108208d0f1d75271300bc5560cf9a85a1fa01e89"
+ integrity sha512-KnPRCkQTyqhanNC0K63GBG3wA8I+D1fQuVnAvcBF8f13akOKeQp1gSbu6f77zCxhEk727iV5oQnbHLYzHrECLg==
+
+"@types/json5@^0.0.29":
+ version "0.0.29"
+ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
+ integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
+
+"@types/node@20.12.7":
+ version "20.12.7"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.7.tgz#04080362fa3dd6c5822061aa3124f5c152cff384"
+ integrity sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==
+ dependencies:
+ undici-types "~5.26.4"
+
+"@types/normalize-package-data@^2.4.0":
+ version "2.4.4"
+ resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901"
+ integrity sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==
+
+"@types/prop-types@*":
+ version "15.7.12"
+ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6"
+ integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==
+
+"@types/react-dom@18.2.25":
+ version "18.2.25"
+ resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.25.tgz#2946a30081f53e7c8d585eb138277245caedc521"
+ integrity sha512-o/V48vf4MQh7juIKZU2QGDfli6p1+OOi5oXx36Hffpc9adsHeXjVp8rHuPkjd8VT8sOJ2Zp05HR7CdpGTIUFUA==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react@*":
+ version "18.3.2"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.2.tgz#462ae4904973bc212fa910424d901e3d137dbfcd"
+ integrity sha512-Btgg89dAnqD4vV7R3hlwOxgqobUQKgx3MmrQRi0yYbs/P0ym8XozIAlkqVilPqHQwXs4e9Tf63rrCgl58BcO4w==
+ dependencies:
+ "@types/prop-types" "*"
+ csstype "^3.0.2"
+
+"@types/react@18.2.79":
+ version "18.2.79"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.79.tgz#c40efb4f255711f554d47b449f796d1c7756d865"
+ integrity sha512-RwGAGXPl9kSXwdNTafkOEuFrTBD5SA2B3iEB96xi8+xu5ddUa/cpvyVCSNn+asgLCTHkb5ZxN8gbuibYJi4s1w==
+ dependencies:
+ "@types/prop-types" "*"
+ csstype "^3.0.2"
+
+"@typescript-eslint/parser@^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.2.0.tgz#44356312aea8852a3a82deebdacd52ba614ec07a"
+ integrity sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==
+ dependencies:
+ "@typescript-eslint/scope-manager" "7.2.0"
+ "@typescript-eslint/types" "7.2.0"
+ "@typescript-eslint/typescript-estree" "7.2.0"
+ "@typescript-eslint/visitor-keys" "7.2.0"
+ debug "^4.3.4"
+
+"@typescript-eslint/scope-manager@7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz#cfb437b09a84f95a0930a76b066e89e35d94e3da"
+ integrity sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==
+ dependencies:
+ "@typescript-eslint/types" "7.2.0"
+ "@typescript-eslint/visitor-keys" "7.2.0"
+
+"@typescript-eslint/types@7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.2.0.tgz#0feb685f16de320e8520f13cca30779c8b7c403f"
+ integrity sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==
+
+"@typescript-eslint/typescript-estree@7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz#5beda2876c4137f8440c5a84b4f0370828682556"
+ integrity sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==
+ dependencies:
+ "@typescript-eslint/types" "7.2.0"
+ "@typescript-eslint/visitor-keys" "7.2.0"
+ debug "^4.3.4"
+ globby "^11.1.0"
+ is-glob "^4.0.3"
+ minimatch "9.0.3"
+ semver "^7.5.4"
+ ts-api-utils "^1.0.1"
+
+"@typescript-eslint/visitor-keys@7.2.0":
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz#5035f177752538a5750cca1af6044b633610bf9e"
+ integrity sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==
+ dependencies:
+ "@typescript-eslint/types" "7.2.0"
+ eslint-visitor-keys "^3.4.1"
+
+"@ungap/structured-clone@^1.2.0":
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406"
+ integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==
+
+"@vercel/git-hooks@^1.0.0":
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/@vercel/git-hooks/-/git-hooks-1.0.0.tgz#40ed416e532b868eb0ef77dd7566cd5059dc0fc3"
+ integrity sha512-OxDFAAdyiJ/H0b8zR9rFCu3BIb78LekBXOphOYG3snV4ULhKFX387pBPpqZ9HLiRTejBWBxYEahkw79tuIgdAA==
+
+acorn-jsx@^5.3.2:
+ version "5.3.2"
+ resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
+ integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
+
+acorn@^8.9.0:
+ version "8.11.3"
+ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a"
+ integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
+
+ajv@^6.12.4:
+ version "6.12.6"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
+
+ansi-escapes@^6.2.0:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-6.2.1.tgz#76c54ce9b081dad39acec4b5d53377913825fb0f"
+ integrity sha512-4nJ3yixlEthEJ9Rk4vPcdBRkZvQZlYyu8j4/Mqz5sgIkddmEnH2Yj2ZrnP9S3tQOvSNRUIgVNF/1yPpRAGNRig==
+
+ansi-regex@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
+ integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==
+
+ansi-regex@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a"
+ integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==
+
+ansi-styles@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d"
+ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==
+ dependencies:
+ color-convert "^1.9.0"
+
+ansi-styles@^4.0.0, ansi-styles@^4.1.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
+ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
+ dependencies:
+ color-convert "^2.0.1"
+
+ansi-styles@^6.0.0, ansi-styles@^6.1.0, ansi-styles@^6.2.1:
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5"
+ integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==
+
+any-promise@^1.0.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f"
+ integrity sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==
+
+anymatch@~3.1.2:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e"
+ integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==
+ dependencies:
+ normalize-path "^3.0.0"
+ picomatch "^2.0.4"
+
+arg@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
+ integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==
+
+argparse@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
+ integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
+
+aria-query@^5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e"
+ integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==
+ dependencies:
+ dequal "^2.0.3"
+
+array-buffer-byte-length@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f"
+ integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==
+ dependencies:
+ call-bind "^1.0.5"
+ is-array-buffer "^3.0.4"
+
+array-includes@^3.1.6, array-includes@^3.1.7:
+ version "3.1.8"
+ resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d"
+ integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.2"
+ es-object-atoms "^1.0.0"
+ get-intrinsic "^1.2.4"
+ is-string "^1.0.7"
+
+array-union@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
+ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==
+
+array.prototype.findlast@^1.2.4:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904"
+ integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.2"
+ es-errors "^1.3.0"
+ es-object-atoms "^1.0.0"
+ es-shim-unscopables "^1.0.2"
+
+array.prototype.findlastindex@^1.2.3:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz#8c35a755c72908719453f87145ca011e39334d0d"
+ integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.2"
+ es-errors "^1.3.0"
+ es-object-atoms "^1.0.0"
+ es-shim-unscopables "^1.0.2"
+
+array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18"
+ integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
+ es-shim-unscopables "^1.0.0"
+
+array.prototype.flatmap@^1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527"
+ integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
+ es-shim-unscopables "^1.0.0"
+
+array.prototype.toreversed@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz#b989a6bf35c4c5051e1dc0325151bf8088954eba"
+ integrity sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
+ es-shim-unscopables "^1.0.0"
+
+array.prototype.tosorted@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz#c8c89348337e51b8a3c48a9227f9ce93ceedcba8"
+ integrity sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg==
+ dependencies:
+ call-bind "^1.0.5"
+ define-properties "^1.2.1"
+ es-abstract "^1.22.3"
+ es-errors "^1.1.0"
+ es-shim-unscopables "^1.0.2"
+
+arraybuffer.prototype.slice@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6"
+ integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==
+ dependencies:
+ array-buffer-byte-length "^1.0.1"
+ call-bind "^1.0.5"
+ define-properties "^1.2.1"
+ es-abstract "^1.22.3"
+ es-errors "^1.2.1"
+ get-intrinsic "^1.2.3"
+ is-array-buffer "^3.0.4"
+ is-shared-array-buffer "^1.0.2"
+
+ast-types-flow@^0.0.8:
+ version "0.0.8"
+ resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.8.tgz#0a85e1c92695769ac13a428bb653e7538bea27d6"
+ integrity sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==
+
+asynckit@^0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
+ integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
+
+autoprefixer@^10.4.19:
+ version "10.4.19"
+ resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.19.tgz#ad25a856e82ee9d7898c59583c1afeb3fa65f89f"
+ integrity sha512-BaENR2+zBZ8xXhM4pUaKUxlVdxZ0EZhjvbopwnXmxRUfqDmwSpC2lAi/QXvx7NRdPCo1WKEcEF6mV64si1z4Ew==
+ dependencies:
+ browserslist "^4.23.0"
+ caniuse-lite "^1.0.30001599"
+ fraction.js "^4.3.7"
+ normalize-range "^0.1.2"
+ picocolors "^1.0.0"
+ postcss-value-parser "^4.2.0"
+
+available-typed-arrays@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846"
+ integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==
+ dependencies:
+ possible-typed-array-names "^1.0.0"
+
+axe-core@=4.7.0:
+ version "4.7.0"
+ resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf"
+ integrity sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==
+
+axios@^1.7.1:
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.1.tgz#522145622a09dfaf49359837db9649ff245a35b9"
+ integrity sha512-+LV37nQcd1EpFalkXksWNBiA17NZ5m5/WspmHGmZmdx1qBOg/VNq/c4eRJiA9VQQHBOs+N0ZhhdU10h2TyNK7Q==
+ dependencies:
+ follow-redirects "^1.15.6"
+ form-data "^4.0.0"
+ proxy-from-env "^1.1.0"
+
+axobject-query@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a"
+ integrity sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==
+ dependencies:
+ dequal "^2.0.3"
+
+balanced-match@^1.0.0:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
+ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
+
+binary-extensions@^2.0.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522"
+ integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==
+
+brace-expansion@^1.1.7:
+ version "1.1.11"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
+ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
+ dependencies:
+ balanced-match "^1.0.0"
+ concat-map "0.0.1"
+
+brace-expansion@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
+ integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
+ dependencies:
+ balanced-match "^1.0.0"
+
+braces@^3.0.2, braces@~3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
+ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+ dependencies:
+ fill-range "^7.0.1"
+
+browserslist@^4.23.0:
+ version "4.23.0"
+ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab"
+ integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==
+ dependencies:
+ caniuse-lite "^1.0.30001587"
+ electron-to-chromium "^1.4.668"
+ node-releases "^2.0.14"
+ update-browserslist-db "^1.0.13"
+
+builtin-modules@^3.3.0:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6"
+ integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==
+
+busboy@1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
+ integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
+ dependencies:
+ streamsearch "^1.1.0"
+
+call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9"
+ integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==
+ dependencies:
+ es-define-property "^1.0.0"
+ es-errors "^1.3.0"
+ function-bind "^1.1.2"
+ get-intrinsic "^1.2.4"
+ set-function-length "^1.2.1"
+
+callsites@^3.0.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
+ integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
+
+camelcase-css@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
+ integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==
+
+caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.30001599:
+ version "1.0.30001620"
+ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001620.tgz#78bb6f35b8fe315b96b8590597094145d0b146b4"
+ integrity sha512-WJvYsOjd1/BYUY6SNGUosK9DUidBPDTnOARHp3fSmFO1ekdxaY6nKRttEVrfMmYi80ctS0kz1wiWmm14fVc3ew==
+
+chalk@5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.3.0.tgz#67c20a7ebef70e7f3970a01f90fa210cb6860385"
+ integrity sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==
+
+chalk@^2.4.2:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
+ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
+ dependencies:
+ ansi-styles "^3.2.1"
+ escape-string-regexp "^1.0.5"
+ supports-color "^5.3.0"
+
+chalk@^4.0.0:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
+ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
+ dependencies:
+ ansi-styles "^4.1.0"
+ supports-color "^7.1.0"
+
+chokidar@^3.5.3:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
+ integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
+ dependencies:
+ anymatch "~3.1.2"
+ braces "~3.0.2"
+ glob-parent "~5.1.2"
+ is-binary-path "~2.1.0"
+ is-glob "~4.0.1"
+ normalize-path "~3.0.0"
+ readdirp "~3.6.0"
+ optionalDependencies:
+ fsevents "~2.3.2"
+
+ci-info@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-4.0.0.tgz#65466f8b280fc019b9f50a5388115d17a63a44f2"
+ integrity sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==
+
+clean-regexp@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/clean-regexp/-/clean-regexp-1.0.0.tgz#8df7c7aae51fd36874e8f8d05b9180bc11a3fed7"
+ integrity sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==
+ dependencies:
+ escape-string-regexp "^1.0.5"
+
+cli-cursor@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-4.0.0.tgz#3cecfe3734bf4fe02a8361cbdc0f6fe28c6a57ea"
+ integrity sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==
+ dependencies:
+ restore-cursor "^4.0.0"
+
+cli-truncate@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-4.0.0.tgz#6cc28a2924fee9e25ce91e973db56c7066e6172a"
+ integrity sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==
+ dependencies:
+ slice-ansi "^5.0.0"
+ string-width "^7.0.0"
+
+client-only@0.0.1, client-only@^0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
+ integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
+
+clsx@^2.1.0:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
+ integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
+
+color-convert@^1.9.0:
+ version "1.9.3"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
+ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
+ dependencies:
+ color-name "1.1.3"
+
+color-convert@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3"
+ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==
+ dependencies:
+ color-name "~1.1.4"
+
+color-name@1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
+ integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==
+
+color-name@~1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
+ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
+
+colorette@^2.0.20:
+ version "2.0.20"
+ resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a"
+ integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==
+
+combined-stream@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
+ integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
+ dependencies:
+ delayed-stream "~1.0.0"
+
+commander@11.1.0:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-11.1.0.tgz#62fdce76006a68e5c1ab3314dc92e800eb83d906"
+ integrity sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==
+
+commander@^4.0.0:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
+ integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==
+
+concat-map@0.0.1:
+ version "0.0.1"
+ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
+ integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
+
+core-js-compat@^3.34.0:
+ version "3.37.1"
+ resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.37.1.tgz#c844310c7852f4bdf49b8d339730b97e17ff09ee"
+ integrity sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==
+ dependencies:
+ browserslist "^4.23.0"
+
+cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
+ version "7.0.3"
+ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
+ integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
+ dependencies:
+ path-key "^3.1.0"
+ shebang-command "^2.0.0"
+ which "^2.0.1"
+
+cssesc@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee"
+ integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==
+
+csstype@^3.0.2:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
+ integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
+
+damerau-levenshtein@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz#b43d286ccbd36bc5b2f7ed41caf2d0aba1f8a6e7"
+ integrity sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==
+
+data-view-buffer@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2"
+ integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==
+ dependencies:
+ call-bind "^1.0.6"
+ es-errors "^1.3.0"
+ is-data-view "^1.0.1"
+
+data-view-byte-length@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2"
+ integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==
+ dependencies:
+ call-bind "^1.0.7"
+ es-errors "^1.3.0"
+ is-data-view "^1.0.1"
+
+data-view-byte-offset@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a"
+ integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==
+ dependencies:
+ call-bind "^1.0.6"
+ es-errors "^1.3.0"
+ is-data-view "^1.0.1"
+
+debug@4.3.4, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
+ version "4.3.4"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
+ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
+ dependencies:
+ ms "2.1.2"
+
+debug@^3.2.7:
+ version "3.2.7"
+ resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
+ integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
+ dependencies:
+ ms "^2.1.1"
+
+deep-is@^0.1.3:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
+ integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
+
+define-data-property@^1.0.1, define-data-property@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
+ integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
+ dependencies:
+ es-define-property "^1.0.0"
+ es-errors "^1.3.0"
+ gopd "^1.0.1"
+
+define-properties@^1.2.0, define-properties@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c"
+ integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==
+ dependencies:
+ define-data-property "^1.0.1"
+ has-property-descriptors "^1.0.0"
+ object-keys "^1.1.1"
+
+delayed-stream@~1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
+ integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
+
+dequal@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
+ integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
+
+didyoumean@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/didyoumean/-/didyoumean-1.2.2.tgz#989346ffe9e839b4555ecf5666edea0d3e8ad037"
+ integrity sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==
+
+dir-glob@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
+ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==
+ dependencies:
+ path-type "^4.0.0"
+
+dlv@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/dlv/-/dlv-1.1.3.tgz#5c198a8a11453596e751494d49874bc7732f2e79"
+ integrity sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==
+
+doctrine@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d"
+ integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==
+ dependencies:
+ esutils "^2.0.2"
+
+doctrine@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961"
+ integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==
+ dependencies:
+ esutils "^2.0.2"
+
+eastasianwidth@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
+ integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==
+
+electron-to-chromium@^1.4.668:
+ version "1.4.774"
+ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.774.tgz#1017d1758aaeeefe5423aa9d67b4b1e5d1d0a856"
+ integrity sha512-132O1XCd7zcTkzS3FgkAzKmnBuNJjK8WjcTtNuoylj7MYbqw5eXehjQ5OK91g0zm7OTKIPeaAG4CPoRfD9M1Mg==
+
+emoji-regex@^10.3.0:
+ version "10.3.0"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.3.0.tgz#76998b9268409eb3dae3de989254d456e70cfe23"
+ integrity sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==
+
+emoji-regex@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
+ integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==
+
+emoji-regex@^9.2.2:
+ version "9.2.2"
+ resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72"
+ integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==
+
+enhanced-resolve@^5.12.0:
+ version "5.16.1"
+ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz#e8bc63d51b826d6f1cbc0a150ecb5a8b0c62e567"
+ integrity sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==
+ dependencies:
+ graceful-fs "^4.2.4"
+ tapable "^2.2.0"
+
+error-ex@^1.3.1:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
+ integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==
+ dependencies:
+ is-arrayish "^0.2.1"
+
+es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3:
+ version "1.23.3"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0"
+ integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==
+ dependencies:
+ array-buffer-byte-length "^1.0.1"
+ arraybuffer.prototype.slice "^1.0.3"
+ available-typed-arrays "^1.0.7"
+ call-bind "^1.0.7"
+ data-view-buffer "^1.0.1"
+ data-view-byte-length "^1.0.1"
+ data-view-byte-offset "^1.0.0"
+ es-define-property "^1.0.0"
+ es-errors "^1.3.0"
+ es-object-atoms "^1.0.0"
+ es-set-tostringtag "^2.0.3"
+ es-to-primitive "^1.2.1"
+ function.prototype.name "^1.1.6"
+ get-intrinsic "^1.2.4"
+ get-symbol-description "^1.0.2"
+ globalthis "^1.0.3"
+ gopd "^1.0.1"
+ has-property-descriptors "^1.0.2"
+ has-proto "^1.0.3"
+ has-symbols "^1.0.3"
+ hasown "^2.0.2"
+ internal-slot "^1.0.7"
+ is-array-buffer "^3.0.4"
+ is-callable "^1.2.7"
+ is-data-view "^1.0.1"
+ is-negative-zero "^2.0.3"
+ is-regex "^1.1.4"
+ is-shared-array-buffer "^1.0.3"
+ is-string "^1.0.7"
+ is-typed-array "^1.1.13"
+ is-weakref "^1.0.2"
+ object-inspect "^1.13.1"
+ object-keys "^1.1.1"
+ object.assign "^4.1.5"
+ regexp.prototype.flags "^1.5.2"
+ safe-array-concat "^1.1.2"
+ safe-regex-test "^1.0.3"
+ string.prototype.trim "^1.2.9"
+ string.prototype.trimend "^1.0.8"
+ string.prototype.trimstart "^1.0.8"
+ typed-array-buffer "^1.0.2"
+ typed-array-byte-length "^1.0.1"
+ typed-array-byte-offset "^1.0.2"
+ typed-array-length "^1.0.6"
+ unbox-primitive "^1.0.2"
+ which-typed-array "^1.1.15"
+
+es-define-property@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845"
+ integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==
+ dependencies:
+ get-intrinsic "^1.2.4"
+
+es-errors@^1.1.0, es-errors@^1.2.1, es-errors@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
+ integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
+
+es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.17:
+ version "1.0.19"
+ resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz#117003d0e5fec237b4b5c08aded722e0c6d50ca8"
+ integrity sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.3"
+ es-errors "^1.3.0"
+ es-set-tostringtag "^2.0.3"
+ function-bind "^1.1.2"
+ get-intrinsic "^1.2.4"
+ globalthis "^1.0.3"
+ has-property-descriptors "^1.0.2"
+ has-proto "^1.0.3"
+ has-symbols "^1.0.3"
+ internal-slot "^1.0.7"
+ iterator.prototype "^1.1.2"
+ safe-array-concat "^1.1.2"
+
+es-object-atoms@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941"
+ integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==
+ dependencies:
+ es-errors "^1.3.0"
+
+es-set-tostringtag@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777"
+ integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==
+ dependencies:
+ get-intrinsic "^1.2.4"
+ has-tostringtag "^1.0.2"
+ hasown "^2.0.1"
+
+es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763"
+ integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==
+ dependencies:
+ hasown "^2.0.0"
+
+es-to-primitive@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a"
+ integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==
+ dependencies:
+ is-callable "^1.1.4"
+ is-date-object "^1.0.1"
+ is-symbol "^1.0.2"
+
+escalade@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27"
+ integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==
+
+escape-string-regexp@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
+ integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==
+
+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==
+
+eslint-config-next@^14.2.2:
+ version "14.2.3"
+ resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.2.3.tgz#2fb0f7c4eccda530a4b5054438162b2303786d4f"
+ integrity sha512-ZkNztm3Q7hjqvB1rRlOX8P9E/cXRL9ajRcs8jufEtwMfTVYRqnmtnaSu57QqHyBlovMuiB8LEzfLBkh5RYV6Fg==
+ dependencies:
+ "@next/eslint-plugin-next" "14.2.3"
+ "@rushstack/eslint-patch" "^1.3.3"
+ "@typescript-eslint/parser" "^5.4.2 || ^6.0.0 || 7.0.0 - 7.2.0"
+ eslint-import-resolver-node "^0.3.6"
+ eslint-import-resolver-typescript "^3.5.2"
+ eslint-plugin-import "^2.28.1"
+ eslint-plugin-jsx-a11y "^6.7.1"
+ eslint-plugin-react "^7.33.2"
+ eslint-plugin-react-hooks "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705"
+
+eslint-config-prettier@^9.1.0:
+ version "9.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f"
+ integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==
+
+eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9:
+ version "0.3.9"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac"
+ integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==
+ dependencies:
+ debug "^3.2.7"
+ is-core-module "^2.13.0"
+ resolve "^1.22.4"
+
+eslint-import-resolver-typescript@^3.5.2:
+ version "3.6.1"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz#7b983680edd3f1c5bce1a5829ae0bc2d57fe9efa"
+ integrity sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==
+ dependencies:
+ debug "^4.3.4"
+ enhanced-resolve "^5.12.0"
+ eslint-module-utils "^2.7.4"
+ fast-glob "^3.3.1"
+ get-tsconfig "^4.5.0"
+ is-core-module "^2.11.0"
+ is-glob "^4.0.3"
+
+eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0:
+ version "2.8.1"
+ resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz#52f2404300c3bd33deece9d7372fb337cc1d7c34"
+ integrity sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==
+ dependencies:
+ debug "^3.2.7"
+
+eslint-plugin-import@^2.28.1:
+ version "2.29.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643"
+ integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==
+ dependencies:
+ array-includes "^3.1.7"
+ array.prototype.findlastindex "^1.2.3"
+ array.prototype.flat "^1.3.2"
+ array.prototype.flatmap "^1.3.2"
+ debug "^3.2.7"
+ doctrine "^2.1.0"
+ eslint-import-resolver-node "^0.3.9"
+ eslint-module-utils "^2.8.0"
+ hasown "^2.0.0"
+ is-core-module "^2.13.1"
+ is-glob "^4.0.3"
+ minimatch "^3.1.2"
+ object.fromentries "^2.0.7"
+ object.groupby "^1.0.1"
+ object.values "^1.1.7"
+ semver "^6.3.1"
+ tsconfig-paths "^3.15.0"
+
+eslint-plugin-jsx-a11y@^6.7.1:
+ version "6.8.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz#2fa9c701d44fcd722b7c771ec322432857fcbad2"
+ integrity sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==
+ dependencies:
+ "@babel/runtime" "^7.23.2"
+ aria-query "^5.3.0"
+ array-includes "^3.1.7"
+ array.prototype.flatmap "^1.3.2"
+ ast-types-flow "^0.0.8"
+ axe-core "=4.7.0"
+ axobject-query "^3.2.1"
+ damerau-levenshtein "^1.0.8"
+ emoji-regex "^9.2.2"
+ es-iterator-helpers "^1.0.15"
+ hasown "^2.0.0"
+ jsx-ast-utils "^3.3.5"
+ language-tags "^1.0.9"
+ minimatch "^3.1.2"
+ object.entries "^1.1.7"
+ object.fromentries "^2.0.7"
+
+"eslint-plugin-react-hooks@^4.5.0 || 5.0.0-canary-7118f5dd7-20230705":
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz#c829eb06c0e6f484b3fbb85a97e57784f328c596"
+ integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==
+
+eslint-plugin-react@^7.33.2:
+ version "7.34.1"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz#6806b70c97796f5bbfb235a5d3379ece5f4da997"
+ integrity sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw==
+ dependencies:
+ array-includes "^3.1.7"
+ array.prototype.findlast "^1.2.4"
+ array.prototype.flatmap "^1.3.2"
+ array.prototype.toreversed "^1.1.2"
+ array.prototype.tosorted "^1.1.3"
+ doctrine "^2.1.0"
+ es-iterator-helpers "^1.0.17"
+ estraverse "^5.3.0"
+ jsx-ast-utils "^2.4.1 || ^3.0.0"
+ minimatch "^3.1.2"
+ object.entries "^1.1.7"
+ object.fromentries "^2.0.7"
+ object.hasown "^1.1.3"
+ object.values "^1.1.7"
+ prop-types "^15.8.1"
+ resolve "^2.0.0-next.5"
+ semver "^6.3.1"
+ string.prototype.matchall "^4.0.10"
+
+eslint-plugin-unicorn@^52.0.0:
+ version "52.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-52.0.0.tgz#c7a559edd52e3932cf2b3a05c3b0efc604c1eeb8"
+ integrity sha512-1Yzm7/m+0R4djH0tjDjfVei/ju2w3AzUGjG6q8JnuNIL5xIwsflyCooW5sfBvQp2pMYQFSWWCFONsjCax1EHng==
+ dependencies:
+ "@babel/helper-validator-identifier" "^7.22.20"
+ "@eslint-community/eslint-utils" "^4.4.0"
+ "@eslint/eslintrc" "^2.1.4"
+ ci-info "^4.0.0"
+ clean-regexp "^1.0.0"
+ core-js-compat "^3.34.0"
+ esquery "^1.5.0"
+ indent-string "^4.0.0"
+ is-builtin-module "^3.2.1"
+ jsesc "^3.0.2"
+ pluralize "^8.0.0"
+ read-pkg-up "^7.0.1"
+ regexp-tree "^0.1.27"
+ regjsparser "^0.10.0"
+ semver "^7.5.4"
+ strip-indent "^3.0.0"
+
+eslint-scope@^7.2.2:
+ version "7.2.2"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f"
+ integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^5.2.0"
+
+eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3:
+ version "3.4.3"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
+ integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
+
+eslint@^8.57.0:
+ version "8.57.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668"
+ integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==
+ dependencies:
+ "@eslint-community/eslint-utils" "^4.2.0"
+ "@eslint-community/regexpp" "^4.6.1"
+ "@eslint/eslintrc" "^2.1.4"
+ "@eslint/js" "8.57.0"
+ "@humanwhocodes/config-array" "^0.11.14"
+ "@humanwhocodes/module-importer" "^1.0.1"
+ "@nodelib/fs.walk" "^1.2.8"
+ "@ungap/structured-clone" "^1.2.0"
+ ajv "^6.12.4"
+ chalk "^4.0.0"
+ cross-spawn "^7.0.2"
+ debug "^4.3.2"
+ doctrine "^3.0.0"
+ escape-string-regexp "^4.0.0"
+ eslint-scope "^7.2.2"
+ eslint-visitor-keys "^3.4.3"
+ espree "^9.6.1"
+ esquery "^1.4.2"
+ esutils "^2.0.2"
+ fast-deep-equal "^3.1.3"
+ file-entry-cache "^6.0.1"
+ find-up "^5.0.0"
+ glob-parent "^6.0.2"
+ globals "^13.19.0"
+ graphemer "^1.4.0"
+ ignore "^5.2.0"
+ imurmurhash "^0.1.4"
+ is-glob "^4.0.0"
+ is-path-inside "^3.0.3"
+ js-yaml "^4.1.0"
+ json-stable-stringify-without-jsonify "^1.0.1"
+ levn "^0.4.1"
+ lodash.merge "^4.6.2"
+ minimatch "^3.1.2"
+ natural-compare "^1.4.0"
+ optionator "^0.9.3"
+ strip-ansi "^6.0.1"
+ text-table "^0.2.0"
+
+espree@^9.6.0, espree@^9.6.1:
+ version "9.6.1"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f"
+ integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==
+ dependencies:
+ acorn "^8.9.0"
+ acorn-jsx "^5.3.2"
+ eslint-visitor-keys "^3.4.1"
+
+esquery@^1.4.2, esquery@^1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b"
+ integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==
+ dependencies:
+ estraverse "^5.1.0"
+
+esrecurse@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
+ integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+ dependencies:
+ estraverse "^5.2.0"
+
+estraverse@^5.1.0, estraverse@^5.2.0, estraverse@^5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
+ integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
+
+esutils@^2.0.2:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
+ integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
+
+eventemitter3@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4"
+ integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==
+
+execa@8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c"
+ integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==
+ dependencies:
+ cross-spawn "^7.0.3"
+ get-stream "^8.0.1"
+ human-signals "^5.0.0"
+ is-stream "^3.0.0"
+ merge-stream "^2.0.0"
+ npm-run-path "^5.1.0"
+ onetime "^6.0.0"
+ signal-exit "^4.1.0"
+ strip-final-newline "^3.0.0"
+
+fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
+ version "3.1.3"
+ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
+ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+
+fast-glob@^3.2.9, fast-glob@^3.3.0, fast-glob@^3.3.1:
+ version "3.3.2"
+ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
+ integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
+ dependencies:
+ "@nodelib/fs.stat" "^2.0.2"
+ "@nodelib/fs.walk" "^1.2.3"
+ glob-parent "^5.1.2"
+ merge2 "^1.3.0"
+ micromatch "^4.0.4"
+
+fast-json-stable-stringify@^2.0.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
+ integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==
+
+fast-levenshtein@^2.0.6:
+ version "2.0.6"
+ resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917"
+ integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
+
+fastq@^1.6.0:
+ version "1.17.1"
+ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47"
+ integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==
+ dependencies:
+ reusify "^1.0.4"
+
+file-entry-cache@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
+ integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
+ dependencies:
+ flat-cache "^3.0.4"
+
+fill-range@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
+ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+ dependencies:
+ to-regex-range "^5.0.1"
+
+find-up@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19"
+ integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==
+ dependencies:
+ locate-path "^5.0.0"
+ path-exists "^4.0.0"
+
+find-up@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
+ integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
+ dependencies:
+ locate-path "^6.0.0"
+ path-exists "^4.0.0"
+
+flat-cache@^3.0.4:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee"
+ integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==
+ dependencies:
+ flatted "^3.2.9"
+ keyv "^4.5.3"
+ rimraf "^3.0.2"
+
+flatted@^3.2.9:
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
+ integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
+
+follow-redirects@^1.15.6:
+ version "1.15.6"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
+ integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
+
+for-each@^0.3.3:
+ version "0.3.3"
+ resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
+ integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==
+ dependencies:
+ is-callable "^1.1.3"
+
+foreground-child@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d"
+ integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==
+ dependencies:
+ cross-spawn "^7.0.0"
+ signal-exit "^4.0.1"
+
+form-data@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
+ integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
+ dependencies:
+ asynckit "^0.4.0"
+ combined-stream "^1.0.8"
+ mime-types "^2.1.12"
+
+fraction.js@^4.3.7:
+ version "4.3.7"
+ resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
+ integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
+
+fs.realpath@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
+ integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
+
+fsevents@~2.3.2:
+ version "2.3.3"
+ resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
+ integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
+
+function-bind@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
+ integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
+
+function.prototype.name@^1.1.5, function.prototype.name@^1.1.6:
+ version "1.1.6"
+ resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd"
+ integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
+ functions-have-names "^1.2.3"
+
+functions-have-names@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
+ integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
+
+geist@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/geist/-/geist-1.3.0.tgz#e22a87478d64ab452c03e4766f8929d76058f93f"
+ integrity sha512-IoGBfcqVEYB4bEwsfHd35jF4+X9LHRPYZymHL4YOltHSs9LJa24DYs1Z7rEMQ/lsEvaAIc61Y9aUxgcJaQ8lrg==
+
+get-east-asian-width@^1.0.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz#5e6ebd9baee6fb8b7b6bd505221065f0cd91f64e"
+ integrity sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==
+
+get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
+ integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==
+ dependencies:
+ es-errors "^1.3.0"
+ function-bind "^1.1.2"
+ has-proto "^1.0.1"
+ has-symbols "^1.0.3"
+ hasown "^2.0.0"
+
+get-stream@^8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2"
+ integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==
+
+get-symbol-description@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5"
+ integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==
+ dependencies:
+ call-bind "^1.0.5"
+ es-errors "^1.3.0"
+ get-intrinsic "^1.2.4"
+
+get-tsconfig@^4.5.0:
+ version "4.7.5"
+ resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.5.tgz#5e012498579e9a6947511ed0cd403272c7acbbaf"
+ integrity sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==
+ dependencies:
+ resolve-pkg-maps "^1.0.0"
+
+glob-parent@^5.1.2, glob-parent@~5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
+ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
+ dependencies:
+ is-glob "^4.0.1"
+
+glob-parent@^6.0.2:
+ version "6.0.2"
+ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3"
+ integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==
+ dependencies:
+ is-glob "^4.0.3"
+
+glob@10.3.10:
+ version "10.3.10"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b"
+ integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==
+ dependencies:
+ foreground-child "^3.1.0"
+ jackspeak "^2.3.5"
+ minimatch "^9.0.1"
+ minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
+ path-scurry "^1.10.1"
+
+glob@^10.3.10:
+ version "10.3.15"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.15.tgz#e72bc61bc3038c90605f5dd48543dc67aaf3b50d"
+ integrity sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==
+ dependencies:
+ foreground-child "^3.1.0"
+ jackspeak "^2.3.6"
+ minimatch "^9.0.1"
+ minipass "^7.0.4"
+ path-scurry "^1.11.0"
+
+glob@^7.1.3:
+ version "7.2.3"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
+ integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.1.1"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
+globals@^13.19.0:
+ version "13.24.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.24.0.tgz#8432a19d78ce0c1e833949c36adb345400bb1171"
+ integrity sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==
+ dependencies:
+ type-fest "^0.20.2"
+
+globalthis@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236"
+ integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==
+ dependencies:
+ define-properties "^1.2.1"
+ gopd "^1.0.1"
+
+globby@^11.1.0:
+ version "11.1.0"
+ resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
+ integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
+ dependencies:
+ array-union "^2.1.0"
+ dir-glob "^3.0.1"
+ fast-glob "^3.2.9"
+ ignore "^5.2.0"
+ merge2 "^1.4.1"
+ slash "^3.0.0"
+
+gopd@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
+ integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
+ dependencies:
+ get-intrinsic "^1.1.3"
+
+graceful-fs@^4.2.11, graceful-fs@^4.2.4:
+ version "4.2.11"
+ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
+ integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
+
+graphemer@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
+ integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
+
+has-bigints@^1.0.1, has-bigints@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa"
+ integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==
+
+has-flag@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd"
+ integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==
+
+has-flag@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
+ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
+
+has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
+ integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==
+ dependencies:
+ es-define-property "^1.0.0"
+
+has-proto@^1.0.1, has-proto@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd"
+ integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==
+
+has-symbols@^1.0.2, has-symbols@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
+ integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
+
+has-tostringtag@^1.0.0, has-tostringtag@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc"
+ integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==
+ dependencies:
+ has-symbols "^1.0.3"
+
+hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
+ integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
+ dependencies:
+ function-bind "^1.1.2"
+
+hosted-git-info@^2.1.4:
+ version "2.8.9"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
+ integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
+
+human-signals@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28"
+ integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==
+
+ignore@^5.2.0:
+ version "5.3.1"
+ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef"
+ integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==
+
+import-fresh@^3.2.1:
+ version "3.3.0"
+ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
+ integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==
+ dependencies:
+ parent-module "^1.0.0"
+ resolve-from "^4.0.0"
+
+imurmurhash@^0.1.4:
+ version "0.1.4"
+ resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
+ integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==
+
+indent-string@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
+ integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
+
+inflight@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
+ integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
+ dependencies:
+ once "^1.3.0"
+ wrappy "1"
+
+inherits@2:
+ version "2.0.4"
+ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
+ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
+
+internal-slot@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802"
+ integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==
+ dependencies:
+ es-errors "^1.3.0"
+ hasown "^2.0.0"
+ side-channel "^1.0.4"
+
+is-array-buffer@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98"
+ integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==
+ dependencies:
+ call-bind "^1.0.2"
+ get-intrinsic "^1.2.1"
+
+is-arrayish@^0.2.1:
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d"
+ integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==
+
+is-async-function@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646"
+ integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-bigint@^1.0.1:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3"
+ integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==
+ dependencies:
+ has-bigints "^1.0.1"
+
+is-binary-path@~2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09"
+ integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==
+ dependencies:
+ binary-extensions "^2.0.0"
+
+is-boolean-object@^1.1.0:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719"
+ integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==
+ dependencies:
+ call-bind "^1.0.2"
+ has-tostringtag "^1.0.0"
+
+is-builtin-module@^3.2.1:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169"
+ integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==
+ dependencies:
+ builtin-modules "^3.3.0"
+
+is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7:
+ version "1.2.7"
+ resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
+ integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
+
+is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1:
+ version "2.13.1"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384"
+ integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==
+ dependencies:
+ hasown "^2.0.0"
+
+is-data-view@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f"
+ integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==
+ dependencies:
+ is-typed-array "^1.1.13"
+
+is-date-object@^1.0.1, is-date-object@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
+ integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-extglob@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
+ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==
+
+is-finalizationregistry@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6"
+ integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==
+ dependencies:
+ call-bind "^1.0.2"
+
+is-fullwidth-code-point@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
+ integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
+
+is-fullwidth-code-point@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88"
+ integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==
+
+is-fullwidth-code-point@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz#9609efced7c2f97da7b60145ef481c787c7ba704"
+ integrity sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==
+ dependencies:
+ get-east-asian-width "^1.0.0"
+
+is-generator-function@^1.0.10:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72"
+ integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
+ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
+ dependencies:
+ is-extglob "^2.1.1"
+
+is-map@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e"
+ integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==
+
+is-negative-zero@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747"
+ integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==
+
+is-number-object@^1.0.4:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc"
+ integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-number@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
+ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
+
+is-path-inside@^3.0.3:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
+ integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
+
+is-regex@^1.1.4:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
+ integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==
+ dependencies:
+ call-bind "^1.0.2"
+ has-tostringtag "^1.0.0"
+
+is-set@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d"
+ integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==
+
+is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688"
+ integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==
+ dependencies:
+ call-bind "^1.0.7"
+
+is-stream@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac"
+ integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==
+
+is-string@^1.0.5, is-string@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
+ integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==
+ dependencies:
+ has-tostringtag "^1.0.0"
+
+is-symbol@^1.0.2, is-symbol@^1.0.3:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c"
+ integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==
+ dependencies:
+ has-symbols "^1.0.2"
+
+is-typed-array@^1.1.13:
+ version "1.1.13"
+ resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229"
+ integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==
+ dependencies:
+ which-typed-array "^1.1.14"
+
+is-weakmap@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd"
+ integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==
+
+is-weakref@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2"
+ integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==
+ dependencies:
+ call-bind "^1.0.2"
+
+is-weakset@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007"
+ integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==
+ dependencies:
+ call-bind "^1.0.7"
+ get-intrinsic "^1.2.4"
+
+isarray@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
+ integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
+
+isexe@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
+ integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
+
+iterator.prototype@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0"
+ integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==
+ dependencies:
+ define-properties "^1.2.1"
+ get-intrinsic "^1.2.1"
+ has-symbols "^1.0.3"
+ reflect.getprototypeof "^1.0.4"
+ set-function-name "^2.0.1"
+
+jackspeak@^2.3.5, jackspeak@^2.3.6:
+ version "2.3.6"
+ resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8"
+ integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==
+ dependencies:
+ "@isaacs/cliui" "^8.0.2"
+ optionalDependencies:
+ "@pkgjs/parseargs" "^0.11.0"
+
+jiti@^1.21.0:
+ version "1.21.0"
+ resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d"
+ integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==
+
+"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
+ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
+
+js-yaml@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
+ integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
+ dependencies:
+ argparse "^2.0.1"
+
+jsesc@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e"
+ integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==
+
+jsesc@~0.5.0:
+ version "0.5.0"
+ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
+ integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==
+
+json-buffer@3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
+ integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==
+
+json-parse-even-better-errors@^2.3.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d"
+ integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==
+
+json-schema-traverse@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
+ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+
+json-stable-stringify-without-jsonify@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
+ integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==
+
+json5@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593"
+ integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==
+ dependencies:
+ minimist "^1.2.0"
+
+"jsx-ast-utils@^2.4.1 || ^3.0.0", jsx-ast-utils@^3.3.5:
+ version "3.3.5"
+ resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz#4766bd05a8e2a11af222becd19e15575e52a853a"
+ integrity sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==
+ dependencies:
+ array-includes "^3.1.6"
+ array.prototype.flat "^1.3.1"
+ object.assign "^4.1.4"
+ object.values "^1.1.6"
+
+keyv@^4.5.3:
+ version "4.5.4"
+ resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
+ integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==
+ dependencies:
+ json-buffer "3.0.1"
+
+language-subtag-registry@^0.3.20:
+ version "0.3.22"
+ resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d"
+ integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==
+
+language-tags@^1.0.9:
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/language-tags/-/language-tags-1.0.9.tgz#1ffdcd0ec0fafb4b1be7f8b11f306ad0f9c08777"
+ integrity sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==
+ dependencies:
+ language-subtag-registry "^0.3.20"
+
+levn@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
+ integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
+ dependencies:
+ prelude-ls "^1.2.1"
+ type-check "~0.4.0"
+
+lilconfig@3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.0.0.tgz#f8067feb033b5b74dab4602a5f5029420be749bc"
+ integrity sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==
+
+lilconfig@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.1.0.tgz#78e23ac89ebb7e1bfbf25b18043de756548e7f52"
+ integrity sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==
+
+lilconfig@^3.0.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.1.tgz#9d8a246fa753106cfc205fd2d77042faca56e5e3"
+ integrity sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==
+
+lines-and-columns@^1.1.6:
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
+ integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==
+
+lint-staged@^15.2.2:
+ version "15.2.2"
+ resolved "https://registry.yarnpkg.com/lint-staged/-/lint-staged-15.2.2.tgz#ad7cbb5b3ab70e043fa05bff82a09ed286bc4c5f"
+ integrity sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==
+ dependencies:
+ chalk "5.3.0"
+ commander "11.1.0"
+ debug "4.3.4"
+ execa "8.0.1"
+ lilconfig "3.0.0"
+ listr2 "8.0.1"
+ micromatch "4.0.5"
+ pidtree "0.6.0"
+ string-argv "0.3.2"
+ yaml "2.3.4"
+
+listr2@8.0.1:
+ version "8.0.1"
+ resolved "https://registry.yarnpkg.com/listr2/-/listr2-8.0.1.tgz#4d3f50ae6cec3c62bdf0e94f5c2c9edebd4b9c34"
+ integrity sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==
+ dependencies:
+ cli-truncate "^4.0.0"
+ colorette "^2.0.20"
+ eventemitter3 "^5.0.1"
+ log-update "^6.0.0"
+ rfdc "^1.3.0"
+ wrap-ansi "^9.0.0"
+
+locate-path@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0"
+ integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==
+ dependencies:
+ p-locate "^4.1.0"
+
+locate-path@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
+ integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
+ dependencies:
+ p-locate "^5.0.0"
+
+lodash.castarray@^4.4.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/lodash.castarray/-/lodash.castarray-4.4.0.tgz#c02513515e309daddd4c24c60cfddcf5976d9115"
+ integrity sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==
+
+lodash.isplainobject@^4.0.6:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
+ integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
+
+lodash.merge@^4.6.2:
+ version "4.6.2"
+ resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
+ integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
+
+log-update@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/log-update/-/log-update-6.0.0.tgz#0ddeb7ac6ad658c944c1de902993fce7c33f5e59"
+ integrity sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==
+ dependencies:
+ ansi-escapes "^6.2.0"
+ cli-cursor "^4.0.0"
+ slice-ansi "^7.0.0"
+ strip-ansi "^7.1.0"
+ wrap-ansi "^9.0.0"
+
+loose-envify@^1.1.0, loose-envify@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
+ integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
+ dependencies:
+ js-tokens "^3.0.0 || ^4.0.0"
+
+lru-cache@^10.2.0:
+ version "10.2.2"
+ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878"
+ integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ==
+
+merge-stream@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
+ integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
+
+merge2@^1.3.0, merge2@^1.4.1:
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
+ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
+
+micromatch@4.0.5, micromatch@^4.0.4, micromatch@^4.0.5:
+ version "4.0.5"
+ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"
+ integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==
+ dependencies:
+ braces "^3.0.2"
+ picomatch "^2.3.1"
+
+mime-db@1.52.0:
+ version "1.52.0"
+ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
+ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
+
+mime-types@^2.1.12:
+ version "2.1.35"
+ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
+ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
+ dependencies:
+ mime-db "1.52.0"
+
+mimic-fn@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
+ integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
+
+mimic-fn@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc"
+ integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==
+
+min-indent@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
+ integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
+
+minimatch@9.0.3:
+ version "9.0.3"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
+ integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
+ dependencies:
+ brace-expansion "^2.0.1"
+
+minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
+ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
+ dependencies:
+ brace-expansion "^1.1.7"
+
+minimatch@^9.0.1:
+ version "9.0.4"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51"
+ integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==
+ dependencies:
+ brace-expansion "^2.0.1"
+
+minimist@^1.2.0, minimist@^1.2.6:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
+ integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
+
+"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.1.tgz#f7f85aff59aa22f110b20e27692465cf3bf89481"
+ integrity sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==
+
+ms@2.1.2:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
+ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
+
+ms@^2.1.1:
+ version "2.1.3"
+ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
+ integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
+
+mz@^2.7.0:
+ version "2.7.0"
+ resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32"
+ integrity sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==
+ dependencies:
+ any-promise "^1.0.0"
+ object-assign "^4.0.1"
+ thenify-all "^1.0.0"
+
+nanoid@^3.3.6, nanoid@^3.3.7:
+ version "3.3.7"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
+ integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
+
+natural-compare@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
+ integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==
+
+next@14.2.2:
+ version "14.2.2"
+ resolved "https://registry.yarnpkg.com/next/-/next-14.2.2.tgz#707311b5e4bf973ada2305233f322bdd0cd9d579"
+ integrity sha512-oGwUaa2bCs47FbuxWMpOoXtBMPYpvTPgdZr3UAo+pu7Ns00z9otmYpoeV1HEiYL06AlRQQIA/ypK526KjJfaxg==
+ dependencies:
+ "@next/env" "14.2.2"
+ "@swc/helpers" "0.5.5"
+ busboy "1.6.0"
+ caniuse-lite "^1.0.30001579"
+ graceful-fs "^4.2.11"
+ postcss "8.4.31"
+ styled-jsx "5.1.1"
+ optionalDependencies:
+ "@next/swc-darwin-arm64" "14.2.2"
+ "@next/swc-darwin-x64" "14.2.2"
+ "@next/swc-linux-arm64-gnu" "14.2.2"
+ "@next/swc-linux-arm64-musl" "14.2.2"
+ "@next/swc-linux-x64-gnu" "14.2.2"
+ "@next/swc-linux-x64-musl" "14.2.2"
+ "@next/swc-win32-arm64-msvc" "14.2.2"
+ "@next/swc-win32-ia32-msvc" "14.2.2"
+ "@next/swc-win32-x64-msvc" "14.2.2"
+
+node-releases@^2.0.14:
+ version "2.0.14"
+ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b"
+ integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==
+
+normalize-package-data@^2.5.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
+ integrity sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==
+ dependencies:
+ hosted-git-info "^2.1.4"
+ resolve "^1.10.0"
+ semver "2 || 3 || 4 || 5"
+ validate-npm-package-license "^3.0.1"
+
+normalize-path@^3.0.0, normalize-path@~3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
+ integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
+
+normalize-range@^0.1.2:
+ version "0.1.2"
+ resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
+ integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
+
+npm-run-path@^5.1.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f"
+ integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==
+ dependencies:
+ path-key "^4.0.0"
+
+object-assign@^4.0.1, object-assign@^4.1.1:
+ version "4.1.1"
+ resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
+ integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
+
+object-hash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
+ integrity sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==
+
+object-inspect@^1.13.1:
+ version "1.13.1"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2"
+ integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==
+
+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.assign@^4.1.4, object.assign@^4.1.5:
+ version "4.1.5"
+ resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0"
+ integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==
+ dependencies:
+ call-bind "^1.0.5"
+ define-properties "^1.2.1"
+ has-symbols "^1.0.3"
+ object-keys "^1.1.1"
+
+object.entries@^1.1.7:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41"
+ integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-object-atoms "^1.0.0"
+
+object.fromentries@^2.0.7:
+ version "2.0.8"
+ resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65"
+ integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.2"
+ es-object-atoms "^1.0.0"
+
+object.groupby@^1.0.1:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e"
+ integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.2"
+
+object.hasown@^1.1.3:
+ version "1.1.4"
+ resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.4.tgz#e270ae377e4c120cdcb7656ce66884a6218283dc"
+ integrity sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg==
+ dependencies:
+ define-properties "^1.2.1"
+ es-abstract "^1.23.2"
+ es-object-atoms "^1.0.0"
+
+object.values@^1.1.6, object.values@^1.1.7:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b"
+ integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-object-atoms "^1.0.0"
+
+once@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
+ integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
+ dependencies:
+ wrappy "1"
+
+onetime@^5.1.0:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
+ integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
+ dependencies:
+ mimic-fn "^2.1.0"
+
+onetime@^6.0.0:
+ version "6.0.0"
+ resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4"
+ integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==
+ dependencies:
+ mimic-fn "^4.0.0"
+
+optionator@^0.9.3:
+ version "0.9.4"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734"
+ integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==
+ dependencies:
+ deep-is "^0.1.3"
+ fast-levenshtein "^2.0.6"
+ levn "^0.4.1"
+ prelude-ls "^1.2.1"
+ type-check "^0.4.0"
+ word-wrap "^1.2.5"
+
+p-limit@^2.2.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1"
+ integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==
+ dependencies:
+ p-try "^2.0.0"
+
+p-limit@^3.0.2:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
+ integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
+ dependencies:
+ yocto-queue "^0.1.0"
+
+p-locate@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07"
+ integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==
+ dependencies:
+ p-limit "^2.2.0"
+
+p-locate@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
+ integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
+ dependencies:
+ p-limit "^3.0.2"
+
+p-try@^2.0.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
+ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
+
+parent-module@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
+ integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
+ dependencies:
+ callsites "^3.0.0"
+
+parse-json@^5.0.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd"
+ integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==
+ dependencies:
+ "@babel/code-frame" "^7.0.0"
+ error-ex "^1.3.1"
+ json-parse-even-better-errors "^2.3.0"
+ lines-and-columns "^1.1.6"
+
+path-exists@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
+ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==
+
+path-is-absolute@^1.0.0:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
+ integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
+
+path-key@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
+ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
+
+path-key@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18"
+ integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==
+
+path-parse@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
+ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
+
+path-scurry@^1.10.1, path-scurry@^1.11.0:
+ version "1.11.1"
+ resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2"
+ integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==
+ dependencies:
+ lru-cache "^10.2.0"
+ minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
+
+path-type@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
+ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
+
+picocolors@^1.0.0, picocolors@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1"
+ integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==
+
+picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
+ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
+
+pidtree@0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.6.0.tgz#90ad7b6d42d5841e69e0a2419ef38f8883aa057c"
+ integrity sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==
+
+pify@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
+ integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
+
+pirates@^4.0.1:
+ version "4.0.6"
+ resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9"
+ integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==
+
+pluralize@^8.0.0:
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-8.0.0.tgz#1a6fa16a38d12a1901e0320fa017051c539ce3b1"
+ integrity sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==
+
+possible-typed-array-names@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f"
+ integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==
+
+postcss-import@^15.1.0:
+ version "15.1.0"
+ resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-15.1.0.tgz#41c64ed8cc0e23735a9698b3249ffdbf704adc70"
+ integrity sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==
+ dependencies:
+ postcss-value-parser "^4.0.0"
+ read-cache "^1.0.0"
+ resolve "^1.1.7"
+
+postcss-js@^4.0.1:
+ version "4.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.1.tgz#61598186f3703bab052f1c4f7d805f3991bee9d2"
+ integrity sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==
+ dependencies:
+ camelcase-css "^2.0.1"
+
+postcss-load-config@^4.0.1:
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-4.0.2.tgz#7159dcf626118d33e299f485d6afe4aff7c4a3e3"
+ integrity sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==
+ dependencies:
+ lilconfig "^3.0.0"
+ yaml "^2.3.4"
+
+postcss-nested@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/postcss-nested/-/postcss-nested-6.0.1.tgz#f83dc9846ca16d2f4fa864f16e9d9f7d0961662c"
+ integrity sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==
+ dependencies:
+ postcss-selector-parser "^6.0.11"
+
+postcss-selector-parser@6.0.10:
+ version "6.0.10"
+ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d"
+ integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==
+ dependencies:
+ cssesc "^3.0.0"
+ util-deprecate "^1.0.2"
+
+postcss-selector-parser@^6.0.11:
+ version "6.0.16"
+ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz#3b88b9f5c5abd989ef4e2fc9ec8eedd34b20fb04"
+ integrity sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==
+ dependencies:
+ cssesc "^3.0.0"
+ util-deprecate "^1.0.2"
+
+postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
+ version "4.2.0"
+ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
+ integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
+
+postcss@8.4.31:
+ version "8.4.31"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
+ integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
+ dependencies:
+ nanoid "^3.3.6"
+ picocolors "^1.0.0"
+ source-map-js "^1.0.2"
+
+postcss@^8.4.23, postcss@^8.4.38:
+ version "8.4.38"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e"
+ integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==
+ dependencies:
+ nanoid "^3.3.7"
+ picocolors "^1.0.0"
+ source-map-js "^1.2.0"
+
+prelude-ls@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
+ integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
+
+prettier-plugin-tailwindcss@^0.5.14:
+ version "0.5.14"
+ resolved "https://registry.yarnpkg.com/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.5.14.tgz#4482eed357d5e22eac259541c70aca5a4c7b9d5c"
+ integrity sha512-Puaz+wPUAhFp8Lo9HuciYKM2Y2XExESjeT+9NQoVFXZsPPnc9VYss2SpxdQ6vbatmt8/4+SN0oe0I1cPDABg9Q==
+
+prettier@3.2.5:
+ version "3.2.5"
+ resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368"
+ integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==
+
+prop-types@^15.8.1:
+ version "15.8.1"
+ resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
+ integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
+ dependencies:
+ loose-envify "^1.4.0"
+ object-assign "^4.1.1"
+ react-is "^16.13.1"
+
+proxy-from-env@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
+ integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
+
+punycode@^2.1.0:
+ version "2.3.1"
+ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
+ integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
+
+queue-microtask@^1.2.2:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
+ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+
+react-dom@18.2.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
+ integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
+ dependencies:
+ loose-envify "^1.1.0"
+ scheduler "^0.23.0"
+
+react-is@^16.13.1:
+ version "16.13.1"
+ resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
+ integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
+
+react@18.2.0:
+ version "18.2.0"
+ resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
+ integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
+ dependencies:
+ loose-envify "^1.1.0"
+
+read-cache@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
+ integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==
+ dependencies:
+ pify "^2.3.0"
+
+read-pkg-up@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-7.0.1.tgz#f3a6135758459733ae2b95638056e1854e7ef507"
+ integrity sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==
+ dependencies:
+ find-up "^4.1.0"
+ read-pkg "^5.2.0"
+ type-fest "^0.8.1"
+
+read-pkg@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc"
+ integrity sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==
+ dependencies:
+ "@types/normalize-package-data" "^2.4.0"
+ normalize-package-data "^2.5.0"
+ parse-json "^5.0.0"
+ type-fest "^0.6.0"
+
+readdirp@~3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7"
+ integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==
+ dependencies:
+ picomatch "^2.2.1"
+
+reflect.getprototypeof@^1.0.4:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859"
+ integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.1"
+ es-errors "^1.3.0"
+ get-intrinsic "^1.2.4"
+ globalthis "^1.0.3"
+ which-builtin-type "^1.1.3"
+
+regenerator-runtime@^0.14.0:
+ version "0.14.1"
+ resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
+ integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
+
+regexp-tree@^0.1.27:
+ version "0.1.27"
+ resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd"
+ integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==
+
+regexp.prototype.flags@^1.5.2:
+ version "1.5.2"
+ resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334"
+ integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==
+ dependencies:
+ call-bind "^1.0.6"
+ define-properties "^1.2.1"
+ es-errors "^1.3.0"
+ set-function-name "^2.0.1"
+
+regjsparser@^0.10.0:
+ version "0.10.0"
+ resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.10.0.tgz#b1ed26051736b436f22fdec1c8f72635f9f44892"
+ integrity sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==
+ dependencies:
+ jsesc "~0.5.0"
+
+resolve-from@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
+ integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
+
+resolve-pkg-maps@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f"
+ integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==
+
+resolve@^1.1.7, resolve@^1.10.0, resolve@^1.22.2, resolve@^1.22.4:
+ version "1.22.8"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
+ integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
+ dependencies:
+ is-core-module "^2.13.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+resolve@^2.0.0-next.5:
+ version "2.0.0-next.5"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c"
+ integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==
+ dependencies:
+ is-core-module "^2.13.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
+restore-cursor@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-4.0.0.tgz#519560a4318975096def6e609d44100edaa4ccb9"
+ integrity sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==
+ dependencies:
+ onetime "^5.1.0"
+ signal-exit "^3.0.2"
+
+reusify@^1.0.4:
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
+ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
+
+rfdc@^1.3.0:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f"
+ integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==
+
+rimraf@^3.0.2:
+ version "3.0.2"
+ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
+ integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
+ dependencies:
+ glob "^7.1.3"
+
+run-parallel@^1.1.9:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
+ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==
+ dependencies:
+ queue-microtask "^1.2.2"
+
+safe-array-concat@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb"
+ integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==
+ dependencies:
+ call-bind "^1.0.7"
+ get-intrinsic "^1.2.4"
+ has-symbols "^1.0.3"
+ isarray "^2.0.5"
+
+safe-regex-test@^1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377"
+ integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==
+ dependencies:
+ call-bind "^1.0.6"
+ es-errors "^1.3.0"
+ is-regex "^1.1.4"
+
+scheduler@^0.23.0:
+ version "0.23.2"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3"
+ integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==
+ dependencies:
+ loose-envify "^1.1.0"
+
+"semver@2 || 3 || 4 || 5":
+ version "5.7.2"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
+ integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
+
+semver@^6.3.1:
+ version "6.3.1"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
+ integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
+
+semver@^7.5.4:
+ version "7.6.2"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
+ integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
+
+set-function-length@^1.2.1:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
+ integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==
+ dependencies:
+ define-data-property "^1.1.4"
+ es-errors "^1.3.0"
+ function-bind "^1.1.2"
+ get-intrinsic "^1.2.4"
+ gopd "^1.0.1"
+ has-property-descriptors "^1.0.2"
+
+set-function-name@^2.0.1, set-function-name@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985"
+ integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==
+ dependencies:
+ define-data-property "^1.1.4"
+ es-errors "^1.3.0"
+ functions-have-names "^1.2.3"
+ has-property-descriptors "^1.0.2"
+
+shebang-command@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
+ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
+ dependencies:
+ shebang-regex "^3.0.0"
+
+shebang-regex@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
+ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
+
+side-channel@^1.0.4, side-channel@^1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2"
+ integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==
+ dependencies:
+ call-bind "^1.0.7"
+ es-errors "^1.3.0"
+ get-intrinsic "^1.2.4"
+ object-inspect "^1.13.1"
+
+signal-exit@^3.0.2:
+ version "3.0.7"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
+ integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
+
+signal-exit@^4.0.1, signal-exit@^4.1.0:
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
+ integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
+
+slash@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
+ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
+
+slice-ansi@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a"
+ integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==
+ dependencies:
+ ansi-styles "^6.0.0"
+ is-fullwidth-code-point "^4.0.0"
+
+slice-ansi@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-7.1.0.tgz#cd6b4655e298a8d1bdeb04250a433094b347b9a9"
+ integrity sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==
+ dependencies:
+ ansi-styles "^6.2.1"
+ is-fullwidth-code-point "^5.0.0"
+
+source-map-js@^1.0.2, source-map-js@^1.2.0:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af"
+ integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==
+
+spdx-correct@^3.0.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.2.0.tgz#4f5ab0668f0059e34f9c00dce331784a12de4e9c"
+ integrity sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==
+ dependencies:
+ spdx-expression-parse "^3.0.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-exceptions@^2.1.0:
+ version "2.5.0"
+ resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz#5d607d27fc806f66d7b64a766650fa890f04ed66"
+ integrity sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==
+
+spdx-expression-parse@^3.0.0:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz#cf70f50482eefdc98e3ce0a6833e4a53ceeba679"
+ integrity sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==
+ dependencies:
+ spdx-exceptions "^2.1.0"
+ spdx-license-ids "^3.0.0"
+
+spdx-license-ids@^3.0.0:
+ version "3.0.17"
+ resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz#887da8aa73218e51a1d917502d79863161a93f9c"
+ integrity sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==
+
+streamsearch@^1.1.0:
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
+ integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
+
+string-argv@0.3.2:
+ version "0.3.2"
+ resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6"
+ integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==
+
+"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0:
+ name string-width-cjs
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+string-width@^5.0.1, string-width@^5.1.2:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794"
+ integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==
+ dependencies:
+ eastasianwidth "^0.2.0"
+ emoji-regex "^9.2.2"
+ strip-ansi "^7.0.1"
+
+string-width@^7.0.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-7.1.0.tgz#d994252935224729ea3719c49f7206dc9c46550a"
+ integrity sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==
+ dependencies:
+ emoji-regex "^10.3.0"
+ get-east-asian-width "^1.0.0"
+ strip-ansi "^7.1.0"
+
+string.prototype.matchall@^4.0.10:
+ version "4.0.11"
+ resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a"
+ integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.2"
+ es-errors "^1.3.0"
+ es-object-atoms "^1.0.0"
+ get-intrinsic "^1.2.4"
+ gopd "^1.0.1"
+ has-symbols "^1.0.3"
+ internal-slot "^1.0.7"
+ regexp.prototype.flags "^1.5.2"
+ set-function-name "^2.0.2"
+ side-channel "^1.0.6"
+
+string.prototype.trim@^1.2.9:
+ version "1.2.9"
+ resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4"
+ integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-abstract "^1.23.0"
+ es-object-atoms "^1.0.0"
+
+string.prototype.trimend@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229"
+ integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-object-atoms "^1.0.0"
+
+string.prototype.trimstart@^1.0.8:
+ version "1.0.8"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde"
+ integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==
+ dependencies:
+ call-bind "^1.0.7"
+ define-properties "^1.2.1"
+ es-object-atoms "^1.0.0"
+
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+strip-ansi@^7.0.1, strip-ansi@^7.1.0:
+ version "7.1.0"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45"
+ integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==
+ dependencies:
+ ansi-regex "^6.0.1"
+
+strip-bom@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"
+ integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==
+
+strip-final-newline@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd"
+ integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==
+
+strip-indent@^3.0.0:
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
+ integrity sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==
+ dependencies:
+ min-indent "^1.0.0"
+
+strip-json-comments@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
+ integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
+
+styled-jsx@5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f"
+ integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==
+ dependencies:
+ client-only "0.0.1"
+
+sucrase@^3.32.0:
+ version "3.35.0"
+ resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263"
+ integrity sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==
+ dependencies:
+ "@jridgewell/gen-mapping" "^0.3.2"
+ commander "^4.0.0"
+ glob "^10.3.10"
+ lines-and-columns "^1.1.6"
+ mz "^2.7.0"
+ pirates "^4.0.1"
+ ts-interface-checker "^0.1.9"
+
+supports-color@^5.3.0:
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
+ integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==
+ dependencies:
+ has-flag "^3.0.0"
+
+supports-color@^7.1.0:
+ version "7.2.0"
+ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da"
+ integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==
+ dependencies:
+ has-flag "^4.0.0"
+
+supports-preserve-symlinks-flag@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
+ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
+
+tailwindcss@^3.4.3:
+ version "3.4.3"
+ resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-3.4.3.tgz#be48f5283df77dfced705451319a5dffb8621519"
+ integrity sha512-U7sxQk/n397Bmx4JHbJx/iSOOv5G+II3f1kpLpY2QeUv5DcPdcTsYLlusZfq1NthHS1c1cZoyFmmkex1rzke0A==
+ dependencies:
+ "@alloc/quick-lru" "^5.2.0"
+ arg "^5.0.2"
+ chokidar "^3.5.3"
+ didyoumean "^1.2.2"
+ dlv "^1.1.3"
+ fast-glob "^3.3.0"
+ glob-parent "^6.0.2"
+ is-glob "^4.0.3"
+ jiti "^1.21.0"
+ lilconfig "^2.1.0"
+ micromatch "^4.0.5"
+ normalize-path "^3.0.0"
+ object-hash "^3.0.0"
+ picocolors "^1.0.0"
+ postcss "^8.4.23"
+ postcss-import "^15.1.0"
+ postcss-js "^4.0.1"
+ postcss-load-config "^4.0.1"
+ postcss-nested "^6.0.1"
+ postcss-selector-parser "^6.0.11"
+ resolve "^1.22.2"
+ sucrase "^3.32.0"
+
+tapable@^2.2.0:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
+ integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
+
+text-table@^0.2.0:
+ version "0.2.0"
+ resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4"
+ integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==
+
+thenify-all@^1.0.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726"
+ integrity sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==
+ dependencies:
+ thenify ">= 3.1.0 < 4"
+
+"thenify@>= 3.1.0 < 4":
+ version "3.3.1"
+ resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.1.tgz#8932e686a4066038a016dd9e2ca46add9838a95f"
+ integrity sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==
+ dependencies:
+ any-promise "^1.0.0"
+
+to-regex-range@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
+ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
+ dependencies:
+ is-number "^7.0.0"
+
+ts-api-utils@^1.0.1:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1"
+ integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==
+
+ts-interface-checker@^0.1.9:
+ version "0.1.13"
+ resolved "https://registry.yarnpkg.com/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz#784fd3d679722bc103b1b4b8030bcddb5db2a699"
+ integrity sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==
+
+tsconfig-paths@^3.15.0:
+ version "3.15.0"
+ resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4"
+ integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==
+ dependencies:
+ "@types/json5" "^0.0.29"
+ json5 "^1.0.2"
+ minimist "^1.2.6"
+ strip-bom "^3.0.0"
+
+tslib@^2.4.0:
+ version "2.6.2"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae"
+ integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==
+
+type-check@^0.4.0, type-check@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
+ integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
+ dependencies:
+ prelude-ls "^1.2.1"
+
+type-fest@^0.20.2:
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
+ integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
+
+type-fest@^0.6.0:
+ version "0.6.0"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
+ integrity sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==
+
+type-fest@^0.8.1:
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
+ integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
+
+typed-array-buffer@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3"
+ integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==
+ dependencies:
+ call-bind "^1.0.7"
+ es-errors "^1.3.0"
+ is-typed-array "^1.1.13"
+
+typed-array-byte-length@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67"
+ integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==
+ dependencies:
+ call-bind "^1.0.7"
+ for-each "^0.3.3"
+ gopd "^1.0.1"
+ has-proto "^1.0.3"
+ is-typed-array "^1.1.13"
+
+typed-array-byte-offset@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063"
+ integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==
+ dependencies:
+ available-typed-arrays "^1.0.7"
+ call-bind "^1.0.7"
+ for-each "^0.3.3"
+ gopd "^1.0.1"
+ has-proto "^1.0.3"
+ is-typed-array "^1.1.13"
+
+typed-array-length@^1.0.6:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3"
+ integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==
+ dependencies:
+ call-bind "^1.0.7"
+ for-each "^0.3.3"
+ gopd "^1.0.1"
+ has-proto "^1.0.3"
+ is-typed-array "^1.1.13"
+ possible-typed-array-names "^1.0.0"
+
+typescript@5.4.5:
+ version "5.4.5"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611"
+ integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==
+
+unbox-primitive@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"
+ integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==
+ dependencies:
+ call-bind "^1.0.2"
+ has-bigints "^1.0.2"
+ has-symbols "^1.0.3"
+ which-boxed-primitive "^1.0.2"
+
+undici-types@~5.26.4:
+ version "5.26.5"
+ resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
+ integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
+
+update-browserslist-db@^1.0.13:
+ version "1.0.16"
+ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz#f6d489ed90fb2f07d67784eb3f53d7891f736356"
+ integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==
+ dependencies:
+ escalade "^3.1.2"
+ picocolors "^1.0.1"
+
+uri-js@^4.2.2:
+ version "4.4.1"
+ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
+ integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==
+ dependencies:
+ punycode "^2.1.0"
+
+util-deprecate@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
+ integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
+
+validate-npm-package-license@^3.0.1:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a"
+ integrity sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==
+ dependencies:
+ spdx-correct "^3.0.0"
+ spdx-expression-parse "^3.0.0"
+
+which-boxed-primitive@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"
+ integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==
+ dependencies:
+ is-bigint "^1.0.1"
+ is-boolean-object "^1.1.0"
+ is-number-object "^1.0.4"
+ is-string "^1.0.5"
+ is-symbol "^1.0.3"
+
+which-builtin-type@^1.1.3:
+ version "1.1.3"
+ resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b"
+ integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==
+ dependencies:
+ function.prototype.name "^1.1.5"
+ has-tostringtag "^1.0.0"
+ is-async-function "^2.0.0"
+ is-date-object "^1.0.5"
+ is-finalizationregistry "^1.0.2"
+ is-generator-function "^1.0.10"
+ is-regex "^1.1.4"
+ is-weakref "^1.0.2"
+ isarray "^2.0.5"
+ which-boxed-primitive "^1.0.2"
+ which-collection "^1.0.1"
+ which-typed-array "^1.1.9"
+
+which-collection@^1.0.1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0"
+ integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==
+ dependencies:
+ is-map "^2.0.3"
+ is-set "^2.0.3"
+ is-weakmap "^2.0.2"
+ is-weakset "^2.0.3"
+
+which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.9:
+ version "1.1.15"
+ resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d"
+ integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==
+ dependencies:
+ available-typed-arrays "^1.0.7"
+ call-bind "^1.0.7"
+ for-each "^0.3.3"
+ gopd "^1.0.1"
+ has-tostringtag "^1.0.2"
+
+which@^2.0.1:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
+ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
+ dependencies:
+ isexe "^2.0.0"
+
+word-wrap@^1.2.5:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
+ integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
+
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
+wrap-ansi@^8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
+ integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
+ dependencies:
+ ansi-styles "^6.1.0"
+ string-width "^5.0.1"
+ strip-ansi "^7.0.1"
+
+wrap-ansi@^9.0.0:
+ version "9.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-9.0.0.tgz#1a3dc8b70d85eeb8398ddfb1e4a02cd186e58b3e"
+ integrity sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==
+ dependencies:
+ ansi-styles "^6.2.1"
+ string-width "^7.0.0"
+ strip-ansi "^7.1.0"
+
+wrappy@1:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
+ integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
+
+yaml@2.3.4:
+ version "2.3.4"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2"
+ integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==
+
+yaml@^2.3.4:
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.4.2.tgz#7a2b30f2243a5fc299e1f14ca58d475ed4bc5362"
+ integrity sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==
+
+yocto-queue@^0.1.0:
+ version "0.1.0"
+ resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
+ integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==