From 3bd62cc7bc145f9f0c6821f9d788b11f83d5cbd9 Mon Sep 17 00:00:00 2001 From: David Joy Date: Wed, 24 Jul 2024 15:31:18 -0400 Subject: [PATCH 01/12] build: ignoring coverage folders in tsconfig.json --- tsconfig.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tsconfig.json b/tsconfig.json index 93e42c95..81422df4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,5 +20,8 @@ "exclude": [ "test-app/**/*", "dist/**/*" + "dist/**/*", + "coverage/**/*", + "cli/coverage", ] } From f9631464fcea033a69afbadb6f4b8150375cd8cd Mon Sep 17 00:00:00 2001 From: David Joy Date: Wed, 24 Jul 2024 15:33:12 -0400 Subject: [PATCH 02/12] refactor: adjusting shell imports to use runtime MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We still needed to update the shell’s header code to use the runtime directory instead of frontend-platform. This adjusts those imports. Also adding missing dependencies. --- package-lock.json | 99 +++++++++++++++---- package.json | 4 +- shell/header/DesktopHeader.jsx | 7 +- shell/header/Header.jsx | 16 +-- shell/header/Header.messages.jsx | 2 +- shell/header/Header.test.jsx | 6 +- shell/header/MobileHeader.jsx | 7 +- .../learning-header/AnonymousUserMenu.jsx | 8 +- .../AuthenticatedUserDropdown.jsx | 11 +-- .../header/learning-header/LearningHeader.jsx | 9 +- shell/header/studio-header/CourseLockUp.jsx | 5 +- shell/header/studio-header/HeaderBody.jsx | 9 +- shell/header/studio-header/StudioHeader.jsx | 7 +- .../studio-header/StudioHeader.test.jsx | 7 +- shell/header/studio-header/UserMenu.jsx | 5 +- 15 files changed, 125 insertions(+), 77 deletions(-) diff --git a/package-lock.json b/package-lock.json index 21ec291c..89c5021b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -71,6 +71,7 @@ "react-dev-utils": "12.0.1", "react-intl": "^6.6.6", "react-refresh": "0.14.2", + "react-responsive": "^10.0.0", "resolve-url-loader": "5.0.0", "sass": "1.69.7", "sass-loader": "13.3.3", @@ -101,7 +102,8 @@ "@types/react-dom": "^17.0.11", "axios-mock-adapter": "^1.22.0", "jsdoc": "^4.0.3", - "nodemon": "^3.1.4" + "nodemon": "^3.1.4", + "react-test-renderer": "^17.0.2" }, "peerDependencies": { "@openedx/paragon": "^22.6.1", @@ -3018,6 +3020,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/@openedx/paragon/node_modules/matchmediaquery": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/matchmediaquery/-/matchmediaquery-0.3.1.tgz", + "integrity": "sha512-Hlk20WQHRIm9EE9luN1kjRjYXAQToHOIAHPJn9buxBwuhfTHoKUcX+lXBbxc85DVQfXYbEQ4HcwQdd128E3qHQ==", + "peer": true, + "dependencies": { + "css-mediaquery": "^0.1.2" + } + }, "node_modules/@openedx/paragon/node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", @@ -3030,6 +3041,30 @@ "node": ">=10" } }, + "node_modules/@openedx/paragon/node_modules/react-responsive": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-8.2.0.tgz", + "integrity": "sha512-iagCqVrw4QSjhxKp3I/YK6+ODkWY6G+YPElvdYKiUUbywwh9Ds0M7r26Fj2/7dWFFbOpcGnJE6uE7aMck8j5Qg==", + "peer": true, + "dependencies": { + "hyphenate-style-name": "^1.0.0", + "matchmediaquery": "^0.3.0", + "prop-types": "^15.6.1", + "shallow-equal": "^1.1.0" + }, + "engines": { + "node": ">= 0.10" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@openedx/paragon/node_modules/shallow-equal": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", + "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==", + "peer": true + }, "node_modules/@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.15", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.15.tgz", @@ -5760,8 +5795,7 @@ "node_modules/css-mediaquery": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/css-mediaquery/-/css-mediaquery-0.1.2.tgz", - "integrity": "sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q==", - "peer": true + "integrity": "sha512-COtn4EROW5dBGlE/4PiKnh6rZpAPxDeFLaEEwt4i10jpDMFt2EhQGS79QmmrO+iKCHv0PU/HrOWEhijFd1x99Q==" }, "node_modules/css-select": { "version": "4.3.0", @@ -8788,8 +8822,7 @@ "node_modules/hyphenate-style-name": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", - "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", - "peer": true + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==" }, "node_modules/i18n-iso-countries": { "version": "4.3.1", @@ -11119,10 +11152,9 @@ } }, "node_modules/matchmediaquery": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/matchmediaquery/-/matchmediaquery-0.3.1.tgz", - "integrity": "sha512-Hlk20WQHRIm9EE9luN1kjRjYXAQToHOIAHPJn9buxBwuhfTHoKUcX+lXBbxc85DVQfXYbEQ4HcwQdd128E3qHQ==", - "peer": true, + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/matchmediaquery/-/matchmediaquery-0.4.2.tgz", + "integrity": "sha512-wrZpoT50ehYOudhDjt/YvUJc6eUzcdFPdmbizfgvswCKNHD1/OBOHYJpHie+HXpu6bSkEGieFMYk6VuutaiRfA==", "dependencies": { "css-mediaquery": "^0.1.2" } @@ -13565,18 +13597,17 @@ } }, "node_modules/react-responsive": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-8.2.0.tgz", - "integrity": "sha512-iagCqVrw4QSjhxKp3I/YK6+ODkWY6G+YPElvdYKiUUbywwh9Ds0M7r26Fj2/7dWFFbOpcGnJE6uE7aMck8j5Qg==", - "peer": true, + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/react-responsive/-/react-responsive-10.0.0.tgz", + "integrity": "sha512-N6/UiRLGQyGUqrarhBZmrSmHi2FXSD++N5VbSKsBBvWfG0ZV7asvUBluSv5lSzdMyEVjzZ6Y8DL4OHABiztDOg==", "dependencies": { "hyphenate-style-name": "^1.0.0", - "matchmediaquery": "^0.3.0", + "matchmediaquery": "^0.4.2", "prop-types": "^15.6.1", - "shallow-equal": "^1.1.0" + "shallow-equal": "^3.1.0" }, "engines": { - "node": ">= 0.10" + "node": ">=14" }, "peerDependencies": { "react": ">=16.8.0" @@ -13614,6 +13645,19 @@ "react-dom": ">=16.8" } }, + "node_modules/react-shallow-renderer": { + "version": "16.15.0", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", + "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", + "dev": true, + "dependencies": { + "object-assign": "^4.1.1", + "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, "node_modules/react-style-singleton": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", @@ -13650,6 +13694,21 @@ "react": "^16.8.3 || ^17.0.0-0 || ^18.0.0" } }, + "node_modules/react-test-renderer": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-17.0.2.tgz", + "integrity": "sha512-yaQ9cB89c17PUb0x6UfWRs7kQCorVdHlutU1boVPEsB8IDZH6n9tHxMacc3y0JoXOJUsZb/t/Mb8FUWMKaM7iQ==", + "dev": true, + "dependencies": { + "object-assign": "^4.1.1", + "react-is": "^17.0.2", + "react-shallow-renderer": "^16.13.1", + "scheduler": "^0.20.2" + }, + "peerDependencies": { + "react": "17.0.2" + } + }, "node_modules/react-transition-group": { "version": "4.4.5", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", @@ -14169,7 +14228,6 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", - "peer": true, "dependencies": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -14429,10 +14487,9 @@ } }, "node_modules/shallow-equal": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", - "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==", - "peer": true + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-3.1.0.tgz", + "integrity": "sha512-pfVOw8QZIXpMbhBWvzBISicvToTiM5WBF1EeAUZDDSb5Dt29yl4AYbyywbJFSEsRUMr7gJaxqCdr4L3tQf9wVg==" }, "node_modules/sharp": { "version": "0.32.6", diff --git a/package.json b/package.json index 40614a57..8bcce0ba 100644 --- a/package.json +++ b/package.json @@ -105,6 +105,7 @@ "react-dev-utils": "12.0.1", "react-intl": "^6.6.6", "react-refresh": "0.14.2", + "react-responsive": "^10.0.0", "resolve-url-loader": "5.0.0", "sass": "1.69.7", "sass-loader": "13.3.3", @@ -130,7 +131,8 @@ "@types/react-dom": "^17.0.11", "axios-mock-adapter": "^1.22.0", "jsdoc": "^4.0.3", - "nodemon": "^3.1.4" + "nodemon": "^3.1.4", + "react-test-renderer": "^17.0.2" }, "peerDependencies": { "@openedx/paragon": "^22.6.1", diff --git a/shell/header/DesktopHeader.jsx b/shell/header/DesktopHeader.jsx index 05cc9372..cfc89b29 100644 --- a/shell/header/DesktopHeader.jsx +++ b/shell/header/DesktopHeader.jsx @@ -1,12 +1,11 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; -import { getConfig } from '@edx/frontend-platform'; +import React from 'react'; +import { getConfig, injectIntl, intlShape } from '../../runtime'; // Local Components -import { Menu, MenuTrigger, MenuContent } from './Menu'; import Avatar from './Avatar'; import { LinkedLogo, Logo } from './Logo'; +import { Menu, MenuContent, MenuTrigger } from './Menu'; // i18n import messages from './Header.messages'; diff --git a/shell/header/Header.jsx b/shell/header/Header.jsx index bff801fe..5f0749c8 100644 --- a/shell/header/Header.jsx +++ b/shell/header/Header.jsx @@ -1,16 +1,16 @@ -import React, { useContext } from 'react'; +import { useContext } from 'react'; import Responsive from 'react-responsive'; -import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; -import { AppContext } from '@edx/frontend-platform/react'; + +import PropTypes from 'prop-types'; import { APP_CONFIG_INITIALIZED, + AppContext, ensureConfig, - mergeConfig, getConfig, - subscribe, -} from '@edx/frontend-platform'; - -import PropTypes from 'prop-types'; + injectIntl, intlShape, + mergeConfig, + subscribe +} from '../../runtime'; import DesktopHeader from './DesktopHeader'; import MobileHeader from './MobileHeader'; diff --git a/shell/header/Header.messages.jsx b/shell/header/Header.messages.jsx index a5ff3a58..7a5e23e3 100644 --- a/shell/header/Header.messages.jsx +++ b/shell/header/Header.messages.jsx @@ -1,4 +1,4 @@ -import { defineMessages } from '@edx/frontend-platform/i18n'; +import { defineMessages } from '../../runtime'; const messages = defineMessages({ 'header.links.courses': { diff --git a/shell/header/Header.test.jsx b/shell/header/Header.test.jsx index 51fef208..3a94d000 100644 --- a/shell/header/Header.test.jsx +++ b/shell/header/Header.test.jsx @@ -1,9 +1,7 @@ /* eslint-disable react/prop-types */ -import React from 'react'; -import { IntlProvider } from '@edx/frontend-platform/i18n'; -import TestRenderer from 'react-test-renderer'; -import { AppContext } from '@edx/frontend-platform/react'; import { Context as ResponsiveContext } from 'react-responsive'; +import TestRenderer from 'react-test-renderer'; +import { AppContext, IntlProvider } from '../../runtime'; import Header from './index'; diff --git a/shell/header/MobileHeader.jsx b/shell/header/MobileHeader.jsx index f8c02fcc..28224f54 100644 --- a/shell/header/MobileHeader.jsx +++ b/shell/header/MobileHeader.jsx @@ -1,12 +1,11 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; -import { getConfig } from '@edx/frontend-platform'; +import React from 'react'; +import { getConfig, injectIntl, intlShape } from '../../runtime'; // Local Components -import { Menu, MenuTrigger, MenuContent } from './Menu'; import Avatar from './Avatar'; import { LinkedLogo, Logo } from './Logo'; +import { Menu, MenuContent, MenuTrigger } from './Menu'; // i18n import messages from './Header.messages'; diff --git a/shell/header/learning-header/AnonymousUserMenu.jsx b/shell/header/learning-header/AnonymousUserMenu.jsx index 74c3f3e2..61e2c070 100644 --- a/shell/header/learning-header/AnonymousUserMenu.jsx +++ b/shell/header/learning-header/AnonymousUserMenu.jsx @@ -1,9 +1,7 @@ -import React from 'react'; - -import { getConfig } from '@edx/frontend-platform'; -import { getLoginRedirectUrl } from '@edx/frontend-platform/auth'; -import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; import { Button } from '@openedx/paragon'; +import { + getConfig, getLoginRedirectUrl, injectIntl, intlShape +} from '../../../runtime'; import genericMessages from '../generic/messages'; diff --git a/shell/header/learning-header/AuthenticatedUserDropdown.jsx b/shell/header/learning-header/AuthenticatedUserDropdown.jsx index 9caadb41..80abfc62 100644 --- a/shell/header/learning-header/AuthenticatedUserDropdown.jsx +++ b/shell/header/learning-header/AuthenticatedUserDropdown.jsx @@ -1,11 +1,10 @@ -import React from 'react'; import PropTypes from 'prop-types'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faUserCircle } from '@fortawesome/free-solid-svg-icons'; -import { getConfig } from '@edx/frontend-platform'; -import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; +// TODO: Fix these +// import { faUserCircle } from '@fortawesome/free-solid-svg-icons'; +// import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Dropdown } from '@openedx/paragon'; +import { getConfig, injectIntl, intlShape } from '../../../runtime'; import messages from './messages'; @@ -21,7 +20,7 @@ const AuthenticatedUserDropdown = ({ intl, username }) => { {intl.formatMessage(messages.help)} - + {/* */} {username} diff --git a/shell/header/learning-header/LearningHeader.jsx b/shell/header/learning-header/LearningHeader.jsx index 373001d1..0c5ef40d 100644 --- a/shell/header/learning-header/LearningHeader.jsx +++ b/shell/header/learning-header/LearningHeader.jsx @@ -1,8 +1,9 @@ -import React, { useContext } from 'react'; import PropTypes from 'prop-types'; -import { getConfig } from '@edx/frontend-platform'; -import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; -import { AppContext } from '@edx/frontend-platform/react'; +import { useContext } from 'react'; +import { + AppContext, + getConfig, injectIntl, intlShape +} from '../../../runtime'; import AnonymousUserMenu from './AnonymousUserMenu'; import AuthenticatedUserDropdown from './AuthenticatedUserDropdown'; diff --git a/shell/header/studio-header/CourseLockUp.jsx b/shell/header/studio-header/CourseLockUp.jsx index c5853d8c..8318ffc8 100644 --- a/shell/header/studio-header/CourseLockUp.jsx +++ b/shell/header/studio-header/CourseLockUp.jsx @@ -1,10 +1,9 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; import { OverlayTrigger, Tooltip, } from '@openedx/paragon'; +import PropTypes from 'prop-types'; +import { injectIntl, intlShape } from '../../../runtime'; import messages from './messages'; const CourseLockUp = ({ diff --git a/shell/header/studio-header/HeaderBody.jsx b/shell/header/studio-header/HeaderBody.jsx index 7a4426d4..6a9bb2ad 100644 --- a/shell/header/studio-header/HeaderBody.jsx +++ b/shell/header/studio-header/HeaderBody.jsx @@ -1,6 +1,3 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { useIntl } from '@edx/frontend-platform/i18n'; import { ActionRow, Button, @@ -11,11 +8,13 @@ import { Row, } from '@openedx/paragon'; import { Close, MenuIcon, Search } from '@openedx/paragon/icons'; +import PropTypes from 'prop-types'; +import { useIntl } from '../../../runtime'; -import CourseLockUp from './CourseLockUp'; -import UserMenu from './UserMenu'; import BrandNav from './BrandNav'; +import CourseLockUp from './CourseLockUp'; import NavDropdownMenu from './NavDropdownMenu'; +import UserMenu from './UserMenu'; import messages from './messages'; const HeaderBody = ({ diff --git a/shell/header/studio-header/StudioHeader.jsx b/shell/header/studio-header/StudioHeader.jsx index 886ad841..36929cc9 100644 --- a/shell/header/studio-header/StudioHeader.jsx +++ b/shell/header/studio-header/StudioHeader.jsx @@ -1,11 +1,10 @@ -import React, { useContext } from 'react'; import PropTypes from 'prop-types'; +import { useContext } from 'react'; import Responsive from 'react-responsive'; -import { AppContext } from '@edx/frontend-platform/react'; -import { ensureConfig } from '@edx/frontend-platform'; +import { AppContext, ensureConfig } from '../../../runtime'; -import MobileHeader from './MobileHeader'; import HeaderBody from './HeaderBody'; +import MobileHeader from './MobileHeader'; ensureConfig([ 'STUDIO_BASE_URL', diff --git a/shell/header/studio-header/StudioHeader.test.jsx b/shell/header/studio-header/StudioHeader.test.jsx index 263cac2f..d58dc11d 100644 --- a/shell/header/studio-header/StudioHeader.test.jsx +++ b/shell/header/studio-header/StudioHeader.test.jsx @@ -1,14 +1,13 @@ /* eslint-disable react/prop-types */ -import React, { useMemo } from 'react'; import { - render, fireEvent, + render, waitFor, } from '@testing-library/react'; +import { useMemo } from 'react'; -import { AppContext } from '@edx/frontend-platform/react'; -import { IntlProvider } from '@edx/frontend-platform/i18n'; import { Context as ResponsiveContext } from 'react-responsive'; +import { AppContext, IntlProvider } from '../../../runtime'; import StudioHeader from './StudioHeader'; import messages from './messages'; diff --git a/shell/header/studio-header/UserMenu.jsx b/shell/header/studio-header/UserMenu.jsx index 03695c16..1af1f72e 100644 --- a/shell/header/studio-header/UserMenu.jsx +++ b/shell/header/studio-header/UserMenu.jsx @@ -1,9 +1,8 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { injectIntl, intlShape } from '@edx/frontend-platform/i18n'; import { Avatar, } from '@openedx/paragon'; +import PropTypes from 'prop-types'; +import { injectIntl, intlShape } from '../../../runtime'; import NavDropdownMenu from './NavDropdownMenu'; import getUserMenuItems from './utils'; From 053da0569cfb63bf7ab66e119a4485575ce42452 Mon Sep 17 00:00:00 2001 From: David Joy Date: Wed, 24 Jul 2024 15:41:25 -0400 Subject: [PATCH 03/12] refactor: removing references to frontend-platform Most of these references are in comments and documentation. Touching the files has also rearranged their imports alphabetically. --- config/getLocalAliases.js | 2 +- docs/template/edx/publish.js | 2 +- index.ts | 2 +- runtime/analytics/interface.js | 13 ++++++++----- runtime/auth/MockAuthService.js | 3 +-- runtime/auth/interface.js | 10 +++++----- runtime/config.js | 6 +++--- runtime/i18n/index.js | 4 ++-- runtime/initialize.js | 14 +++++++------- runtime/logging/interface.js | 5 ++--- runtime/pubSub.js | 2 +- runtime/react/AuthenticatedPageRoute.jsx | 6 +++--- runtime/react/LoginRedirect.jsx | 2 +- runtime/react/PageWrap.jsx | 4 ++-- runtime/react/hooks.js | 2 +- runtime/react/hooks.test.jsx | 4 ++-- runtime/react/index.js | 4 ++-- runtime/testing/index.js | 2 +- runtime/testing/initializeMockApp.js | 7 +++---- runtime/utils.js | 2 +- tsconfig.json | 1 - 21 files changed, 48 insertions(+), 49 deletions(-) diff --git a/config/getLocalAliases.js b/config/getLocalAliases.js index 45f7ca65..e76a0034 100644 --- a/config/getLocalAliases.js +++ b/config/getLocalAliases.js @@ -24,7 +24,7 @@ Some working examples, as of the time of this writing: { moduleName: '@openedx/paragon/scss', dir: '../paragon', dist: 'scss' } { moduleName: '@openedx/paragon', dir: '../paragon', dist: 'dist' } -{ moduleName: '@edx/frontend-platform', dir: '../frontend-platform', dist: 'dist' } +{ moduleName: '@openedx/frontend-base', dir: '../frontend-base', dist: 'dist' } */ function getLocalAliases() { diff --git a/docs/template/edx/publish.js b/docs/template/edx/publish.js index 4c390f56..919181e9 100644 --- a/docs/template/edx/publish.js +++ b/docs/template/edx/publish.js @@ -635,7 +635,7 @@ exports.publish = (memberData, opts, tutorials) => { files = find({kind: 'file'}); packages = find({kind: 'package'}); - generate('Open edX frontend-platform API Documentation', + generate('Open edX frontend-base API Documentation', packages.concat( [{ kind: 'mainpage', diff --git a/index.ts b/index.ts index 5b9b0ca1..b85804d5 100644 --- a/index.ts +++ b/index.ts @@ -97,5 +97,5 @@ export { subscribe, unsubscribe, useAppEvent, - useIntl, + useIntl } from './runtime'; diff --git a/runtime/analytics/interface.js b/runtime/analytics/interface.js index 48d60be6..d035f2ef 100755 --- a/runtime/analytics/interface.js +++ b/runtime/analytics/interface.js @@ -1,5 +1,5 @@ /** - * #### Import members from **@edx/frontend-platform/analytics** + * #### Import members from **@openedx/frontend-base** Analytics * * Contains a shared interface for tracking events. Has a default implementation of * SegmentAnalyticsService, which supports Segment and the Tracking Log API (hosted in LMS). @@ -8,10 +8,13 @@ * you're not using the `initialize` function, analytics can be configured via: * * ``` - * import { configure, SegmentAnalyticsService } from '@edx/frontend-platform/analytics'; - * import { getConfig } from '@edx/frontend-platform'; - * import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth'; - * import { getLoggingService } from '@edx/frontend-platform/logging'; + * import { + * getConfig, + * getAuthenticatedHttpClient, + * getLoggingService, + * configureAnalytics, + * SegmentAnalyticsService + * } from '@openedx/frontend-base'; * * configure(SegmentAnalyticsService, { * config: getConfig(), diff --git a/runtime/auth/MockAuthService.js b/runtime/auth/MockAuthService.js index 159f556c..9b29dccb 100644 --- a/runtime/auth/MockAuthService.js +++ b/runtime/auth/MockAuthService.js @@ -46,8 +46,7 @@ const optionsPropTypes = { * you could do the following to set up a MockAuthService for your test: * * ``` - * import { getConfig, mergeConfig } from '@edx/frontend-platform'; - * import { configure, MockAuthService } from '@edx/frontend-platform/auth'; + * import { getConfig, mergeConfig, configureAuth, MockAuthService } from '@openedx/frontend-base'; * import MockAdapter from 'axios-mock-adapter'; * * const mockLoggingService = { diff --git a/runtime/auth/interface.js b/runtime/auth/interface.js index cd3e416d..efddf576 100644 --- a/runtime/auth/interface.js +++ b/runtime/auth/interface.js @@ -1,5 +1,5 @@ /** - * #### Import members from **@edx/frontend-platform/auth** + * #### Import members from **@openedx/frontend-base** * * Simplifies the process of making authenticated API requests to backend edX services by providing * common authN/authZ client code that enables the login/logout flow and handles ensuring the @@ -12,10 +12,10 @@ * import { * configure, * fetchAuthenticatedUser, - * getAuthenticatedHttpClient - * } from '@edx/frontend-platform/auth'; - * import { getConfig } from '@edx/frontend-platform'; - * import { getLoggingService } from '@edx/frontend-platform/logging'; + * getAuthenticatedHttpClient, + * getConfig, + * getLoggingService + * } from '@openedx/frontend-base'; * * configure({ * loggingService: getLoggingService(), diff --git a/runtime/config.js b/runtime/config.js index 3adea36d..41b20825 100644 --- a/runtime/config.js +++ b/runtime/config.js @@ -1,5 +1,5 @@ /** - * #### Import members from **@edx/frontend-platform** + * #### Import members from **@edx/frontend-base** * * The configuration module provides utilities for working with an application's configuration * document (ConfigDocument). Configuration variables can be supplied to the @@ -180,7 +180,7 @@ let config = { * Example: * * ``` - * import { getConfig } from '@edx/frontend-platform'; + * import { getConfig } from '@openedx/frontend-base'; * * const { * LMS_BASE_URL, @@ -202,7 +202,7 @@ export function getConfig() { * Example: * * ``` - * import { setConfig } from '@edx/frontend-platform'; + * import { setConfig } from '@openedx/frontend-base'; * * setConfig({ * LMS_BASE_URL, // This is overriding the ENTIRE document - this is not merged in! diff --git a/runtime/i18n/index.js b/runtime/i18n/index.js index 7ff12e4f..6d439f6f 100644 --- a/runtime/i18n/index.js +++ b/runtime/i18n/index.js @@ -1,5 +1,5 @@ /** - * #### Import members from **@edx/frontend-platform/i18n** + * #### Import members from **@openedx/frontend-base** * The i18n module relies on react-intl and re-exports all of that package's exports. * * For each locale we want to support, react-intl needs 1) the locale-data, which includes @@ -18,7 +18,7 @@ * * * @module Internationalization - * @see {@link https://github.com/openedx/frontend-platform/blob/master/docs/how_tos/i18n.rst} + * @see {@link https://github.com/openedx/frontend-base/blob/master/docs/how_tos/i18n.rst} * @see {@link https://formatjs.io/docs/react-intl/components/ Intl} for components exported from this module. * */ diff --git a/runtime/initialize.js b/runtime/initialize.js index c7f89d11..93e620e4 100644 --- a/runtime/initialize.js +++ b/runtime/initialize.js @@ -1,5 +1,5 @@ /** - * #### Import members from **@edx/frontend-platform** + * #### Import members from **@openedx/frontend-base** * * The initialization module provides a function for managing an application's initialization * lifecycle. It also provides constants and default handler implementations. @@ -10,9 +10,11 @@ * APP_INIT_ERROR, * APP_READY, * subscribe, - * } from '@edx/frontend-platform'; - * import { AppProvider, ErrorPage, PageWrap } from '@edx/frontend-platform/react'; - * import React from 'react'; + * AppProvider, + * ErrorPage, + * PageWrap + * } from '@openedx/frontend-base'; + * import React from 'react'; * import ReactDOM from 'react-dom'; * import { Routes, Route } from 'react-router-dom'; * @@ -53,8 +55,6 @@ import { This 'env.config' package is a special 'magic' alias in our webpack configuration in frontend-build. It points at an `env.config.js` file in the root of an MFE's repository if it exists and falls back to an empty object `{}` if the file doesn't exist. This acts like an 'optional' import, in a sense. -Note that the env.config.js file in frontend-platform's root directory is NOT used by the actual -initialization code, it's just there for the test suite and test-app application. */ import envConfig from 'env.config'; // eslint-disable-line import/no-unresolved import { @@ -128,7 +128,7 @@ export const basename = getPath(getConfig().PUBLIC_PATH); * The default handler for the initialization lifecycle's `initError` phase. Logs the error to the * LoggingService using `logError` * - * @see {@link module:frontend-platform/logging~logError} + * @see {@link module:frontend-base~logError} * @param {*} error */ export async function initError(error) { diff --git a/runtime/logging/interface.js b/runtime/logging/interface.js index 4c38748d..82dbe15c 100644 --- a/runtime/logging/interface.js +++ b/runtime/logging/interface.js @@ -1,5 +1,5 @@ /** - * #### Import members from **@edx/frontend-platform/logging** + * #### Import members from **@openedx/frontend-base logging** * * Contains a shared interface for logging information. (The default implementation is in * NewRelicLoggingService.js.) When in development mode, all messages will instead be sent to the console. @@ -8,8 +8,7 @@ * you're not using the `initialize` function, logging (via New Relic) can be configured via: * * ``` - * import { configure, NewRelicLoggingService, logInfo, logError } from '@edx/frontend-platform/logging'; - * import { geConfig } from '@edx/frontend-platform'; + * import { getConfig, configure, NewRelicLoggingService, logInfo, logError } from '@openedx/frontend-base'; * * configureLogging(NewRelicLoggingService, { * config: getConfig(), diff --git a/runtime/pubSub.js b/runtime/pubSub.js index 1104f244..db540ea1 100644 --- a/runtime/pubSub.js +++ b/runtime/pubSub.js @@ -1,5 +1,5 @@ /** - * #### Import members from **@edx/frontend-platform** + * #### Import members from **@openedx/frontend-base** * * The PubSub module is a thin wrapper around the base functionality of * [PubSubJS](https://github.com/mroderick/PubSubJS). For the sake of simplicity and not relying diff --git a/runtime/react/AuthenticatedPageRoute.jsx b/runtime/react/AuthenticatedPageRoute.jsx index d67231c8..99ebc721 100644 --- a/runtime/react/AuthenticatedPageRoute.jsx +++ b/runtime/react/AuthenticatedPageRoute.jsx @@ -1,9 +1,9 @@ -import React, { useContext } from 'react'; import PropTypes from 'prop-types'; +import { useContext } from 'react'; +import { getLoginRedirectUrl } from '../auth'; import AppContext from './AppContext'; import PageWrap from './PageWrap'; -import { getLoginRedirectUrl } from '../auth'; /** * A react-router route that redirects to the login page when the route becomes active and the user @@ -16,7 +16,7 @@ import { getLoginRedirectUrl } from '../auth'; * Like a `PageWrap`, also calls `sendPageEvent` when the route becomes active. * * @see PageWrap - * @see {@link module:frontend-platform/analytics~sendPageEvent} + * @see {@link module:frontend-base~sendPageEvent} * @memberof module:React * @param {Object} props * @param {string} props.redirectUrl The URL anonymous users should be redirected to, rather than diff --git a/runtime/react/LoginRedirect.jsx b/runtime/react/LoginRedirect.jsx index 47cca4d7..43601fc9 100644 --- a/runtime/react/LoginRedirect.jsx +++ b/runtime/react/LoginRedirect.jsx @@ -5,7 +5,7 @@ import { redirectToLogin } from '../auth'; * A React component that, when rendered, redirects to the login page as a side effect. Uses * `redirectToLogin` to perform the redirect. * - * @see {@link module:frontend-platform/auth~redirectToLogin} + * @see {@link module:frontend-base~redirectToLogin} * @memberof module:React */ export default function LoginRedirect() { diff --git a/runtime/react/PageWrap.jsx b/runtime/react/PageWrap.jsx index d7130cd7..2d6dac15 100644 --- a/runtime/react/PageWrap.jsx +++ b/runtime/react/PageWrap.jsx @@ -1,6 +1,6 @@ /* eslint-disable react/prop-types */ // eslint-disable-next-line no-unused-vars -import React, { useEffect } from 'react'; +import { useEffect } from 'react'; import { useLocation } from 'react-router-dom'; import { sendPageEvent } from '../analytics'; @@ -8,7 +8,7 @@ import { sendPageEvent } from '../analytics'; /** * A Wrapper component that calls `sendPageEvent` when it becomes active. * - * @see {@link module:frontend-platform/analytics~sendPageEvent} + * @see {@link module:frontend-base~sendPageEvent} * @memberof module:React * @param {Object} props */ diff --git a/runtime/react/hooks.js b/runtime/react/hooks.js index b1d4e219..83800cc0 100644 --- a/runtime/react/hooks.js +++ b/runtime/react/hooks.js @@ -33,7 +33,7 @@ export const useTrackColorSchemeChoice = () => { useEffect(() => { const trackColorSchemeChoice = ({ matches }) => { const preferredColorScheme = matches ? 'dark' : 'light'; - sendTrackEvent('openedx.ui.frontend-platform.prefers-color-scheme.selected', { preferredColorScheme }); + sendTrackEvent('openedx.ui.frontend-base.prefers-color-scheme.selected', { preferredColorScheme }); }; const colorSchemeQuery = window.matchMedia?.('(prefers-color-scheme: dark)'); if (colorSchemeQuery) { diff --git a/runtime/react/hooks.test.jsx b/runtime/react/hooks.test.jsx index 48623a3b..8cae0ab3 100644 --- a/runtime/react/hooks.test.jsx +++ b/runtime/react/hooks.test.jsx @@ -29,7 +29,7 @@ describe('useTrackColorSchemeChoice hook', () => { expect(sendTrackEvent).toHaveBeenCalledTimes(1); expect(sendTrackEvent).toHaveBeenCalledWith( - 'openedx.ui.frontend-platform.prefers-color-scheme.selected', + 'openedx.ui.frontend-base.prefers-color-scheme.selected', { preferredColorScheme: 'dark' }, ); }); @@ -40,7 +40,7 @@ describe('useTrackColorSchemeChoice hook', () => { expect(sendTrackEvent).toHaveBeenCalledTimes(1); expect(sendTrackEvent).toHaveBeenCalledWith( - 'openedx.ui.frontend-platform.prefers-color-scheme.selected', + 'openedx.ui.frontend-base.prefers-color-scheme.selected', { preferredColorScheme: 'light' }, ); }); diff --git a/runtime/react/index.js b/runtime/react/index.js index 0985d927..52f7d7c5 100644 --- a/runtime/react/index.js +++ b/runtime/react/index.js @@ -1,5 +1,5 @@ /** - * #### Import members from **@edx/frontend-platform/react** + * #### Import members from **@openedx/frontend-base** React * The React module provides a variety of React components, hooks, and contexts for use in an * application. * @@ -11,6 +11,6 @@ export { default as AppProvider } from './AppProvider'; export { default as AuthenticatedPageRoute } from './AuthenticatedPageRoute'; export { default as ErrorBoundary } from './ErrorBoundary'; export { default as ErrorPage } from './ErrorPage'; +export { useAppEvent } from './hooks'; export { default as LoginRedirect } from './LoginRedirect'; export { default as PageWrap } from './PageWrap'; -export { useAppEvent } from './hooks'; diff --git a/runtime/testing/index.js b/runtime/testing/index.js index 422ebe39..f7878baf 100644 --- a/runtime/testing/index.js +++ b/runtime/testing/index.js @@ -1,5 +1,5 @@ /** - * #### Import members from **@edx/frontend-platform/testing** + * #### Import members from **@openedx/frontend-base** Testing * The testing module provides helpers for writing tests in Jest. * * @module Testing diff --git a/runtime/testing/initializeMockApp.js b/runtime/testing/initializeMockApp.js index 27f50c1a..8e2bead1 100644 --- a/runtime/testing/initializeMockApp.js +++ b/runtime/testing/initializeMockApp.js @@ -1,8 +1,8 @@ import { configure as configureAnalytics, MockAnalyticsService } from '../analytics'; -import { configure as configureI18n } from '../i18n'; -import { configure as configureLogging, MockLoggingService } from '../logging'; import { configure as configureAuth, MockAuthService } from '../auth'; import { getConfig } from '../config'; +import { configure as configureI18n } from '../i18n'; +import { configure as configureLogging, MockLoggingService } from '../logging'; import mockMessages from './mockMessages'; /** @@ -24,8 +24,7 @@ import mockMessages from './mockMessages'; * Example: * * ``` - * import { initializeMockApp } from '@edx/frontend-platform/testing'; - * import { logInfo } from '@edx/frontend-platform/logging'; + * import { initializeMockApp, logInfo } from '@openedx/frontend-base'; * * describe('initializeMockApp', () => { * it('mocks things correctly', () => { diff --git a/runtime/utils.js b/runtime/utils.js index 11ca0146..a0353f08 100644 --- a/runtime/utils.js +++ b/runtime/utils.js @@ -1,5 +1,5 @@ /** - * #### Import members from **@edx/frontend-platform** + * #### Import members from **@openedx/frontend-base** * * @module Utilities */ diff --git a/tsconfig.json b/tsconfig.json index 81422df4..8a2d06ee 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -19,7 +19,6 @@ ], "exclude": [ "test-app/**/*", - "dist/**/*" "dist/**/*", "coverage/**/*", "cli/coverage", From 7bd5407a6261d7e081bafb9b8830bc7dac8b19db Mon Sep 17 00:00:00 2001 From: David Joy Date: Wed, 24 Jul 2024 15:42:12 -0400 Subject: [PATCH 04/12] build: adding a TS declaration file --- index.d.ts | 110 ++++++++++++++++++++++++++++++++++++++++++++++++++ tsconfig.json | 1 + 2 files changed, 111 insertions(+) create mode 100644 index.d.ts diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 00000000..b2cc84e7 --- /dev/null +++ b/index.d.ts @@ -0,0 +1,110 @@ +export { + APP_ANALYTICS_INITIALIZED, + APP_AUTH_INITIALIZED, + APP_CONFIG_INITIALIZED, + APP_I18N_INITIALIZED, + APP_INIT_ERROR, + APP_LOGGING_INITIALIZED, + APP_PUBSUB_INITIALIZED, + APP_READY, + APP_TOPIC, + AUTHENTICATED_USER_CHANGED, + AUTHENTICATED_USER_TOPIC, + AppContext, + AppProvider, + AuthenticatedPageRoute, + AxiosJwtAuthService, + CONFIG_CHANGED, + CONFIG_TOPIC, + ErrorBoundary, + ErrorPage, + FormattedDate, + FormattedMessage, + FormattedNumber, + FormattedPlural, + FormattedRelativeTime, + FormattedTime, + IntlProvider, + LOCALE_CHANGED, + LOCALE_TOPIC, + LoginRedirect, + MockAnalyticsService, + MockAuthService, + MockLoggingService, + NewRelicLoggingService, + PageWrap, + SegmentAnalyticsService, + auth, + camelCaseObject, + configureAnalytics, + configureAuth, + configureI18n, + configureLogging, + convertKeyNames, + createIntl, + defineMessages, + ensureAuthenticatedUser, + ensureConfig, + ensureDefinedConfig, + fetchAuthenticatedUser, + getAnalyticsService, + getAuthService, + getAuthenticatedHttpClient, + getAuthenticatedUser, + getConfig, + getCountryList, + getCountryMessages, + getHttpClient, + getLanguageList, + getLanguageMessages, + getLocale, + getLoggingService, + getLoginRedirectUrl, + getLogoutRedirectUrl, + getMessages, + getPath, + getPrimaryLanguageSubtag, + getQueryParameters, + handleRtl, + history, + hydrateAuthenticatedUser, + identifyAnonymousUser, + identifyAuthenticatedUser, + initError, + initialize, + initializeMockApp, + injectIntl, + intlShape, + isRtl, + logError, + logInfo, + mergeConfig, + mergeMessages, + mockMessages, + modifyObjectKeys, + parseURL, + publish, + redirectToLogin, + redirectToLogout, + resetAnalyticsService, + resetLoggingService, + sendPageEvent, + sendTrackEvent, + sendTrackingLogEvent, + setAuthenticatedUser, + setConfig, + snakeCaseObject, + subscribe, + unsubscribe, + useAppEvent, + useIntl +} from './runtime'; + +declare module 'env.config' { + + export default { + modules: { + [key]: Component + } + }; +} diff --git a/tsconfig.json b/tsconfig.json index 8a2d06ee..02825d2e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,6 +13,7 @@ "runtime/**/*", "shell/**/*", "index.ts", + "index.d.ts", "config/tsconfig.json", "jest.config.js", "babel.config.js", From 5bf8fffb80fdeda3b2cc4980dfa90b98411c385c Mon Sep 17 00:00:00 2001 From: David Joy Date: Wed, 31 Jul 2024 10:57:27 -0400 Subject: [PATCH 05/12] docs: adding an ADR about how SCSS must be imported --- .../0008-stylesheet-import-in-env-config.md | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 docs/decisions/0008-stylesheet-import-in-env-config.md diff --git a/docs/decisions/0008-stylesheet-import-in-env-config.md b/docs/decisions/0008-stylesheet-import-in-env-config.md new file mode 100644 index 00000000..42299b54 --- /dev/null +++ b/docs/decisions/0008-stylesheet-import-in-env-config.md @@ -0,0 +1,39 @@ +# Shell stylesheet must be imported in env.config file. + +## Summary + +A project must import the stylesheet for the application shell in its env.config file. + +## Context + +There is a particular quirk of the stylesheet loaders for webpack (style-loader and/or css-loader) where the import of stylesheets into JavaScript files must take place in a JS file in the project, not in library dependency like frontend-base. Further, the stylesheet imported into JS must _itself_ be a part of the project. + +If, for instance, we try to import a stylesheet from frontend-base (shell, header, footer, etc.) inside a React component inside the shell, webpack silently ignores the import and refuses to load the stylesheet. If we try to import a stylesheet from frontend-base directly into the env.config file in the project, that will also fail with webpack silently ignoring the stylesheet. If, however, frontend-base exports the stylesheet and it's loaded into a SCSS file in the project and _that_ is imported into env.config, everything works correctly. + +This slight indirection through a SCSS file in the project is necessary, and arguably desirable. It ensure as common, unified entry point for SCSS from dependencies of the project. SCSS from the project or micro-frontend itself can be imported into its own components, or can be imported into this top-level SCSS file as desired. Further, this ensures that every aspect of the style of a project or MFE can easily be customized since the stylesheet is supplied through the env.config file. + +## Decision + +As a best practice, a project should have a top-level SCSS file as a peer to the env.config file. This SCSS file should import the stylesheet from the frontend-base shell application. It should, in turn, be imported into the env.config file. + +## Implementation + +The `project.scss` file should import the stylesheet from the shell: + +```diff ++ @import '@openedx/frontend-base/shell/index.scss'; + +// other styles +``` + +The env.config file should then import the top-level SCSS file: + +```diff ++ import './project.scss'; + +const config = { + // config document +} + +export default config; +``` From 1d25dc52187e813eae838a7a2929c32b8df64417 Mon Sep 17 00:00:00 2001 From: David Joy Date: Wed, 31 Jul 2024 11:55:43 -0400 Subject: [PATCH 06/12] feat: getting a basic shell dev build working for MFEs This commit also adds a first draft of the steps necessary to convert an MFE to use the shell. Not everything described in those steps actually exists yet. The CLI commands may change, as well, along with the guts of the new webpack.shell.dev.config.js configuration. --- Makefile | 15 +- README.md | 51 ++++++- bin/openedx.js | 4 + cli/presets.js | 7 + config/webpack.shell.dev.config.js | 225 +++++++++++++++++++++++++++++ index.d.ts | 19 ++- package.json | 5 +- shell/bootstrap.tsx | 19 +-- tsconfig.json | 3 +- 9 files changed, 317 insertions(+), 31 deletions(-) create mode 100644 config/webpack.shell.dev.config.js diff --git a/Makefile b/Makefile index 6f69d3f1..8828e1d6 100644 --- a/Makefile +++ b/Makefile @@ -12,13 +12,14 @@ cat_docs_command = cat ./docs/_API-header.md ./docs/_API-body.md > ./docs/API.md build: rm -rf ./dist - ./node_modules/.bin/fedx-scripts babel src --out-dir dist --source-maps --ignore **/*.test.jsx,**/*.test.js,**/setupTest.js --copy-files - @# --copy-files will bring in everything else that wasn't processed by babel. Remove what we don't want. - @find dist -name '*.test.js*' -delete - rm ./dist/setupTest.js - cp ./package.json ./dist/package.json - cp ./LICENSE ./dist/LICENSE - cp ./README.md ./dist/README.md + tsc + cp index.d.ts dist/index.d.ts + mkdir -p ./scss/header/studio-header + + cp shell/index.scss dist/shell/index.scss + cp shell/header/index.scss dist/shell/header/index.scss + cp shell/header/Menu/menu.scss dist/shell/header/Menu/menu.scss + cp shell/header/studio-header/StudioHeader.scss dist/shell/header/studio-header/StudioHeader.scss docs-build: ${doc_command} diff --git a/README.md b/README.md index d70e1ef5..d12aca96 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ module.exports = { Follow the steps below to migrate an MFE to use frontend-base. -## Migrating to frontend-base +## Migrating to frontend-base (no shell) ### 1. Edit package.json `scripts` @@ -256,6 +256,55 @@ Remember to make the following substitution for these functions: + import { configureLogging } from '@openedx/frontend-base'; ``` +## Migrating to the frontend-base shell (:rotating_light: Work In Progress) + +This is an interim migration that helps prepare an MFE to be released as a set of modules suitable for module federation or being included as a plugin into the shell application. + +This migration may require some refactoring of the top-level files of the application; it is less straight-forward than simply replacing frontend-build and frontend-platform with frontend-base. + +Prior to attempting this, you _must_ complete the steps above to migrate your MFE to use frontend-base instead of frontend-build and frontend-platform. + +In spirit, in this migration we remove the initialization and header/footer code from the MFE and instead rely on the shell to manage our application. We turn the MFE into a set of exported modules, and to maintain backwards compatibility, we create a small 'project' in the repository that helps us build the MFE as an independent application. + +### 1. Remove initialization + +In your index.(jsx|tsx) file, you need to remove the subscribe and initialization code. If you have customizations here, they will need to migrate to your env.config.tsx file instead and take advantage of the shell's provided customization mechanisms. + +### 2. Migrate header/footer dependencies + +If your application uses a custom header or footer, you can use the shell's header and footer plugin slots to provide your custom header/footer components. This is done through the env.config.tsx file. + +### 3. Export the modules of your app as a component. + +This may require a little interpretation. In spirit, the modules of your app are the 'pages' of an Open edX Frontend site that it provides. This likely corresponds to the top-level react-router routes in your app. At the time of this writing, we don't have module federation yet, so to use the shell, you export all of your application code in a single component. In frontend-app-profile, for instance, this is the ProfilePage component. Some MFEs have put their router and pages directly into the index.jsx file inside the initialization callback - this code will need to be moved to a single component that can be exported. + +### 4. Create a project.scss file + +Create a new project.scss file at the top of your application. It's responsible for: + +1. Importing the shell's stylesheet, which includes Paragon's core stylesheet. +2. Importing your brand stylesheet. +3. Importing the stylesheets from your application. + +You must then import this new stylesheet into your env.config.tsx file: + +```diff ++ import './project.scss'; + +const config = { + // config document +} + +export default config; +``` + +### 5. Add new build scripts to package.json + +After the previous steps, the legacy `build` and `start` scripts in package.json will no longer work properly. They need to be replaced with versions from the `openedx` CLI that: + +- Build the MFE for production using the shell application. +- Build the MFE for dev using the shell application. +- Build the MFE for release as a library. ## Merging repositories diff --git a/bin/openedx.js b/bin/openedx.js index dfb6285e..e9f3e7ae 100755 --- a/bin/openedx.js +++ b/bin/openedx.js @@ -64,6 +64,10 @@ switch (commandName) { ensureConfigOption(presets.webpackDevServer); require('webpack-dev-server/bin/webpack-dev-server'); break; + case 'shell-dev-server': + ensureConfigOption(presets.shellDevServer); + require('webpack-dev-server/bin/webpack-dev-server'); + break; case 'formatjs': { const commonArgs = [ '--format', 'node_modules/@openedx/frontend-base/cli/formatter.js', diff --git a/cli/presets.js b/cli/presets.js index 9010eb59..ef398e67 100644 --- a/cli/presets.js +++ b/cli/presets.js @@ -26,6 +26,12 @@ const webpackDevServer = new ConfigPreset({ searchFilepaths, }); +const shellDevServer = new ConfigPreset({ + defaultFilename: 'webpack.shell.dev.config.js', + searchFilenames: ['webpack.shell.dev.config.js'], + searchFilepaths, +}); + const webpackDevServerStage = new ConfigPreset({ defaultFilename: 'webpack.dev-stage.config.js', searchFilenames: ['webpack.dev-stage.config.js'], @@ -46,6 +52,7 @@ module.exports = { webpackDevServer, 'webpack-dev': webpackDevServer, 'webpack-dev-server': webpackDevServer, + shellDevServer, webpackDevServerStage, 'webpack-dev-server-stage': webpackDevServerStage, 'webpack-dev-stage': webpackDevServerStage, diff --git a/config/webpack.shell.dev.config.js b/config/webpack.shell.dev.config.js new file mode 100644 index 00000000..8983a367 --- /dev/null +++ b/config/webpack.shell.dev.config.js @@ -0,0 +1,225 @@ +// This is the dev Webpack config. All settings here should prefer a fast build +// time at the expense of creating larger, unoptimized bundles. +const ImageMinimizerPlugin = require('image-minimizer-webpack-plugin'); + +const Dotenv = require('dotenv-webpack'); +const dotenv = require('dotenv'); +const HtmlWebpackPlugin = require('html-webpack-plugin'); +const path = require('path'); +const PostCssAutoprefixerPlugin = require('autoprefixer'); +const PostCssRTLCSS = require('postcss-rtlcss'); +const PostCssCustomMediaCSS = require('postcss-custom-media'); +const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin'); +const { transform } = require('@formatjs/ts-transformer'); + +const resolvePrivateEnvConfig = require('../cli/resolvePrivateEnvConfig'); +const getLocalAliases = require('./getLocalAliases'); + +// Add process env vars. Currently used only for setting the +// server port and the publicPath +dotenv.config({ + path: path.resolve(process.cwd(), '.env.development'), +}); + +// Allow private/local overrides of env vars from .env.development for config settings +// that you'd like to persist locally during development, without the risk of checking +// in temporary modifications to .env.development. +resolvePrivateEnvConfig('.env.private'); + +const aliases = getLocalAliases(); +const PUBLIC_PATH = process.env.PUBLIC_PATH || '/'; + +module.exports = { + entry: { + app: path.resolve(__dirname, '../shell/index'), + }, + output: { + path: path.resolve(process.cwd(), './dist'), + publicPath: PUBLIC_PATH, + }, + resolve: { + alias: { + ...aliases, + 'env.config': path.resolve(process.cwd(), './env.config'), + }, + fallback: { + // This causes the system to return an empty object if it can't find an env.config.js file in + // the application being built. + 'env.config': false, + }, + extensions: ['.js', '.jsx', '.ts', '.tsx'], + }, + ignoreWarnings: [ + // Ignore warnings raised by source-map-loader. + // some third party packages may ship miss-configured sourcemaps, that interrupts the build + // See: https://github.com/facebook/create-react-app/discussions/11278#discussioncomment-1780169 + /** + * + * @param {import('webpack').WebpackError} warning + * @returns {boolean} + */ + function ignoreSourcemapsloaderWarnings(warning) { + return ( + warning.module + && warning.module.resource.includes('node_modules') + && warning.details + && warning.details.includes('source-map-loader') + ); + }, + ], + mode: 'development', + devtool: 'eval-source-map', + module: { + // Specify file-by-file rules to Webpack. Some file-types need a particular kind of loader. + rules: [ + { + test: /\.(js|jsx|ts|tsx)$/, + include: [ + [ + /src/, + path.resolve(process.cwd(), './env.config.tsx'), + // /env.config/ // \.(js|jsx|ts|tsx)/, + ] + ], + use: { + loader: require.resolve('ts-loader'), + options: { + transpileOnly: true, + compilerOptions: { + noEmit: false, + }, + getCustomTransformers() { + return { + before: [ + transform({ + overrideIdFn: '[sha512:contenthash:base64:6]', + }), + ], + }; + }, + }, + }, + }, + // We are not extracting CSS from the javascript bundles in development because extracting + // prevents hot-reloading from working, it increases build time, and we don't care about + // flash-of-unstyled-content issues in development. + { + test: /(.scss|.css)$/, + use: [ + require.resolve('style-loader'), // creates style nodes from JS strings + { + loader: require.resolve('css-loader'), // translates CSS into CommonJS + options: { + sourceMap: true, + modules: { + compileType: 'icss', + }, + }, + }, + { + loader: require.resolve('postcss-loader'), + options: { + postcssOptions: { + plugins: [ + PostCssAutoprefixerPlugin(), + PostCssRTLCSS(), + PostCssCustomMediaCSS(), + ], + }, + }, + }, + require.resolve('resolve-url-loader'), + { + loader: require.resolve('sass-loader'), // compiles Sass to CSS + options: { + sourceMap: true, + sassOptions: { + includePaths: [ + path.join(process.cwd(), 'node_modules'), + path.join(process.cwd(), 'src'), + ], + // silences compiler warnings regarding deprecation warnings + quietDeps: true, + }, + }, + }, + ], + }, + // Webpack, by default, uses the url-loader for images and fonts that are required/included by + // files it processes, which just base64 encodes them and inlines them in the javascript + // bundles. This makes the javascript bundles ginormous and defeats caching so we will use the + // file-loader instead to copy the files directly to the output directory. + { + test: /\.(woff2?|ttf|svg|eot)(\?v=\d+\.\d+\.\d+)?$/, + loader: require.resolve('file-loader'), + }, + { + test: /favicon.ico$/, + loader: require.resolve('file-loader'), + options: { + name: '[name].[ext]', // <-- retain original file name + }, + }, + { + test: /\.(jpe?g|png|gif)(\?v=\d+\.\d+\.\d+)?$/, + loader: require.resolve('file-loader'), + }, + ], + }, + optimization: { + minimizer: [ + '...', + new ImageMinimizerPlugin({ + minimizer: { + implementation: ImageMinimizerPlugin.sharpMinify, + options: { + encodeOptions: { + ...['png', 'jpeg', 'jpg'].reduce((accumulator, value) => ( + { ...accumulator, [value]: { progressive: true, quality: 65 } } + ), {}), + gif: { + effort: 5, + }, + }, + }, + }, + }), + ], + }, + // Specify additional processing or side-effects done on the Webpack output bundles as a whole. + plugins: [ + // Generates an HTML file in the output directory. + new HtmlWebpackPlugin({ + inject: true, // Appends script tags linking to the webpack bundles at the end of the body + template: path.resolve(process.cwd(), 'public/index.html'), + FAVICON_URL: process.env.FAVICON_URL || null, + OPTIMIZELY_PROJECT_ID: process.env.OPTIMIZELY_PROJECT_ID || null, + NODE_ENV: process.env.NODE_ENV || null, + }), + new Dotenv({ + path: path.resolve(process.cwd(), '.env.development'), + systemvars: true, + }), + new ReactRefreshWebpackPlugin(), + ], + // This configures webpack-dev-server which serves bundles from memory and provides live + // reloading. + devServer: { + host: '0.0.0.0', + port: process.env.PORT || 8080, + historyApiFallback: { + index: path.join(PUBLIC_PATH, 'index.html'), + disableDotRule: true, + }, + // Enable hot reloading server. It will provide WDS_SOCKET_PATH endpoint + // for the WebpackDevServer client so it can learn when the files were + // updated. The WebpackDevServer client is included as an entry point + // in the webpack development configuration. Note that only changes + // to CSS are currently hot reloaded. JS changes will refresh the browser. + hot: true, + webSocketServer: 'ws', + devMiddleware: { + publicPath: PUBLIC_PATH, + }, + }, +}; diff --git a/index.d.ts b/index.d.ts index b2cc84e7..7b5ce813 100644 --- a/index.d.ts +++ b/index.d.ts @@ -101,10 +101,19 @@ export { } from './runtime'; declare module 'env.config' { + export default OpenedXConfig; +} + +declare module '*.svg' { + const content: string; + export default content; +} - export default { - modules: { - [key]: Component - } - }; +export interface OpenedXConfig { + /** + * The application content for the shell. This is a temporary configuration option while we + * convert micro-frontends to plugins. It must be a React functional component that takes no + * arguments and returns JSX. + */ + app?: () => JSX.Element } diff --git a/package.json b/package.json index 8bcce0ba..96c16fc1 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "files": [ "/dist", "/config", - "/cli" + "/cli", + "/shell/**/*.scss" ], "bin": { "openedx": "dist/bin/openedx.js", @@ -19,7 +20,7 @@ "transifex-utils.js": "dist/cli/scripts/transifex-utils.js" }, "scripts": { - "build": "tsc", + "build": "make build", "build:watch": "tsc --watch", "clean": "rm -rf dist", "docs": "jsdoc -c jsdoc.json", diff --git a/shell/bootstrap.tsx b/shell/bootstrap.tsx index 7af5329e..5ef7cb7e 100644 --- a/shell/bootstrap.tsx +++ b/shell/bootstrap.tsx @@ -1,32 +1,23 @@ -import { init } from '@module-federation/runtime'; +import { createElement } from 'react'; import ReactDOM from 'react-dom'; + import { APP_INIT_ERROR, APP_READY, AppProvider, + getConfig, initialize, subscribe, } from '../runtime'; import Header from './header'; -import './index.scss'; const messages = []; -init({ - name: 'host', - remotes: [ - { - name: 'guest', - entry: 'http://localhost:8081/remoteEntry.js', - }, - ], -}); - subscribe(APP_READY, () => { ReactDOM.render(
-
Hi there.
+ {getConfig().app ? createElement(getConfig().app, {}) : null} , document.getElementById('root'), ); @@ -39,6 +30,6 @@ subscribe(APP_INIT_ERROR, (error) => { initialize({ messages, handlers: { - auth: () => { }, // This MFE turns off auth so it can run independently of edx-platform. + auth: () => {}, // This MFE turns off auth so it can run independently of edx-platform. }, }); diff --git a/tsconfig.json b/tsconfig.json index 02825d2e..ae1228ed 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,17 +4,16 @@ "rootDir": ".", "outDir": "dist", "noEmit": false, + "declaration": false, }, "include": [ "bin/**/*", "cli/**/*", "config/**/*", - "config/.eslintrc.js", "runtime/**/*", "shell/**/*", "index.ts", "index.d.ts", - "config/tsconfig.json", "jest.config.js", "babel.config.js", ], From 4122a850117dc78661680c5b4983853c85b5e800 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 24 Jul 2024 21:32:32 +0000 Subject: [PATCH 07/12] fix(deps): update dependency @openedx/paragon to v22.7.0 --- test-app/package-lock.json | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/test-app/package-lock.json b/test-app/package-lock.json index 9148e8e1..f9c4b1f9 100644 --- a/test-app/package-lock.json +++ b/test-app/package-lock.json @@ -83,6 +83,7 @@ "postcss-custom-media": "10.0.6", "postcss-loader": "7.3.4", "postcss-rtlcss": "5.1.2", + "prop-types": "^15.8.1", "pubsub-js": "^1.9.4", "react-dev-utils": "12.0.1", "react-intl": "^6.6.6", @@ -391,9 +392,17 @@ "link": true }, "node_modules/@openedx/paragon": { - "version": "22.6.1", - "resolved": "https://registry.npmjs.org/@openedx/paragon/-/paragon-22.6.1.tgz", - "integrity": "sha512-xblrspAfsYsiDzyLIh+tceiTPgx1HY6v0eceatTYSj/BINxN8Dcqh9uQOZi2eJc1os3w2dr0nZRGnTt8cYu2BA==", + "version": "22.7.0", + "resolved": "https://registry.npmjs.org/@openedx/paragon/-/paragon-22.7.0.tgz", + "integrity": "sha512-BWj4vYXUmLS0BinJckxbhNp0o1UPfwURinaSgTxxBkF0L2VUtAO+SldVWvKDqlltzoR062yjcBA5QSGq8Jxgeg==", + "license": "Apache-2.0", + "workspaces": [ + "example", + "component-generator", + "www", + "icons", + "dependent-usage-analyzer" + ], "dependencies": { "@fortawesome/fontawesome-svg-core": "^6.1.1", "@fortawesome/react-fontawesome": "^0.1.18", From eb1fe4b6ac7998d5710194d47c81c0c1a4621115 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 25 Jul 2024 02:39:55 +0000 Subject: [PATCH 08/12] fix(deps): update dependency postcss to v8.4.40 --- package-lock.json | 11 ++++++----- package.json | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 89c5021b..4ebeaf5b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,7 +62,7 @@ "lodash.merge": "^4.6.2", "lodash.snakecase": "^4.1.1", "mini-css-extract-plugin": "1.6.2", - "postcss": "8.4.38", + "postcss": "8.4.40", "postcss-custom-media": "10.0.6", "postcss-loader": "7.3.4", "postcss-rtlcss": "5.1.2", @@ -12176,9 +12176,9 @@ } }, "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "version": "8.4.40", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", + "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", "funding": [ { "type": "opencollective", @@ -12193,9 +12193,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "source-map-js": "^1.2.0" }, "engines": { diff --git a/package.json b/package.json index 96c16fc1..2aab6155 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "lodash.merge": "^4.6.2", "lodash.snakecase": "^4.1.1", "mini-css-extract-plugin": "1.6.2", - "postcss": "8.4.38", + "postcss": "8.4.40", "postcss-custom-media": "10.0.6", "postcss-loader": "7.3.4", "postcss-rtlcss": "5.1.2", From c8038a5a0025c972ed1db44351d71809ddabd99f Mon Sep 17 00:00:00 2001 From: David Joy Date: Wed, 31 Jul 2024 12:01:18 -0400 Subject: [PATCH 09/12] build: Temporarily turn off renovate automerge We still have two repositories to merge into frontend-base: frontend-component-footer and frontend-plugin-framework. If Renovate pushes commits to main while we're trying to pull in hundreds of commits from those repositories, it makes rebasing on top of renovate's commits nearly impossible. For now, let's just turn off auto-merging of renovate commits until we get these repos in. --- renovate.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/renovate.json b/renovate.json index 129b49ac..00fcd1f6 100644 --- a/renovate.json +++ b/renovate.json @@ -4,7 +4,7 @@ "config:recommended" ], "patch": { - "automerge": true + "automerge": false }, "rebaseStalePrs": true, "packageRules": [ @@ -17,7 +17,7 @@ { "matchPackagePatterns": ["@edx", "@openedx"], "matchUpdateTypes": ["minor", "patch"], - "automerge": true + "automerge": false } ] } From d5dd9f7a772ce5f4e1d69bda23662c44c7c26c95 Mon Sep 17 00:00:00 2001 From: David Joy Date: Wed, 31 Jul 2024 12:17:46 -0400 Subject: [PATCH 10/12] fix: fixing up jest dependencies Should satisfy the linter. --- package-lock.json | 7 +++++++ package.json | 1 + shell/header/setupTest.js | 1 - test-app/package-lock.json | 6 ++++-- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4ebeaf5b..bc548dd1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -101,6 +101,7 @@ "@types/react": "^17.0.0", "@types/react-dom": "^17.0.11", "axios-mock-adapter": "^1.22.0", + "jest-chain": "^1.1.6", "jsdoc": "^4.0.3", "nodemon": "^3.1.4", "react-test-renderer": "^17.0.2" @@ -9728,6 +9729,12 @@ } } }, + "node_modules/jest-chain": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/jest-chain/-/jest-chain-1.1.6.tgz", + "integrity": "sha512-eIkGzVBGQ1VuEErDceMYAET53pcwYVVTXtJEbY+x60Dwi+2M2uOt4rhKAej+wfVOAlE4G0plI9mstmv6GBtJjw==", + "dev": true + }, "node_modules/jest-changed-files": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", diff --git a/package.json b/package.json index 2aab6155..5fb424ab 100644 --- a/package.json +++ b/package.json @@ -131,6 +131,7 @@ "@types/react": "^17.0.0", "@types/react-dom": "^17.0.11", "axios-mock-adapter": "^1.22.0", + "jest-chain": "^1.1.6", "jsdoc": "^4.0.3", "nodemon": "^3.1.4", "react-test-renderer": "^17.0.2" diff --git a/shell/header/setupTest.js b/shell/header/setupTest.js index 8f26495a..44992f2d 100644 --- a/shell/header/setupTest.js +++ b/shell/header/setupTest.js @@ -1,7 +1,6 @@ /* eslint-disable import/no-extraneous-dependencies */ import '@testing-library/jest-dom'; -import '@testing-library/jest-dom/extend-expect'; import { render as rtlRender } from '@testing-library/react'; import 'jest-chain'; import PropTypes from 'prop-types'; diff --git a/test-app/package-lock.json b/test-app/package-lock.json index f9c4b1f9..4b889576 100644 --- a/test-app/package-lock.json +++ b/test-app/package-lock.json @@ -79,7 +79,7 @@ "lodash.merge": "^4.6.2", "lodash.snakecase": "^4.1.1", "mini-css-extract-plugin": "1.6.2", - "postcss": "8.4.38", + "postcss": "8.4.40", "postcss-custom-media": "10.0.6", "postcss-loader": "7.3.4", "postcss-rtlcss": "5.1.2", @@ -88,6 +88,7 @@ "react-dev-utils": "12.0.1", "react-intl": "^6.6.6", "react-refresh": "0.14.2", + "react-responsive": "^10.0.0", "resolve-url-loader": "5.0.0", "sass": "1.69.7", "sass-loader": "13.3.3", @@ -118,7 +119,8 @@ "@types/react-dom": "^17.0.11", "axios-mock-adapter": "^1.22.0", "jsdoc": "^4.0.3", - "nodemon": "^3.1.4" + "nodemon": "^3.1.4", + "react-test-renderer": "^17.0.2" }, "peerDependencies": { "@openedx/paragon": "^22.6.1", From 1bf4ff774f99d7322f94ac648b88854e15f6efe8 Mon Sep 17 00:00:00 2001 From: David Joy Date: Wed, 31 Jul 2024 13:16:31 -0400 Subject: [PATCH 11/12] fix: getting rid of d.ts linting errors, exporting properly At least I think this exports it properly; seems to work in apps! --- .eslintrc.js | 1 + Makefile | 2 +- frontend-base.d.ts | 12 +++++ index.d.ts | 119 --------------------------------------------- index.ts | 9 ++++ package.json | 3 +- tsconfig.json | 3 +- 7 files changed, 25 insertions(+), 124 deletions(-) create mode 100644 frontend-base.d.ts delete mode 100644 index.d.ts diff --git a/.eslintrc.js b/.eslintrc.js index e50d3c32..27ba428e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -7,6 +7,7 @@ module.exports = createConfig('eslint', { 'test-app', 'docs', '.eslintrc.js', + 'frontend-base.d.ts', ], parserOptions: { project: path.resolve(__dirname, './tsconfig.json'), diff --git a/Makefile b/Makefile index 8828e1d6..d662cf2c 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ cat_docs_command = cat ./docs/_API-header.md ./docs/_API-body.md > ./docs/API.md build: rm -rf ./dist tsc - cp index.d.ts dist/index.d.ts + cp frontend-base.d.ts dist/frontend-base.d.ts mkdir -p ./scss/header/studio-header cp shell/index.scss dist/shell/index.scss diff --git a/frontend-base.d.ts b/frontend-base.d.ts new file mode 100644 index 00000000..b2db15f7 --- /dev/null +++ b/frontend-base.d.ts @@ -0,0 +1,12 @@ +/// + +import { OpenedXConfig } from "./dist"; + +declare module 'env.config' { + export default OpenedXConfig; +} + +declare module '*.svg' { + const content: string; + export default content; +} diff --git a/index.d.ts b/index.d.ts deleted file mode 100644 index 7b5ce813..00000000 --- a/index.d.ts +++ /dev/null @@ -1,119 +0,0 @@ -export { - APP_ANALYTICS_INITIALIZED, - APP_AUTH_INITIALIZED, - APP_CONFIG_INITIALIZED, - APP_I18N_INITIALIZED, - APP_INIT_ERROR, - APP_LOGGING_INITIALIZED, - APP_PUBSUB_INITIALIZED, - APP_READY, - APP_TOPIC, - AUTHENTICATED_USER_CHANGED, - AUTHENTICATED_USER_TOPIC, - AppContext, - AppProvider, - AuthenticatedPageRoute, - AxiosJwtAuthService, - CONFIG_CHANGED, - CONFIG_TOPIC, - ErrorBoundary, - ErrorPage, - FormattedDate, - FormattedMessage, - FormattedNumber, - FormattedPlural, - FormattedRelativeTime, - FormattedTime, - IntlProvider, - LOCALE_CHANGED, - LOCALE_TOPIC, - LoginRedirect, - MockAnalyticsService, - MockAuthService, - MockLoggingService, - NewRelicLoggingService, - PageWrap, - SegmentAnalyticsService, - auth, - camelCaseObject, - configureAnalytics, - configureAuth, - configureI18n, - configureLogging, - convertKeyNames, - createIntl, - defineMessages, - ensureAuthenticatedUser, - ensureConfig, - ensureDefinedConfig, - fetchAuthenticatedUser, - getAnalyticsService, - getAuthService, - getAuthenticatedHttpClient, - getAuthenticatedUser, - getConfig, - getCountryList, - getCountryMessages, - getHttpClient, - getLanguageList, - getLanguageMessages, - getLocale, - getLoggingService, - getLoginRedirectUrl, - getLogoutRedirectUrl, - getMessages, - getPath, - getPrimaryLanguageSubtag, - getQueryParameters, - handleRtl, - history, - hydrateAuthenticatedUser, - identifyAnonymousUser, - identifyAuthenticatedUser, - initError, - initialize, - initializeMockApp, - injectIntl, - intlShape, - isRtl, - logError, - logInfo, - mergeConfig, - mergeMessages, - mockMessages, - modifyObjectKeys, - parseURL, - publish, - redirectToLogin, - redirectToLogout, - resetAnalyticsService, - resetLoggingService, - sendPageEvent, - sendTrackEvent, - sendTrackingLogEvent, - setAuthenticatedUser, - setConfig, - snakeCaseObject, - subscribe, - unsubscribe, - useAppEvent, - useIntl -} from './runtime'; - -declare module 'env.config' { - export default OpenedXConfig; -} - -declare module '*.svg' { - const content: string; - export default content; -} - -export interface OpenedXConfig { - /** - * The application content for the shell. This is a temporary configuration option while we - * convert micro-frontends to plugins. It must be a React functional component that takes no - * arguments and returns JSX. - */ - app?: () => JSX.Element -} diff --git a/index.ts b/index.ts index b85804d5..701c8cec 100644 --- a/index.ts +++ b/index.ts @@ -99,3 +99,12 @@ export { useAppEvent, useIntl } from './runtime'; + +export interface OpenedXConfig { + /** + * The application content for the shell. This is a temporary configuration option while we + * convert micro-frontends to plugins. It must be a React functional component that takes no + * arguments and returns JSX. + */ + app?: () => JSX.Element +} diff --git a/package.json b/package.json index 5fb424ab..a200d699 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ }, "main": "dist/index.js", "module": "dist/index.js", - "types": "dist/index.d.ts", + "types": "dist/frontend-base.d.ts", "files": [ "/dist", "/config", @@ -21,7 +21,6 @@ }, "scripts": { "build": "make build", - "build:watch": "tsc --watch", "clean": "rm -rf dist", "docs": "jsdoc -c jsdoc.json", "docs:watch": "nodemon -w runtime -w docs/template -w README.md -e js,jsx,ts,tsx --exec npm run docs", diff --git a/tsconfig.json b/tsconfig.json index ae1228ed..1c23ce1e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,7 @@ "rootDir": ".", "outDir": "dist", "noEmit": false, - "declaration": false, + "declaration": true, }, "include": [ "bin/**/*", @@ -13,7 +13,6 @@ "runtime/**/*", "shell/**/*", "index.ts", - "index.d.ts", "jest.config.js", "babel.config.js", ], From 1263a54c3273ad24831890888a2c5638576c98b1 Mon Sep 17 00:00:00 2001 From: David Joy Date: Wed, 31 Jul 2024 13:22:22 -0400 Subject: [PATCH 12/12] test: removing old snapshot and updating test-app- package-lock.json Just tryin to get the test suite to pass here! --- test-app/package-lock.json | 1 + test-app/src/__snapshots__/App.test.jsx.snap | 101 ------------------- 2 files changed, 1 insertion(+), 101 deletions(-) delete mode 100644 test-app/src/__snapshots__/App.test.jsx.snap diff --git a/test-app/package-lock.json b/test-app/package-lock.json index 4b889576..e7238f79 100644 --- a/test-app/package-lock.json +++ b/test-app/package-lock.json @@ -118,6 +118,7 @@ "@types/react": "^17.0.0", "@types/react-dom": "^17.0.11", "axios-mock-adapter": "^1.22.0", + "jest-chain": "^1.1.6", "jsdoc": "^4.0.3", "nodemon": "^3.1.4", "react-test-renderer": "^17.0.2" diff --git a/test-app/src/__snapshots__/App.test.jsx.snap b/test-app/src/__snapshots__/App.test.jsx.snap deleted file mode 100644 index cc695322..00000000 --- a/test-app/src/__snapshots__/App.test.jsx.snap +++ /dev/null @@ -1,101 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Basic test should render 1`] = ` -
-

- Test page -

-

- SCSS parsing tests -

-

- The Apples -

- ("The Apples" should be red) -

- ES6 parsing tests -

-
    -
  • - macintosh -
  • -
  • - granny smith -
  • -
  • - fuji -
  • -
  • - golden delicious -
  • -
-

- TSX parsing tests -

- appleFromTsx -

- Asset import tests -

- apple -
- apple -

- Photo by Louis Hansel @shotsoflouis on Unsplash -

-

- process.env tests -

-

- Test process.env variable: - foo -

-

- Non-existent process.env variable (nothing here is good): -

-

- env.config.js tests -

-

- - env.config.js boolean test: - - Good, false meant false. We did not cast a boolean to a string. -

-

- env.config.js integer test: - It was an integer. Great. -

-

- Right-to-left language handling tests -

-

- I'm aligned right, but left in RTL. -

-
-`;