diff --git a/plugins/woocommerce-admin/.eslintrc.js b/plugins/woocommerce-admin/.eslintrc.js index 878756104aa..081febe5a43 100644 --- a/plugins/woocommerce-admin/.eslintrc.js +++ b/plugins/woocommerce-admin/.eslintrc.js @@ -1,5 +1,6 @@ module.exports = { - extends: [ 'plugin:@woocommerce/eslint-plugin/recommended' ], + extends: [ 'plugin:@woocommerce/eslint-plugin/recommended', 'plugin:xstate/all' ], + plugins: [ 'xstate' ], root: true, overrides: [ { diff --git a/plugins/woocommerce-admin/client/core-profiler/index.tsx b/plugins/woocommerce-admin/client/core-profiler/index.tsx index ff6ed1e02d2..52f1d89dd28 100644 --- a/plugins/woocommerce-admin/client/core-profiler/index.tsx +++ b/plugins/woocommerce-admin/client/core-profiler/index.tsx @@ -14,13 +14,6 @@ import { UserProfile } from './pages/UserProfile'; import { BusinessInfo } from './pages/BusinessInfo'; import { BusinessLocation } from './pages/BusinessLocation'; -/** Uncomment below to display xstate inspector during development */ -// import { inspect } from '@xstate/inspect'; -// inspect( { -// // url: 'https://stately.ai/viz?inspect', // (default) -// iframe: false, // open in new window -// } ); - // TODO: Typescript support can be improved, but for now lets write the types ourselves // https://stately.ai/blog/introducing-typescript-typegen-for-xstate diff --git a/plugins/woocommerce-admin/client/index.js b/plugins/woocommerce-admin/client/index.js index 67173157a26..9feefdbba9e 100644 --- a/plugins/woocommerce-admin/client/index.js +++ b/plugins/woocommerce-admin/client/index.js @@ -18,6 +18,7 @@ import { PageLayout, EmbedLayout, PrimaryLayout as NoticeArea } from './layout'; import { EmbeddedBodyLayout } from './embedded-body-layout'; import { WcAdminPaymentsGatewaysBannerSlot } from './payments/payments-settings-banner-slotfill'; import { WcAdminConflictErrorSlot } from './settings/conflict-error-slotfill.js'; +import './xstate.js'; // Modify webpack pubilcPath at runtime based on location of WordPress Plugin. // eslint-disable-next-line no-undef,camelcase diff --git a/plugins/woocommerce-admin/client/xstate.js b/plugins/woocommerce-admin/client/xstate.js new file mode 100644 index 00000000000..0b115a91fe4 --- /dev/null +++ b/plugins/woocommerce-admin/client/xstate.js @@ -0,0 +1,30 @@ +/** + * This script configures the XState development tools in the + * development environment. It should not be included in production. + * + * To enable the XState inspector, open the browser console and type: + * localStorage.setItem("xstate_inspect", "true") + */ + +async function enableXStateInspect() { + const { inspect } = await import( '@xstate/inspect' ); + const { Interpreter } = await import( 'xstate' ); + // configure the XState inspector to open in a new tab + inspect( { + url: 'https://stately.ai/viz?inspect', + iframe: false, + } ); + // configure all XServices to use the inspector + Interpreter.defaultOptions.devTools = true; + // eslint-disable-next-line no-console + console.log( + 'Devtools: XState inspector enabled for WooCommerce Admin. To disable, type localStorage.setItem("xstate_inspect", "false")' + ); +} + +if ( + process.env.NODE_ENV === 'development' && + window.localStorage.getItem( 'xstate_inspect' ) === 'true' +) { + enableXStateInspect(); +} diff --git a/plugins/woocommerce-admin/package.json b/plugins/woocommerce-admin/package.json index 2e24f0620c6..e6b060a3535 100644 --- a/plugins/woocommerce-admin/package.json +++ b/plugins/woocommerce-admin/package.json @@ -190,6 +190,7 @@ "eslint-import-resolver-webpack": "^0.13.2", "eslint-plugin-import": "^2.25.4", "eslint-plugin-react": "^7.29.2", + "eslint-plugin-xstate": "^1.1.0", "expose-loader": "^3.1.0", "fork-ts-checker-webpack-plugin": "^6.5.0", "jest": "^27.5.1", diff --git a/plugins/woocommerce/changelog/dev-xstate-inspector-toggling b/plugins/woocommerce/changelog/dev-xstate-inspector-toggling new file mode 100644 index 00000000000..3a63e9d9f2e --- /dev/null +++ b/plugins/woocommerce/changelog/dev-xstate-inspector-toggling @@ -0,0 +1,6 @@ +Significance: patch +Type: dev + +Added xstate inspector toggling via localStorage flag and dev node environment, and eslint xstate plugin + + diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d8bd12b6e2a..4f39db6fa8c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2845,6 +2845,9 @@ importers: eslint-plugin-react: specifier: ^7.29.2 version: 7.29.4(eslint@8.32.0) + eslint-plugin-xstate: + specifier: ^1.1.0 + version: 1.1.0(eslint@8.32.0) expose-loader: specifier: ^3.1.0 version: 3.1.0(webpack@5.70.0) @@ -8689,9 +8692,9 @@ packages: '@babel/core': 7.21.3 '@babel/helper-annotate-as-pure': 7.16.7 '@babel/helper-module-imports': 7.16.7 - '@babel/helper-plugin-utils': 7.18.9 + '@babel/helper-plugin-utils': 7.20.2 '@babel/plugin-syntax-jsx': 7.16.7(@babel/core@7.21.3) - '@babel/types': 7.17.0 + '@babel/types': 7.21.3 dev: true /@babel/plugin-transform-react-jsx@7.19.0(@babel/core@7.12.9): @@ -26083,6 +26086,19 @@ packages: eslint: 8.32.0 dev: true + /eslint-plugin-xstate@1.1.0(eslint@8.32.0): + resolution: {integrity: sha512-NKgrV/YwwJvKXDq+cTERgLLTxBr7Uxsz2NZYic3e1sqcs7u56uRZDWDk6q7pYquNqqX2AT5X8Urn6qHs4lv8PQ==} + engines: {node: '>=8.0.0'} + peerDependencies: + eslint: ^7.1.0||^8.17.0 + dependencies: + eslint: 8.32.0 + lodash.camelcase: 4.3.0 + lodash.snakecase: 4.1.1 + lodash.upperfirst: 4.3.1 + sanctuary: 3.1.0 + dev: true + /eslint-scope@4.0.3: resolution: {integrity: sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==} engines: {node: '>=4.0.0'} @@ -33250,6 +33266,10 @@ packages: resolution: {integrity: sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=} dev: true + /lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + dev: true + /lodash.debounce@4.0.8: resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} @@ -33321,6 +33341,10 @@ packages: resolution: {integrity: sha512-V/rTAABKLFjoecTZjKSv+A1ZomG8hZg8hlgeG6wwQVD9AGv+10zqqSf6mFq2tVA703Zd5R0YhSuSlXA+E/Ei+Q==} dev: false + /lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + dev: true + /lodash.sortby@4.7.0: resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} @@ -33334,6 +33358,10 @@ packages: /lodash.uniq@4.5.0: resolution: {integrity: sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=} + /lodash.upperfirst@4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + dev: true + /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -39425,6 +39453,62 @@ packages: /safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + /sanctuary-def@0.22.0: + resolution: {integrity: sha512-lywS27TfuPHzelMh6M1YWBcB//Lom4Gko/tGjKYbDPkPet1B5KplsSdjY+5sF4mwp6+PDUodsk/Y3Uskrc/ebw==} + dependencies: + sanctuary-either: 2.1.0 + sanctuary-show: 2.0.0 + sanctuary-type-classes: 12.1.0 + sanctuary-type-identifiers: 3.0.0 + dev: true + + /sanctuary-either@2.1.0: + resolution: {integrity: sha512-AsQCma2yGAVS7Dlxme/09NZWQfcXBNylVmkuvarp8uOe9otSwClOgQyyePN2OxO4hTf3Au1Ck4ggm+97Je06kA==} + dependencies: + sanctuary-show: 2.0.0 + sanctuary-type-classes: 12.1.0 + dev: true + + /sanctuary-maybe@2.1.0: + resolution: {integrity: sha512-xCmvaEkYaIz5klWUrsgvgORKTL3bVYxATp7HyGBY0ZCu9tHJtSYDTpwnqMkRknHFIU986Kr2M/dJdiFvuc6UCQ==} + dependencies: + sanctuary-show: 2.0.0 + sanctuary-type-classes: 12.1.0 + dev: true + + /sanctuary-pair@2.1.0: + resolution: {integrity: sha512-yY1JzzIJ/Ex7rjN8NmQLB7yv6GVzNeaMvxoYSW8w1ReLQI0n2sGOVCnAVipZuCv7wmfd+BavSXp59rklJeYytw==} + dependencies: + sanctuary-show: 2.0.0 + sanctuary-type-classes: 12.1.0 + dev: true + + /sanctuary-show@2.0.0: + resolution: {integrity: sha512-REj4ZiioUXnDLj6EpJ9HcYDIEGaEexmB9Fg5o6InZR9f0x5PfnnC21QeU9SZ9E7G8zXSZPNjy8VRUK4safbesw==} + dev: true + + /sanctuary-type-classes@12.1.0: + resolution: {integrity: sha512-oWP071Q88dEgJwxHLZp8tc7DoS+mWmYhYOuhP85zznPpIxV1ZjJfyRvcR59YCazyFxyFeBif7bJx1giLhDZW0Q==} + dependencies: + sanctuary-type-identifiers: 3.0.0 + dev: true + + /sanctuary-type-identifiers@3.0.0: + resolution: {integrity: sha512-YFXYcG0Ura1dSPd/1xLYtE2XAWUEsBHhMTZvYBOvwT8MeFQwdUOCMm2DC+r94z6H93FVq0qxDac8/D7QpJj6Mg==} + dev: true + + /sanctuary@3.1.0: + resolution: {integrity: sha512-yTpWmslb5Q2jXcHYeIfCzJksIpe3pngBaFBDpjdPXONWyVSB3hBVDZZ8EmitohaMZqjLB+JREeEL0YOVtdxILA==} + dependencies: + sanctuary-def: 0.22.0 + sanctuary-either: 2.1.0 + sanctuary-maybe: 2.1.0 + sanctuary-pair: 2.1.0 + sanctuary-show: 2.0.0 + sanctuary-type-classes: 12.1.0 + sanctuary-type-identifiers: 3.0.0 + dev: true + /sane@4.1.0: resolution: {integrity: sha512-hhbzAgTIX8O7SHfp2c8/kREfEn4qO/9q8C9beyY6+tvZ87EpoZ3i1RIEvp27YBswnNbY9mWd6paKVmKbAgLfZA==} engines: {node: 6.* || 8.* || >= 10.*}