Fix TypeScript build for `packages` and add types for wc/data's onboarding store (https://github.com/woocommerce/woocommerce-admin/pull/6595)

This commit is contained in:
Sam Seay 2021-03-25 10:29:37 +13:00 committed by GitHub
parent babb964ca7
commit cc01b9816e
29 changed files with 336 additions and 142 deletions

View File

@ -63,10 +63,12 @@ const isScssFile = ( filepath ) => {
* @return {string} Build path
*/
function getBuildPath( file, buildFolder ) {
const pkgName = getPackageName( file );
// if the file has extension of ts, replace with js
const fileName = file.replace( '.ts', '.js' );
const pkgName = getPackageName( fileName );
const pkgSrcPath = path.resolve( PACKAGES_DIR, pkgName, SRC_DIR );
const pkgBuildPath = path.resolve( PACKAGES_DIR, pkgName, buildFolder );
const relativeToSrcPath = path.relative( pkgSrcPath, file );
const relativeToSrcPath = path.relative( pkgSrcPath, fileName );
return path.resolve( pkgBuildPath, relativeToSrcPath );
}
@ -198,7 +200,7 @@ function buildJsFileFor( file, silent, environment ) {
*/
async function buildPackage( packagePath ) {
const srcDir = path.resolve( packagePath, SRC_DIR );
const jsFiles = glob.sync( `${ srcDir }/**/*.js`, {
const jsFiles = glob.sync( `${ srcDir }/**/*.{ts,tsx,js}`, {
ignore: [
`${ srcDir }/**/test/**/*.js`,
`${ srcDir }/**/__mocks__/**/*.js`,
@ -212,7 +214,9 @@ async function buildPackage( packagePath ) {
process.stdout.write( `${ path.basename( packagePath ) }\n` );
// Build js files individually.
jsFiles.forEach( ( file ) => buildJsFile( file, true ) );
jsFiles.forEach( ( file ) => {
buildJsFile( file, true );
} );
process.stdout.write( `${ DONE }\n` );
}

View File

@ -22,13 +22,16 @@ const overrideOptions = ( target, targetName, options ) => {
const babelConfigs = {
main: Object.assign( {}, babelDefaultConfig, {
plugins,
presets: map( babelDefaultConfig.presets, ( preset ) =>
overrideOptions( preset, '@babel/preset-env', {
modules: 'commonjs',
corejs: '3',
useBuiltIns: 'usage',
} )
),
presets: [
[ '@babel/preset-typescript' ],
...map( babelDefaultConfig.presets, ( preset ) =>
overrideOptions( preset, '@babel/preset-env', {
modules: 'commonjs',
corejs: '3',
useBuiltIns: 'usage',
} )
),
],
} ),
module: Object.assign( {}, babelDefaultConfig, {
plugins: map( plugins, ( plugin ) =>
@ -36,13 +39,16 @@ const babelConfigs = {
useESModules: true,
} )
),
presets: map( babelDefaultConfig.presets, ( preset ) =>
overrideOptions( preset, '@babel/preset-env', {
modules: false,
corejs: '3',
useBuiltIns: 'usage',
} )
),
presets: [
[ '@babel/preset-typescript' ],
...map( babelDefaultConfig.presets, ( preset ) =>
overrideOptions( preset, '@babel/preset-env', {
modules: false,
corejs: '3',
useBuiltIns: 'usage',
} )
),
],
} ),
};

View File

@ -2,14 +2,6 @@
* External dependencies
*/
import { Component, Suspense, lazy } from '@wordpress/element';
import { compose } from '@wordpress/compose';
import { withSelect } from '@wordpress/data';
import { identity } from 'lodash';
import { getSetting } from '@woocommerce/wc-admin-settings';
import {
ONBOARDING_STORE_NAME,
withOnboardingHydration,
} from '@woocommerce/data';
import { Spinner } from '@woocommerce/components';
/**
@ -37,16 +29,4 @@ class Dashboard extends Component {
}
}
const onboardingData = getSetting( 'onboarding', {} );
export default compose(
!! onboardingData.tasksStatus
? withOnboardingHydration( { tasksStatus: onboardingData.tasksStatus } )
: identity,
withSelect( ( select ) => {
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
const profileItems = getProfileItems();
return { profileItems };
} )
)( Dashboard );
export default Dashboard;

View File

@ -8,19 +8,26 @@ import { getSetting } from '@woocommerce/wc-admin-settings';
import {
ONBOARDING_STORE_NAME,
withOnboardingHydration,
WCDataSelector,
} from '@woocommerce/data';
import { getHistory, getNewPath } from '@woocommerce/navigation';
import type { History } from 'history';
/**
* Internal dependencies
*/
import Layout from './layout';
const Homescreen = ( { profileItems, query } ) => {
type HomescreenProps = ReturnType< typeof withSelectHandler > & {
query: Record< string, string >;
};
const Homescreen = ( { profileItems, query }: HomescreenProps ) => {
const { completed: profilerCompleted, skipped: profilerSkipped } =
profileItems || {};
if ( ! profilerCompleted && ! profilerSkipped ) {
getHistory().push( getNewPath( {}, '/setup-wizard', {} ) );
( getHistory() as History ).push(
getNewPath( {}, '/setup-wizard', {} )
);
}
return <Layout query={ query } />;
@ -28,6 +35,13 @@ const Homescreen = ( { profileItems, query } ) => {
const onboardingData = getSetting( 'onboarding', {} );
const withSelectHandler = ( select: WCDataSelector ) => {
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
const profileItems = getProfileItems();
return { profileItems };
};
export default compose(
onboardingData.profile || onboardingData.tasksStatus
? withOnboardingHydration( {
@ -35,10 +49,5 @@ export default compose(
tasksStatus: onboardingData.tasksStatus,
} )
: identity,
withSelect( ( select ) => {
const { getProfileItems } = select( ONBOARDING_STORE_NAME );
const profileItems = getProfileItems();
return { profileItems };
} )
withSelect( withSelectHandler )
)( Homescreen );

View File

@ -9139,6 +9139,12 @@
"@types/unist": "*"
}
},
"@types/history": {
"version": "4.7.8",
"resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.8.tgz",
"integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==",
"dev": true
},
"@types/html-minifier-terser": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz",
@ -9315,6 +9321,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",

View File

@ -156,7 +156,9 @@
"@testing-library/react-hooks": "3.7.0",
"@testing-library/user-event": "12.8.3",
"@types/expect-puppeteer": "^4.4.5",
"@types/history": "^4.7.8",
"@types/jest": "^26.0.20",
"@types/lodash": "^4.14.168",
"@types/puppeteer": "^5.4.3",
"@typescript-eslint/eslint-plugin": "4.19.0",
"@woocommerce/api": "^0.1.1",

View File

@ -27,5 +27,8 @@
},
"publishConfig": {
"access": "public"
},
"peerDependencies": {
"@wordpress/core-data": "^2.24.2"
}
}

View File

@ -1,62 +0,0 @@
/**
* External dependencies
*/
import '@wordpress/core-data';
export { SETTINGS_STORE_NAME } from './settings';
export { withSettingsHydration } from './settings/with-settings-hydration';
export { useSettings } from './settings/use-settings';
export { PLUGINS_STORE_NAME } from './plugins';
export { pluginNames } from './plugins/constants';
export { withPluginsHydration } from './plugins/with-plugins-hydration';
export { ONBOARDING_STORE_NAME } from './onboarding';
export { withOnboardingHydration } from './onboarding/with-onboarding-hydration';
export { USER_STORE_NAME } from './user';
export { withCurrentUserHydration } from './user/with-current-user-hydration';
export { useUser } from './user/use-user';
export { useUserPreferences } from './user/use-user-preferences';
export { OPTIONS_STORE_NAME } from './options';
export { withOptionsHydration } from './options/with-options-hydration';
export { REVIEWS_STORE_NAME } from './reviews';
export { NOTES_STORE_NAME } from './notes';
export { REPORTS_STORE_NAME } from './reports';
export { ITEMS_STORE_NAME } from './items';
export { getLeaderboard, searchItemsByString } from './items/utils';
export { NAVIGATION_STORE_NAME } from './navigation';
export { withNavigationHydration } from './navigation/with-navigation-hydration';
export {
getFilterQuery,
getSummaryNumbers,
getReportTableData,
getReportTableQuery,
getReportChartData,
getTooltipValueFormat,
} from './reports/utils';
export {
MAX_PER_PAGE,
QUERY_DEFAULTS,
NAMESPACE,
WC_ADMIN_NAMESPACE,
WCS_NAMESPACE,
SECOND,
MINUTE,
HOUR,
DAY,
WEEK,
MONTH,
} from './constants';
export { EXPORT_STORE_NAME } from './export';
export { IMPORT_STORE_NAME } from './import';

View File

@ -0,0 +1,119 @@
/**
* External dependencies
*/
import '@wordpress/core-data';
/**
* Internal dependencies
*/
import type { REVIEWS_STORE_NAME } from './reviews';
import type { SETTINGS_STORE_NAME } from './settings';
import type { PLUGINS_STORE_NAME } from './plugins';
import type { ONBOARDING_STORE_NAME } from './onboarding';
import type { USER_STORE_NAME } from './user';
import type { OPTIONS_STORE_NAME } from './options';
import type { NAVIGATION_STORE_NAME } from './navigation';
import type { NOTES_STORE_NAME } from './notes';
import type { REPORTS_STORE_NAME } from './reports';
import type { ITEMS_STORE_NAME } from './items';
import { OnboardingSelectors } from './onboarding/selectors';
import { WPDataSelectors } from './types';
export { SETTINGS_STORE_NAME } from './settings';
export { withSettingsHydration } from './settings/with-settings-hydration';
export { useSettings } from './settings/use-settings';
export { PLUGINS_STORE_NAME } from './plugins';
export { pluginNames } from './plugins/constants';
export { withPluginsHydration } from './plugins/with-plugins-hydration';
export { ONBOARDING_STORE_NAME } from './onboarding';
export { withOnboardingHydration } from './onboarding/with-onboarding-hydration';
export { USER_STORE_NAME } from './user';
export { withCurrentUserHydration } from './user/with-current-user-hydration';
export { useUser } from './user/use-user';
export { useUserPreferences } from './user/use-user-preferences';
export { OPTIONS_STORE_NAME } from './options';
export { withOptionsHydration } from './options/with-options-hydration';
export { REVIEWS_STORE_NAME } from './reviews';
export { NOTES_STORE_NAME } from './notes';
export { REPORTS_STORE_NAME } from './reports';
export { ITEMS_STORE_NAME } from './items';
export { getLeaderboard, searchItemsByString } from './items/utils';
export { NAVIGATION_STORE_NAME } from './navigation';
export { withNavigationHydration } from './navigation/with-navigation-hydration';
export {
getFilterQuery,
getSummaryNumbers,
getReportTableData,
getReportTableQuery,
getReportChartData,
getTooltipValueFormat,
} from './reports/utils';
export {
MAX_PER_PAGE,
QUERY_DEFAULTS,
NAMESPACE,
WC_ADMIN_NAMESPACE,
WCS_NAMESPACE,
SECOND,
MINUTE,
HOUR,
DAY,
WEEK,
MONTH,
} from './constants';
export { EXPORT_STORE_NAME } from './export';
export { IMPORT_STORE_NAME } from './import';
type WCDataStoreName =
| typeof REVIEWS_STORE_NAME
| typeof SETTINGS_STORE_NAME
| typeof PLUGINS_STORE_NAME
| typeof ONBOARDING_STORE_NAME
| typeof USER_STORE_NAME
| typeof OPTIONS_STORE_NAME
| typeof NAVIGATION_STORE_NAME
| typeof NOTES_STORE_NAME
| typeof REPORTS_STORE_NAME
| typeof ITEMS_STORE_NAME;
// As we add types to all the package selectors we can fill out these unknown types with real ones. See one
// of the already typed selectors for an example of how you can do this.
type WCSelectorType< T > = T extends typeof REVIEWS_STORE_NAME
? WPDataSelectors
: T extends typeof SETTINGS_STORE_NAME
? WPDataSelectors
: T extends typeof PLUGINS_STORE_NAME
? WPDataSelectors
: T extends typeof ONBOARDING_STORE_NAME
? OnboardingSelectors
: T extends typeof USER_STORE_NAME
? WPDataSelectors
: T extends typeof OPTIONS_STORE_NAME
? WPDataSelectors
: T extends typeof NAVIGATION_STORE_NAME
? WPDataSelectors
: T extends typeof NOTES_STORE_NAME
? WPDataSelectors
: T extends typeof REPORTS_STORE_NAME
? WPDataSelectors
: T extends typeof ITEMS_STORE_NAME
? WPDataSelectors
: never;
export interface WCDataSelector {
< T extends WCDataStoreName >( storeName: T ): WCSelectorType< T >;
}
export * from './onboarding/selectors';

View File

@ -3,13 +3,29 @@
*/
import TYPES from './action-types';
const onboarding = (
state = {
errors: {},
profileItems: {},
requesting: {},
tasksStatus: {},
export const defaultState = {
errors: {},
profileItems: {
business_extensions: null,
completed: null,
industry: null,
other_platform: null,
other_platform_name: null,
product_count: null,
product_types: null,
revenue: null,
selling_venues: null,
setup_client: null,
skipped: null,
theme: null,
wccom_connected: null,
},
requesting: {},
tasksStatus: {},
};
const onboarding = (
state = defaultState,
{ type, profileItems, replace, error, isRequesting, selector, tasksStatus }
) => {
switch ( type ) {

View File

@ -1,15 +0,0 @@
export const getProfileItems = ( state ) => {
return state.profileItems || {};
};
export const getTasksStatus = ( state ) => {
return state.tasksStatus || {};
};
export const getOnboardingError = ( state, selector ) => {
return state.errors[ selector ] || false;
};
export const isOnboardingRequesting = ( state, selector ) => {
return state.requesting[ selector ] || false;
};

View File

@ -0,0 +1,114 @@
/**
* Internal dependencies
*/
import { WPDataSelectors } from '../types';
export const getProfileItems = (
state: OnboardingState
): ProfileItemsState | Record< string, never > => {
return state.profileItems || {};
};
export const getTasksStatus = (
state: OnboardingState
): TasksStatusState | Record< string, never > => {
return state.tasksStatus || {};
};
export const getOnboardingError = (
state: OnboardingState,
selector: string
): unknown | false => {
return state.errors[ selector ] || false;
};
export const isOnboardingRequesting = (
state: OnboardingState,
selector: string
): boolean => {
return state.requesting[ selector ] || false;
};
// Types
export type OnboardingSelectors = {
getProfileItems: () => ReturnType< typeof getProfileItems >;
getTasksStatus: () => ReturnType< typeof getTasksStatus >;
getOnboardingError: () => ReturnType< typeof getOnboardingError >;
isOnboardingRequesting: () => ReturnType< typeof isOnboardingRequesting >;
} & WPDataSelectors;
export type OnboardingState = {
profileItems: ProfileItemsState;
tasksStatus: TasksStatusState;
// TODO clarify what the error record's type is
errors: Record< string, unknown >;
requesting: Record< string, boolean >;
};
export type TasksStatusState = {
automatedTaxSupportedCountries: string[];
enabledPaymentGateways: string[];
hasHomepage: boolean;
hasPaymentGateway: boolean;
hasPhysicalProducts: boolean;
hasProducts: boolean;
isAppearanceComplete: boolean;
isTaxComplete: boolean;
shippingZonesCount: number;
stripeSupportedCountries: string[];
stylesheet: string;
taxJarActivated: boolean;
// TODO - fill out this type
themeMods: unknown;
wcPayIsConnected: false;
};
export type Industry = {
slug: string;
};
export type ProductCount = '0' | '1-10' | '11-100' | '101 - 1000' | '1000+';
export type ProductTypeSlug =
| 'physical'
| 'bookings'
| 'download'
| 'memberships'
| 'product-add-ons'
| 'product-bundles'
| 'subscriptions';
export type OtherPlatformSlug =
| 'shopify'
| 'bigcommerce'
| 'wix'
| 'amazon'
| 'ebay'
| 'etsy'
| 'squarespace'
| 'other';
export type RevenueTypeSlug =
| 'none'
| 'rather-not-say'
| 'up-to-2500'
| '2500-10000'
| '10000-50000'
| '50000-250000'
| 'more-than-250000';
export type ProfileItemsState = {
business_extensions: [ ] | null;
completed: boolean | null;
industry: Industry[] | null;
other_platform: OtherPlatformSlug | null;
other_platform_name: string | null;
product_count: ProductCount | null;
product_types: ProductTypeSlug[] | null;
revenue: RevenueTypeSlug | null;
selling_venues: string | null;
setup_client: boolean | null;
skipped: boolean | null;
theme: string | null;
wccom_connected: boolean | null;
};

View File

@ -5,21 +5,13 @@
/**
* Internal dependencies
*/
import reducer from '../reducer';
import reducer, { defaultState } from '../reducer';
import TYPES from '../action-types';
const defaultState = {
errors: {},
profileItems: {},
requesting: {},
tasksStatus: {},
};
describe( 'plugins reducer', () => {
it( 'should return a default state', () => {
const state = reducer( undefined, {} );
expect( state ).toEqual( defaultState );
expect( state ).not.toBe( defaultState );
} );
it( 'should handle SET_PROFILE_ITEMS', () => {

View File

@ -0,0 +1,8 @@
// Type for the basic selectors built into @wordpress/data, note these
// types define the interface for the public selectors, so state is not an
// argument.
export type WPDataSelectors = {
hasStartedResolution: ( selector: string, args?: string[] ) => boolean;
hasFinishedResolution: ( selector: string, args?: string[] ) => boolean;
isResolving: ( selector: string, args: [ ] ) => boolean;
};

View File

@ -27,7 +27,7 @@
"**/?(*.)test.[jt]s"
],
"transform": {
"^.+\\.[t|j]s?$": "babel-jest"
"^.+\\.[jt]sx?$": "babel-jest"
},
"testPathIgnorePatterns": [
"/node_modules/",

View File

@ -1 +1,3 @@
declare module '@woocommerce/e2e-utils';
declare module '@wordpress/data';
declare module '@wordpress/compose';

View File

@ -88,7 +88,11 @@ const webpackConfig = {
},
{
test: /\.(t|j)sx?$/,
exclude: /node_modules(\/|\\)(?!(debug))/,
exclude: [
/node_modules(\/|\\)(?!(debug))/,
/build/,
/build-module/,
],
use: {
loader: 'babel-loader',
options: {