From af99c169314cdad446146f8edca8b351c3279c78 Mon Sep 17 00:00:00 2001 From: Darren Ethier Date: Tue, 23 Feb 2021 20:36:24 -0500 Subject: [PATCH] Add TypeScript support and convert cart data store to TypeScript (https://github.com/woocommerce/woocommerce-blocks/pull/3768) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add typescript support * Add type declarations for Cart and CartResponse interfaces * make sure we’re resolving .ts files as well as .js files on imports * add more types * type the cart data store * Apply suggestions from code review (implement .tsx in configs) Co-authored-by: Jon Surrell * remove global fetchMock declaration and directly import where used. * rename type * remove named action types and just infer by returning action creator values as const * use interface instead of type * rename * renames * create CartAction type as union of action creator returned types and implement in reducer * remove unused imports * refresh package-lock after rebase * Add base TS config that projects will inherit from * Add tsconfig for assets/js/data project * Ignore TS error on cart store registration We will address this in cooldown when we have time to investigate further * Add tsc to build step to catch TypeScript errors * add a separate command for tsc and tweak build command to use * restore checkJs and allowJs values in config and remove ts check from build command * Add ts:check-all command * Add TypeScript checking workflows * Change triggers for TypeScript workflow * Use npm ci instead of npm install * Remove ts:check-all from TypeScript workflow * Remove TS Check GitHub workflow * Remove type-defs dir from TS include, and remove ts:check-all script We no longer need the ts:check-all script because ts:check will do this for us, the old ts:check did nothing and did not work. * fix coupon loading issues * include .ts files only from type-defs folder Co-authored-by: Jon Surrell Co-authored-by: Thomas Roberts --- plugins/woocommerce-blocks/.eslintrc.js | 16 + .../test/payment-method-data-context.js | 2 + .../blocks/cart-checkout/cart/test/block.js | 4 + .../cart/{action-types.js => action-types.ts} | 2 +- .../js/data/cart/{actions.js => actions.ts} | 192 +++--- .../data/cart/{constants.js => constants.ts} | 0 .../js/data/cart/{index.js => index.ts} | 4 + .../js/data/cart/{reducers.js => reducers.ts} | 101 ++-- .../data/cart/{resolvers.js => resolvers.ts} | 5 +- .../assets/js/data/cart/selectors.js | 164 ----- .../assets/js/data/cart/selectors.ts | 155 +++++ .../{default-states.js => default-states.ts} | 47 +- ...{shared-controls.js => shared-controls.ts} | 27 +- .../assets/js/data/tsconfig.json | 6 + .../assets/js/data/types.ts | 8 + .../assets/js/type-defs/cart-response.ts | 193 ++++++ .../assets/js/type-defs/cart.ts | 188 ++++++ .../assets/js/type-defs/index.ts | 2 + plugins/woocommerce-blocks/babel.config.js | 1 + .../woocommerce-blocks/bin/webpack-configs.js | 33 +- plugins/woocommerce-blocks/globals.d.ts | 1 - plugins/woocommerce-blocks/package-lock.json | 572 +++++++++++++++++- plugins/woocommerce-blocks/package.json | 24 +- plugins/woocommerce-blocks/tsconfig.base.json | 55 ++ plugins/woocommerce-blocks/tsconfig.json | 52 +- 25 files changed, 1475 insertions(+), 379 deletions(-) rename plugins/woocommerce-blocks/assets/js/data/cart/{action-types.js => action-types.ts} (97%) rename plugins/woocommerce-blocks/assets/js/data/cart/{actions.js => actions.ts} (59%) rename plugins/woocommerce-blocks/assets/js/data/cart/{constants.js => constants.ts} (100%) rename plugins/woocommerce-blocks/assets/js/data/cart/{index.js => index.ts} (70%) rename plugins/woocommerce-blocks/assets/js/data/cart/{reducers.js => reducers.ts} (55%) rename plugins/woocommerce-blocks/assets/js/data/cart/{resolvers.js => resolvers.ts} (74%) delete mode 100644 plugins/woocommerce-blocks/assets/js/data/cart/selectors.js create mode 100644 plugins/woocommerce-blocks/assets/js/data/cart/selectors.ts rename plugins/woocommerce-blocks/assets/js/data/{default-states.js => default-states.ts} (50%) rename plugins/woocommerce-blocks/assets/js/data/{shared-controls.js => shared-controls.ts} (65%) create mode 100644 plugins/woocommerce-blocks/assets/js/data/tsconfig.json create mode 100644 plugins/woocommerce-blocks/assets/js/data/types.ts create mode 100644 plugins/woocommerce-blocks/assets/js/type-defs/cart-response.ts create mode 100644 plugins/woocommerce-blocks/assets/js/type-defs/cart.ts create mode 100644 plugins/woocommerce-blocks/assets/js/type-defs/index.ts delete mode 100644 plugins/woocommerce-blocks/globals.d.ts create mode 100644 plugins/woocommerce-blocks/tsconfig.base.json diff --git a/plugins/woocommerce-blocks/.eslintrc.js b/plugins/woocommerce-blocks/.eslintrc.js index 05dfec49ec3..411d716dba5 100644 --- a/plugins/woocommerce-blocks/.eslintrc.js +++ b/plugins/woocommerce-blocks/.eslintrc.js @@ -52,6 +52,7 @@ module.exports = { 'import/resolver': { node: {}, webpack: {}, + typescript: {}, }, }, rules: { @@ -67,5 +68,20 @@ module.exports = { 'you-dont-need-lodash-underscore/omit': 'off', }, }, + { + files: [ '*.ts', '*.tsx' ], + parser: '@typescript-eslint/parser', + extends: [ + 'plugin:@woocommerce/eslint-plugin/recommended', + 'plugin:you-dont-need-lodash-underscore/compatible', + 'plugin:@typescript-eslint/recommended', + ], + rules: { + '@typescript-eslint/no-explicit-any': 'error', + 'no-use-before-define': 'off', + '@typescript-eslint/no-use-before-define': [ 'error' ], + 'jsdoc/require-param': 'off', + }, + }, ], }; diff --git a/plugins/woocommerce-blocks/assets/js/base/context/cart-checkout/payment-methods/test/payment-method-data-context.js b/plugins/woocommerce-blocks/assets/js/base/context/cart-checkout/payment-methods/test/payment-method-data-context.js index 2464d80d52f..d803f591fce 100644 --- a/plugins/woocommerce-blocks/assets/js/base/context/cart-checkout/payment-methods/test/payment-method-data-context.js +++ b/plugins/woocommerce-blocks/assets/js/base/context/cart-checkout/payment-methods/test/payment-method-data-context.js @@ -11,6 +11,7 @@ import { __experimentalDeRegisterPaymentMethod, __experimentalDeRegisterExpressPaymentMethod, } from '@woocommerce/blocks-registry'; +import { default as fetchMock } from 'jest-fetch-mock'; /** * Internal dependencies @@ -129,6 +130,7 @@ describe( 'Testing Payment Method Data Context Provider', () => { if ( req.url.match( /wc\/store\/cart/ ) ) { return Promise.resolve( JSON.stringify( previewCart ) ); } + return Promise.resolve( '' ); } ); // need to clear the store resolution state between tests. await dispatch( storeKey ).invalidateResolutionForStore(); diff --git a/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/cart/test/block.js b/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/cart/test/block.js index ed674178c0e..8ad8b4a5ee9 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/cart/test/block.js +++ b/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/cart/test/block.js @@ -5,6 +5,8 @@ import { render, screen, waitFor } from '@testing-library/react'; import { previewCart } from '@woocommerce/resource-previews'; import { dispatch } from '@wordpress/data'; import { CART_STORE_KEY as storeKey } from '@woocommerce/block-data'; +import { default as fetchMock } from 'jest-fetch-mock'; + /** * Internal dependencies */ @@ -17,6 +19,7 @@ describe( 'Testing cart', () => { if ( req.url.match( /wc\/store\/cart/ ) ) { return Promise.resolve( JSON.stringify( previewCart ) ); } + return Promise.resolve( '' ); } ); // need to clear the store resolution state between tests. await dispatch( storeKey ).invalidateResolutionForStore(); @@ -51,6 +54,7 @@ describe( 'Testing cart', () => { JSON.stringify( defaultCartState.cartData ) ); } + return Promise.resolve( '' ); } ); render( + camelCase( key ) + ) as unknown ) as Cart; return { type: types.RECEIVE_CART, - response, - }; + response: cart, + } as const; } /** - * Returns an action object used for receiving customer facing errors from the - * API. + * Returns an action object used for receiving customer facing errors from the API. * - * @param {Object} [error={}] An error object containing the error message - * and response code. - * @param {boolean} [replace=true] Should existing errors be replaced, or should - * the error be appended. - * @return {Object} Object for action. + * @param {ResponseError|null} [error=null] An error object containing the error + * message and response code. + * @param {boolean} [replace=true] Should existing errors be replaced, + * or should the error be appended. */ -export function receiveError( error = {}, replace = true ) { +export function receiveError( + error: ResponseError | null = null, + replace = true +) { return { type: replace ? types.REPLACE_ERRORS : types.RECEIVE_ERROR, error, - }; + } as const; } /** * Returns an action object used to track when a coupon is applying. * - * @param {string} [couponCode] Coupon being added. - * @return {Object} Object for action. + * @param {string} [couponCode] Coupon being added. */ -export function receiveApplyingCoupon( couponCode ) { +export function receiveApplyingCoupon( couponCode: string ) { return { type: types.APPLYING_COUPON, couponCode, - }; + } as const; } /** * Returns an action object used to track when a coupon is removing. * - * @param {string} [couponCode] Coupon being removed. - * @return {Object} Object for action. + * @param {string} [couponCode] Coupon being removed.. */ -export function receiveRemovingCoupon( couponCode ) { +export function receiveRemovingCoupon( couponCode: string ) { return { type: types.REMOVING_COUPON, couponCode, - }; + } as const; } /** * Returns an action object for updating a single cart item in the store. * - * @param {Object} [response={}] A cart item API response. - * @return {Object} Object for action. + * @param {CartResponseItem} [response=null] A cart item API response. */ -export function receiveCartItem( response = {} ) { +export function receiveCartItem( response: CartResponseItem | null = null ) { return { type: types.RECEIVE_CART_ITEM, cartItem: response, - }; + } as const; } /** - * Returns an action object to indicate if the specified cart item - * quantity is being updated. + * Returns an action object to indicate if the specified cart item quantity is + * being updated. * - * @param {string} cartItemKey Cart item being updated. - * @param {boolean} isPendingQuantity Flag for update state; true if API request - * is pending. - * @return {Object} Object for action. + * @param {string} cartItemKey Cart item being updated. + * @param {boolean} [isPendingQuantity=true] Flag for update state; true if API + * request is pending. */ -export function itemIsPendingQuantity( cartItemKey, isPendingQuantity = true ) { +export function itemIsPendingQuantity( + cartItemKey: string, + isPendingQuantity = true +) { return { type: types.ITEM_PENDING_QUANTITY, cartItemKey, isPendingQuantity, - }; + } as const; } /** * Returns an action object to remove a cart item from the store. * - * @param {string} cartItemKey Cart item to remove. - * @param {boolean} isPendingDelete Flag for update state; true if API request - * is pending. - * @return {Object} Object for action. + * @param {string} cartItemKey Cart item to remove. + * @param {boolean} [isPendingDelete=true] Flag for update state; true if API + * request is pending. */ -export function itemIsPendingDelete( cartItemKey, isPendingDelete = true ) { +export function itemIsPendingDelete( + cartItemKey: string, + isPendingDelete = true +) { return { type: types.RECEIVE_REMOVED_ITEM, cartItemKey, isPendingDelete, - }; + } as const; } /** - * Returns an action object used to track when customer data is being updated (billing and/or shipping). - * - * @param {boolean} isResolving if we're updating customer data or not. - * @return {Object} Object for action. + * Returns an action object used to track when customer data is being updated + * (billing and/or shipping). */ -export function updatingCustomerData( isResolving ) { +export function updatingCustomerData( isResolving: boolean ) { return { type: types.UPDATING_CUSTOMER_DATA, isResolving, - }; + } as const; } /** * Returns an action object used to track whether the shipping rate is being * selected or not. * - * @param {boolean} isResolving True if shipping rate is being selected. - * - * @return {Object} Action object. + * @param {boolean} isResolving True if shipping rate is being selected. */ -export function shippingRatesBeingSelected( isResolving ) { +export function shippingRatesBeingSelected( isResolving: boolean ) { return { type: types.UPDATING_SELECTED_SHIPPING_RATE, isResolving, - }; + } as const; } /** * Applies a coupon code and either invalidates caches, or receives an error if * the coupon cannot be applied. * - * @throws Will throw an error if there is an API problem. - * @param {string} couponCode The coupon code to apply to the cart. + * @param {string} couponCode The coupon code to apply to the cart. + * @throws Will throw an error if there is an API problem. */ -export function* applyCoupon( couponCode ) { +export function* applyCoupon( + couponCode: string +): Generator< unknown, boolean, { response: CartResponse } > { yield receiveApplyingCoupon( couponCode ); try { @@ -186,10 +196,12 @@ export function* applyCoupon( couponCode ) { * Removes a coupon code and either invalidates caches, or receives an error if * the coupon cannot be removed. * - * @throws Will throw an error if there is an API problem. - * @param {string} couponCode The coupon code to remove from the cart. + * @param {string} couponCode The coupon code to remove from the cart. + * @throws Will throw an error if there is an API problem. */ -export function* removeCoupon( couponCode ) { +export function* removeCoupon( + couponCode: string +): Generator< unknown, boolean, { response: CartResponse } > { yield receiveRemovingCoupon( couponCode ); try { @@ -226,11 +238,14 @@ export function* removeCoupon( couponCode ) { * - If successful, yields action to add item from store. * - If error, yields action to store error. * - * @throws Will throw an error if there is an API problem. - * @param {number} productId Product ID to add to cart. - * @param {number} quantity Number of product ID being added to cart. + * @param {number} productId Product ID to add to cart. + * @param {number} [quantity=1] Number of product ID being added to cart. + * @throws Will throw an error if there is an API problem. */ -export function* addItemToCart( productId, quantity = 1 ) { +export function* addItemToCart( + productId: number, + quantity = 1 +): Generator< unknown, void, { response: CartResponse } > { try { const { response } = yield apiFetchWithHeaders( { path: `/wc/store/cart/add-item`, @@ -254,8 +269,6 @@ export function* addItemToCart( productId, quantity = 1 ) { // Re-throw the error. throw error; } - - return true; } /** @@ -267,7 +280,9 @@ export function* addItemToCart( productId, quantity = 1 ) { * * @param {string} cartItemKey Cart item being updated. */ -export function* removeItemFromCart( cartItemKey ) { +export function* removeItemFromCart( + cartItemKey: string +): Generator< unknown, void, { response: CartResponse } > { yield itemIsPendingDelete( cartItemKey ); try { @@ -296,9 +311,13 @@ export function* removeItemFromCart( cartItemKey ) { * - If error, yields action to store error. * * @param {string} cartItemKey Cart item being updated. - * @param {number} quantity Specified (new) quantity. + * @param {number} quantity Specified (new) quantity. */ -export function* changeCartItemQuantity( cartItemKey, quantity ) { +export function* changeCartItemQuantity( + cartItemKey: string, + quantity: number + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- unclear how to represent multiple different yields as type +): Generator< unknown, void, any > { const cartItem = yield select( CART_STORE_KEY, 'getCartItem', cartItemKey ); yield itemIsPendingQuantity( cartItemKey ); @@ -331,10 +350,14 @@ export function* changeCartItemQuantity( cartItemKey, quantity ) { /** * Selects a shipping rate. * - * @param {string} rateId the id of the rate being selected. - * @param {number|string} [packageId] the key of the packages that we will select within. + * @param {string} rateId The id of the rate being selected. + * @param {number | string} [packageId] The key of the packages that we will + * select within. */ -export function* selectShippingRate( rateId, packageId = 0 ) { +export function* selectShippingRate( + rateId: string, + packageId = 0 +): Generator< unknown, boolean, { response: CartResponse } > { try { yield shippingRatesBeingSelected( true ); const { response } = yield apiFetchWithHeaders( { @@ -364,12 +387,23 @@ export function* selectShippingRate( rateId, packageId = 0 ) { return true; } +type BillingAddressShippingAddress = { + // eslint-disable-next-line camelcase + billing_address: CartBillingAddress; + // eslint-disable-next-line camelcase + shipping_address: CartShippingAddress; +}; + /** - * Updates the shipping and/or billing address for the customer and returns an updated cart. + * Updates the shipping and/or billing address for the customer and returns an + * updated cart. * - * @param {Object} customerData Address data to be updated; can contain both billing_address and shipping_address. + * @param {BillingAddressShippingAddress} customerData Address data to be updated; can contain both + * billing_address and shipping_address. */ -export function* updateCustomerData( customerData ) { +export function* updateCustomerData( + customerData: BillingAddressShippingAddress +): Generator< unknown, boolean, { response: CartResponse } > { yield updatingCustomerData( true ); try { @@ -397,3 +431,15 @@ export function* updateCustomerData( customerData ) { yield updatingCustomerData( false ); return true; } + +export type CartAction = ReturnType< + | typeof receiveCart + | typeof receiveError + | typeof receiveApplyingCoupon + | typeof receiveRemovingCoupon + | typeof receiveCartItem + | typeof itemIsPendingQuantity + | typeof itemIsPendingDelete + | typeof updatingCustomerData + | typeof shippingRatesBeingSelected +>; diff --git a/plugins/woocommerce-blocks/assets/js/data/cart/constants.js b/plugins/woocommerce-blocks/assets/js/data/cart/constants.ts similarity index 100% rename from plugins/woocommerce-blocks/assets/js/data/cart/constants.js rename to plugins/woocommerce-blocks/assets/js/data/cart/constants.ts diff --git a/plugins/woocommerce-blocks/assets/js/data/cart/index.js b/plugins/woocommerce-blocks/assets/js/data/cart/index.ts similarity index 70% rename from plugins/woocommerce-blocks/assets/js/data/cart/index.js rename to plugins/woocommerce-blocks/assets/js/data/cart/index.ts index 7b1c636bd92..2a4ca48c2d4 100644 --- a/plugins/woocommerce-blocks/assets/js/data/cart/index.js +++ b/plugins/woocommerce-blocks/assets/js/data/cart/index.ts @@ -15,8 +15,12 @@ import reducer from './reducers'; import { controls } from '../shared-controls'; registerStore( STORE_KEY, { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore -- Can't figure out how to resolve this now reducer, actions, + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore -- not sure how to resolve the type issues here. controls: { ...dataControls, ...controls }, selectors, resolvers, diff --git a/plugins/woocommerce-blocks/assets/js/data/cart/reducers.js b/plugins/woocommerce-blocks/assets/js/data/cart/reducers.ts similarity index 55% rename from plugins/woocommerce-blocks/assets/js/data/cart/reducers.js rename to plugins/woocommerce-blocks/assets/js/data/cart/reducers.ts index ef8db19a238..644c2c67210 100644 --- a/plugins/woocommerce-blocks/assets/js/data/cart/reducers.js +++ b/plugins/woocommerce-blocks/assets/js/data/cart/reducers.ts @@ -1,26 +1,30 @@ /** * External dependencies */ -import { camelCase, mapKeys } from 'lodash'; +import type { CartItem } from '@woocommerce/types'; /** * Internal dependencies */ import { ACTION_TYPES as types } from './action-types'; -import { defaultCartState } from '../default-states'; +import { defaultCartState, CartState } from '../default-states'; +import type { CartAction } from './actions'; /** * Sub-reducer for cart items array. * - * @param {Array} state cartData.items state slice. - * @param {Object} action Action object. + * @param {Array} state cartData.items state slice. + * @param {CartAction} action Action object. */ -const cartItemsReducer = ( state = [], action ) => { +const cartItemsReducer = ( + state: Array< CartItem > = [], + action: CartAction +) => { switch ( action.type ) { case types.RECEIVE_CART_ITEM: // Replace specified cart element with the new data from server. return state.map( ( cartItem ) => { - if ( cartItem.key === action.cartItem.key ) { + if ( cartItem.key === action.cartItem?.key ) { return action.cartItem; } return cartItem; @@ -32,51 +36,62 @@ const cartItemsReducer = ( state = [], action ) => { /** * Reducer for receiving items related to the cart. * - * @param {Object} state The current state in the store. - * @param {Object} action Action object. + * @param {CartState} state The current state in the store. + * @param {CartAction} action Action object. * - * @return {Object} New or existing state. + * @return {CartState} New or existing state. */ -const reducer = ( state = defaultCartState, action ) => { +const reducer = ( + state: CartState = defaultCartState, + action: CartAction +): CartState => { switch ( action.type ) { case types.RECEIVE_ERROR: - state = { - ...state, - errors: state.errors.concat( action.error ), - }; + if ( action.error ) { + state = { + ...state, + errors: state.errors.concat( action.error ), + }; + } break; case types.REPLACE_ERRORS: - state = { - ...state, - errors: [ action.error ], - }; + if ( action.error ) { + state = { + ...state, + errors: [ action.error ], + }; + } break; case types.RECEIVE_CART: - state = { - ...state, - errors: [], - cartData: mapKeys( action.response, ( _, key ) => - camelCase( key ) - ), - }; + if ( action.response ) { + state = { + ...state, + errors: [], + cartData: action.response, + }; + } break; case types.APPLYING_COUPON: - state = { - ...state, - metaData: { - ...state.metaData, - applyingCoupon: action.couponCode, - }, - }; + if ( action.couponCode || action.couponCode === '' ) { + state = { + ...state, + metaData: { + ...state.metaData, + applyingCoupon: action.couponCode, + }, + }; + } break; case types.REMOVING_COUPON: - state = { - ...state, - metaData: { - ...state.metaData, - removingCoupon: action.couponCode, - }, - }; + if ( action.couponCode || action.couponCode === '' ) { + state = { + ...state, + metaData: { + ...state.metaData, + removingCoupon: action.couponCode, + }, + }; + } break; case types.ITEM_PENDING_QUANTITY: @@ -85,7 +100,7 @@ const reducer = ( state = defaultCartState, action ) => { const keysPendingQuantity = state.cartItemsPendingQuantity.filter( ( key ) => key !== action.cartItemKey ); - if ( action.isPendingQuantity ) { + if ( action.isPendingQuantity && action.cartItemKey ) { keysPendingQuantity.push( action.cartItemKey ); } state = { @@ -97,7 +112,7 @@ const reducer = ( state = defaultCartState, action ) => { const keysPendingDelete = state.cartItemsPendingDelete.filter( ( key ) => key !== action.cartItemKey ); - if ( action.isPendingDelete ) { + if ( action.isPendingDelete && action.cartItemKey ) { keysPendingDelete.push( action.cartItemKey ); } state = { @@ -121,7 +136,7 @@ const reducer = ( state = defaultCartState, action ) => { ...state, metaData: { ...state.metaData, - updatingCustomerData: action.isResolving, + updatingCustomerData: !! action.isResolving, }, }; break; @@ -130,7 +145,7 @@ const reducer = ( state = defaultCartState, action ) => { ...state, metaData: { ...state.metaData, - updatingSelectedRate: action.isResolving, + updatingSelectedRate: !! action.isResolving, }, }; } diff --git a/plugins/woocommerce-blocks/assets/js/data/cart/resolvers.js b/plugins/woocommerce-blocks/assets/js/data/cart/resolvers.ts similarity index 74% rename from plugins/woocommerce-blocks/assets/js/data/cart/resolvers.js rename to plugins/woocommerce-blocks/assets/js/data/cart/resolvers.ts index 720047a1790..af5bc6d531e 100644 --- a/plugins/woocommerce-blocks/assets/js/data/cart/resolvers.js +++ b/plugins/woocommerce-blocks/assets/js/data/cart/resolvers.ts @@ -2,6 +2,7 @@ * External dependencies */ import { select, apiFetch } from '@wordpress/data-controls'; +import { CartResponse, Cart } from '@woocommerce/types'; /** * Internal dependencies @@ -12,7 +13,7 @@ import { STORE_KEY, CART_API_ERROR } from './constants'; /** * Resolver for retrieving all cart data. */ -export function* getCartData() { +export function* getCartData(): Generator< unknown, void, CartResponse > { const cartData = yield apiFetch( { path: '/wc/store/cart', method: 'GET', @@ -30,6 +31,6 @@ export function* getCartData() { /** * Resolver for retrieving cart totals. */ -export function* getCartTotals() { +export function* getCartTotals(): Generator< unknown, void, Cart > { yield select( STORE_KEY, 'getCartData' ); } diff --git a/plugins/woocommerce-blocks/assets/js/data/cart/selectors.js b/plugins/woocommerce-blocks/assets/js/data/cart/selectors.js deleted file mode 100644 index adea19a7506..00000000000 --- a/plugins/woocommerce-blocks/assets/js/data/cart/selectors.js +++ /dev/null @@ -1,164 +0,0 @@ -/** @typedef { import('@woocommerce/type-defs/cart').CartData } CartData */ -/** @typedef { import('@woocommerce/type-defs/cart').CartTotals } CartTotals */ - -/** - * Retrieves cart data from state. - * - * @param {Object} state The current state. - * @return {CartData} The data to return. - */ -export const getCartData = ( state ) => { - return state.cartData; -}; - -/** - * Retrieves cart totals from state. - * - * @param {Object} state The current state. - * @return {CartTotals} The data to return. - */ -export const getCartTotals = ( state ) => { - return ( - state.cartData.totals || { - currency_code: '', - currency_symbol: '', - currency_minor_unit: 2, - currency_decimal_separator: '.', - currency_thousand_separator: ',', - currency_prefix: '', - currency_suffix: '', - total_items: '0', - total_items_tax: '0', - total_fees: '0', - total_fees_tax: '0', - total_discount: '0', - total_discount_tax: '0', - total_shipping: '0', - total_shipping_tax: '0', - total_price: '0', - total_tax: '0', - tax_lines: [], - } - ); -}; - -/** - * Retrieves cart meta from state. - * - * @param {Object} state The current state. - * @return {Object} The data to return. - */ -export const getCartMeta = ( state ) => { - return ( - state.metaData || { - applyingCoupon: '', - removingCoupon: '', - } - ); -}; - -/** - * Retrieves cart errors from state. - * - * @param {Object} state The current state. - * @return {Array} Array of errors. - */ -export const getCartErrors = ( state ) => { - return state.errors || []; -}; - -/** - * Returns true if any coupon is being applied. - * - * @param {Object} state The current state. - * @return {boolean} True if a coupon is being applied. - */ -export const isApplyingCoupon = ( state ) => { - return !! state.metaData.applyingCoupon; -}; - -/** - * Retrieves the coupon code currently being applied. - * - * @param {Object} state The current state. - * @return {string} The data to return. - */ -export const getCouponBeingApplied = ( state ) => { - return state.metaData.applyingCoupon || ''; -}; - -/** - * Returns true if any coupon is being removed. - * - * @param {Object} state The current state. - * @return {boolean} True if a coupon is being removed. - */ -export const isRemovingCoupon = ( state ) => { - return !! state.metaData.removingCoupon; -}; - -/** - * Retrieves the coupon code currently being removed. - * - * @param {Object} state The current state. - * @return {string} The data to return. - */ -export const getCouponBeingRemoved = ( state ) => { - return state.metaData.removingCoupon || ''; -}; - -/** - * Returns cart item matching specified key. - * - * @param {Object} state The current state. - * @param {string} cartItemKey Key for a cart item. - * @return {Object} Cart item object, or undefined if not found. - */ -export const getCartItem = ( state, cartItemKey ) => { - return state.cartData.items.find( - ( cartItem ) => cartItem.key === cartItemKey - ); -}; - -/** - * Returns true if the specified cart item quantity is being updated. - * - * @param {Object} state The current state. - * @param {string} cartItemKey Key for a cart item. - * @return {boolean} True if a item has a pending request to be updated. - */ -export const isItemPendingQuantity = ( state, cartItemKey ) => { - return state.cartItemsPendingQuantity.includes( cartItemKey ); -}; - -/** - * Returns true if the specified cart item quantity is being updated. - * - * @param {Object} state The current state. - * @param {string} cartItemKey Key for a cart item. - * @return {boolean} True if a item has a pending request to be updated. - */ -export const isItemPendingDelete = ( state, cartItemKey ) => { - return state.cartItemsPendingDelete.includes( cartItemKey ); -}; -/** - * Retrieves if the address is being applied for shipping. - * - * @param {Object} state The current state. - * @return {boolean} are shipping rates loading. - */ -export const isCustomerDataUpdating = ( state ) => { - return !! state.metaData.updatingCustomerData; -}; - -/** - * Retrieves if the shipping rate selection is being persisted. - * - * @param {Object} state The current state. - * - * @return {boolean} True if the shipping rate selection is being persisted to - * the server. - */ -export const isShippingRateBeingSelected = ( state ) => { - return !! state.metaData.updatingSelectedRate; -}; diff --git a/plugins/woocommerce-blocks/assets/js/data/cart/selectors.ts b/plugins/woocommerce-blocks/assets/js/data/cart/selectors.ts new file mode 100644 index 00000000000..4999107ce64 --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/data/cart/selectors.ts @@ -0,0 +1,155 @@ +/** + * External dependencies + */ +import type { Cart, CartTotals, CartMeta, CartItem } from '@woocommerce/types'; + +/** + * Internal dependencies + */ +import { CartState, defaultCartState } from '../default-states'; +import { ResponseError } from '../types'; + +/** + * Retrieves cart data from state. + * + * @param {CartState} state The current state. + * @return {Cart} The data to return. + */ +export const getCartData = ( state: CartState ): Cart => { + return state.cartData; +}; + +/** + * Retrieves cart totals from state. + * + * @param {CartState} state The current state. + * @return {CartTotals} The data to return. + */ +export const getCartTotals = ( state: CartState ): CartTotals => { + return state.cartData.totals || defaultCartState.cartData.totals; +}; + +/** + * Retrieves cart meta from state. + * + * @param {CartState} state The current state. + * @return {CartMeta} The data to return. + */ +export const getCartMeta = ( state: CartState ): CartMeta => { + return state.metaData || defaultCartState.metaData; +}; + +/** + * Retrieves cart errors from state. + * + * @param {CartState} state The current state. + * @return {Array} Array of errors. + */ +export const getCartErrors = ( state: CartState ): Array< ResponseError > => { + return state.errors || []; +}; + +/** + * Returns true if any coupon is being applied. + * + * @param {CartState} state The current state. + * @return {boolean} True if a coupon is being applied. + */ +export const isApplyingCoupon = ( state: CartState ): boolean => { + return !! state.metaData.applyingCoupon; +}; + +/** + * Retrieves the coupon code currently being applied. + * + * @param {CartState} state The current state. + * @return {string} The data to return. + */ +export const getCouponBeingApplied = ( state: CartState ): string => { + return state.metaData.applyingCoupon || ''; +}; + +/** + * Returns true if any coupon is being removed. + * + * @param {CartState} state The current state. + * @return {boolean} True if a coupon is being removed. + */ +export const isRemovingCoupon = ( state: CartState ): boolean => { + return !! state.metaData.removingCoupon; +}; + +/** + * Retrieves the coupon code currently being removed. + * + * @param {CartState} state The current state. + * @return {string} The data to return. + */ +export const getCouponBeingRemoved = ( state: CartState ): string => { + return state.metaData.removingCoupon || ''; +}; + +/** + * Returns cart item matching specified key. + * + * @param {CartState} state The current state. + * @param {string} cartItemKey Key for a cart item. + * @return {CartItem | void} Cart item object, or undefined if not found. + */ +export const getCartItem = ( + state: CartState, + cartItemKey: string +): CartItem | void => { + return state.cartData.items.find( + ( cartItem ) => cartItem.key === cartItemKey + ); +}; + +/** + * Returns true if the specified cart item quantity is being updated. + * + * @param {CartState} state The current state. + * @param {string} cartItemKey Key for a cart item. + * @return {boolean} True if a item has a pending request to be updated. + */ +export const isItemPendingQuantity = ( + state: CartState, + cartItemKey: string +): boolean => { + return state.cartItemsPendingQuantity.includes( cartItemKey ); +}; + +/** + * Returns true if the specified cart item quantity is being updated. + * + * @param {CartState} state The current state. + * @param {string} cartItemKey Key for a cart item. + * @return {boolean} True if a item has a pending request to be updated. + */ +export const isItemPendingDelete = ( + state: CartState, + cartItemKey: string +): boolean => { + return state.cartItemsPendingDelete.includes( cartItemKey ); +}; +/** + * Retrieves if the address is being applied for shipping. + * + * @param {CartState} state The current state. + * @return {boolean} are shipping rates loading. + */ +export const isCustomerDataUpdating = ( state: CartState ): boolean => { + return !! state.metaData.updatingCustomerData; +}; + +/** + * Retrieves if the shipping rate selection is being persisted. + * + * @param {CartState} state The current state. + * + * @return {boolean} True if the shipping rate selection is being persisted to + * the server. + */ +export const isShippingRateBeingSelected = ( state: CartState ): boolean => { + return !! state.metaData.updatingSelectedRate; +}; diff --git a/plugins/woocommerce-blocks/assets/js/data/default-states.js b/plugins/woocommerce-blocks/assets/js/data/default-states.ts similarity index 50% rename from plugins/woocommerce-blocks/assets/js/data/default-states.js rename to plugins/woocommerce-blocks/assets/js/data/default-states.ts index 34056597e1f..03a73ffe76a 100644 --- a/plugins/woocommerce-blocks/assets/js/data/default-states.js +++ b/plugins/woocommerce-blocks/assets/js/data/default-states.ts @@ -1,4 +1,22 @@ -export const defaultCartState = { +/** + * External dependencies + */ +import type { Cart, CartMeta } from '@woocommerce/types'; + +/** + * Internal dependencies + */ +import type { ResponseError } from './types'; + +export interface CartState { + cartItemsPendingQuantity: Array< string >; + cartItemsPendingDelete: Array< string >; + cartData: Cart; + metaData: CartMeta; + errors: Array< ResponseError >; +} + +export const defaultCartState: CartState = { cartItemsPendingQuantity: [], cartItemsPendingDelete: [], cartData: { @@ -15,11 +33,26 @@ export const defaultCartState = { postcode: '', country: '', }, + billingAddress: { + first_name: '', + last_name: '', + company: '', + address_1: '', + address_2: '', + city: '', + state: '', + postcode: '', + country: '', + phone: '', + email: '', + }, items: [], - fees: [], itemsCount: 0, itemsWeight: 0, needsShipping: true, + needsPayment: false, + hasCalculatedShipping: true, + fees: [], totals: { currency_code: '', currency_symbol: '', @@ -40,7 +73,15 @@ export const defaultCartState = { total_tax: '0', tax_lines: [], }, + errors: [], + paymentRequirements: [], + extensions: [], + }, + metaData: { + updatingCustomerData: false, + updatingSelectedRate: false, + applyingCoupon: '', + removingCoupon: '', }, - metaData: {}, errors: [], }; diff --git a/plugins/woocommerce-blocks/assets/js/data/shared-controls.js b/plugins/woocommerce-blocks/assets/js/data/shared-controls.ts similarity index 65% rename from plugins/woocommerce-blocks/assets/js/data/shared-controls.js rename to plugins/woocommerce-blocks/assets/js/data/shared-controls.ts index e115d2a0b92..73291460ae4 100644 --- a/plugins/woocommerce-blocks/assets/js/data/shared-controls.js +++ b/plugins/woocommerce-blocks/assets/js/data/shared-controls.ts @@ -2,17 +2,24 @@ * External dependencies */ import { __ } from '@wordpress/i18n'; -import triggerFetch from '@wordpress/api-fetch'; +import triggerFetch, { APIFetchOptions } from '@wordpress/api-fetch'; + +export interface ApiFetchWithHeadersAction { + type: string; + options: APIFetchOptions; +} /** * Dispatched a control action for triggering an api fetch call with no parsing. * Typically this would be used in scenarios where headers are needed. * - * @param {Object} options The options for the API request. + * @param {APIFetchOptions} options The options for the API request. * - * @return {Object} The control action descriptor. + * @return {ApiFetchWithHeadersAction} The control action descriptor. */ -export const apiFetchWithHeaders = ( options ) => { +export const apiFetchWithHeaders = ( + options: APIFetchOptions +): ApiFetchWithHeadersAction => { return { type: 'API_FETCH_WITH_HEADERS', options, @@ -37,7 +44,11 @@ const invalidJsonError = { * the controls property of the registration object. */ export const controls = { - API_FETCH_WITH_HEADERS( { options } ) { + API_FETCH_WITH_HEADERS( { + options, + }: { + options: APIFetchOptions; + } ): Promise< unknown > { return new Promise( ( resolve, reject ) => { triggerFetch( { ...options, parse: false } ) .then( ( fetchResponse ) => { @@ -48,6 +59,8 @@ export const controls = { response, headers: fetchResponse.headers, } ); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore -- this does exist but doesn't appear to be typed in the api-fetch types. triggerFetch.setNonce( fetchResponse.headers ); } ) .catch( () => { @@ -55,12 +68,14 @@ export const controls = { } ); } ) .catch( ( errorResponse ) => { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore -- this does exist but doesn't appear to be typed in the api-fetch types. triggerFetch.setNonce( errorResponse.headers ); if ( typeof errorResponse.json === 'function' ) { // Parse error response before rejecting it. errorResponse .json() - .then( ( error ) => { + .then( ( error: unknown ) => { reject( error ); } ) .catch( () => { diff --git a/plugins/woocommerce-blocks/assets/js/data/tsconfig.json b/plugins/woocommerce-blocks/assets/js/data/tsconfig.json new file mode 100644 index 00000000000..584b5fa9059 --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/data/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../../tsconfig.base.json", + "compilerOptions": {}, + "include": [ ".", "../type-defs/**.ts" ], + "exclude": [ "**/test/**" ] +} diff --git a/plugins/woocommerce-blocks/assets/js/data/types.ts b/plugins/woocommerce-blocks/assets/js/data/types.ts new file mode 100644 index 00000000000..9a806139716 --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/data/types.ts @@ -0,0 +1,8 @@ +export interface ResponseError { + code: string; + message: string; + data: { + status: number; + [ key: string ]: unknown; + }; +} diff --git a/plugins/woocommerce-blocks/assets/js/type-defs/cart-response.ts b/plugins/woocommerce-blocks/assets/js/type-defs/cart-response.ts new file mode 100644 index 00000000000..96fea6757c1 --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/type-defs/cart-response.ts @@ -0,0 +1,193 @@ +/* eslint-disable camelcase -- API responses have camelcase properties */ +export interface CurrencyResponseInfo { + currency_code: string; + currency_symbol: string; + currency_minor_unit: number; + currency_decimal_separator: string; + currency_thousand_separator: string; + currency_prefix: string; + currency_suffix: string; +} + +export interface CartResponseTotalsItem extends CurrencyResponseInfo { + total_discount: string; + total_discount_tax: string; +} + +export interface CartResponseCouponItem { + code: string; + discount_type: string; + totals: CartResponseTotalsItem; +} + +export interface ResponseFirstNameLastName { + first_name: string; + last_name: string; +} + +export interface ResponseBaseAddress { + address_1: string; + address_2: string; + city: string; + state: string; + postcode: string; + country: string; +} + +export interface ShippingRateItemItem { + key: string; + name: string; + quantity: number; +} + +export interface MetaKeyValue { + key: string; + value: string; +} + +export interface CartResponseShippingRateItemShippingRate + extends CurrencyResponseInfo { + rate_id: string; + name: string; + description: string; + delivery_time: string; + price: string; + taxes: string; + instance_id: number; + method_id: string; + meta_data: Array< MetaKeyValue >; + selected: boolean; +} + +export interface CartResponseShippingRateItem { + package_id: number; + name: string; + destination: ResponseBaseAddress; + items: Array< ShippingRateItemItem >; + shipping_rates: Array< CartResponseShippingRateItemShippingRate >; +} + +export interface CartResponseShippingAddress + extends ResponseBaseAddress, + ResponseFirstNameLastName { + company: string; +} + +export interface CartResponseBillingAddress + extends CartResponseShippingAddress { + phone: string; + email: string; +} + +export interface CartResponseImageItem { + id: number; + src: string; + thumbnail: string; + srcset: string; + sizes: string; + name: string; + alt: string; +} + +export interface CartResponseVariationItem { + attribute: string; + value: string; +} + +export interface CartResponseItemPrices extends CurrencyResponseInfo { + price: string; + regular_price: string; + sale_price: string; + price_range: null | { min_amount: string; max_amount: string }; + raw_prices: { + precision: number; + price: string; + regular_price: string; + sale_price: string; + }; +} + +export interface CartResponseItemTotals extends CurrencyResponseInfo { + line_subtotal: string; + line_subtotal_tax: string; + line_total: string; + line_total_tax: string; +} + +export interface CartResponseItem { + key: string; + id: number; + quantity: number; + quantity_limit: number; + name: string; + summary: string; + short_description: string; + description: string; + sku: string; + low_stock_remaining: string; + backorders_allowed: boolean; + show_backorder_badge: boolean; + sold_individually: boolean; + permalink: string; + images: Array< CartResponseImageItem >; + variation: Array< CartResponseVariationItem >; + prices: CartResponseItemPrices; + totals: CartResponseItemTotals; +} + +export interface CartResponseTotalsTaxLineItem { + name: string; + price: string; +} + +export interface CartResponseFeeItemTotals extends CurrencyResponseInfo { + total: string; + total_tax: string; +} + +export interface CartResponseFeeItem { + id: string; + name: string; + totals: CartResponseFeeItemTotals; +} + +export interface CartResponseTotals extends CurrencyResponseInfo { + total_items: string; + total_items_tax: string; + total_fees: string; + total_fees_tax: string; + total_discount: string; + total_discount_tax: string; + total_shipping: string; + total_shipping_tax: string; + total_price: string; + total_tax: string; + tax_lines: Array< CartResponseTotalsTaxLineItem >; +} + +export interface CartResponseErrorItem { + code: string; + message: string; +} + +export interface CartResponseExtensionItem { + [ key: string ]: unknown; +} + +export interface CartResponse { + coupons: Array< CartResponseCouponItem >; + shipping_rates: Array< CartResponseShippingRateItem >; + shipping_address: CartResponseShippingAddress; + billing_address: CartResponseBillingAddress; + items: Array< CartResponseItem >; + items_count: number; + items_weight: number; + needs_payment: boolean; + needs_shipping: boolean; + has_calculated_shipping: boolean; + fees: Array< CartResponseFeeItem >; + totals: CartResponseTotalsItem; + errors: Array< CartResponseErrorItem >; + payment_requirements: Array< unknown >; + extensions: Array< CartResponseExtensionItem >; +} diff --git a/plugins/woocommerce-blocks/assets/js/type-defs/cart.ts b/plugins/woocommerce-blocks/assets/js/type-defs/cart.ts new file mode 100644 index 00000000000..6d8c67a283b --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/type-defs/cart.ts @@ -0,0 +1,188 @@ +/* eslint-disable camelcase -- API responses have camelcase properties */ + +/** + * Internal dependencies + */ +import { MetaKeyValue, ShippingRateItemItem } from './cart-response'; +export interface CurrencyInfo { + currency_code: string; + currency_symbol: string; + currency_minor_unit: number; + currency_decimal_separator: string; + currency_thousand_separator: string; + currency_prefix: string; + currency_suffix: string; +} + +export interface CartTotalsItem extends CurrencyInfo { + total_discount: string; + total_discount_tax: string; +} + +export interface CartCouponItem { + code: string; + discount_type: string; + totals: CartTotalsItem; +} + +export interface FirstNameLastName { + first_name: string; + last_name: string; +} + +export interface BaseAddress { + address_1: string; + address_2: string; + city: string; + state: string; + postcode: string; + country: string; +} + +export interface CartShippingRateItemShippingRate extends CurrencyInfo { + rate_id: string; + name: string; + description: string; + delivery_time: string; + price: string; + taxes: string; + instance_id: number; + method_id: string; + meta_data: Array< MetaKeyValue >; + selected: boolean; +} + +export interface CartShippingRateItem { + package_id: number; + name: string; + destination: BaseAddress; + items: Array< ShippingRateItemItem >; + shipping_rates: Array< CartShippingRateItemShippingRate >; +} + +export interface CartShippingAddress extends BaseAddress, FirstNameLastName { + company: string; +} + +export interface CartBillingAddress extends CartShippingAddress { + phone: string; + email: string; +} + +export interface CartImageItem { + id: number; + src: string; + thumbnail: string; + srcset: string; + sizes: string; + name: string; + alt: string; +} + +export interface CartVariationItem { + attribute: string; + value: string; +} + +export interface CartItemPrices extends CurrencyInfo { + price: string; + regular_price: string; + sale_price: string; + price_range: null | { min_amount: string; max_amount: string }; + raw_prices: { + precision: number; + price: string; + regular_price: string; + sale_price: string; + }; +} + +export interface CartItemTotals extends CurrencyInfo { + line_subtotal: string; + line_subtotal_tax: string; + line_total: string; + line_total_tax: string; +} + +export interface CartItem { + key: string; + id: number; + quantity: number; + quantity_limit: number; + name: string; + summary: string; + short_description: string; + description: string; + sku: string; + low_stock_remaining: string; + backorders_allowed: boolean; + show_backorder_badge: boolean; + sold_individually: boolean; + permalink: string; + images: Array< CartImageItem >; + variation: Array< CartVariationItem >; + prices: CartItemPrices; + totals: CartItemTotals; +} + +export interface CartTotalsTaxLineItem { + name: string; + price: string; +} + +export interface CartFeeItemTotals extends CurrencyInfo { + total: string; + total_tax: string; +} + +export interface CartFeeItem { + id: string; + name: string; + totals: CartFeeItemTotals; +} + +export interface CartTotals extends CurrencyInfo { + total_items: string; + total_items_tax: string; + total_fees: string; + total_fees_tax: string; + total_discount: string; + total_discount_tax: string; + total_shipping: string; + total_shipping_tax: string; + total_price: string; + total_tax: string; + tax_lines: Array< CartTotalsTaxLineItem >; +} + +export interface CartErrorItem { + code: string; + message: string; +} + +export interface CartExtensionItem { + [ key: string ]: unknown; +} +export interface Cart { + coupons: Array< CartCouponItem >; + shippingRates: Array< CartShippingRateItem >; + shippingAddress: CartShippingAddress; + billingAddress: CartBillingAddress; + items: Array< CartItem >; + itemsCount: number; + itemsWeight: number; + needsPayment: boolean; + needsShipping: boolean; + hasCalculatedShipping: boolean; + fees: Array< CartFeeItem >; + totals: CartTotals; + errors: Array< CartErrorItem >; + paymentRequirements: Array< unknown >; + extensions: Array< CartExtensionItem >; +} +export interface CartMeta { + updatingCustomerData: boolean; + updatingSelectedRate: boolean; + applyingCoupon: string; + removingCoupon: string; +} diff --git a/plugins/woocommerce-blocks/assets/js/type-defs/index.ts b/plugins/woocommerce-blocks/assets/js/type-defs/index.ts new file mode 100644 index 00000000000..da27ed91751 --- /dev/null +++ b/plugins/woocommerce-blocks/assets/js/type-defs/index.ts @@ -0,0 +1,2 @@ +export * from './cart-response'; +export * from './cart'; diff --git a/plugins/woocommerce-blocks/babel.config.js b/plugins/woocommerce-blocks/babel.config.js index 197e0cf8cc2..d0ef22d83f0 100644 --- a/plugins/woocommerce-blocks/babel.config.js +++ b/plugins/woocommerce-blocks/babel.config.js @@ -8,5 +8,6 @@ module.exports = { }, }, ], + [ '@babel/preset-typescript' ], ], }; diff --git a/plugins/woocommerce-blocks/bin/webpack-configs.js b/plugins/woocommerce-blocks/bin/webpack-configs.js index 31727ab50bc..522ae887320 100644 --- a/plugins/woocommerce-blocks/bin/webpack-configs.js +++ b/plugins/woocommerce-blocks/bin/webpack-configs.js @@ -81,7 +81,7 @@ const getCoreConfig = ( options = {} ) => { module: { rules: [ { - test: /\.jsx?$/, + test: /\.(t|j)sx?$/, exclude: /node_modules/, use: { loader: 'babel-loader?cacheDirectory', @@ -123,7 +123,10 @@ woocommerce_blocks_env = ${ NODE_ENV } `.trim(), } ), ], - resolve, + resolve: { + ...resolve, + extensions: [ '.js', '.ts', '.tsx' ], + }, }; }; @@ -169,7 +172,7 @@ const getMainConfig = ( options = {} ) => { module: { rules: [ { - test: /\.jsx?$/, + test: /\.(j|t)sx?$/, exclude: /node_modules/, use: { loader: 'babel-loader?cacheDirectory', @@ -210,7 +213,10 @@ const getMainConfig = ( options = {} ) => { ( result ) => ( result.resource = dashIconReplacementModule ) ), ], - resolve, + resolve: { + ...resolve, + extensions: [ '.js', '.ts', '.tsx' ], + }, }; }; @@ -245,7 +251,7 @@ const getFrontConfig = ( options = {} ) => { module: { rules: [ { - test: /\.jsx?$/, + test: /\.(j|t)sx?$/, exclude: /node_modules/, use: { loader: 'babel-loader?cacheDirectory', @@ -310,7 +316,10 @@ const getFrontConfig = ( options = {} ) => { ( result ) => ( result.resource = dashIconReplacementModule ) ), ], - resolve, + resolve: { + ...resolve, + extensions: [ '.js', '.ts', '.tsx' ], + }, }; }; @@ -343,7 +352,7 @@ const getPaymentsConfig = ( options = {} ) => { module: { rules: [ { - test: /\.jsx?$/, + test: /\.(j|t)sx?$/, exclude: /node_modules/, use: { loader: 'babel-loader?cacheDirectory', @@ -411,7 +420,10 @@ const getPaymentsConfig = ( options = {} ) => { ( result ) => ( result.resource = dashIconReplacementModule ) ), ], - resolve, + resolve: { + ...resolve, + extensions: [ '.js', '.ts', '.tsx' ], + }, }; }; @@ -570,7 +582,10 @@ const getStylingConfig = ( options = {} ) => { // Remove JS files generated by MiniCssExtractPlugin. new RemoveFilesPlugin( `./build/*style${ fileSuffix }.js` ), ], - resolve, + resolve: { + ...resolve, + extensions: [ '.js', '.ts', '.tsx' ], + }, }; }; diff --git a/plugins/woocommerce-blocks/globals.d.ts b/plugins/woocommerce-blocks/globals.d.ts deleted file mode 100644 index f06070a1548..00000000000 --- a/plugins/woocommerce-blocks/globals.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare var fetchMock: any; diff --git a/plugins/woocommerce-blocks/package-lock.json b/plugins/woocommerce-blocks/package-lock.json index ae5458f42cf..6f717862a8a 100644 --- a/plugins/woocommerce-blocks/package-lock.json +++ b/plugins/woocommerce-blocks/package-lock.json @@ -133,15 +133,23 @@ } }, "@babel/helper-compilation-targets": { - "version": "7.12.16", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.16.tgz", - "integrity": "sha512-dBHNEEaZx7F3KoUYqagIhRIeqyyuI65xMndMZ3WwGwEBI609I4TleYQHcrS627vbKyNTXqShoN+fvYD9HuQxAg==", + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.12.17.tgz", + "integrity": "sha512-5EkibqLVYOuZ89BSg2lv+GG8feywLuvMXNYgf0Im4MssE0mFWPztSpJbildNnUgw0bLI2EsIN4MpSHC2iUJkQA==", "dev": true, "requires": { "@babel/compat-data": "^7.12.13", - "@babel/helper-validator-option": "^7.12.16", + "@babel/helper-validator-option": "^7.12.17", "browserslist": "^4.14.5", "semver": "^5.5.0" + }, + "dependencies": { + "@babel/helper-validator-option": { + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz", + "integrity": "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==", + "dev": true + } } }, "@babel/helper-create-class-features-plugin": { @@ -158,9 +166,9 @@ } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.12.16", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.16.tgz", - "integrity": "sha512-jAcQ1biDYZBdaAxB4yg46/XirgX7jBDiMHDbwYQOgtViLBXGxJpZQ24jutmBqAIB/q+AwB6j+NbBXjKxEY8vqg==", + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.12.17.tgz", + "integrity": "sha512-p2VGmBu9oefLZ2nQpgnEnG0ZlRPvL8gAGvPUMQwUdaE8k49rOMuZpOwdQoy5qJf6K8jL3bcAMhVUlHAjIgJHUg==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.12.13", @@ -407,9 +415,9 @@ } }, "@babel/plugin-proposal-dynamic-import": { - "version": "7.12.16", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.16.tgz", - "integrity": "sha512-yiDkYFapVxNOCcBfLnsb/qdsliroM+vc3LHiZwS4gh7pFjo5Xq3BDhYBNn3H3ao+hWPvqeeTdU+s+FIvokov+w==", + "version": "7.12.17", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.12.17.tgz", + "integrity": "sha512-ZNGoFZqrnuy9H2izB2jLlnNDAfVPlGl5NhFEiFe4D84ix9GQGygF+CWMGHKuE+bpyS/AOuDQCnkiRNqW2IzS1Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.12.13", @@ -3775,6 +3783,12 @@ "@types/node": "*" } }, + "@types/lodash": { + "version": "4.14.168", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz", + "integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q==", + "dev": true + }, "@types/markdown-to-jsx": { "version": "6.11.3", "resolved": "https://registry.npmjs.org/@types/markdown-to-jsx/-/markdown-to-jsx-6.11.3.tgz", @@ -3904,9 +3918,10 @@ } }, "@types/react": { - "version": "16.14.3", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.3.tgz", - "integrity": "sha512-zPrXn03hmPYqh9DznqSFQsoRtrQ4aHgnZDO+hMGvsE/PORvDTdJCHQ6XvJV31ic+0LzF73huPFXUb++W6Kri0Q==", + "version": "16.14.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.2.tgz", + "integrity": "sha512-BzzcAlyDxXl2nANlabtT4thtvbbnhee8hMmH/CcJrISDBVcJS1iOsP1f0OAgSdGE0MsY9tqcrb9YoZcOFv9dbQ==", + "dev": true, "requires": { "@types/prop-types": "*", "csstype": "^3.0.2" @@ -3915,7 +3930,8 @@ "csstype": { "version": "3.0.6", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.6.tgz", - "integrity": "sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw==" + "integrity": "sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw==", + "dev": true } } }, @@ -4085,6 +4101,12 @@ } } }, + "@types/wordpress__api-fetch": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/@types/wordpress__api-fetch/-/wordpress__api-fetch-3.2.3.tgz", + "integrity": "sha512-DsbGPr5lB/8ITClw0wt4JBDVff1X2XgkAyFvei2w6s+2HYpEB5GaTqJI4wY/Jn0rWqpFsX68sO5Kl2vKkgyMuw==", + "dev": true + }, "@types/wordpress__data": { "version": "4.6.9", "resolved": "https://registry.npmjs.org/@types/wordpress__data/-/wordpress__data-4.6.9.tgz", @@ -4095,6 +4117,16 @@ "redux": "^4.0.1" } }, + "@types/wordpress__data-controls": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/wordpress__data-controls/-/wordpress__data-controls-1.0.4.tgz", + "integrity": "sha512-PejgPEZNS+tSupgU3mFd3lAdrPJgm8Jvh2uEHjSxTYgDDk7TMjoBOX069sid4kF9ck5nDLqg59UcPUDT0F2PnA==", + "dev": true, + "requires": { + "@types/wordpress__api-fetch": "*", + "@types/wordpress__data": "*" + } + }, "@types/wordpress__element": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/@types/wordpress__element/-/wordpress__element-2.4.1.tgz", @@ -4131,6 +4163,233 @@ "@types/node": "*" } }, + "@typescript-eslint/eslint-plugin": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.14.1.tgz", + "integrity": "sha512-5JriGbYhtqMS1kRcZTQxndz1lKMwwEXKbwZbkUZNnp6MJX0+OVXnG0kOlBZP4LUAxEyzu3cs+EXd/97MJXsGfw==", + "dev": true, + "requires": { + "@typescript-eslint/experimental-utils": "4.14.1", + "@typescript-eslint/scope-manager": "4.14.1", + "debug": "^4.1.1", + "functional-red-black-tree": "^1.0.1", + "lodash": "^4.17.15", + "regexpp": "^3.0.0", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + }, + "dependencies": { + "@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true + }, + "@typescript-eslint/experimental-utils": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.14.1.tgz", + "integrity": "sha512-2CuHWOJwvpw0LofbyG5gvYjEyoJeSvVH2PnfUQSn0KQr4v8Dql2pr43ohmx4fdPQ/eVoTSFjTi/bsGEXl/zUUQ==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.3", + "@typescript-eslint/scope-manager": "4.14.1", + "@typescript-eslint/types": "4.14.1", + "@typescript-eslint/typescript-estree": "4.14.1", + "eslint-scope": "^5.0.0", + "eslint-utils": "^2.0.0" + } + }, + "@typescript-eslint/scope-manager": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.14.1.tgz", + "integrity": "sha512-F4bjJcSqXqHnC9JGUlnqSa3fC2YH5zTtmACS1Hk+WX/nFB0guuynVK5ev35D4XZbdKjulXBAQMyRr216kmxghw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.14.1", + "@typescript-eslint/visitor-keys": "4.14.1" + } + }, + "@typescript-eslint/types": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.14.1.tgz", + "integrity": "sha512-SkhzHdI/AllAgQSxXM89XwS1Tkic7csPdndUuTKabEwRcEfR8uQ/iPA3Dgio1rqsV3jtqZhY0QQni8rLswJM2w==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.14.1.tgz", + "integrity": "sha512-M8+7MbzKC1PvJIA8kR2sSBnex8bsR5auatLCnVlNTJczmJgqRn8M+sAlQfkEq7M4IY3WmaNJ+LJjPVRrREVSHQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.14.1", + "@typescript-eslint/visitor-keys": "4.14.1", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.14.1.tgz", + "integrity": "sha512-TAblbDXOI7bd0C/9PE1G+AFo7R5uc+ty1ArDoxmrC1ah61Hn6shURKy7gLdRb1qKJmjHkqu5Oq+e4Kt0jwf1IA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.14.1", + "eslint-visitor-keys": "^2.0.0" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true + }, + "fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globby": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", + "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, "@typescript-eslint/experimental-utils": { "version": "4.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.0.tgz", @@ -4157,6 +4416,205 @@ } } }, + "@typescript-eslint/parser": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-4.14.1.tgz", + "integrity": "sha512-mL3+gU18g9JPsHZuKMZ8Z0Ss9YP1S5xYZ7n68Z98GnPq02pYNQuRXL85b9GYhl6jpdvUc45Km7hAl71vybjUmw==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "4.14.1", + "@typescript-eslint/types": "4.14.1", + "@typescript-eslint/typescript-estree": "4.14.1", + "debug": "^4.1.1" + }, + "dependencies": { + "@nodelib/fs.stat": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.4.tgz", + "integrity": "sha512-IYlHJA0clt2+Vg7bccq+TzRdJvv19c2INqBSsoOLp1je7xjtr7J26+WXR72MCdvU9q1qTzIWDfhMf+DRvQJK4Q==", + "dev": true + }, + "@typescript-eslint/scope-manager": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.14.1.tgz", + "integrity": "sha512-F4bjJcSqXqHnC9JGUlnqSa3fC2YH5zTtmACS1Hk+WX/nFB0guuynVK5ev35D4XZbdKjulXBAQMyRr216kmxghw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.14.1", + "@typescript-eslint/visitor-keys": "4.14.1" + } + }, + "@typescript-eslint/types": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.14.1.tgz", + "integrity": "sha512-SkhzHdI/AllAgQSxXM89XwS1Tkic7csPdndUuTKabEwRcEfR8uQ/iPA3Dgio1rqsV3jtqZhY0QQni8rLswJM2w==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.14.1.tgz", + "integrity": "sha512-M8+7MbzKC1PvJIA8kR2sSBnex8bsR5auatLCnVlNTJczmJgqRn8M+sAlQfkEq7M4IY3WmaNJ+LJjPVRrREVSHQ==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.14.1", + "@typescript-eslint/visitor-keys": "4.14.1", + "debug": "^4.1.1", + "globby": "^11.0.1", + "is-glob": "^4.0.1", + "lodash": "^4.17.15", + "semver": "^7.3.2", + "tsutils": "^3.17.1" + } + }, + "@typescript-eslint/visitor-keys": { + "version": "4.14.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.14.1.tgz", + "integrity": "sha512-TAblbDXOI7bd0C/9PE1G+AFo7R5uc+ty1ArDoxmrC1ah61Hn6shURKy7gLdRb1qKJmjHkqu5Oq+e4Kt0jwf1IA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "4.14.1", + "eslint-visitor-keys": "^2.0.0" + } + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "eslint-visitor-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz", + "integrity": "sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==", + "dev": true + }, + "fast-glob": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.5.tgz", + "integrity": "sha512-2DtFcgT68wiTTiwZ2hNdJfcHNke9XOfnwmBRWXhmeKM8rF0TGwmC/Qto3S7RoZKp5cilZbxzO5iTNTQsJ+EeDg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.0", + "merge2": "^1.3.0", + "micromatch": "^4.0.2", + "picomatch": "^2.2.1" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globby": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.2.tgz", + "integrity": "sha512-2ZThXDvvV8fYFRVIxnrMQBipZQDr7MxKAmQK1vujaj9/7eF0efG7BPUKJ7jP7G5SLF37xKDXvO4S/KKLj/Z0og==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.1.1", + "ignore": "^5.1.4", + "merge2": "^1.3.0", + "slash": "^3.0.0" + } + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "micromatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", + "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.0.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz", + "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, "@typescript-eslint/scope-manager": { "version": "4.15.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.15.0.tgz", @@ -11661,12 +12119,12 @@ "dev": true }, "core-js-compat": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.8.3.tgz", - "integrity": "sha512-1sCb0wBXnBIL16pfFG1Gkvei6UzvKyTNYpiC41yrdjEv0UoJoq9E/abTMzyYJ6JpTkAj15dLjbqifIzEBDVvog==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.9.0.tgz", + "integrity": "sha512-YK6fwFjCOKWwGnjFUR3c544YsnA/7DoLL0ysncuOJ4pwbriAtOpvM2bygdlcXbvQCQZ7bBU9CL4t7tGl7ETRpQ==", "dev": true, "requires": { - "browserslist": "^4.16.1", + "browserslist": "^4.16.3", "semver": "7.0.0" }, "dependencies": { @@ -13976,6 +14434,36 @@ "resolve": "^1.13.1" } }, + "eslint-import-resolver-typescript": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-2.3.0.tgz", + "integrity": "sha512-MHSXvmj5e0SGOOBhBbt7C+fWj1bJbtSYFAD85Xeg8nvUtuooTod2HQb8bfhE9f5QyyNxEfgzqOYFCvmdDIcCuw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "glob": "^7.1.6", + "is-glob": "^4.0.1", + "resolve": "^1.17.0", + "tsconfig-paths": "^3.9.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, "eslint-import-resolver-webpack": { "version": "0.13.0", "resolved": "https://registry.npmjs.org/eslint-import-resolver-webpack/-/eslint-import-resolver-webpack-0.13.0.tgz", @@ -31879,9 +32367,9 @@ } }, "typescript": { - "version": "3.9.7", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", - "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.1.3.tgz", + "integrity": "sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==", "dev": true }, "ua-parser-js": { @@ -33438,6 +33926,15 @@ "uuid": "^7.0.2" }, "dependencies": { + "@types/react": { + "version": "16.14.4", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.4.tgz", + "integrity": "sha512-ETj7GbkPGjca/A4trkVeGvoIakmLV6ZtX3J8dcmOpzKzWVybbrOxanwaIPG71GZwImoMDY6Fq4wIe34lEqZ0FQ==", + "requires": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, "@wordpress/compose": { "version": "3.24.3", "resolved": "https://registry.npmjs.org/@wordpress/compose/-/compose-3.24.3.tgz", @@ -33543,6 +34040,11 @@ "lodash": "^4.17.19" } }, + "csstype": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.6.tgz", + "integrity": "sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw==" + }, "downshift": { "version": "5.4.7", "resolved": "https://registry.npmjs.org/downshift/-/downshift-5.4.7.tgz", @@ -33582,6 +34084,15 @@ "use-memo-one": "^1.1.1" }, "dependencies": { + "@types/react": { + "version": "16.14.4", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.4.tgz", + "integrity": "sha512-ETj7GbkPGjca/A4trkVeGvoIakmLV6ZtX3J8dcmOpzKzWVybbrOxanwaIPG71GZwImoMDY6Fq4wIe34lEqZ0FQ==", + "requires": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, "@wordpress/deprecated": { "version": "2.11.1", "resolved": "https://registry.npmjs.org/@wordpress/deprecated/-/deprecated-2.11.1.tgz", @@ -33646,6 +34157,11 @@ "lodash": "^4.17.19" } }, + "csstype": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.6.tgz", + "integrity": "sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw==" + }, "lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", @@ -33667,6 +34183,20 @@ "react-dom": "^16.13.1" }, "dependencies": { + "@types/react": { + "version": "16.14.4", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.4.tgz", + "integrity": "sha512-ETj7GbkPGjca/A4trkVeGvoIakmLV6ZtX3J8dcmOpzKzWVybbrOxanwaIPG71GZwImoMDY6Fq4wIe34lEqZ0FQ==", + "requires": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "csstype": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.6.tgz", + "integrity": "sha512-+ZAmfyWMT7TiIlzdqJgjMb7S4f1beorDbWbsocyK4RaiqA5RTX3K14bnBWmmA9QEM0gRdsjyyrEmcyga8Zsxmw==" + }, "lodash": { "version": "4.17.20", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", diff --git a/plugins/woocommerce-blocks/package.json b/plugins/woocommerce-blocks/package.json index 126e6af8679..25a6d0e1fbc 100644 --- a/plugins/woocommerce-blocks/package.json +++ b/plugins/woocommerce-blocks/package.json @@ -40,9 +40,9 @@ "lint:ci": "npm run lint:js && npm run lint:css", "lint:css": "stylelint 'assets/**/*.scss'", "lint:css-fix": "stylelint 'assets/**/*.scss' --fix", - "lint:js": "wp-scripts lint-js", - "lint:js:report": "npm run lint:js -- --output-file eslint_report.json --format json", - "lint:js-fix": "eslint assets/js --ext=js,jsx --fix", + "lint:js": "wp-scripts lint-js --ext=js,ts,tsx", + "lint:js:report": "npm run lint:js -- --output-file eslint_report.json --ext=js,ts,tsx --format json", + "lint:js-fix": "eslint assets/js --ext=js,jsx,ts,tsx --fix", "lint:php": "composer run-script phpcs ./src", "package-plugin": "rimraf woocommerce-gutenberg-products-block.zip && ./bin/build-plugin-zip.sh", "package-plugin:dev": "rimraf woocommerce-gutenberg-products-block.zip && ./bin/build-plugin-zip.sh -d", @@ -61,6 +61,7 @@ "test:help": "wp-scripts test-unit-js --help", "test:update": "wp-scripts test-unit-js --updateSnapshot --config tests/js/jest.config.json", "test:watch": "npm run test -- --watch", + "ts:check": "tsc --build", "wp-env": "wp-env", "wp-env:config": "./bin/wp-env-pre-config.sh" }, @@ -71,6 +72,7 @@ "@babel/plugin-proposal-class-properties": "7.12.13", "@babel/polyfill": "7.12.1", "@babel/preset-env": "7.12.16", + "@babel/preset-typescript": "^7.12.7", "@octokit/graphql": "4.6.0", "@storybook/addon-a11y": "6.0.28", "@storybook/addon-actions": "6.0.28", @@ -86,9 +88,14 @@ "@testing-library/react-hooks": "^5.0.3", "@testing-library/user-event": "12.6.3", "@types/jest": "26.0.20", - "@types/react": "16.14.3", + "@types/lodash": "^4.14.168", + "@types/react": "16.14.2", + "@types/wordpress__api-fetch": "^3.2.3", "@types/wordpress__data": "4.6.9", + "@types/wordpress__data-controls": "^1.0.4", "@types/wordpress__element": "2.4.1", + "@typescript-eslint/eslint-plugin": "^4.14.1", + "@typescript-eslint/parser": "^4.14.1", "@woocommerce/eslint-plugin": "1.1.0", "@woocommerce/woocommerce-rest-api": "1.0.1", "@wordpress/babel-preset-default": "4.18.1", @@ -103,7 +110,7 @@ "@wordpress/element": "2.17.1", "@wordpress/env": "3.0.0", "@wordpress/html-entities": "2.8.0", - "@wordpress/i18n": "3.15.0", + "@wordpress/i18n": "^3.15.0", "@wordpress/is-shallow-equal": "^1.8.0", "@wordpress/scripts": "13.0.1", "autoprefixer": "10.2.3", @@ -120,7 +127,8 @@ "cross-env": "6.0.3", "cssnano": "4.1.10", "deep-freeze": "0.0.1", - "eslint-import-resolver-webpack": "0.13.0", + "eslint-import-resolver-typescript": "^2.3.0", + "eslint-import-resolver-webpack": "^0.13.0", "eslint-plugin-import": "2.22.1", "eslint-plugin-woocommerce": "file:bin/eslint-plugin-woocommerce", "eslint-plugin-you-dont-need-lodash-underscore": "6.10.0", @@ -145,7 +153,7 @@ "rimraf": "3.0.2", "sass-loader": "10.1.0", "source-map-explorer": "2.5.1", - "typescript": "3.9.7", + "typescript": "^4.1.3", "webpack": "4.44.2", "webpack-cli": "3.3.12", "webpack-rtl-plugin": "2.0.0", @@ -190,7 +198,7 @@ "*.scss": [ "npm run lint:css" ], - "*.js": [ + "*.{js,ts,tsx}": [ "prettier --write", "npm run lint:js" ], diff --git a/plugins/woocommerce-blocks/tsconfig.base.json b/plugins/woocommerce-blocks/tsconfig.base.json new file mode 100644 index 00000000000..caa64202bfd --- /dev/null +++ b/plugins/woocommerce-blocks/tsconfig.base.json @@ -0,0 +1,55 @@ +{ + "exclude": [ "node_modules"], + "compilerOptions": { + "outDir": "./build", + "sourceMap": true, + "baseUrl": ".", + "module": "esnext", + "emitDeclarationOnly": true, + // Import non-ES modules as default imports. + "esModuleInterop": true, + "resolveJsonModule": true, + // Preserve JSX, allows compatibility with wp-element jsx babel transforms + "jsx": "preserve", + "target": "esnext", + "allowJs": true, + "moduleResolution": "node", + "lib": [ "dom", "esnext" ], + "checkJs": true, + "strict": true, + "strictNullChecks": true, + "allowSyntheticDefaultImports": true, + "composite": true, + "rootDir": ".", + "typeRoots": [ "./node_modules/@types" ], + "types": [], + "paths": { + "@woocommerce/atomic-blocks": [ "assets/js/base/atomic/blocks" ], + "@woocommerce/atomic-blocks/*": [ + "assets/js/base/atomic/blocks/*" + ], + "@woocommerce/atomic-utils": [ "assets/js/atomic/utils" ], + "@woocommerce/base-components/*": [ "assets/js/base/components/*" ], + "@woocommerce/base-context": [ "assets/js/base/context" ], + "@woocommerce/base-hocs/*": [ "assets/js/base/hocs/*" ], + "@woocommerce/base-hooks": [ "assets/js/base/hooks" ], + "@woocommerce/base-utils": [ "assets/js/base/utils" ], + "@woocommerce/editor-components/*": [ + "assets/js/editor-components/*" + ], + "@woocommerce/block-data": [ "assets/js/data" ], + "@woocommerce/block-hocs": [ "assets/js/hocs" ], + "@woocommerce/blocks-registry": [ "assets/js/blocks-registry" ], + "@woocommerce/blocks-checkout": [ "packages/checkout" ], + "@woocommerce/block-settings": [ "assets/js/settings/blocks" ], + "@woocommerce/e2e-tests": [ "node_modules/woocommerce/tests/e2e" ], + "@woocommerce/icons": [ "assets/js/icons" ], + "@woocommerce/resource-previews": [ "assets/js/previews" ], + "@woocommerce/knobs": [ "storybook/knobs" ], + "@woocommerce/settings": [ "assets/js/settings/shared" ], + "@woocommerce/shared-context": [ "assets/js/shared/context" ], + "@woocommerce/type-defs/*": [ "assets/js/type-defs/*" ], + "@woocommerce/types": [ "assets/js/type-defs" ] + } + } +} diff --git a/plugins/woocommerce-blocks/tsconfig.json b/plugins/woocommerce-blocks/tsconfig.json index 035a8f7e69f..11b49cdc5de 100644 --- a/plugins/woocommerce-blocks/tsconfig.json +++ b/plugins/woocommerce-blocks/tsconfig.json @@ -1,50 +1,6 @@ { - "compilerOptions": { - "baseUrl": ".", - "module": "commonjs", - "moduleResolution": "node", - "lib": [ "dom", "esnext" ], - "allowJs": true, - "checkJs": true, - "noEmit": true, - "traceResolution": true, - "strictNullChecks": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - "jsx": "preserve", - "allowSyntheticDefaultImports": true, - "paths": { - "@woocommerce/atomic-blocks": [ "assets/js/base/atomic/blocks" ], - "@woocommerce/atomic-blocks/*": [ - "assets/js/base/atomic/blocks/*" - ], - "@woocommerce/atomic-utils": [ "assets/js/atomic/utils" ], - "@woocommerce/base-components/*": [ "assets/js/base/components/*" ], - "@woocommerce/base-context": [ "assets/js/base/context" ], - "@woocommerce/base-hocs/*": [ "assets/js/base/hocs/*" ], - "@woocommerce/base-hooks": [ "assets/js/base/hooks" ], - "@woocommerce/base-utils": [ "assets/js/base/utils" ], - "@woocommerce/editor-components/*": [ - "assets/js/editor-components/*" - ], - "@woocommerce/block-data": [ "assets/js/data" ], - "@woocommerce/block-hocs": [ "assets/js/hocs" ], - "@woocommerce/blocks-registry": [ "assets/js/blocks-registry" ], - "@woocommerce/blocks-checkout": [ "packages/checkout" ], - "@woocommerce/price-format": [ "packages/prices" ], - "@woocommerce/block-settings": [ "assets/js/settings/blocks" ], - "@woocommerce/e2e-tests": [ - "node_modules/woocommerce/tests/e2e" - ], - "@woocommerce/icons": [ "assets/js/icons" ], - "@woocommerce/resource-previews": [ "assets/js/previews" ], - "@woocommerce/knobs": [ "storybook/knobs" ], - "@woocommerce/settings": [ "assets/js/settings/shared" ], - "@woocommerce/shared-context": [ "assets/js/shared/context" ], - "@woocommerce/type-defs/*": [ "assets/js/type-defs/*" ] - } - }, - "include": [ "./assets/js/**/*.js", "./globals.d.ts" ] + "extends": "./tsconfig.base.json", + "include": [ "./assets/js/**/*" ], + "exclude": [ "./assets/js/data" ], + "references": [ { "path": "./assets/js/data" } ] }