diff --git a/.gitignore b/.gitignore index 7eece73b15..bae85f9b0b 100644 --- a/.gitignore +++ b/.gitignore @@ -80,3 +80,7 @@ scripts/jest/.jest-cache # credentials file to load credentials.json +# Locally I have had to add these because of: https://github.com/yarnpkg/yarn/issues/7807 +# May need to include globally if other people experienece installing issues +.yarnrc +.yarn \ No newline at end of file diff --git a/package.json b/package.json index 4afdd6910a..5646cf6718 100644 --- a/package.json +++ b/package.json @@ -179,6 +179,6 @@ "webpack": "^4.41.5", "webpack-cli": "^3.3.2", "webpack-dev-server": "^3.4.1", - "workbox-webpack-plugin": "^4.3.1" + "workbox-webpack-plugin": "^5.1.3" } } diff --git a/packages/developer-portal/src/components/hocs/__tests__/route-fetcher.tsx b/packages/developer-portal/src/components/hocs/__tests__/route-fetcher.tsx index 31ee160852..213b26e1be 100644 --- a/packages/developer-portal/src/components/hocs/__tests__/route-fetcher.tsx +++ b/packages/developer-portal/src/components/hocs/__tests__/route-fetcher.tsx @@ -12,7 +12,7 @@ const props = { Component, routerProps: { match: { - path: Routes.CLIENT, + path: Routes.DEVELOPER, params: { page: 1 }, }, location: { diff --git a/packages/developer-portal/src/components/pages/__tests__/__snapshots__/developer-submit-app-successfully.tsx.snap b/packages/developer-portal/src/components/pages/__tests__/__snapshots__/developer-submit-app-successfully.tsx.snap deleted file mode 100644 index 0284a8937c..0000000000 --- a/packages/developer-portal/src/components/pages/__tests__/__snapshots__/developer-submit-app-successfully.tsx.snap +++ /dev/null @@ -1,77 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`DeveloperSubmitAppSuccessfully renders correctly 1`] = ` - - - - - My Apps - - - Submit another app - - - } - isCard={true} - title="Success" - > -

- Your App has now been registered and can be accessed by clicking on ‘My Apps’ below. -

-
-

- You will be directed to the ‘My Apps’ page where you will be able to access the ‘Client ID’ of your App (required for authentication) and or make any changes to your App by clicking ‘Edit Details’. -

-
-

- - Currently, your App is only visible to you - - and will not be available in the Marketplace until you have made it ‘Listed’. When you are ready to do this, click on ‘Edit Detail’ and tick the ‘Is Listed’ check box located in the ‘Marketplace Status’ section. -

-
-

- - Please note: - - Any changes you make now to your App (including making it ‘Listed’) will require approval. These are called ‘Revisions’. All revisions will be sent to our Admin department and whilst your App is being reviewed, you will not be able to make any further changes and the App will be marked as ‘Pending Revision’. -

-
-

- Once you have ‘Listed’ your application, and any revisions have been approved, your app will be live in the Marketplace and available for install by customers. -

-
-

- For any issues or support, please visit the - - ‘Help’ - - page. -

-
-
-
-
-`; diff --git a/packages/developer-portal/src/components/pages/__tests__/developer-submit-app-successfully.tsx b/packages/developer-portal/src/components/pages/__tests__/developer-submit-app-successfully.tsx deleted file mode 100644 index 262bc80660..0000000000 --- a/packages/developer-portal/src/components/pages/__tests__/developer-submit-app-successfully.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import * as React from 'react' -import { shallow } from 'enzyme' -import { - DeveloperSubmitAppSuccessfully, - DeveloperSubmitAppSuccessfullyProps, -} from '../developer-submit-app-successfully' - -describe('DeveloperSubmitAppSuccessfully', () => { - it('renders correctly', () => { - const props: DeveloperSubmitAppSuccessfullyProps = { - onGoBackToApps: jest.fn(), - onSubmitAnotherApp: jest.fn(), - } - - expect(shallow()).toMatchSnapshot() - }) -}) diff --git a/packages/developer-portal/src/components/pages/__tests__/__snapshots__/api-docs.tsx.snap b/packages/developer-portal/src/components/pages/api-docs/__tests__/__snapshots__/api-docs.test.tsx.snap similarity index 100% rename from packages/developer-portal/src/components/pages/__tests__/__snapshots__/api-docs.tsx.snap rename to packages/developer-portal/src/components/pages/api-docs/__tests__/__snapshots__/api-docs.test.tsx.snap diff --git a/packages/developer-portal/src/components/pages/__tests__/api-docs.tsx b/packages/developer-portal/src/components/pages/api-docs/__tests__/api-docs.test.tsx similarity index 91% rename from packages/developer-portal/src/components/pages/__tests__/api-docs.tsx rename to packages/developer-portal/src/components/pages/api-docs/__tests__/api-docs.test.tsx index a91dd08edf..6f7a1eeaf7 100644 --- a/packages/developer-portal/src/components/pages/__tests__/api-docs.tsx +++ b/packages/developer-portal/src/components/pages/api-docs/__tests__/api-docs.test.tsx @@ -20,7 +20,7 @@ describe('ApiDocs', () => { describe('parseIframeUrl', () => { it('should run correctly', () => { - const pathname = `${Routes.DEVELOPER_API_DOCS}/platform-glossary` + const pathname = `${Routes.API_DOCS}/platform-glossary` const hash = '#company' const result = parseIframeUrl(pathname, hash) expect(result).toEqual('/platform-glossary#company') diff --git a/packages/developer-portal/src/components/pages/api-docs.tsx b/packages/developer-portal/src/components/pages/api-docs/api-docs.tsx similarity index 84% rename from packages/developer-portal/src/components/pages/api-docs.tsx rename to packages/developer-portal/src/components/pages/api-docs/api-docs.tsx index 3136b8e04f..35f89b33ab 100644 --- a/packages/developer-portal/src/components/pages/api-docs.tsx +++ b/packages/developer-portal/src/components/pages/api-docs/api-docs.tsx @@ -2,13 +2,13 @@ import * as React from 'react' import { useHistory } from 'react-router' import ErrorBoundary from '@/components/hocs/error-boundary' import { UnsupportBrowserPopUp } from '@/components/ui/unsupport-browser-pop-up' -import { IFRAME_URLS } from '../../constants/iframe-urls' -import Routes from '../../constants/routes' import { isIE } from '@/utils/browser' +import Routes from '@/constants/routes' +import { IFRAME_URLS } from '@/constants/iframe-urls' export const parseIframeUrl = (pathname: string, hash: string): string => { - const path = pathname.split(Routes.DEVELOPER_API_DOCS)[1] - return `${path}${hash}` + const documentPagePath = pathname.split(Routes.API_DOCS)[1] + return `${documentPagePath}${hash}` } const ApiDocsPage: React.FC = () => { diff --git a/packages/developer-portal/src/components/pages/api-docs/index.ts b/packages/developer-portal/src/components/pages/api-docs/index.ts new file mode 100644 index 0000000000..d77d2767a5 --- /dev/null +++ b/packages/developer-portal/src/components/pages/api-docs/index.ts @@ -0,0 +1,2 @@ +import APIDocs from './api-docs' +export default APIDocs diff --git a/packages/developer-portal/src/components/pages/app-detail/__tests__/app-detail.test.tsx b/packages/developer-portal/src/components/pages/app-detail/__tests__/app-detail.test.tsx index 69c512b481..513aa3c482 100644 --- a/packages/developer-portal/src/components/pages/app-detail/__tests__/app-detail.test.tsx +++ b/packages/developer-portal/src/components/pages/app-detail/__tests__/app-detail.test.tsx @@ -35,7 +35,7 @@ describe('DeveloperAppDetail', () => { expect( mount( - + , diff --git a/packages/developer-portal/src/components/pages/app-detail/__tests__/app-management.test.tsx b/packages/developer-portal/src/components/pages/app-detail/__tests__/app-management.test.tsx index c9a77ff4f9..f14bd63577 100644 --- a/packages/developer-portal/src/components/pages/app-detail/__tests__/app-management.test.tsx +++ b/packages/developer-portal/src/components/pages/app-detail/__tests__/app-management.test.tsx @@ -43,7 +43,7 @@ describe('ManageApp', () => { expect( mount( - + { it('should run correctly', () => { const fn = onMarketplaceButtonClick(history) fn() - expect(history.replace).toBeCalledWith(Routes.CLIENT) + expect(history.replace).toBeCalledWith(Routes.DEVELOPER) }) }) describe('onRegisterButtonClick', () => { @@ -74,7 +74,7 @@ describe('Authentication', () => { it('should run correctly', () => { const fn = onDevelopersButtonClick(history) fn() - expect(history.replace).toBeCalledWith(Routes.DEVELOPER_DESKTOP) + expect(history.replace).toBeCalledWith(Routes.DESKTOP) }) }) }) diff --git a/packages/developer-portal/src/components/pages/authentication/authentication.tsx b/packages/developer-portal/src/components/pages/authentication/authentication.tsx index f6a12eaf6f..4220421180 100644 --- a/packages/developer-portal/src/components/pages/authentication/authentication.tsx +++ b/packages/developer-portal/src/components/pages/authentication/authentication.tsx @@ -17,7 +17,7 @@ export interface AuthenticationParamTypes { export const onDevelopersButtonClick = (history: History) => { return () => { - history.replace(Routes.DEVELOPER_DESKTOP) + history.replace(Routes.DESKTOP) } } @@ -58,7 +58,7 @@ export const renderClientModal = (history, dispatch) => { please visit the  - Desktop + Desktop  page within the Developers Portal, where you can subscribe to a Developer Edition of Agency Cloud. diff --git a/packages/developer-portal/src/components/pages/developer-desktop/__styles__/pricing-tile.tsx b/packages/developer-portal/src/components/pages/desktop/__styles__/pricing-tile.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-desktop/__styles__/pricing-tile.tsx rename to packages/developer-portal/src/components/pages/desktop/__styles__/pricing-tile.tsx diff --git a/packages/developer-portal/src/components/pages/developer-desktop/__tests__/__snapshots__/developer-desktop.tsx.snap b/packages/developer-portal/src/components/pages/desktop/__tests__/__snapshots__/desktop.test.tsx.snap similarity index 100% rename from packages/developer-portal/src/components/pages/developer-desktop/__tests__/__snapshots__/developer-desktop.tsx.snap rename to packages/developer-portal/src/components/pages/desktop/__tests__/__snapshots__/desktop.test.tsx.snap diff --git a/packages/developer-portal/src/components/pages/developer-desktop/__tests__/developer-desktop.tsx b/packages/developer-portal/src/components/pages/desktop/__tests__/desktop.test.tsx similarity index 97% rename from packages/developer-portal/src/components/pages/developer-desktop/__tests__/developer-desktop.tsx rename to packages/developer-portal/src/components/pages/desktop/__tests__/desktop.test.tsx index 606db34350..7361aa8451 100644 --- a/packages/developer-portal/src/components/pages/developer-desktop/__tests__/developer-desktop.tsx +++ b/packages/developer-portal/src/components/pages/desktop/__tests__/desktop.test.tsx @@ -3,7 +3,7 @@ import { mount } from 'enzyme' import { Provider } from 'react-redux' import configureStore from 'redux-mock-store' import appState from '@/reducers/__stubs__/app-state' -import { DeveloperDesktopPage, handleToggleVisibleModal } from '../developer-desktop' +import { DeveloperDesktopPage, handleToggleVisibleModal } from '../desktop' describe('DeveloperDesktopPage', () => { let store diff --git a/packages/developer-portal/src/components/pages/developer-desktop/developer-desktop.tsx b/packages/developer-portal/src/components/pages/desktop/desktop.tsx similarity index 97% rename from packages/developer-portal/src/components/pages/developer-desktop/developer-desktop.tsx rename to packages/developer-portal/src/components/pages/desktop/desktop.tsx index 99d7ec9b9a..b7d0cdefc5 100644 --- a/packages/developer-portal/src/components/pages/developer-desktop/developer-desktop.tsx +++ b/packages/developer-portal/src/components/pages/desktop/desktop.tsx @@ -31,7 +31,7 @@ export const DeveloperDesktopContentPartOne: React.FC = () => {

To learn more about what’s possible with the Desktop API, please visit the{' '} - + documentation.

diff --git a/packages/developer-portal/src/components/pages/desktop/index.ts b/packages/developer-portal/src/components/pages/desktop/index.ts new file mode 100644 index 0000000000..814a0ba95c --- /dev/null +++ b/packages/developer-portal/src/components/pages/desktop/index.ts @@ -0,0 +1 @@ +export { default } from './desktop' diff --git a/packages/developer-portal/src/components/pages/developer-desktop/index.ts b/packages/developer-portal/src/components/pages/developer-desktop/index.ts deleted file mode 100644 index 645f2fde85..0000000000 --- a/packages/developer-portal/src/components/pages/developer-desktop/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { default } from './developer-desktop' diff --git a/packages/developer-portal/src/components/pages/developer-submit-app-successfully.tsx b/packages/developer-portal/src/components/pages/developer-submit-app-successfully.tsx deleted file mode 100644 index 2246537a2e..0000000000 --- a/packages/developer-portal/src/components/pages/developer-submit-app-successfully.tsx +++ /dev/null @@ -1,70 +0,0 @@ -import * as React from 'react' -import { FlexContainerResponsive, Button } from '@reapit/elements' -import CallToAction from '../ui/call-to-action' -import styles from '@/styles/pages/developer-submit-app-successfully.scss?mod' -import { Link } from 'react-router-dom' -import Routes from '@/constants/routes' - -export interface DeveloperSubmitAppSuccessfullyProps { - onGoBackToApps: () => void - onSubmitAnotherApp: () => void -} -export const DeveloperSubmitAppSuccessfully: React.FC = ({ - onGoBackToApps, - onSubmitAnotherApp, -}) => ( - - - - - - - } - > -

Your App has now been registered and can be accessed by clicking on ‘My Apps’ below.

-
-

- You will be directed to the ‘My Apps’ page where you will be able to access the ‘Client - ID’ of your App (required for authentication) and or make any changes to your App by clicking - ‘Edit Details’. -

-
-

- Currently, your App is only visible to you and will not be available in the Marketplace until - you have made it ‘Listed’. When you are ready to do this, click on ‘Edit Detail’ and - tick the ‘Is Listed’ check box located in the ‘Marketplace Status’ section. -

-
-

- Please note: Any changes you make now to your App (including making it ‘Listed’) - will require approval. These are called ‘Revisions’. All revisions will be sent to our Admin - department and whilst your App is being reviewed, you will not be able to make any further changes and the App - will be marked as ‘Pending Revision’. -

-
-

- Once you have ‘Listed’ your application, and any revisions have been approved, your app will be - live in the Marketplace and available for install by customers. -

-
-

- For any issues or support, please visit the ‘Help’ page. -

- -
-
-
-
-) - -export default DeveloperSubmitAppSuccessfully diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/agency-cloud-integration-section.test.tsx.snap b/packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/agency-cloud-integration-section.test.tsx.snap similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/agency-cloud-integration-section.test.tsx.snap rename to packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/agency-cloud-integration-section.test.tsx.snap diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/authentication-flow-section.test.tsx.snap b/packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/authentication-flow-section.test.tsx.snap similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/authentication-flow-section.test.tsx.snap rename to packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/authentication-flow-section.test.tsx.snap diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/developer-edit-app.test.tsx.snap b/packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/developer-edit-app.test.tsx.snap similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/developer-edit-app.test.tsx.snap rename to packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/developer-edit-app.test.tsx.snap diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/general-information-section.test.tsx.snap b/packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/general-information-section.test.tsx.snap similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/general-information-section.test.tsx.snap rename to packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/general-information-section.test.tsx.snap diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/marketplace-status-section.test.tsx.snap b/packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/marketplace-status-section.test.tsx.snap similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/marketplace-status-section.test.tsx.snap rename to packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/marketplace-status-section.test.tsx.snap diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/permission-section.test.tsx.snap b/packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/permission-section.test.tsx.snap similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/permission-section.test.tsx.snap rename to packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/permission-section.test.tsx.snap diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/redirect-uri-section.test.tsx.snap b/packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/redirect-uri-section.test.tsx.snap similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/redirect-uri-section.test.tsx.snap rename to packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/redirect-uri-section.test.tsx.snap diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/upload-image-section.test.tsx.snap b/packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/upload-image-section.test.tsx.snap similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/__snapshots__/upload-image-section.test.tsx.snap rename to packages/developer-portal/src/components/pages/edit-app/__tests__/__snapshots__/upload-image-section.test.tsx.snap diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/agency-cloud-integration-section.test.tsx b/packages/developer-portal/src/components/pages/edit-app/__tests__/agency-cloud-integration-section.test.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/agency-cloud-integration-section.test.tsx rename to packages/developer-portal/src/components/pages/edit-app/__tests__/agency-cloud-integration-section.test.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/authentication-flow-section.test.tsx b/packages/developer-portal/src/components/pages/edit-app/__tests__/authentication-flow-section.test.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/authentication-flow-section.test.tsx rename to packages/developer-portal/src/components/pages/edit-app/__tests__/authentication-flow-section.test.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/developer-edit-app.test.tsx b/packages/developer-portal/src/components/pages/edit-app/__tests__/developer-edit-app.test.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/developer-edit-app.test.tsx rename to packages/developer-portal/src/components/pages/edit-app/__tests__/developer-edit-app.test.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/general-information-section.test.tsx b/packages/developer-portal/src/components/pages/edit-app/__tests__/general-information-section.test.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/general-information-section.test.tsx rename to packages/developer-portal/src/components/pages/edit-app/__tests__/general-information-section.test.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/marketplace-status-section.test.tsx b/packages/developer-portal/src/components/pages/edit-app/__tests__/marketplace-status-section.test.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/marketplace-status-section.test.tsx rename to packages/developer-portal/src/components/pages/edit-app/__tests__/marketplace-status-section.test.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/permission-section.test.tsx b/packages/developer-portal/src/components/pages/edit-app/__tests__/permission-section.test.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/permission-section.test.tsx rename to packages/developer-portal/src/components/pages/edit-app/__tests__/permission-section.test.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/redirect-uri-section.test.tsx b/packages/developer-portal/src/components/pages/edit-app/__tests__/redirect-uri-section.test.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/redirect-uri-section.test.tsx rename to packages/developer-portal/src/components/pages/edit-app/__tests__/redirect-uri-section.test.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/__test__/upload-image-section.test.tsx b/packages/developer-portal/src/components/pages/edit-app/__tests__/upload-image-section.test.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/__test__/upload-image-section.test.tsx rename to packages/developer-portal/src/components/pages/edit-app/__tests__/upload-image-section.test.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/agency-cloud-integration-section.tsx b/packages/developer-portal/src/components/pages/edit-app/agency-cloud-integration-section.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/agency-cloud-integration-section.tsx rename to packages/developer-portal/src/components/pages/edit-app/agency-cloud-integration-section.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/authentication-flow-section.tsx b/packages/developer-portal/src/components/pages/edit-app/authentication-flow-section.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/authentication-flow-section.tsx rename to packages/developer-portal/src/components/pages/edit-app/authentication-flow-section.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/developer-edit-app.tsx b/packages/developer-portal/src/components/pages/edit-app/developer-edit-app.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/developer-edit-app.tsx rename to packages/developer-portal/src/components/pages/edit-app/developer-edit-app.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/form-schema/form-fields.ts b/packages/developer-portal/src/components/pages/edit-app/form-schema/form-fields.ts similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/form-schema/form-fields.ts rename to packages/developer-portal/src/components/pages/edit-app/form-schema/form-fields.ts diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/form-schema/validation-schema.ts b/packages/developer-portal/src/components/pages/edit-app/form-schema/validation-schema.ts similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/form-schema/validation-schema.ts rename to packages/developer-portal/src/components/pages/edit-app/form-schema/validation-schema.ts diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/general-information-section.tsx b/packages/developer-portal/src/components/pages/edit-app/general-information-section.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/general-information-section.tsx rename to packages/developer-portal/src/components/pages/edit-app/general-information-section.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/index.ts b/packages/developer-portal/src/components/pages/edit-app/index.ts similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/index.ts rename to packages/developer-portal/src/components/pages/edit-app/index.ts diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/marketplace-status-section.tsx b/packages/developer-portal/src/components/pages/edit-app/marketplace-status-section.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/marketplace-status-section.tsx rename to packages/developer-portal/src/components/pages/edit-app/marketplace-status-section.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/permission-section.tsx b/packages/developer-portal/src/components/pages/edit-app/permission-section.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/permission-section.tsx rename to packages/developer-portal/src/components/pages/edit-app/permission-section.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/redirect-uri-section.tsx b/packages/developer-portal/src/components/pages/edit-app/redirect-uri-section.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/redirect-uri-section.tsx rename to packages/developer-portal/src/components/pages/edit-app/redirect-uri-section.tsx diff --git a/packages/developer-portal/src/components/pages/developer-edit-app/upload-image-section.tsx b/packages/developer-portal/src/components/pages/edit-app/upload-image-section.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/developer-edit-app/upload-image-section.tsx rename to packages/developer-portal/src/components/pages/edit-app/upload-image-section.tsx diff --git a/packages/developer-portal/src/components/pages/__tests__/__snapshots__/developer-help.test.tsx.snap b/packages/developer-portal/src/components/pages/help/__tests__/__snapshots__/help.test.tsx.snap similarity index 100% rename from packages/developer-portal/src/components/pages/__tests__/__snapshots__/developer-help.test.tsx.snap rename to packages/developer-portal/src/components/pages/help/__tests__/__snapshots__/help.test.tsx.snap diff --git a/packages/developer-portal/src/components/pages/__tests__/developer-help.test.tsx b/packages/developer-portal/src/components/pages/help/__tests__/help.test.tsx similarity index 88% rename from packages/developer-portal/src/components/pages/__tests__/developer-help.test.tsx rename to packages/developer-portal/src/components/pages/help/__tests__/help.test.tsx index 6a81b87345..5ac1c1e949 100644 --- a/packages/developer-portal/src/components/pages/__tests__/developer-help.test.tsx +++ b/packages/developer-portal/src/components/pages/help/__tests__/help.test.tsx @@ -1,5 +1,5 @@ import * as React from 'react' -import initChatBot from '../../../scripts/chat-bot' +import initChatBot from '../../../../scripts/chat-bot' import { mount } from 'enzyme' import * as ReactRedux from 'react-redux' import { @@ -10,17 +10,17 @@ import { handleFaq, handleViewRoadmap, handleWhatsNew, -} from '../developer-help' +} from '../help' import Routes from '@/constants/routes' import configureStore from 'redux-mock-store' import { history } from '@/core/router' import { HelpLinks } from '@/constants/developer-help-links' -import { mockLoginSession } from '../../../sagas/__tests__/auth' import appState from '@/reducers/__stubs__/app-state' +import { mockLoginSession } from '@/sagas/__tests__/auth' -jest.mock('../../../scripts/chat-bot') +jest.mock('../../../../scripts/chat-bot') -jest.mock('../../../core/router', () => ({ +jest.mock('../../../../core/router', () => ({ history: { push: jest.fn(), }, @@ -53,7 +53,7 @@ describe('handleGotoWelcomeGuide', () => { it('should called with correct props', () => { const spy = jest.spyOn(history, 'push') handleGotoWelcomeGuide() - expect(spy).toHaveBeenCalledWith(Routes.DEVELOPER_WELCOME) + expect(spy).toHaveBeenCalledWith(Routes.WELCOME) }) }) diff --git a/packages/developer-portal/src/components/pages/developer-help.tsx b/packages/developer-portal/src/components/pages/help/help.tsx similarity index 97% rename from packages/developer-portal/src/components/pages/developer-help.tsx rename to packages/developer-portal/src/components/pages/help/help.tsx index 9c0838bd1b..b682fd9761 100644 --- a/packages/developer-portal/src/components/pages/developer-help.tsx +++ b/packages/developer-portal/src/components/pages/help/help.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { useSelector } from 'react-redux' -import initChatBot from '../../scripts/chat-bot' +import initChatBot from '../../../scripts/chat-bot' import { history } from '@/core/router' import { H3 } from '@reapit/elements' import Routes from '@/constants/routes' @@ -17,7 +17,7 @@ import { LoginIdentity } from '@reapit/cognito-auth' import { selectLoginIdentity } from '@/selector/auth' export const handleGotoWelcomeGuide = () => { - history.push(Routes.DEVELOPER_WELCOME) + history.push(Routes.WELCOME) } export const handleReportBug = () => { diff --git a/packages/developer-portal/src/components/pages/help/index.ts b/packages/developer-portal/src/components/pages/help/index.ts new file mode 100644 index 0000000000..ac304f016c --- /dev/null +++ b/packages/developer-portal/src/components/pages/help/index.ts @@ -0,0 +1,2 @@ +import Help from './help' +export default Help diff --git a/packages/developer-portal/src/components/pages/__tests__/__snapshots__/register-confirm.tsx.snap b/packages/developer-portal/src/components/pages/register-confirm/__tests__/__snapshots__/register-confirm.test.tsx.snap similarity index 100% rename from packages/developer-portal/src/components/pages/__tests__/__snapshots__/register-confirm.tsx.snap rename to packages/developer-portal/src/components/pages/register-confirm/__tests__/__snapshots__/register-confirm.test.tsx.snap diff --git a/packages/developer-portal/src/components/pages/__tests__/register-confirm.tsx b/packages/developer-portal/src/components/pages/register-confirm/__tests__/register-confirm.test.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/__tests__/register-confirm.tsx rename to packages/developer-portal/src/components/pages/register-confirm/__tests__/register-confirm.test.tsx diff --git a/packages/developer-portal/src/components/pages/register-confirm/index.ts b/packages/developer-portal/src/components/pages/register-confirm/index.ts new file mode 100644 index 0000000000..d47adffa0a --- /dev/null +++ b/packages/developer-portal/src/components/pages/register-confirm/index.ts @@ -0,0 +1,2 @@ +import RegisterConfirm from './register-confirm' +export default RegisterConfirm diff --git a/packages/developer-portal/src/components/pages/register-confirm.tsx b/packages/developer-portal/src/components/pages/register-confirm/register-confirm.tsx similarity index 100% rename from packages/developer-portal/src/components/pages/register-confirm.tsx rename to packages/developer-portal/src/components/pages/register-confirm/register-confirm.tsx diff --git a/packages/developer-portal/src/components/pages/settings/__tests__/__snapshots__/settings.test.tsx.snap b/packages/developer-portal/src/components/pages/settings/__tests__/__snapshots__/settings.test.tsx.snap index df36c95add..d9e9c6e3ac 100644 --- a/packages/developer-portal/src/components/pages/settings/__tests__/__snapshots__/settings.test.tsx.snap +++ b/packages/developer-portal/src/components/pages/settings/__tests__/__snapshots__/settings.test.tsx.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`DeveloperSettingsPage should match snapshot 1`] = ` +exports[`SettingsPage should match snapshot 1`] = ` { +describe('SettingsPage', () => { it('should match snapshot', () => { const mockStore = configureStore() const store = mockStore(mockState) const wrapper = shallow( - + , ) expect(wrapper).toMatchSnapshot() diff --git a/packages/developer-portal/src/components/pages/__tests__/__snapshots__/swagger.tsx.snap b/packages/developer-portal/src/components/pages/swagger/__tests__/__snapshots__/swagger.test.tsx.snap similarity index 100% rename from packages/developer-portal/src/components/pages/__tests__/__snapshots__/swagger.tsx.snap rename to packages/developer-portal/src/components/pages/swagger/__tests__/__snapshots__/swagger.test.tsx.snap diff --git a/packages/developer-portal/src/components/pages/__tests__/swagger.tsx b/packages/developer-portal/src/components/pages/swagger/__tests__/swagger.test.tsx similarity index 98% rename from packages/developer-portal/src/components/pages/__tests__/swagger.tsx rename to packages/developer-portal/src/components/pages/swagger/__tests__/swagger.test.tsx index eb3cdb1702..45df00d95a 100644 --- a/packages/developer-portal/src/components/pages/__tests__/swagger.tsx +++ b/packages/developer-portal/src/components/pages/swagger/__tests__/swagger.test.tsx @@ -4,7 +4,7 @@ import { getAccessToken } from '@/utils/session' import Swagger, { handleOnComplete, fetchInterceptor, fetchAccessToken, InterceptorParams } from '../swagger' -jest.mock('../../../core/store') +jest.mock('../../../../core/store') jest.mock('@/utils/session') describe('Swagger', () => { diff --git a/packages/developer-portal/src/components/pages/swagger/index.ts b/packages/developer-portal/src/components/pages/swagger/index.ts new file mode 100644 index 0000000000..ead8acfe3b --- /dev/null +++ b/packages/developer-portal/src/components/pages/swagger/index.ts @@ -0,0 +1,2 @@ +import Swagger from './swagger' +export default Swagger diff --git a/packages/developer-portal/src/components/pages/swagger.tsx b/packages/developer-portal/src/components/pages/swagger/swagger.tsx similarity index 91% rename from packages/developer-portal/src/components/pages/swagger.tsx rename to packages/developer-portal/src/components/pages/swagger/swagger.tsx index ebf9f3ab3b..bf291ae309 100644 --- a/packages/developer-portal/src/components/pages/swagger.tsx +++ b/packages/developer-portal/src/components/pages/swagger/swagger.tsx @@ -1,12 +1,11 @@ import * as React from 'react' import SwaggerUI from 'swagger-ui-react' import 'swagger-ui-react/swagger-ui.css' -import '../../styles/vendor/swagger.scss' +import '../../../styles/vendor/swagger.scss' import ErrorBoundary from '@/components/hocs/error-boundary' -import { Loader } from '@reapit/elements' -import { SandboxPopUp } from '../ui/sandbox-pop-up' +import { Loader, StringMap } from '@reapit/elements' import { getAccessToken } from '@/utils/session' -import { StringMap } from '../../types/core' +import { SandboxPopUp } from '@/components/ui/sandbox-pop-up' export type InterceptorParams = { url: string diff --git a/packages/developer-portal/src/components/pages/webhooks/webhook-test-modal.tsx b/packages/developer-portal/src/components/pages/webhooks/webhook-test-modal.tsx index d969ab7eba..89ad188e05 100644 --- a/packages/developer-portal/src/components/pages/webhooks/webhook-test-modal.tsx +++ b/packages/developer-portal/src/components/pages/webhooks/webhook-test-modal.tsx @@ -94,7 +94,7 @@ export const WebhookTestModalBody: React.FunctionComponent diff --git a/packages/developer-portal/src/components/pages/webhooks/webhooks.tsx b/packages/developer-portal/src/components/pages/webhooks/webhooks.tsx index 04570f33f8..60ad121f19 100644 --- a/packages/developer-portal/src/components/pages/webhooks/webhooks.tsx +++ b/packages/developer-portal/src/components/pages/webhooks/webhooks.tsx @@ -202,7 +202,7 @@ export const DeveloperWebhooks = () => { different webhook subscription per topic or per customer. For more information about Webhooks, please see our diff --git a/packages/developer-portal/src/components/pages/__tests__/__snapshots__/developer-welcome.tsx.snap b/packages/developer-portal/src/components/pages/welcome/__tests__/__snapshots__/welcome.test.tsx.snap similarity index 100% rename from packages/developer-portal/src/components/pages/__tests__/__snapshots__/developer-welcome.tsx.snap rename to packages/developer-portal/src/components/pages/welcome/__tests__/__snapshots__/welcome.test.tsx.snap diff --git a/packages/developer-portal/src/components/pages/__tests__/developer-welcome.tsx b/packages/developer-portal/src/components/pages/welcome/__tests__/welcome.test.tsx similarity index 98% rename from packages/developer-portal/src/components/pages/__tests__/developer-welcome.tsx rename to packages/developer-portal/src/components/pages/welcome/__tests__/welcome.test.tsx index 5be587fe5d..141b2137be 100644 --- a/packages/developer-portal/src/components/pages/__tests__/developer-welcome.tsx +++ b/packages/developer-portal/src/components/pages/welcome/__tests__/welcome.test.tsx @@ -9,7 +9,7 @@ import { Managing, Support, Welcome, -} from '../developer-welcome' +} from '../welcome' import routes from '@/constants/routes' import { HelpGuide } from '@reapit/elements' diff --git a/packages/developer-portal/src/components/pages/welcome/index.ts b/packages/developer-portal/src/components/pages/welcome/index.ts new file mode 100644 index 0000000000..eaae4b28c0 --- /dev/null +++ b/packages/developer-portal/src/components/pages/welcome/index.ts @@ -0,0 +1,2 @@ +import Welcome from './welcome' +export default Welcome diff --git a/packages/developer-portal/src/components/pages/developer-welcome.tsx b/packages/developer-portal/src/components/pages/welcome/welcome.tsx similarity index 97% rename from packages/developer-portal/src/components/pages/developer-welcome.tsx rename to packages/developer-portal/src/components/pages/welcome/welcome.tsx index e281069575..731e9106ff 100644 --- a/packages/developer-portal/src/components/pages/developer-welcome.tsx +++ b/packages/developer-portal/src/components/pages/welcome/welcome.tsx @@ -48,7 +48,7 @@ export const Documentation = () => {

- + APIs @@ -56,7 +56,7 @@ export const Documentation = () => { Our interactive documentation allows you to easily experiment with our APIs with a ‘Try it now’ function to quickly build requests and inspect responses. To try it yourself and to see what data is available, click{' '} - + here . @@ -156,7 +156,7 @@ export const Support = () => { You are currently logged into our alpha release of Reapit Foundations and we are continuing to update, add additional features and address any issues that may appear. In the meantime, if you would like to request a feature or report a bug, this can be done from the{' '} - + ‘Help’ {' '} section on the left. diff --git a/packages/developer-portal/src/components/ui/__tests__/help-item-list.tsx b/packages/developer-portal/src/components/ui/__tests__/help-item-list.tsx index b2c3780cff..33d70245c9 100644 --- a/packages/developer-portal/src/components/ui/__tests__/help-item-list.tsx +++ b/packages/developer-portal/src/components/ui/__tests__/help-item-list.tsx @@ -3,8 +3,7 @@ import { shallow } from 'enzyme' import toJson from 'enzyme-to-json' import { HelpItemList } from '../help-item-list' - -import { helpItems } from '@/components/pages/developer-help' +import { helpItems } from '@/components/pages/help/help' describe('HelpItemList', () => { it('should match a snapshot', () => { diff --git a/packages/developer-portal/src/components/ui/developer-edition-modal/__tests__/__snapshots__/success-content.tsx.snap b/packages/developer-portal/src/components/ui/developer-edition-modal/__tests__/__snapshots__/success-content.tsx.snap index 112aedc5e0..c10aa6e5e3 100644 --- a/packages/developer-portal/src/components/ui/developer-edition-modal/__tests__/__snapshots__/success-content.tsx.snap +++ b/packages/developer-portal/src/components/ui/developer-edition-modal/__tests__/__snapshots__/success-content.tsx.snap @@ -34,13 +34,22 @@ exports[`SuccessContent should match snapshot 1`] = ` /> - CLOSE - + + + CLOSE + + + DOWNLOAD NOW + + } /> diff --git a/packages/developer-portal/src/components/ui/developer-edition-modal/__tests__/success-content.tsx b/packages/developer-portal/src/components/ui/developer-edition-modal/__tests__/success-content.tsx index 5395cef13c..a32b61fbf2 100644 --- a/packages/developer-portal/src/components/ui/developer-edition-modal/__tests__/success-content.tsx +++ b/packages/developer-portal/src/components/ui/developer-edition-modal/__tests__/success-content.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { shallow } from 'enzyme' -import { SuccessContent } from '../success-content' +import { SuccessContent, handleDownload } from '../success-content' import { developerStub } from '@/sagas/__stubs__/developer' describe('SuccessContent', () => { @@ -9,3 +9,14 @@ describe('SuccessContent', () => { expect(wrapper).toMatchSnapshot() }) }) + +describe('handleDownload', () => { + it('should open download link', () => { + const downloadURL = 'downloadURL' + window.reapit.config.developerEditionDownloadUrl = downloadURL + window.open = jest.fn() + + handleDownload() + expect(window.open).toBeCalledWith(downloadURL, '_self') + }) +}) diff --git a/packages/developer-portal/src/components/ui/developer-edition-modal/success-content.tsx b/packages/developer-portal/src/components/ui/developer-edition-modal/success-content.tsx index 78daad4f0e..fd0744772a 100644 --- a/packages/developer-portal/src/components/ui/developer-edition-modal/success-content.tsx +++ b/packages/developer-portal/src/components/ui/developer-edition-modal/success-content.tsx @@ -8,6 +8,10 @@ export type SuccessContentProps = Pick & { developer?: DeveloperModel } +export const handleDownload = () => { + window.open(window.reapit.config.developerEditionDownloadUrl, '_self') +} + export const SuccessContent: React.FC = ({ developer, afterClose }) => { if (!developer) return null @@ -44,9 +48,14 @@ export const SuccessContent: React.FC = ({ developer, after /> - CLOSE - + <> + + + } /> diff --git a/packages/developer-portal/src/components/ui/menu.tsx b/packages/developer-portal/src/components/ui/menu.tsx index 1daef0ff67..bccc28310c 100644 --- a/packages/developer-portal/src/components/ui/menu.tsx +++ b/packages/developer-portal/src/components/ui/menu.tsx @@ -65,35 +65,35 @@ export const generateMenuConfig = ( { title: 'API', key: 'SWAGGER', - url: Routes.DEVELOPER_SWAGGER, + url: Routes.SWAGGER, type: 'PRIMARY', icon: , }, { title: 'Webhooks', key: 'WEBHOOKS', - url: Routes.DEVELOPER_WEBHOOKS, + url: Routes.WEBHOOKS, type: 'PRIMARY', icon: , }, { title: 'Docs', key: 'API_DOCS', - url: Routes.DEVELOPER_API_DOCS, + url: Routes.API_DOCS, type: 'PRIMARY', icon: , }, { title: 'Desktop', key: 'DESKTOP', - url: Routes.DEVELOPER_DESKTOP, + url: Routes.DESKTOP, type: 'PRIMARY', icon: , }, { title: 'Help', key: 'HELP', - url: Routes.DEVELOPER_HELP, + url: Routes.HELP, type: 'PRIMARY', icon: , }, diff --git a/packages/developer-portal/src/components/ui/submit-app-wizard/steps/step-before-you-start.tsx b/packages/developer-portal/src/components/ui/submit-app-wizard/steps/step-before-you-start.tsx index 54053d2756..e54180f5e1 100644 --- a/packages/developer-portal/src/components/ui/submit-app-wizard/steps/step-before-you-start.tsx +++ b/packages/developer-portal/src/components/ui/submit-app-wizard/steps/step-before-you-start.tsx @@ -5,8 +5,7 @@ import Routes from '@/constants/routes' import { WizardStepComponent, SetWizardStep } from '../types' import { wizzardSteps } from '../constant' -export const onViewDocs = (history: History) => () => - history.push(`${Routes.DEVELOPER_API_DOCS}/developer-portal`) +export const onViewDocs = (history: History) => () => history.push(`${Routes.API_DOCS}/developer-portal`) export const onCreateNewApp = (setWizardStep: SetWizardStep) => () => { setWizardStep(wizzardSteps.INPUT_APP_NAME) @@ -31,7 +30,7 @@ export const StepBeforeYouStart: WizardStepComponent = ({ setWizardStep }) => { <> diff --git a/packages/developer-portal/src/constants/routes.ts b/packages/developer-portal/src/constants/routes.ts index da6e41352d..4044abcc53 100644 --- a/packages/developer-portal/src/constants/routes.ts +++ b/packages/developer-portal/src/constants/routes.ts @@ -2,23 +2,23 @@ const Routes = { AUTHENTICATION: '/authentication', AUTHENTICATION_LOGIN_TYPE: '/authentication/:loginType', DEVELOPER: '/developer', - DEVELOPER_WELCOME: '/developer/welcome', + WELCOME: '/developer/welcome', APPS: '/developer/apps', - DEVELOPER_APP_DETAIL: '/developer/apps/:appid', - DEVELOPER_SWAGGER: '/developer/swagger', - DEVELOPER_DESKTOP: '/developer/desktop', + APP_DETAIL: '/developer/apps/:appid', + SWAGGER: '/developer/swagger', + DESKTOP: '/developer/desktop', APPS_EDIT: '/developer/apps/:appid/edit', - DEVELOPER_API_DOCS: '/developer/api-docs', + API_DOCS: '/developer/api-docs', ANALYTICS: '/developer/analytics', ANALYTICS_TAB: '/developer/analytics/:activeTab?', - DEVELOPER_RESET_PASSWORD: '/developer/reset-password', - DEVELOPER_WEBHOOKS: '/developer/webhooks', + RESET_PASSWORD: '/developer/reset-password', + WEBHOOKS: '/developer/webhooks', SETTINGS: '/developer/settings/', SETTINGS_ORGANISATION_TAB: '/developer/settings/organisation', SETTINGS_BILLING_TAB: '/developer/settings/billing', SUBMIT_APP: '/developer/submit-app', - DEVELOPER_HELP: '/developer/help', - DEVELOPER_APP_PREVIEW: '/developer/apps/:appId/preview', + HELP: '/developer/help', + APP_PREVIEW: '/developer/apps/:appId/preview', DEVELOPER_EDITION_DOWNLOAD: '/developer/edition-download', REGISTER: '/register', REGISTER_CONFIRM: '/register/confirm', diff --git a/packages/developer-portal/src/core/__tests__/__snapshots__/router.tsx.snap b/packages/developer-portal/src/core/__tests__/__snapshots__/router.tsx.snap index ba67c6f73e..af4aeec8c0 100644 --- a/packages/developer-portal/src/core/__tests__/__snapshots__/router.tsx.snap +++ b/packages/developer-portal/src/core/__tests__/__snapshots__/router.tsx.snap @@ -302,6 +302,20 @@ exports[`Router should match a snapshot 1`] = ` fetcher={true} path="/developer/settings/" /> + catchChunkError(() => import('../compone const Login = React.lazy(() => catchChunkError(() => import('../components/pages/login'))) const Register = React.lazy(() => catchChunkError(() => import('../components/pages/register'))) const Apps = React.lazy(() => catchChunkError(() => import('../components/pages/apps'))) -const DeveloperAppDetail = React.lazy(() => catchChunkError(() => import('../components/pages/app-detail'))) -const DeveloperEditApp = React.lazy(() => catchChunkError(() => import('../components/pages/developer-edit-app'))) +const AppDetail = React.lazy(() => catchChunkError(() => import('../components/pages/app-detail'))) +const EditApp = React.lazy(() => catchChunkError(() => import('../components/pages/edit-app'))) const ApiDocsPage = React.lazy(() => catchChunkError(() => import('../components/pages/api-docs'))) const SwaggerPage = React.lazy(() => catchChunkError(() => import('../components/pages/swagger'))) -const DeveloperDesktopPage = React.lazy(() => catchChunkError(() => import('../components/pages/developer-desktop'))) -const DeveloperWelcomePage = React.lazy(() => catchChunkError(() => import('../components/pages/developer-welcome'))) -const DeveloperHelpPage = React.lazy(() => catchChunkError(() => import('../components/pages/developer-help'))) +const DesktopPage = React.lazy(() => catchChunkError(() => import('../components/pages/desktop'))) +const WelcomePage = React.lazy(() => catchChunkError(() => import('../components/pages/welcome'))) +const HelpPage = React.lazy(() => catchChunkError(() => import('../components/pages/help'))) const AnalyticsPage = React.lazy(() => catchChunkError(() => import('@/components/pages/analytics'))) const RegisterConfirm = React.lazy(() => catchChunkError(() => import('../components/pages/register-confirm'))) const WebhooksPage = React.lazy(() => catchChunkError(() => import('../components/pages/webhooks'))) -const SettingsPage = React.lazy(() => catchChunkError(() => import('../components/pages/settings/settings'))) +const SettingsPage = React.lazy(() => catchChunkError(() => import('../components/pages/settings/'))) const SettingsOrganisationTabPage = React.lazy(() => catchChunkError(() => import('../components/pages/settings/settings-organisation-tab')), @@ -33,7 +33,7 @@ const SettingsBillingTabPage = React.lazy(() => catchChunkError(() => import('../components/pages/settings/settings-billing-tab')), ) -const DeveloperEditionDownloadPage = React.lazy(() => +const EditionDownloadPage = React.lazy(() => catchChunkError(() => import('../components/pages/developer-edition-download')), ) @@ -49,7 +49,7 @@ const Router = () => { } /> - + @@ -60,25 +60,15 @@ const Router = () => { component={Authentication} /> - - - - - - + + + + + + + { fetcher component={SettingsOrganisationTabPage} /> - - + + } /> diff --git a/packages/developer-portal/src/tests/badges/badge-branches.svg b/packages/developer-portal/src/tests/badges/badge-branches.svg index 828389066b..bc9049555a 100644 --- a/packages/developer-portal/src/tests/badges/badge-branches.svg +++ b/packages/developer-portal/src/tests/badges/badge-branches.svg @@ -1 +1 @@ -Coverage:branchesCoverage:branches69.97%69.97% \ No newline at end of file +Coverage:branchesCoverage:branches68.64%68.64% \ No newline at end of file diff --git a/packages/developer-portal/src/tests/badges/badge-functions.svg b/packages/developer-portal/src/tests/badges/badge-functions.svg index c306084d0c..c5dbd4c6b6 100644 --- a/packages/developer-portal/src/tests/badges/badge-functions.svg +++ b/packages/developer-portal/src/tests/badges/badge-functions.svg @@ -1 +1 @@ -Coverage:functionsCoverage:functions81.82%81.82% \ No newline at end of file +Coverage:functionsCoverage:functions79.36%79.36% \ No newline at end of file diff --git a/packages/developer-portal/src/tests/badges/badge-lines.svg b/packages/developer-portal/src/tests/badges/badge-lines.svg index 2a4ce36294..ddec17d912 100644 --- a/packages/developer-portal/src/tests/badges/badge-lines.svg +++ b/packages/developer-portal/src/tests/badges/badge-lines.svg @@ -1 +1 @@ -Coverage:linesCoverage:lines91.2%91.2% \ No newline at end of file +Coverage:linesCoverage:lines89.8%89.8% \ No newline at end of file diff --git a/packages/developer-portal/src/tests/badges/badge-statements.svg b/packages/developer-portal/src/tests/badges/badge-statements.svg index 5c999ee2ea..9b15b3d0ec 100644 --- a/packages/developer-portal/src/tests/badges/badge-statements.svg +++ b/packages/developer-portal/src/tests/badges/badge-statements.svg @@ -1 +1 @@ -Coverage:statementsCoverage:statements90.2%90.2% \ No newline at end of file +Coverage:statementsCoverage:statements88.79%88.79% \ No newline at end of file diff --git a/packages/developer-portal/src/tests/cypress/hooks/login.ts b/packages/developer-portal/src/tests/cypress/hooks/login.ts index 6c2dcd9c9f..9dadaeb4b4 100644 --- a/packages/developer-portal/src/tests/cypress/hooks/login.ts +++ b/packages/developer-portal/src/tests/cypress/hooks/login.ts @@ -76,7 +76,7 @@ export const loginDeveloperHook = () => { userName: developerUserName, password: developerPassword, loginType: 'DEVELOPER', - loginRoute: ROUTES.DEVELOPER_LOGIN, + loginRoute: Routes.LOGIN, beforeLogin: () => { cy.setCookie(`${env}-${COOKIE_DEVELOPER_FIRST_TIME_LOGIN_COMPLETE}`, new Date().toString()) cy.setCookie(`${env}-${COOKIE_DEVELOPER_TERMS_ACCEPTED}`, new Date().toString()) diff --git a/packages/developer-portal/src/tests/cypress/pages/developer-settings-page.ts b/packages/developer-portal/src/tests/cypress/pages/developer-settings-page.ts index 1e2e41d7b8..091e484ed6 100644 --- a/packages/developer-portal/src/tests/cypress/pages/developer-settings-page.ts +++ b/packages/developer-portal/src/tests/cypress/pages/developer-settings-page.ts @@ -1,7 +1,7 @@ import Routes from '@/constants/routes' import api from '../fixtures/routes' -const developerSettingsMetaData = { +const SettingsMetaData = { url: Routes.SETTINGS, selectors: { companyName: 'input[data-test="company-name"]', @@ -13,8 +13,8 @@ const developerSettingsMetaData = { apiRoute: `${api.developers}/**`, } -const developerSettingsAppPage = { - ...developerSettingsMetaData, +const SettingsAppPage = { + ...SettingsMetaData, } -export default developerSettingsAppPage +export default SettingsAppPage diff --git a/packages/developer-portal/src/utils/__tests__/admin-stats.ts b/packages/developer-portal/src/utils/__tests__/admin-stats.ts deleted file mode 100644 index ce14ba02f0..0000000000 --- a/packages/developer-portal/src/utils/__tests__/admin-stats.ts +++ /dev/null @@ -1,62 +0,0 @@ -import MockDate from 'mockdate' -import { Range } from '@/components/pages/admin-stats/admin-stats' -import { getDateRange, getDataLabel, getChartConfig, numOfObjectCreatedInDate, getRangeName } from '../admin-stats' - -beforeEach(() => { - MockDate.set(new Date(2020, 1, 21)) -}) - -afterEach(() => { - MockDate.reset() -}) - -describe('admin stats utils', () => { - describe('getDataLabel', () => { - it('should run correctly', () => { - expect(getDataLabel('APPS')).toEqual('Apps') - expect(getDataLabel('DEVELOPERS')).toEqual('Developers') - expect(getDataLabel('INSTALLATIONS')).toEqual('Installations') - }) - }) - - describe('getDateRange', () => { - it('should run correctly', () => { - const weekRange = { from: new Date(2020, 1, 14), to: new Date(2020, 1, 21) } - const monthRange = { from: new Date(2020, 0, 21), to: new Date(2020, 1, 21) } - expect(getDateRange('WEEK')).toEqual(weekRange) - expect(getDateRange('MONTH')).toEqual(monthRange) - }) - }) - - describe('numOfObjectCreatedInDate', () => { - it('should run correctly', () => { - const data = [ - { id: 1, created: new Date(2020, 1, 14) }, - { id: 2, created: new Date(2020, 1, 15) }, - { id: 3, created: new Date(2020, 1, 16) }, - ] - const date = new Date(2020, 1, 14) - expect(numOfObjectCreatedInDate(data, date)).toEqual(1) - }) - }) - - describe('getChartConfig', () => { - it('should run correctly', () => { - const labels = ['Mon', 'Tue'] - const data = [10, 20] - const chartConfig = getChartConfig(labels, data, 'DEVELOPERS') - expect(chartConfig.labels.length).toBe(2) - expect(chartConfig.datasets[0].data.length).toBe(2) - }) - }) - - describe('getRangeName', () => { - it('should run correctly', () => { - const ranges: Array = ['WEEK', 'MONTH', 'ALL'] - const names: Array = ['Last Week', 'Last Month', 'All Time'] - ranges.forEach((range, index) => { - expect(getRangeName(range)).toEqual(names[index]) - }) - }) - }) -}) diff --git a/packages/developer-portal/src/utils/__tests__/auth-route.ts b/packages/developer-portal/src/utils/__tests__/auth-route.ts index 0bec383fc5..268c1d83f7 100644 --- a/packages/developer-portal/src/utils/__tests__/auth-route.ts +++ b/packages/developer-portal/src/utils/__tests__/auth-route.ts @@ -6,8 +6,8 @@ describe('getDefaultRoute', () => { expect(getDefaultRoute(true)).toEqual(`${window.location.origin}${Routes.APPS}`) }) - it('should return origin url + Routes.DEVELOPER_WELCOME', () => { - expect(getDefaultRoute(false)).toEqual(`${window.location.origin}${Routes.DEVELOPER_WELCOME}`) + it('should return origin url + Routes.WELCOME', () => { + expect(getDefaultRoute(false)).toEqual(`${window.location.origin}${Routes.WELCOME}`) }) }) @@ -20,7 +20,7 @@ describe('getDefaultPathByLoginType', () => { expect(getDefaultPath(false, true)).toEqual(Routes.APPS) }) - it('should return Routes.DEVELOPER_WELCOME', () => { - expect(getDefaultPath(false, false)).toEqual(Routes.DEVELOPER_WELCOME) + it('should return Routes.WELCOME', () => { + expect(getDefaultPath(false, false)).toEqual(Routes.WELCOME) }) }) diff --git a/packages/developer-portal/src/utils/auth-route.ts b/packages/developer-portal/src/utils/auth-route.ts index 7af7b3ea3c..c67b765ea6 100644 --- a/packages/developer-portal/src/utils/auth-route.ts +++ b/packages/developer-portal/src/utils/auth-route.ts @@ -4,14 +4,12 @@ export function getDefaultRoute(isFirtTimeLogin: boolean) { if (window.location.pathname === Routes.DEVELOPER_EDITION_DOWNLOAD) { return `${window.location.origin}${Routes.DEVELOPER_EDITION_DOWNLOAD}` } - return !isFirtTimeLogin - ? `${window.location.origin}${Routes.DEVELOPER_WELCOME}` - : `${window.location.origin}${Routes.APPS}` + return !isFirtTimeLogin ? `${window.location.origin}${Routes.WELCOME}` : `${window.location.origin}${Routes.APPS}` } export function getDefaultPath(isDesktopMode: boolean, isFirtTimeLogin: boolean) { if (isDesktopMode) { return Routes.APPS } - return !isFirtTimeLogin ? Routes.DEVELOPER_WELCOME : Routes.APPS + return !isFirtTimeLogin ? Routes.WELCOME : Routes.APPS } diff --git a/packages/developer-portal/src/utils/form/settings-contact-information.ts b/packages/developer-portal/src/utils/form/settings-contact-information.ts index 72b6cc0ebc..9fda227f0a 100644 --- a/packages/developer-portal/src/utils/form/settings-contact-information.ts +++ b/packages/developer-portal/src/utils/form/settings-contact-information.ts @@ -2,10 +2,10 @@ import { ContactInformationValues } from '@/components/pages/settings/forms/cont import ErrorMessages from '@/constants/error-messages' import { isValidPersonName, isValidTelephone } from '@/utils/validate' -export type DeveloperSettingsContactInformationErrorKeys = Partial +export type SettingsContactInformationErrorKeys = Partial export const validate = (values: ContactInformationValues) => { - let errors: DeveloperSettingsContactInformationErrorKeys = {} + let errors: SettingsContactInformationErrorKeys = {} if (values.telephone && !isValidTelephone(values.telephone)) { errors.telephone = ErrorMessages.FIELD_PHONE_NUMER diff --git a/packages/developer-portal/src/utils/route-dispatcher.ts b/packages/developer-portal/src/utils/route-dispatcher.ts index b61224a093..75913a1f03 100644 --- a/packages/developer-portal/src/utils/route-dispatcher.ts +++ b/packages/developer-portal/src/utils/route-dispatcher.ts @@ -32,7 +32,7 @@ const routeDispatcher = async (route: RouteValue, params?: StringMap, search?: s } break } - case Routes.DEVELOPER_APP_DETAIL: { + case Routes.APP_DETAIL: { if (id) { const clientId = selectClientId(store.state) const developerId = selectDeveloperId(store.state) || '' @@ -59,10 +59,10 @@ const routeDispatcher = async (route: RouteValue, params?: StringMap, search?: s case Routes.SETTINGS: store.dispatch(requestDeveloperData()) break - case Routes.DEVELOPER_WEBHOOKS: + case Routes.WEBHOOKS: store.dispatch(developerRequestData({ page: 1, appsPerPage: GET_ALL_PAGE_SIZE } as DeveloperRequestParams)) break - case Routes.DEVELOPER_HELP: + case Routes.HELP: // Need the fetcher to have retrieved the login session only. break default: diff --git a/packages/elements/package.json b/packages/elements/package.json index 98af1bda6e..543eec48e3 100644 --- a/packages/elements/package.json +++ b/packages/elements/package.json @@ -95,6 +95,7 @@ "rollup-plugin-typescript2": "^0.27.1" }, "peerDependencies": { + "dayjs": "^1.8.19", "react": "^16.11.0", "react-dom": "^16.11.0", "react-router": "^5.1.2", diff --git a/packages/geo-diary-v2/manifest.json b/packages/geo-diary-v2/manifest.json new file mode 100644 index 0000000000..f83ccae22b --- /dev/null +++ b/packages/geo-diary-v2/manifest.json @@ -0,0 +1,25 @@ +{ + "short_name": "Geo Diary", + "name": "Geo Diary App", + "icons": [ + { + "src": "logo.png", + "sizes": "64x64 32x32 24x24 16x16", + "type": "image/x-icon" + }, + { + "src": "logo.png", + "type": "image/png", + "sizes": "192x192" + }, + { + "src": "logo.png", + "type": "image/png", + "sizes": "512x512" + } + ], + "start_url": ".", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/packages/geo-diary-v2/package.json b/packages/geo-diary-v2/package.json index f620e9c61d..16be1c105e 100644 --- a/packages/geo-diary-v2/package.json +++ b/packages/geo-diary-v2/package.json @@ -11,7 +11,7 @@ "author": "Reapit", "main": "./src/index.ts", "scripts": { - "build:prod": "rimraf public/dist && webpack --config ../../scripts/webpack/webpack.config.prod.js", + "build:prod": "rimraf public/dist && webpack --config ../../scripts/webpack/webpack.pwa.prod.js", "fetch-config": "yarn config-manager fetchConfig geo-diary-v2", "release:dev": "node ../../scripts/release/release-dev.js geo-diary-v2 reapit-geo-diary-v2-dev", "start:dev": "webpack-dev-server --hot --progress --color --mode development --config ../../scripts/webpack/webpack.config.dev.js", diff --git a/packages/geo-diary-v2/src/core/index.tsx b/packages/geo-diary-v2/src/core/index.tsx index e591f430fa..9fd00545aa 100644 --- a/packages/geo-diary-v2/src/core/index.tsx +++ b/packages/geo-diary-v2/src/core/index.tsx @@ -1,4 +1,5 @@ import * as Sentry from '@sentry/browser' +import { injectSwitchModeToWindow } from '@reapit/elements' import load from 'little-loader' import qs from 'query-string' import React from 'react' @@ -6,7 +7,7 @@ import { render } from 'react-dom' import ReactGA from 'react-ga' import { Config } from '@/types/global' import App from './app' -import { injectSwitchModeToWindow } from '@reapit/elements' +import * as serviceWorker from './service-worker' injectSwitchModeToWindow() @@ -71,3 +72,10 @@ if (module['hot']) { } run() +if (process.env.NODE_ENV === 'development') { + serviceWorker.unregister() + console.info(`UnRegister-${process.env.APP_VERSION}`) +} else { + serviceWorker.register() + console.info(`Register-${process.env.APP_VERSION}`) +} diff --git a/packages/geo-diary-v2/src/core/service-worker.ts b/packages/geo-diary-v2/src/core/service-worker.ts new file mode 100644 index 0000000000..b06a126765 --- /dev/null +++ b/packages/geo-diary-v2/src/core/service-worker.ts @@ -0,0 +1,140 @@ +// This optional code is used to register a service worker. +// register() is not called by default. + +import { notification } from '@reapit/elements' + +// This lets the app load faster on subsequent visits in production, and gives +// it offline capabilities. However, it also means that developers (and users) +// will only see deployed updates on subsequent visits to a page, after all the +// existing tabs open on the page have been closed, since previously cached +// resources are updated in the background. + +// To learn more about the benefits of this model and instructions on how to +// opt-in, read https://bit.ly/CRA-PWA + +const isLocalhost = Boolean( + window.location.hostname === 'localhost' || + // [::1] is the IPv6 localhost address. + window.location.hostname === '[::1]' || + // 127.0.0.0/8 are considered localhost for IPv4. + window.location.hostname.match(/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/), +) + +type Config = { + onSuccess?: (registration: ServiceWorkerRegistration) => void + onUpdate?: (registration: ServiceWorkerRegistration) => void +} + +export function register(config?: Config) { + if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { + // The URL constructor is available in all browsers that support SW. + const publicUrl = new URL('/', window.location.href) + if (publicUrl.origin !== window.location.origin) { + // Our service worker won't work if PUBLIC_URL is on a different origin + // from what our page is served on. This might happen if a CDN is used to + // serve assets; see https://github.com/facebook/create-react-app/issues/2374 + return + } + + window.addEventListener('load', () => { + const swUrl = '/service-worker.js' + + if (isLocalhost) { + // This is running on localhost. Let's check if a service worker still exists or not. + checkValidServiceWorker(swUrl, config) + + // Add some additional logging to localhost, pointing developers to the + // service worker/PWA documentation. + navigator.serviceWorker.ready.then(() => { + console.log( + 'This web app is being served cache-first by a service ' + + 'worker. To learn more, visit https://bit.ly/CRA-PWA', + ) + }) + } else { + // Is not localhost. Just register service worker + registerValidSW(swUrl, config) + } + }) + } +} + +function registerValidSW(swUrl: string, config?: Config) { + navigator.serviceWorker + .register(swUrl) + .then(registration => { + registration.onupdatefound = () => { + const installingWorker = registration.installing + if (installingWorker == null) { + return + } + installingWorker.onstatechange = () => { + if (installingWorker.state === 'installed') { + if (navigator.serviceWorker.controller) { + notification.success({ + message: 'New version available, please press CTRL-SHIFT-R to update', + duration: 0, + placement: 'bottomRight', + }) + + console.log( + 'New content is available and will be used when all ' + + 'tabs for this page are closed. See https://bit.ly/CRA-PWA.', + ) + + // Execute callback + if (config && config.onUpdate) { + config.onUpdate(registration) + } + } else { + // At this point, everything has been precached. + // It's the perfect time to display a + // "Content is cached for offline use." message. + console.log('Content is cached for offline use.') + + // Execute callback + if (config && config.onSuccess) { + config.onSuccess(registration) + } + } + } + } + } + }) + .catch(error => { + console.error('Error during service worker registration:', error) + }) +} + +function checkValidServiceWorker(swUrl: string, config?: Config) { + // Check if the service worker can be found. If it can't reload the page. + fetch(swUrl, { + headers: { 'Service-Worker': 'script' }, + }) + .then(response => { + // Ensure service worker exists, and that we really are getting a JS file. + const contentType = response.headers.get('content-type') + if (response.status === 404 || (contentType != null && contentType.indexOf('javascript') === -1)) { + // No service worker found. Probably a different app. Reload the page. + navigator.serviceWorker.ready.then(registration => { + registration.unregister().then(() => { + window.location.reload() + }) + }) + } else { + // Service worker found. Proceed as normal. + registerValidSW(swUrl, config) + } + }) + .catch(() => { + console.log('No internet connection found. App is running in offline mode.') + }) +} + +export function unregister() { + if ('serviceWorker' in navigator) { + navigator.serviceWorker.ready.then(registration => { + registration.unregister() + }) + } +} diff --git a/packages/react-app-scaffolder/README.md b/packages/react-app-scaffolder/README.md index 96c1031493..b9184f76de 100644 --- a/packages/react-app-scaffolder/README.md +++ b/packages/react-app-scaffolder/README.md @@ -1,9 +1,23 @@ -# Reapit React-Redux App Scaffolder +# Reapit React App Scaffolder A CLI for generating React Apps, optimised for the marketplace, including Reapit Connect authentication and Elements. For usage visit [here](https://foundations-documentation.reapit.cloud/api/web#react-app-scaffolder). -- **Tech Stack**: Yeoman, React, Redux, Jest, React, Router, Styled-Components, Sass, CSS Modules +- **Tech Stack**: Yeoman, React, Redux, Jest, React, Router, Linaria - **Cloud Services**: NPM - **Production**: https://www.npmjs.com/package/@reapit/generator-react-redux-app For detailed documentation [visit here](https://foundations-documentation.reapit.cloud/open-source/packages#react-app-scaffolder). + +For internal scaffolds, navigate to project folder and execute `yarn scaffold` to load the CLI. + +For external users first; + +`npm install -g yo @reapit/generator-react-app-scaffolder` + +Then + +`yo @reapit/react-app-scaffolder` to load the CLI. + +For internal maintainers, to build an app locally, navigate to one of the external options within the templates folder, `yarn` and `yarn start:dev` to develop the scaffold. + +For internal apps, scaffold a local app and copy your changes back to the main directory. \ No newline at end of file diff --git a/packages/react-app-scaffolder/app/index.js b/packages/react-app-scaffolder/app/index.js index 07fc6908ba..c13dbcf2d9 100644 --- a/packages/react-app-scaffolder/app/index.js +++ b/packages/react-app-scaffolder/app/index.js @@ -3,26 +3,23 @@ const { promisify } = require('util') const process = require('process') const exec = promisify(require('child_process').exec) const spawn = require('cross-spawn') -const { execSync } = require('child_process') const path = require('path') const fs = require('fs') const yosay = require('yosay') -const { constantCase } = require('change-case') module.exports = class extends Generator { _installAndExport() { return new Promise(async (resolve, reject) => { - const { isFoundation } = this.answers + const { isFoundations } = this.answers this.log(yosay('Installing dependencies... this may take a minute!')) - if (!isFoundation) { + if (!isFoundations) { await exec(`yarn`) } - const prettierConfigPath = path.resolve(__dirname, '../../../.prettierrc.js') await exec(`yarn prettier --write ./package.json`) - await exec(`yarn prettier "**/*.ts" "**/*.tsx" --write`) + this.log(yosay('App installed successfully!')) this._pushToGithub() @@ -58,62 +55,30 @@ module.exports = class extends Generator { } _addPackageJson() { - const { isFoundation, name, author, repo, description } = this.answers - - if (isFoundation) { - return - } + const { isFoundations, name, author, repo, description } = this.answers - if (this.redux) { - this.fs.copyTpl(this.templatePath('./is-foundation-redux/**/*'), this.destinationPath('./'), { - name, author, repo, description - }) - } + const local = require(this.templatePath('./_package.json')) + const base = require(this.destinationPath('./package.json')) - if (!this.redux) { - this.fs.copyTpl(this.templatePath('./is-foundation-no-redux/**/*'), this.destinationPath('./'), { - name, author, repo, description - }) + const merged = { + ...local, + ...base, } - } - _addPackageJson() { - const { isFoundation, name, author, repo, description } = this.answers - - if (isFoundation) { - return - } - - if (this.redux) { - this.fs.copyTpl(this.templatePath('./is-foundation-redux/**/*'), this.destinationPath('./'), { - name, author, repo, description - }) - } - - if (!this.redux) { - this.fs.copyTpl(this.templatePath('./is-foundation-no-redux/**/*'), this.destinationPath('./'), { - name, author, repo, description + this.fs.delete(this.destinationPath('./package.json')) + this.fs.commit([], () => { + this.fs.write(this.destinationPath('./temp.package.json'), JSON.stringify(merged)) + this.fs.commit([], () => { + this.fs.copyTpl(this.destinationPath('./temp.package.json'), this.destinationPath('./package.json'), { + name, + author, + repo, + description, + }) + this.fs.delete(this.destinationPath('./temp.package.json')) + this.fs.commit([], () => {}) }) - } - } - - - _addAzure() { - const { name, azure } = this.answers - if (azure) { - this.fs.copy(this.templatePath('redu'), this.destinationPath(`./azure-pipelines.yml`)) - } - } - - _addStyleSolution() { - const { sass, name, isFoundation } = this.answers - - - if (sass) { - this.fs.copyTpl(this.templatePath('./base-is-sass/**/*'), this.destinationPath('./'), { isFoundation }) - } else { - this.fs.copyTpl(this.templatePath('./base-is-linaria/**/*'), this.destinationPath('./'), { isFoundation }) - } + }) } constructor(args, opts) { @@ -123,94 +88,35 @@ module.exports = class extends Generator { async writeBaseFiles() { return new Promise((resolve, reject) => { - const { name, repo, description, author, isFoundation, stylesSolution, clientId, sass } = this.answers - const { redux, graphql } = this - - /** - * settings destination path - * for non isFoundation: it will be the folder where the scaffolder is executed - * for isFoundation: we have to deter - */ - - this.fs.copyTpl(this.templatePath('_README.md'), this.destinationPath('./README.md'), { - name, - }) - - this.fs.copyTpl(this.templatePath('_gitignore'), this.destinationPath('./.gitignore'), { - name, - }) - - this.fs.copyTpl(this.templatePath('_eslintrc.js'), this.destinationPath('./.eslintrc.js'), { - name, - }) - - this.fs.copyTpl(this.templatePath('_prettierrc.js'), this.destinationPath('./.prettierrc.js'), { - name, - }) + const { name, isFoundations, clientId } = this.answers + const configPath = isFoundations ? './_config.internal.json' : './_config.external.json' - this.fs.copyTpl(this.templatePath('_config.json'), this.destinationPath('./config.json'), { + this.fs.copyTpl(this.templatePath(configPath), this.destinationPath('./config.json'), { clientId, }) - this.fs.copyTpl(this.templatePath('_config.example.json'), this.destinationPath('./config.example.json'), { - clientId, - }) - - this.fs.copyTpl(this.templatePath('./base'), this.destinationPath('./'), { + this.fs.copyTpl(this.templatePath('_README.md'), this.destinationPath('./README.md'), { name, - nameInConstantCase: constantCase(name), - redux, - graphql, - stylesSolution, - isFoundation }) - if (isFoundation) { - // Any any additional base files specialized for non-foundation project will need to uncomment this like - // Select recursively dot files - // glob isn't really smart at the moment. In the future, when need to add non dot files, uncomment this - // this.fs.copyTpl(this.templatePath('./base-is-foundation/**/.*'), this.destinationPath('./'), { - // name, - // repo, - // description, - // author, - // }) - this.fs.copyTpl(this.templatePath('./base-is-foundation/*'), this.destinationPath('./'), { - name, - repo, - description, - author, - }) - } else { - this.fs.copyTpl(this.templatePath('./base-is-not-foundation/**/*'), this.destinationPath('./'), { - name, - nameInConstantCase: constantCase(name), - repo, - description, - author, - clientId, - }) - } - - this.fs.copyTpl(this.templatePath(this.projectTypePath), this.destinationPath('./'), { - name, - nameInConstantCase: constantCase(name), - redux, - graphql, - stylesSolution, - graphql, - stylesSolution, - sass - }) + this.fs.copyTpl(this.templatePath(this.projectPath), this.destinationPath('./')) this.fs.commit([], () => { - this._addStyleSolution(), - this._addPackageJson(), - this._addAzure() + + if (!isFoundations) { + this.fs.copyTpl(this.templatePath('_prettierrc.js'), this.destinationPath('./.prettierrc.js')) + this.fs.copyTpl(this.templatePath('_eslintrc.js'), this.destinationPath('./.eslintrc.js')) + this.fs.copyTpl(this.templatePath('_gitignore'), this.destinationPath('./.gitignore')) + } + this.fs.commit([], () => { - this._installAndExport() - .then(resolve) - .catch(reject) + this._addPackageJson() + + this.fs.commit([], () => { + this._installAndExport() + .then(resolve) + .catch(reject) + }) }) }) }) @@ -250,21 +156,15 @@ module.exports = class extends Generator { }, { type: 'confirm', - name: 'isFoundation', - message: 'Is this project for internal use (mono-repo)', - default: true, - }, - { - name: 'sass', - message: 'Would you like to use Sass?', - type: 'confirm', + name: 'isFoundations', + message: 'Is this a Reapit internal project?', default: false, }, { type: 'list', name: 'stateManagementStyle', - message: 'Pick project type', - choices: ['Redux', 'No Redux'], + message: 'How do you want to manage state?', + choices: ['Redux', 'React Hooks & Context'], }, { type: 'confirm', @@ -274,36 +174,28 @@ module.exports = class extends Generator { }, ]) - const { stateManagementStyle, stylesSolution } = this.answers - if (stateManagementStyle === 'Redux') { - this.projectTypePath = 'redux' - this.redux = true - } - - if (stateManagementStyle === 'No Redux') { - this.projectTypePath = 'no-redux' - this.redux = false + const { stateManagementStyle, isFoundations } = this.answers + if (stateManagementStyle === 'Redux' && isFoundations) { + this.projectPath = './redux-internal' } - if (stateManagementStyle === 'Apollo GraphQL') { - this.projectTypePath = 'apollo' - this.graphql = true + if (stateManagementStyle === 'Redux' && !isFoundations) { + this.projectPath = './redux-external' } - if (stylesSolution === 'Styled Components') { - this.answers.stylesSolution = 'styledComponents' + if (stateManagementStyle === 'React Hooks & Context' && isFoundations) { + this.projectPath = './hooks-internal' } - if (stylesSolution === 'Sass/CSS') { - this.answers.stylesSolution = 'sass' + if (stateManagementStyle === 'React Hooks & Context' && !isFoundations) { + this.projectPath = './hooks-external' } - /** * Destination path - * isFoundation ->./package/{appName} - * else current path + * isFoundations ->./package/{appName} + * else current path/{appName} */ - if (this.answers.isFoundation) { + if (isFoundations) { this.packagePath = path.resolve(__dirname, '../..', this.answers.name) /** * create directory if not diff --git a/packages/react-app-scaffolder/app/templates/_README.md b/packages/react-app-scaffolder/app/templates/_README.md index ba91c0cfec..dd0eea6719 100644 --- a/packages/react-app-scaffolder/app/templates/_README.md +++ b/packages/react-app-scaffolder/app/templates/_README.md @@ -1,12 +1,5 @@ # <%= name %> -<%= name %> for Reapit PAAS platform. Initial scaffold from [React App Boilerplate](https://github.com/reapit/react-app) +<%= name %> an app built for Reapit Marketplace. -## Read on: - -- [Getting Started](./src/docs/GETTING_STARTED.md) -- [Api Platform](./src/docs/API_PLATFORM.md) -- [Code Style](./src/docs/CODE_STYLE.md) -- [Version Control](./VERSION_CONTROL.md) -- [Definition of Done](./src/docs/DEFINITION_OF_DONE.md) -- [Deployment](./src/docs/DEPLOYMENT.md) +Initial scaffold using the steps from [here](https://foundations-documentation.reapit.cloud/developer-portal), using [Reapit React App Scaffolder](https://www.npmjs.com/package/@reapit/generator-react-app-scaffolder) \ No newline at end of file diff --git a/packages/react-app-scaffolder/app/templates/_config.external.json b/packages/react-app-scaffolder/app/templates/_config.external.json new file mode 100644 index 0000000000..6d156b8f08 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/_config.external.json @@ -0,0 +1,7 @@ +{ + "appEnv": "local", + "cognitoClientId": "<%= clientId %>", + "cognitoOAuthUrl": "https://dev.connect.reapit.cloud", + "cognitoUserPoolId": "eu-west-2_hbt0B7yys", + "platformApiUrl": "https://dev.platform.reapit.cloud" +} diff --git a/packages/react-app-scaffolder/app/templates/_config.example.json b/packages/react-app-scaffolder/app/templates/_config.internal.json similarity index 99% rename from packages/react-app-scaffolder/app/templates/_config.example.json rename to packages/react-app-scaffolder/app/templates/_config.internal.json index 692adaf253..5d3433212c 100644 --- a/packages/react-app-scaffolder/app/templates/_config.example.json +++ b/packages/react-app-scaffolder/app/templates/_config.internal.json @@ -6,4 +6,4 @@ "cognitoOAuthUrl": "https://dev.connect.reapit.cloud", "cognitoUserPoolId": "eu-west-2_hbt0B7yys", "platformApiUrl": "https://dev.platform.reapit.cloud" -} +} \ No newline at end of file diff --git a/packages/react-app-scaffolder/app/templates/_gitignore b/packages/react-app-scaffolder/app/templates/_gitignore index bcd5078bd8..a2e8df3890 100644 --- a/packages/react-app-scaffolder/app/templates/_gitignore +++ b/packages/react-app-scaffolder/app/templates/_gitignore @@ -16,3 +16,11 @@ yarn-error.log* *.log .cache/ +yarn.lock + +public/dist +src/tests + +.jest-cache +.linaria-cache +.webpack-cache diff --git a/packages/react-app-scaffolder/app/templates/_jest.config.js b/packages/react-app-scaffolder/app/templates/_jest.config.js deleted file mode 100644 index e3d7b18525..0000000000 --- a/packages/react-app-scaffolder/app/templates/_jest.config.js +++ /dev/null @@ -1,26 +0,0 @@ -const { pathsToModuleNameMapper } = require('ts-jest/utils') -const { compilerOptions } = require('./tsconfig') - -module.exports = { - preset: 'ts-jest', - setupFiles: ['/src/scripts/jest-setup.js'], - collectCoverageFrom: ['/src/**/*.ts', '/src/**/*.tsx'], - coverageDirectory: './src/tests/coverage', - coveragePathIgnorePatterns: ['[/\\\\](node_modules|src/types|src/tests|src/scripts)[/\\\\]', 'index.tsx'], - modulePathIgnorePatterns: ['[/\\\\](node_modules)[/\\\\]'], - snapshotSerializers: ['enzyme-to-json/serializer'], - moduleNameMapper: { - '^.+.(?=.*scss|sass|css|jpg|png).*': '/src/scripts/css-stub.js', - ...pathsToModuleNameMapper(compilerOptions.paths, { - prefix: '/' - }) - }, - coverageThreshold: { - global: { - branches: 0, - functions: 0, - lines: 0, - statements: 0 - } - } -} \ No newline at end of file diff --git a/packages/react-app-scaffolder/app/templates/_package.json b/packages/react-app-scaffolder/app/templates/_package.json new file mode 100644 index 0000000000..7c76605044 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/_package.json @@ -0,0 +1,9 @@ +{ + "name": "<%= name %>", + "description": "<%= description %>", + "repository": { + "type": "git", + "url": "git+<%= repo %>" + }, + "author": "<%= author %>" +} diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/__snapshots__/authenticated.tsx.snap b/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/__snapshots__/authenticated.tsx.snap deleted file mode 100644 index 5b71532eb0..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/__snapshots__/authenticated.tsx.snap +++ /dev/null @@ -1,20 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Authenticated should match a snapshot 1`] = ` - - -

- Welcome To Reapit Elements -

- - You are now authenticated against our sandbox data - - - -`; diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/__snapshots__/home.tsx.snap b/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/__snapshots__/home.tsx.snap deleted file mode 100644 index 903688c646..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/__snapshots__/home.tsx.snap +++ /dev/null @@ -1,27 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Home should match a snapshot 1`] = ` - - -

- Welcome To Reapit Elements -

- - Click - - here - - to login - -
-
-`; diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/__snapshots__/login.tsx.snap b/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/__snapshots__/login.tsx.snap deleted file mode 100644 index da5a785eb6..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/__snapshots__/login.tsx.snap +++ /dev/null @@ -1,37 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Login should match a snapshot 1`] = ` -
-
-

- Sign in -

-

- Welcome to smb -

- -
-
- Reapit Graphic -
-
-`; diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/home.tsx b/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/home.tsx deleted file mode 100644 index 644f30ccc3..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/home.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import * as React from 'react' -import { shallow } from 'enzyme' -import toJson from 'enzyme-to-json' -import { Home, HomeProps } from '../home' - -const props: HomeProps = { - approvalsState: { - loading: false, - homeData: {}, - }, - // @ts-ignore: just pick the needed props for the test - match: { - params: { - page: '2', - }, - }, -} - -describe('Home', () => { - it('should match a snapshot', () => { - expect(toJson(shallow())).toMatchSnapshot() - }) -}) diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/login.tsx b/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/login.tsx deleted file mode 100644 index 4abbad8af0..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/__tests__/login.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import * as React from 'react' -import { shallow } from 'enzyme' -import toJson from 'enzyme-to-json' -import { Login, LoginProps } from '../login' - -const props: LoginProps = { - error: false, - isLogin: false, - login: jest.fn(), - authChangeLoginType: jest.fn(), - loginType: 'CLIENT', - // @ts-ignore: ignore to fullfil the definition of RouteComponentProps - location: { - pathname: '/client', - }, -} - -describe('Login', () => { - it('should match a snapshot', () => { - expect(toJson(shallow())).toMatchSnapshot() - }) -}) diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/authenticated.tsx b/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/authenticated.tsx deleted file mode 100644 index d46ac3db14..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/authenticated.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from 'react' -import { H3, FlexContainerBasic, FlexContainerResponsive, SubTitleH5 } from '@reapit/elements' - -export interface AuthenticatedMappedActions {} - -export interface AuthenticatedMappedProps {} - -export type AuthenticatedProps = AuthenticatedMappedActions & AuthenticatedMappedProps - -export const Authenticated: React.FunctionComponent = () => { - return ( - - -

Welcome To Reapit Foundations

- You are now authenticated against our sandbox data -
-
- ) -} - -export default Authenticated diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/home.tsx b/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/home.tsx deleted file mode 100644 index 6dd617ae62..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/home.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import * as React from 'react' -import { withRouter, RouteComponentProps } from 'react-router' -import { Link } from 'react-router-dom' -import { H3, FlexContainerBasic, FlexContainerResponsive, SubTitleH5 } from '@reapit/elements' - -export type HomeMappedActions = {} - -export type HomeMappedProps = { - homeState: any -} - -export type HomeProps = HomeMappedActions & HomeMappedProps & RouteComponentProps<{ page?: any }> - -export const Home: React.FunctionComponent = () => { - return ( - - -

Welcome To Reapit Foundations

- - Click here to login - -
-
- ) -} - -export default withRouter(Home) diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/login.tsx b/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/login.tsx deleted file mode 100644 index 536357f15e..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/components/pages/login.tsx +++ /dev/null @@ -1,135 +0,0 @@ -import * as React from 'react' -import { Redirect } from 'react-router-dom' -import { withRouter, RouteComponentProps } from 'react-router' -import Routes from '@/constants/routes' -import { Input, Button, H1, Level, Alert, isEmail, Formik, Form } from '@reapit/elements' -import { LoginParams } from '@reapit/cognito-auth' -<% if (stylesSolution == 'sass') { %>import loginStyles from '@/styles/pages/login.scss?mod'<%}%> -<% if (stylesSolution == 'styledComponents') { %>import { Container, Wrapper, ImageContainer } from './__styles__/login'<%}%> -import logoImage from '@/assets/images/reapit-graphic.jpg' - -export type LoginMappedActions = { - login: (params: LoginParams) => void -} - -export type LoginMappedProps = { - hasSession: boolean - error: boolean -} - -export type LoginFormValues = { - email: string - password: string -} - -export type LoginFormError = { - email?: string - password?: string -} - -export function validate(values: LoginFormValues) { - let errors = {} as LoginFormError - - if (!values.email) { - errors.email = 'Required' - } else if (!isEmail(values.email)) { - errors.email = 'Invalid email address' - } - - if (!values.password) { - errors.password = 'Required' - } - - return errors -} - -export type LoginProps = LoginMappedActions & LoginMappedProps & RouteComponentProps - -export const onSubmitHandler = (setIsSubmitting: any, login: any, values: LoginFormValues) => { - const { email, password } = values - - setIsSubmitting(true) - login({ userName: email, password, loginType: 'CLIENT' } as LoginParams) -} - -export const Login: React.FunctionComponent = (props: LoginProps) => { - const [isSubmitting, setIsSubmitting] = React.useState(false) - const { hasSession, error, login } = props - <% if (stylesSolution == 'sass') { %>const { disabled, wrapper, container, image } = loginStyles<%}%> - - React.useEffect(() => { - if (error) { - setIsSubmitting(false) - } - }, [error]) - - if (hasSession) { - return - } - - return ( - <% if (stylesSolution == 'sass') { %>
-
-

Sign in

-

Welcome to <%= name %>

<%}%> - - <% if (stylesSolution == 'styledComponents') { %> - -

Sign in

-

Welcome to <%= name %>

<%}%> - - onSubmitHandler(setIsSubmitting, login, values)} - render={() => ( -
- - - - - - - - {error && } - - )} - /> - - - <% if (stylesSolution == 'sass') { %> -
- -
- Reapit Graphic -
-
- <%}%> - <% if (stylesSolution == 'styledComponents') { %> - - - - Reapit Graphic - - - <%}%> - ) -} - -export default withRouter(Login) diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/core/__tests__/__snapshots__/app.tsx.snap b/packages/react-app-scaffolder/app/templates/apollo/src/core/__tests__/__snapshots__/app.tsx.snap deleted file mode 100644 index 11f21ac70a..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/core/__tests__/__snapshots__/app.tsx.snap +++ /dev/null @@ -1,1847 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`App should match a snapshot 1`] = ` - - Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - }, - Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - } => Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - }, - }, - "watches": Set {}, - }, - "clearStoreCallbacks": Array [], - "defaultOptions": Object {}, - "disableNetworkFetches": false, - "link": ApolloLink { - "request": [Function], - }, - "localState": LocalState { - "cache": InMemoryCache { - "addTypename": true, - "cacheKeyRoot": KeyTrie { - "weakness": true, - }, - "config": Object { - "addTypename": true, - "dataIdFromObject": [Function], - "fragmentMatcher": HeuristicFragmentMatcher {}, - "freezeResults": false, - "resultCaching": true, - }, - "data": DepTrackingCache { - "data": Object {}, - "depend": [Function], - }, - "maybeBroadcastWatch": [Function], - "optimisticData": DepTrackingCache { - "data": Object {}, - "depend": [Function], - }, - "silenceBroadcast": false, - "storeReader": StoreReader { - "executeSelectionSet": [Function], - "executeStoreQuery": [Function], - "executeSubSelectedArray": [Function], - "freezeResults": false, - }, - "storeWriter": StoreWriter {}, - "typenameDocumentCache": Map { - Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - } => Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - }, - Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - } => Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - }, - }, - "watches": Set {}, - }, - "client": [Circular], - "resolvers": Object { - "Mutation": Object {}, - "Query": Object { - "contacts": [Function], - }, - }, - }, - "mutate": [Function], - "query": [Function], - "queryDeduplication": true, - "queryManager": QueryManager { - "assumeImmutableResults": false, - "clientAwareness": Object { - "name": undefined, - "version": undefined, - }, - "dataStore": DataStore { - "cache": InMemoryCache { - "addTypename": true, - "cacheKeyRoot": KeyTrie { - "weakness": true, - }, - "config": Object { - "addTypename": true, - "dataIdFromObject": [Function], - "fragmentMatcher": HeuristicFragmentMatcher {}, - "freezeResults": false, - "resultCaching": true, - }, - "data": DepTrackingCache { - "data": Object {}, - "depend": [Function], - }, - "maybeBroadcastWatch": [Function], - "optimisticData": DepTrackingCache { - "data": Object {}, - "depend": [Function], - }, - "silenceBroadcast": false, - "storeReader": StoreReader { - "executeSelectionSet": [Function], - "executeStoreQuery": [Function], - "executeSubSelectedArray": [Function], - "freezeResults": false, - }, - "storeWriter": StoreWriter {}, - "typenameDocumentCache": Map { - Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - } => Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - }, - Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - } => Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - }, - }, - "watches": Set {}, - }, - }, - "fetchQueryRejectFns": Map {}, - "idCounter": 1, - "inFlightLinkObservables": Map {}, - "link": ApolloLink { - "request": [Function], - }, - "localState": LocalState { - "cache": InMemoryCache { - "addTypename": true, - "cacheKeyRoot": KeyTrie { - "weakness": true, - }, - "config": Object { - "addTypename": true, - "dataIdFromObject": [Function], - "fragmentMatcher": HeuristicFragmentMatcher {}, - "freezeResults": false, - "resultCaching": true, - }, - "data": DepTrackingCache { - "data": Object {}, - "depend": [Function], - }, - "maybeBroadcastWatch": [Function], - "optimisticData": DepTrackingCache { - "data": Object {}, - "depend": [Function], - }, - "silenceBroadcast": false, - "storeReader": StoreReader { - "executeSelectionSet": [Function], - "executeStoreQuery": [Function], - "executeSubSelectedArray": [Function], - "freezeResults": false, - }, - "storeWriter": StoreWriter {}, - "typenameDocumentCache": Map { - Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - } => Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - }, - Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - } => Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - }, - }, - "watches": Set {}, - }, - "client": [Circular], - "resolvers": Object { - "Mutation": Object {}, - "Query": Object { - "contacts": [Function], - }, - }, - }, - "mutationStore": MutationStore { - "store": Object {}, - }, - "onBroadcast": [Function], - "pollingInfoByQueryId": Map {}, - "queries": Map {}, - "queryDeduplication": true, - "queryStore": QueryStore { - "store": Object {}, - }, - "ssrMode": false, - "transformCache": WeakMap {}, - }, - "reFetchObservableQueries": [Function], - "resetStore": [Function], - "resetStoreCallbacks": Array [], - "store": DataStore { - "cache": InMemoryCache { - "addTypename": true, - "cacheKeyRoot": KeyTrie { - "weakness": true, - }, - "config": Object { - "addTypename": true, - "dataIdFromObject": [Function], - "fragmentMatcher": HeuristicFragmentMatcher {}, - "freezeResults": false, - "resultCaching": true, - }, - "data": DepTrackingCache { - "data": Object {}, - "depend": [Function], - }, - "maybeBroadcastWatch": [Function], - "optimisticData": DepTrackingCache { - "data": Object {}, - "depend": [Function], - }, - "silenceBroadcast": false, - "storeReader": StoreReader { - "executeSelectionSet": [Function], - "executeStoreQuery": [Function], - "executeSubSelectedArray": [Function], - "freezeResults": false, - }, - "storeWriter": StoreWriter {}, - "typenameDocumentCache": Map { - Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - } => Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - }, - Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - } => Object { - "definitions": Array [ - Object { - "kind": "OperationDefinition", - "name": Object { - "kind": "Name", - "value": "GeneratedClientQuery", - }, - "operation": "query", - "selectionSet": Object { - "kind": "SelectionSet", - "selections": Array [], - }, - }, - ], - "kind": "Document", - }, - }, - "watches": Set {}, - }, - }, - "typeDefs": Object { - "definitions": Array [ - Object { - "directives": Array [], - "fields": Array [ - Object { - "arguments": Array [ - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "id", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - ], - "directives": Array [], - "kind": "FieldDefinition", - "name": Object { - "kind": "Name", - "value": "contact", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "Contact", - }, - }, - }, - }, - Object { - "arguments": Array [ - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "name", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "address", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "negotiatorId", - }, - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "officeId", - }, - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "active", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "Boolean", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "pageNumber", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "Int", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "pageSize", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "Int", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "sortBy", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "identityCheck", - }, - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "marketingConsent", - }, - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - }, - ], - "directives": Array [], - "kind": "FieldDefinition", - "name": Object { - "kind": "Name", - "value": "contacts", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "Contacts", - }, - }, - }, - }, - Object { - "arguments": Array [ - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "id", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "checkId", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - ], - "directives": Array [], - "kind": "FieldDefinition", - "name": Object { - "kind": "Name", - "value": "contactIdentityCheck", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "ContactIdentityCheck", - }, - }, - }, - }, - Object { - "arguments": Array [ - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "id", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "pageNumber", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "Int", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "pageSize", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "Int", - }, - }, - }, - ], - "directives": Array [], - "kind": "FieldDefinition", - "name": Object { - "kind": "Name", - "value": "contactIdentityChecks", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "ContactIdentityChecks", - }, - }, - }, - }, - ], - "interfaces": Array [], - "kind": "ObjectTypeDefinition", - "name": Object { - "kind": "Name", - "value": "Query", - }, - }, - Object { - "directives": Array [], - "fields": Array [ - Object { - "arguments": Array [ - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "title", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "forename", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "surname", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "dateOfBirth", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "active", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "Boolean", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "marketingConsent", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "communications", - }, - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "ContactCommunicationInput", - }, - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "officeIds", - }, - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "negotiatorIds", - }, - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "addresses", - }, - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "ContactAddressInput", - }, - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "metadata", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "JSON", - }, - }, - }, - ], - "directives": Array [], - "kind": "FieldDefinition", - "name": Object { - "kind": "Name", - "value": "createContact", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "Contact", - }, - }, - }, - }, - Object { - "arguments": Array [ - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "id", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "title", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "forename", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "surname", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "dateOfBirth", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "active", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "Boolean", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "marketingConsent", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "communications", - }, - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "ContactCommunicationInput", - }, - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "officeIds", - }, - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "negotiatorIds", - }, - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "addresses", - }, - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "ContactAddressInput", - }, - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "metadata", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "JSON", - }, - }, - }, - ], - "directives": Array [], - "kind": "FieldDefinition", - "name": Object { - "kind": "Name", - "value": "updateContact", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "Contact", - }, - }, - }, - }, - Object { - "arguments": Array [ - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "contactId", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "checkDate", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "status", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "negotiatorId", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "documents", - }, - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "ContactIdentityDocumentInput", - }, - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "metadata", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "JSON", - }, - }, - }, - ], - "directives": Array [], - "kind": "FieldDefinition", - "name": Object { - "kind": "Name", - "value": "createContactIdentityCheck", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "ContactIdentityCheck", - }, - }, - }, - }, - Object { - "arguments": Array [ - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "id", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "contactId", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "checkDate", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "status", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "negotiatorId", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "documents", - }, - "type": Object { - "kind": "ListType", - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "ContactIdentityDocumentInput", - }, - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "metadata", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "JSON", - }, - }, - }, - ], - "directives": Array [], - "kind": "FieldDefinition", - "name": Object { - "kind": "Name", - "value": "updateIdentityCheck", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "ContactIdentityCheck", - }, - }, - }, - }, - Object { - "arguments": Array [ - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "userName", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "password", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "String", - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "loginType", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "LoginType", - }, - }, - }, - }, - Object { - "directives": Array [], - "kind": "InputValueDefinition", - "name": Object { - "kind": "Name", - "value": "mode", - }, - "type": Object { - "kind": "NonNullType", - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "LoginMode", - }, - }, - }, - }, - ], - "directives": Array [], - "kind": "FieldDefinition", - "name": Object { - "kind": "Name", - "value": "login", - }, - "type": Object { - "kind": "NamedType", - "name": Object { - "kind": "Name", - "value": "Token", - }, - }, - }, - ], - "interfaces": Array [], - "kind": "ObjectTypeDefinition", - "name": Object { - "kind": "Name", - "value": "Mutation", - }, - }, - ], - "kind": "Document", - "loc": Object { - "end": 1872, - "source": Object { - "body": "type Query { - # contact - contact( - id: String!, - ): Contact! - - contacts( - name: String, - address: String, - negotiatorId: [String!], - officeId: [String!], - active: Boolean, - pageNumber: Int, - pageSize: Int, - sortBy: String, - identityCheck: [String!], - marketingConsent: [String!], - ): Contacts! - - # contact-identity-check - contactIdentityCheck( - id: String!, - checkId: String!, - ): ContactIdentityCheck! - - contactIdentityChecks( - id: String!, - pageNumber: Int, - pageSize: Int, - ): ContactIdentityChecks! - -} - -type Mutation { - # contact - createContact( - title: String, - forename: String, - surname: String, - dateOfBirth: String, - active: Boolean, - marketingConsent: String, - communications: [ContactCommunicationInput!], - officeIds: [String!], - negotiatorIds: [String!], - addresses: [ContactAddressInput!], - metadata: JSON, - ): Contact! - - updateContact( - id: String!, - title: String, - forename: String, - surname: String, - dateOfBirth: String, - active: Boolean, - marketingConsent: String, - communications: [ContactCommunicationInput!], - officeIds: [String!], - negotiatorIds: [String!], - addresses: [ContactAddressInput!], - metadata: JSON, - ): Contact! - - # contact-identity-check - createContactIdentityCheck( - contactId: String!, - checkDate: String, - status: String, - negotiatorId: String, - documents: [ContactIdentityDocumentInput!], - metadata: JSON, - ): ContactIdentityCheck! - - updateIdentityCheck( - id: String!, - contactId: String!, - checkDate: String, - status: String, - negotiatorId: String, - documents: [ContactIdentityDocumentInput!], - metadata: JSON, - ): ContactIdentityCheck! - - login( - userName: String!, - password: String!, - loginType: LoginType!, - mode: LoginMode!, - ): Token -} -", - "locationOffset": Object { - "column": 1, - "line": 1, - }, - "name": "GraphQL request", - }, - "start": 0, - }, - }, - "version": "2.6.8", - "watchQuery": [Function], - } - } - > - - - - -`; diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/core/__tests__/__snapshots__/private-route-wrapper.tsx.snap b/packages/react-app-scaffolder/app/templates/apollo/src/core/__tests__/__snapshots__/private-route-wrapper.tsx.snap deleted file mode 100644 index faa51af46d..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/core/__tests__/__snapshots__/private-route-wrapper.tsx.snap +++ /dev/null @@ -1,835 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`PrivateRouter should match a snapshot 1`] = ` -Object { - "asFragment": [Function], - "baseElement": -
- - , - "container":
- , - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; - -exports[`PrivateRouter should match a snapshot 2`] = ` -Object { - "asFragment": [Function], - "baseElement": -
- , - "container":
, - "debug": [Function], - "findAllByAltText": [Function], - "findAllByDisplayValue": [Function], - "findAllByLabelText": [Function], - "findAllByPlaceholderText": [Function], - "findAllByRole": [Function], - "findAllByTestId": [Function], - "findAllByText": [Function], - "findAllByTitle": [Function], - "findByAltText": [Function], - "findByDisplayValue": [Function], - "findByLabelText": [Function], - "findByPlaceholderText": [Function], - "findByRole": [Function], - "findByTestId": [Function], - "findByText": [Function], - "findByTitle": [Function], - "getAllByAltText": [Function], - "getAllByDisplayValue": [Function], - "getAllByLabelText": [Function], - "getAllByPlaceholderText": [Function], - "getAllByRole": [Function], - "getAllByTestId": [Function], - "getAllByText": [Function], - "getAllByTitle": [Function], - "getByAltText": [Function], - "getByDisplayValue": [Function], - "getByLabelText": [Function], - "getByPlaceholderText": [Function], - "getByRole": [Function], - "getByTestId": [Function], - "getByText": [Function], - "getByTitle": [Function], - "queryAllByAltText": [Function], - "queryAllByDisplayValue": [Function], - "queryAllByLabelText": [Function], - "queryAllByPlaceholderText": [Function], - "queryAllByRole": [Function], - "queryAllByTestId": [Function], - "queryAllByText": [Function], - "queryAllByTitle": [Function], - "queryByAltText": [Function], - "queryByDisplayValue": [Function], - "queryByLabelText": [Function], - "queryByPlaceholderText": [Function], - "queryByRole": [Function], - "queryByTestId": [Function], - "queryByText": [Function], - "queryByTitle": [Function], - "rerender": [Function], - "unmount": [Function], -} -`; diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/core/private-route-wrapper.tsx b/packages/react-app-scaffolder/app/templates/apollo/src/core/private-route-wrapper.tsx deleted file mode 100644 index 58587d8930..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/core/private-route-wrapper.tsx +++ /dev/null @@ -1,53 +0,0 @@ -import * as React from 'react' -import { withRouter, RouteComponentProps, Redirect } from 'react-router-dom' -import Menu from '@/components/ui/menu' -import { Loader, AppNavContainer, Section, FlexContainerBasic } from '@reapit/elements' -import { redirectToOAuth } from '@reapit/cognito-auth' -import { AuthContext } from '@/context' -import Routes from '@/constants/routes' - -const { Suspense } = React - -export type PrivateRouteWrapperProps = RouteComponentProps & { - path: string -} - -export const PrivateRouteWrapper: React.FunctionComponent = ({ children }) => { - const { loginSession, refreshParams, getLoginSession } = React.useContext(AuthContext) - - if (!loginSession && !refreshParams) { - redirectToOAuth(window.reapit.config.cognitoClientId) - return null - } - - if (!loginSession && refreshParams) { - getLoginSession(refreshParams) - } - - if (!loginSession) { - return null - } - - if (location.pathname === '/') { - return - } - - return ( - - - - - - - } - > - {children} - - - - ) -} - -export default withRouter(PrivateRouteWrapper) diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__mocks__/contact.ts b/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__mocks__/contact.ts deleted file mode 100644 index 63fd063889..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__mocks__/contact.ts +++ /dev/null @@ -1,24 +0,0 @@ -export const contact = { - __typename: 'Contact', - active: false, - addresses: [ - { - __typename: 'ContactAddress', - buildingName: 'building name', - buildingNumber: '1', - line1: '15 Furzen Crescent', - line2: 'line2', - line3: 'line3', - postcode: 'AL10 9QN', - }, - ], - created: '2019-11-26T11:19:23.0000000Z', - dateOfBirth: '1986-06-29T13:00:00.0000000Z', - forename: 'Development', - id: 'MOD19000001', - identityCheck: 'pass', - marketingConsent: 'notAsked', - modified: '2019-12-13T13:32:28.0000000Z', - surname: 'Environment', - title: 'Mrs', -} diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__mocks__/contacts.ts b/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__mocks__/contacts.ts deleted file mode 100644 index 58008eacc2..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__mocks__/contacts.ts +++ /dev/null @@ -1,243 +0,0 @@ -export const contacts = { - __typename: 'Contacts', - _embedded: [ - { - __typename: 'Contact', - active: false, - addresses: [ - { - __typename: 'ContactAddress', - buildingName: 'building name', - buildingNumber: '1', - line1: '15 Furzen Crescent', - line2: 'line2', - line3: 'line3', - postcode: 'AL10 9QN', - }, - ], - created: '2019-11-26T11:19:23.0000000Z', - dateOfBirth: '1986-06-29T13:00:00.0000000Z', - forename: 'Development', - id: 'MOD19000001', - identityCheck: 'pass', - marketingConsent: 'notAsked', - modified: '2019-12-13T13:32:28.0000000Z', - surname: 'Environment', - title: 'Mrs', - }, - { - __typename: 'Contact', - active: true, - addresses: [ - { - __typename: 'ContactAddress', - buildingName: '', - buildingNumber: '38', - line1: 'Stephen Crescent', - line2: 'Humberston', - line3: 'Grimsby', - postcode: 'DN36 4DT', - }, - ], - created: '2019-11-05T12:47:50.0000000Z', - dateOfBirth: '1981-03-25', - forename: 'Paul', - id: 'AYL19000004', - identityCheck: 'cancelled', - marketingConsent: 'notAsked', - modified: '2019-11-26T13:18:04.0000000Z', - surname: 'Rideout', - title: 'Mr', - }, - { - __typename: 'Contact', - active: false, - addresses: [ - { - __typename: 'ContactAddress', - buildingName: '', - buildingNumber: '86a', - line1: 'Potternewton Lane', - line2: 'Chapel Allerton', - line3: 'Leeds', - postcode: 'LS7 3LW', - }, - ], - created: '2019-11-05T12:35:44.0000000Z', - dateOfBirth: '1981-03-25', - forename: 'Dave', - id: 'AYL19000003', - identityCheck: 'pending', - marketingConsent: 'notAsked', - modified: '2019-11-26T13:18:04.0000000Z', - surname: 'Gilbert', - title: 'Mr', - }, - { - __typename: 'Contact', - active: false, - addresses: [ - { - __typename: 'ContactAddress', - buildingName: 'Tyto Alba', - buildingNumber: '38', - line1: 'Stephen Crescent', - line2: 'Humberston', - line3: 'Grimsby', - postcode: 'DN36 4DT', - }, - ], - created: '2019-11-04T11:32:55.0000000Z', - dateOfBirth: '1981-03-26', - forename: 'Charles', - id: 'AYL19000002', - identityCheck: 'cancelled', - marketingConsent: 'notAsked', - modified: '2019-11-26T13:18:04.0000000Z', - surname: 'Babbage', - title: 'Mr', - }, - { - __typename: 'Contact', - active: true, - addresses: [ - { - __typename: 'ContactAddress', - buildingName: 'Name', - buildingNumber: '38', - line1: 'Stephen Crescent', - line2: 'Grimsby', - line3: 'N E Lincs', - postcode: 'DN36 4DT', - }, - ], - created: '2019-11-03T19:45:29.0000000Z', - dateOfBirth: '1981-03-24T17:00:00.0000000Z', - forename: 'Dawson', - id: 'RPT19000366', - identityCheck: 'pending', - marketingConsent: 'notAsked', - modified: '2019-12-11T07:11:42.0000000Z', - surname: 'Scott', - title: 'Mr', - }, - { - __typename: 'Contact', - active: true, - addresses: [ - { - __typename: 'ContactAddress', - buildingName: 'Ash Lodge', - buildingNumber: '3', - line1: 'Northbourne Road', - line2: 'London', - line3: '', - postcode: 'SE5 9RL', - }, - ], - created: '2019-11-03T19:09:58.0000000Z', - dateOfBirth: '1984-09-24', - forename: 'Katy', - id: 'RPT19000365', - identityCheck: 'pending', - marketingConsent: 'notAsked', - modified: '2019-11-04T16:16:28.0000000Z', - surname: 'Easton', - title: 'Ms', - }, - { - __typename: 'Contact', - active: true, - addresses: [ - { - __typename: 'ContactAddress', - buildingName: 'aa', - buildingNumber: '37', - line1: 'Kingsway Place', - line2: 'London', - line3: 'a', - postcode: 'EC1R 0LU', - }, - ], - created: '2019-10-31T14:19:51.0000000Z', - dateOfBirth: '2019-12-12', - forename: 'H', - id: 'AYL19000001', - identityCheck: 'pass', - marketingConsent: 'grant', - modified: '2019-12-13T05:38:17.0000000Z', - surname: 'Phillips', - title: 'Mrs', - }, - { - __typename: 'Contact', - active: true, - addresses: [ - { - __typename: 'ContactAddress', - buildingName: '', - buildingNumber: '46', - line1: 'Farm Street', - line2: 'High Wycombe', - line3: 'Milton Keynes', - postcode: 'MK4 4AG', - }, - ], - created: '2019-10-25T11:09:08.0000000Z', - dateOfBirth: '1986-06-30', - forename: 'Rogan', - id: 'RPT19000363', - identityCheck: 'pending', - marketingConsent: 'notAsked', - modified: '2019-12-10T10:13:44.0000000Z', - surname: 'Johnstone', - title: 'Mr', - }, - { - __typename: 'Contact', - active: true, - addresses: null, - created: '2019-10-24T09:11:29.0000000Z', - dateOfBirth: null, - forename: 'James', - id: 'BED19000003', - identityCheck: 'pending', - marketingConsent: 'notAsked', - modified: '2019-10-24T09:14:55.0000000Z', - surname: 'Brown', - title: 'Mr', - }, - { - __typename: 'Contact', - active: true, - addresses: null, - created: '2019-10-24T08:29:00.0000000Z', - dateOfBirth: null, - forename: '', - id: 'RPT19000362', - identityCheck: 'unchecked', - marketingConsent: 'notAsked', - modified: '2019-10-24T08:30:17.0000000Z', - surname: '', - title: '', - }, - ], - _links: { - first: { - href: '/contacts/?PageNumber=1&PageSize=10', - }, - last: { - href: '/contacts/?PageNumber=397&PageSize=10', - }, - next: { - href: '/contacts/?PageNumber=2&PageSize=10', - }, - self: { - href: '/contacts/?PageNumber=1&PageSize=10', - }, - }, - pageCount: 10, - pageNumber: 1, - pageSize: 10, - totalCount: 3966, -} diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__mocks__/error.ts b/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__mocks__/error.ts deleted file mode 100644 index 7d2d3432ee..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__mocks__/error.ts +++ /dev/null @@ -1,7 +0,0 @@ -export const error = { - message: 'mockError', - graphQLErrors: [], - networkError: { name: 'Error', message: 'Error' }, - extraInfo: [], - name: 'Error', -} diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__mocks__/token.ts b/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__mocks__/token.ts deleted file mode 100644 index b24f710d1c..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__mocks__/token.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { LoginParams } from '@reapit/cognito-auth' - -export const token = { - __typename: 'Token', - accessToken: 'mockAccessToken', - refreshToken: 'mockRefreshToken', -} - -export const loginParams = { - userName: 'mockUsername', - password: 'mockPassword', - loginType: 'CLIENT', - mode: 'WEB', -} as LoginParams diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__tests__/client.test.ts b/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__tests__/client.test.ts deleted file mode 100644 index 1795abcefd..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__tests__/client.test.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Operation, IdGetterObj } from 'apollo-boost' -import { ErrorResponse } from 'apollo-link-error' -import { GraphQLError } from 'graphql' -import { getClient, generateRequest, onError, dataIdFromObject } from '@/graphql/client' - -describe('client', () => { - describe('getClient', () => { - it('should run correctly', () => { - const mockAccessToken = 'mockAccessToken' - const result = getClient(mockAccessToken) - expect(result).toBeDefined() - }) - }) - describe('generateRequest', () => { - it('should run correctly', done => { - // @ts-ignore - const mockOperation = { - setContext: jest.fn(), - } as Operation - generateRequest('mockToken')(mockOperation) - setTimeout(() => { - expect(mockOperation.setContext).toBeCalled() - done() - }, 1000) - }) - }) - describe('onError', () => { - it('should run correctly when have both', () => { - const mockError = { - graphQLErrors: [new GraphQLError('123')] as ReadonlyArray, - networkError: new Error('abc'), - } as ErrorResponse - onError(mockError) - }) - - it('should run correctly when no graphQLErrors', () => { - const mockError = { - graphQLErrors: [] as ReadonlyArray, - networkError: new Error('abc'), - } as ErrorResponse - onError(mockError) - }) - - it('should run correctly when no networkError', () => { - const mockError = { - graphQLErrors: [new GraphQLError('123')] as ReadonlyArray, - networkError: undefined, - } as ErrorResponse - onError(mockError) - }) - - it('should run correctly when no error', () => { - const mockError = { - graphQLErrors: [] as ReadonlyArray, - networkError: undefined, - } as ErrorResponse - onError(mockError) - }) - }) - - describe('dataIdFromObject', () => { - it('should run correctly', () => { - const mockObject = { - __typename: 'mockType', - id: '1', - } as IdGetterObj - const result = dataIdFromObject(mockObject) - const output = `${mockObject.__typename}:${mockObject.id}` - expect(result).toEqual(output) - }) - }) -}) diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__tests__/resolver.test.ts b/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__tests__/resolver.test.ts deleted file mode 100644 index cb8c68a361..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/__tests__/resolver.test.ts +++ /dev/null @@ -1,14 +0,0 @@ -import resolvers from '../resolvers' -import { contacts } from '../__mocks__/contacts' - -describe('resolvers', () => { - describe('contacts', () => { - it('should run correctly', async done => { - const result = await resolvers.Query.contacts() - setTimeout(() => { - expect(result).toEqual(contacts) - done() - }, 2000) - }) - }) -}) diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/client.ts b/packages/react-app-scaffolder/app/templates/apollo/src/graphql/client.ts deleted file mode 100644 index 8d768100af..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/client.ts +++ /dev/null @@ -1,54 +0,0 @@ -import ApolloClient, { InMemoryCache, Operation, defaultDataIdFromObject, IdGetterObj } from 'apollo-boost' -import { ErrorHandler, ErrorResponse } from 'apollo-link-error' -import { ApolloCache } from 'apollo-cache' -import typeDefs from './schema.graphql' -import resolvers from './resolvers' - -export const generateRequest = (accessToken: string) => async (operation: Operation) => { - operation.setContext({ - headers: { - authorization: accessToken, - }, - }) -} - -export const onError: ErrorHandler = ({ graphQLErrors, networkError }: ErrorResponse) => { - if (graphQLErrors) { - graphQLErrors.map(({ message, locations, path }) => - console.log(`[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`), - ) - } - if (networkError) console.log(`[Network error]: ${networkError}`) -} - -export const dataIdFromObject = (object: IdGetterObj) => { - // Will open when custom object ID for caching - // switch (object.__typename) { - // // Custom keycache here! - // default: - // return defaultDataIdFromObject(object) - // } - return defaultDataIdFromObject(object) -} - -const cache: ApolloCache = new InMemoryCache({ - dataIdFromObject, -}) - -const clientState = { - cache, - defaults: {}, - resolvers, - typeDefs, -} - -export const getClient = (accessToken: string, uri: string) => - new ApolloClient({ - uri, - onError, - cache, - request: generateRequest(accessToken), - clientState, - }) - -export default getClient diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/resolvers.ts b/packages/react-app-scaffolder/app/templates/apollo/src/graphql/resolvers.ts deleted file mode 100644 index cbc9e3919e..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/resolvers.ts +++ /dev/null @@ -1,14 +0,0 @@ -import sleep from '@/utils/sleep' -import { contacts } from './__mocks__/contacts' - -const resolvers = { - Query: { - contacts: async () => { - await sleep(1000) - return contacts - }, - }, - Mutation: {}, -} - -export default resolvers diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/schema.graphql b/packages/react-app-scaffolder/app/templates/apollo/src/graphql/schema.graphql deleted file mode 100644 index 4253cc49dc..0000000000 --- a/packages/react-app-scaffolder/app/templates/apollo/src/graphql/schema.graphql +++ /dev/null @@ -1,3 +0,0 @@ -type Query {} - -type Mutation {} diff --git a/packages/react-app-scaffolder/app/templates/base-is-linaria/src/styles/index.css b/packages/react-app-scaffolder/app/templates/base-is-linaria/src/styles/index.css deleted file mode 100644 index 3c02e6809d..0000000000 --- a/packages/react-app-scaffolder/app/templates/base-is-linaria/src/styles/index.css +++ /dev/null @@ -1,9 +0,0 @@ -@import url('https://fonts.googleapis.com/css?family=Source+Code+Pro&display=swap'); -@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap'); - - -<%if (!isFoundation) { %> -/* need this because we import production elements. in foundation we import the code from element directly which imports the element styles */ -@import "~@reapit/elements/dist/index.css" -<% } %> - diff --git a/packages/react-app-scaffolder/app/templates/base-is-sass/src/styles/base/colors.scss b/packages/react-app-scaffolder/app/templates/base-is-sass/src/styles/base/colors.scss deleted file mode 100644 index cefdf1553b..0000000000 --- a/packages/react-app-scaffolder/app/templates/base-is-sass/src/styles/base/colors.scss +++ /dev/null @@ -1,27 +0,0 @@ -$white: #fff; -$black: #12263f; -$grey-dark: #6e84a3; -$grey: #95aac9; -$grey-lighter: #e3ebf6; -$grey-lightest: #f9fbfd; - -$green: #5fe781; -$green-lighter: #acf2bd; -$green-lightest: #e6ffed; -$red: #e96171; -$red-lighter: #fdb8c0; -$red-lightest: #ffeef0; - -$reapit-dark-blue: #262f69; -$reapit-mid-blue: #0061a8; -$reapit-light-blue: #23a4de; -$reapit-lightest-blue: #7bc9eb; - -$reapit-orange: #ec631b; -$reapit-lime: #cddb00; -$reapit-teal: #006580; -$reapit-plumb: #7a2c81; -$reapit-purple: #a4185c; -$reapit-gold: #ffb71b; -$reapit-green: #a0c862; -$reapit-red: #d3033d; diff --git a/packages/react-app-scaffolder/app/templates/base-is-sass/src/styles/base/layout.scss b/packages/react-app-scaffolder/app/templates/base-is-sass/src/styles/base/layout.scss deleted file mode 100644 index a21cb393db..0000000000 --- a/packages/react-app-scaffolder/app/templates/base-is-sass/src/styles/base/layout.scss +++ /dev/null @@ -1,14 +0,0 @@ -$layout-base: 1rem; -// Generic layout values that scale to rem base -$layout-quarter: calc(1rem / 4); -$layout-third: calc(1rem / 3); -$layout-half: calc(1rem / 2); -$layout-two-third: calc(1rem * 0.67); -$layout-three-quarter: calc(1rem * 0.75); -$layout-one-quarter: calc(1rem * 1.25); -$layout-one-half: calc(1rem * 1.5); -$layout-double: calc(1rem * 2); -$layout-two-half: calc(1rem * 2.5); -$layout-triple: calc(1rem * 3); -$layout-quadruple: calc(1rem * 4); -$layout-sextuple: calc(1rem * 6); diff --git a/packages/react-app-scaffolder/app/templates/base-is-sass/src/styles/index.scss b/packages/react-app-scaffolder/app/templates/base-is-sass/src/styles/index.scss deleted file mode 100644 index 279ed39041..0000000000 --- a/packages/react-app-scaffolder/app/templates/base-is-sass/src/styles/index.scss +++ /dev/null @@ -1,8 +0,0 @@ -@charset "utf-8"; -@import url('https://fonts.googleapis.com/css?family=Source+Code+Pro&display=swap'); -@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap'); - -<%if (!isFoundation) { %> -/* need this because we import production elements. in foundation we import the code from element directly which imports the element styles */ -@import "~@reapit/elements/dist/index.css" -<% } %> diff --git a/packages/react-app-scaffolder/app/templates/base/.npmrc b/packages/react-app-scaffolder/app/templates/base/.npmrc deleted file mode 100644 index bd3327ab5a..0000000000 --- a/packages/react-app-scaffolder/app/templates/base/.npmrc +++ /dev/null @@ -1 +0,0 @@ -//registry.npmjs.org/:_authToken=${NPM_TOKEN} \ No newline at end of file diff --git a/packages/react-app-scaffolder/app/templates/base/public/index.js b/packages/react-app-scaffolder/app/templates/base/public/index.js deleted file mode 100644 index d0e80f1ee1..0000000000 --- a/packages/react-app-scaffolder/app/templates/base/public/index.js +++ /dev/null @@ -1,38 +0,0 @@ -const http = require('http') -const url = require('url') -const fs = require('fs') -const path = require('path') -const port = 8080 - -http - .createServer((request, response) => { - try { - const requestUrl = url.parse(request.url) - const fsPath = `${__dirname}/dist${path.normalize(requestUrl.pathname)}` // need to use path.normalize so people can't access directories underneath baseDirectory - const fileStream = /\.(js|css|woff|gif|jpg|jpeg|tiff|png)$/i.test(fsPath) - ? fs.createReadStream(fsPath) - : fs.createReadStream(`${__dirname}/dist/index.html`) - - fileStream.pipe(response) - fileStream.on('open', () => { - response.writeHead(200) - }) - fileStream.on('error', e => { - response.writeHead(404) // assume the file doesn't exist - response.end() - }) - } catch (e) { - response.writeHead(500) - response.end() // end the response so browsers don't hang - console.log(e.stack) - } - }) - .listen(port) - -process.title = process.argv[2] -process.on('SIGINT', () => { - console.log(`Gracefully shutting down ${process.title}`) - process.exit() -}) - -console.log(`Listening on port ${port}`) diff --git a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427936/353acc2c-88f2-4de3-83eb-6cc2c9b05af1.ttf b/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427936/353acc2c-88f2-4de3-83eb-6cc2c9b05af1.ttf deleted file mode 100755 index 7a2e60c6d8..0000000000 Binary files a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427936/353acc2c-88f2-4de3-83eb-6cc2c9b05af1.ttf and /dev/null differ diff --git a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427936/9803fddf-c005-431a-92d5-0f18688f945d.woff2 b/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427936/9803fddf-c005-431a-92d5-0f18688f945d.woff2 deleted file mode 100755 index c38d9ef1e7..0000000000 Binary files a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427936/9803fddf-c005-431a-92d5-0f18688f945d.woff2 and /dev/null differ diff --git a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427936/ea9b8ac3-ff16-4387-a473-32a6a617329f.woff b/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427936/ea9b8ac3-ff16-4387-a473-32a6a617329f.woff deleted file mode 100755 index 8695bba38d..0000000000 Binary files a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427936/ea9b8ac3-ff16-4387-a473-32a6a617329f.woff and /dev/null differ diff --git a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427936/f2cf6cf9-9ec6-4945-a525-f5873d143c2a.eot b/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427936/f2cf6cf9-9ec6-4945-a525-f5873d143c2a.eot deleted file mode 100755 index 3b2fb12725..0000000000 Binary files a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427936/f2cf6cf9-9ec6-4945-a525-f5873d143c2a.eot and /dev/null differ diff --git a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427944/1c070cdb-18d8-440e-be9d-2448fa3930c4.eot b/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427944/1c070cdb-18d8-440e-be9d-2448fa3930c4.eot deleted file mode 100755 index 3c246ee6fb..0000000000 Binary files a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427944/1c070cdb-18d8-440e-be9d-2448fa3930c4.eot and /dev/null differ diff --git a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427944/66c06801-da3e-4587-a89c-674cfbe39c21.woff2 b/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427944/66c06801-da3e-4587-a89c-674cfbe39c21.woff2 deleted file mode 100755 index 0c0e23f86f..0000000000 Binary files a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427944/66c06801-da3e-4587-a89c-674cfbe39c21.woff2 and /dev/null differ diff --git a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427944/c21bf502-6b58-4bf0-9ddd-169929c263e7.ttf b/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427944/c21bf502-6b58-4bf0-9ddd-169929c263e7.ttf deleted file mode 100755 index 406dc21fd0..0000000000 Binary files a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427944/c21bf502-6b58-4bf0-9ddd-169929c263e7.ttf and /dev/null differ diff --git a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427944/f3c7f613-9728-4ed6-a383-1c8519b215d2.woff b/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427944/f3c7f613-9728-4ed6-a383-1c8519b215d2.woff deleted file mode 100755 index 8b3d1ec354..0000000000 Binary files a/packages/react-app-scaffolder/app/templates/base/src/assets/fonts/1427944/f3c7f613-9728-4ed6-a383-1c8519b215d2.woff and /dev/null differ diff --git a/packages/react-app-scaffolder/app/templates/hooks-external/.eslintrc.js b/packages/react-app-scaffolder/app/templates/hooks-external/.eslintrc.js new file mode 100644 index 0000000000..bc51f80efb --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/hooks-external/.eslintrc.js @@ -0,0 +1,76 @@ +module.exports = { + env: { + browser: true, + es6: true, + node: true, + amd: true, + jest: true, + }, + extends: [ + 'eslint:recommended', + 'plugin:react/recommended', + 'plugin:@typescript-eslint/eslint-recommended', + 'prettier', + 'prettier/@typescript-eslint', + 'prettier/react', + 'prettier/standard', + ], + globals: { + Atomics: 'readonly', + SharedArrayBuffer: 'readonly', + }, + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + ecmaVersion: 2018, + sourceType: 'module', + }, + plugins: ['react', '@typescript-eslint', 'prettier', 'react-hooks'], + ignorePatterns: [ + '__mocks__/', + 'node_modules/', + 'setup-tests.ts', + 'jest.config.js', + '.prettierrc.js', + 'react-app-scaffolder/', + 'marketplace-api-schema.ts', + 'platform-schema.ts', + ], + rules: { + quotes: ['error', 'single', { avoidEscape: true, allowTemplateLiterals: false }], + semi: ['error', 'never'], + 'no-unused-vars': ['error', { vars: 'all', args: 'after-used' }], + '@typescript-eslint/no-unused-vars': [2, { args: 'none' }], + 'prettier/prettier': ['error', { + 'endOfLine': 'auto' + }], + 'max-len': ['error', { code: 120, ignoreUrls: true }], + 'no-confusing-arrow': ['error', { allowParens: false }], + 'no-mixed-operators': [ + 'error', + { + groups: [ + ['&', '|', '^', '~', '<<', '>>', '>>>'], + ['==', '!=', '===', '!==', '>', '>=', '<', '<='], + ['&&', '||'], + ['in', 'instanceof'], + ], + }, + ], + 'no-tabs': ['error', { allowIndentationTabs: true }], + 'no-unexpected-multiline': 'error', + // Disabling as conflicts with Prettier + indent: 0, + // Disabling as we are validating types with TypeScript not PropTypes + 'react/prop-types': 0, + "react-hooks/rules-of-hooks": 0, + "react-hooks/exhaustive-deps": 0, + }, + settings: { + react: { + version: 'detect', + }, + }, +} diff --git a/packages/react-app-scaffolder/app/templates/hooks-external/.gitignore b/packages/react-app-scaffolder/app/templates/hooks-external/.gitignore new file mode 100644 index 0000000000..aeb663f439 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/hooks-external/.gitignore @@ -0,0 +1,24 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/src/tests/coverage + +# misc +.DS_Store +reapit-config.json +config.json + +# log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +*.log + +.cache/ +yarn.lock + +public/dist +src/tests + +.jest-cache \ No newline at end of file diff --git a/packages/react-app-scaffolder/app/templates/base-is-not-foundation/.prettierrc.js b/packages/react-app-scaffolder/app/templates/hooks-external/.prettierrc.js similarity index 100% rename from packages/react-app-scaffolder/app/templates/base-is-not-foundation/.prettierrc.js rename to packages/react-app-scaffolder/app/templates/hooks-external/.prettierrc.js diff --git a/packages/react-app-scaffolder/app/templates/hooks-external/config.example.json b/packages/react-app-scaffolder/app/templates/hooks-external/config.example.json new file mode 100644 index 0000000000..98a80ad258 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/hooks-external/config.example.json @@ -0,0 +1,7 @@ +{ + "appEnv": "local", + "cognitoClientId": "", + "cognitoOAuthUrl": "https://dev.connect.reapit.cloud", + "cognitoUserPoolId": "eu-west-2_hbt0B7yys", + "platformApiUrl": "https://dev.platform.reapit.cloud" +} diff --git a/packages/react-app-scaffolder/app/templates/hooks-external/jest.config.js b/packages/react-app-scaffolder/app/templates/hooks-external/jest.config.js new file mode 100644 index 0000000000..92f778077a --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/hooks-external/jest.config.js @@ -0,0 +1,42 @@ +const path = require('path') +const { defaults } = require('jest-config') +const { pathsToModuleNameMapper } = require('ts-jest/utils') +const { compilerOptions } = require('./tsconfig') + +module.exports = { + preset: 'ts-jest', + testPathIgnorePatterns: ['/src/tests/'], + setupFiles: ['/src/scripts/jest/jest-setup.js'], + collectCoverageFrom: ['/src/**/*.ts', '/src/**/*.tsx'], + coverageDirectory: './src/tests/coverage', + coveragePathIgnorePatterns: [ + '[/\\\\](node_modules|src/types|src/tests|src/scripts)[/\\\\]', + 'index.tsx', + '.d.ts', + ], + modulePathIgnorePatterns: ['[/\\\\](node_modules)[/\\\\]'], + moduleNameMapper: { + '^.+.(?=.*scss|sass|css|png|jpg|pdf).*': '/src/scripts/jest/css-stub.js', + ...pathsToModuleNameMapper(compilerOptions.paths, { + prefix: '/', + }), + }, + moduleFileExtensions: [...defaults.moduleFileExtensions, 'ts', 'tsx'], + snapshotSerializers: ['enzyme-to-json/serializer'], + verbose: false, + projects: ['/jest.config.js'], + transform: { + '^.+\\.svg$': '/src/scripts/jest/svg-transform.js', + }, + globalSetup: '/src/scripts/jest/jest-global.js', + coverageThreshold: { + global: { + branches: 65, + functions: 55, + lines: 85, + statements: 85, + }, + }, + coverageReporters: ['json-summary', 'text', 'lcov'], + cacheDirectory: path.join(__dirname, '.jest-cache'), +} diff --git a/packages/react-app-scaffolder/app/templates/hooks-external/package.json b/packages/react-app-scaffolder/app/templates/hooks-external/package.json new file mode 100644 index 0000000000..9ea8dccb76 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/hooks-external/package.json @@ -0,0 +1,80 @@ +{ + "version": "0.0.1", + "main": "./src/index.ts", + "license": "MIT", + "private": true, + "scripts": { + "build:prod": "webpack --color --mode production --config './src/scripts/webpack-prod.js'", + "start:dev": "webpack-dev-server --hot --progress --color --mode development --config ./src/scripts/webpack-dev.js", + "lint": "concurrently \"tsc --noEmit\" \"eslint --cache --ext=ts,tsx src\"", + "lint:fix": "eslint --cache --ext=ts,tsx src --fix", + "start:prod": "serve public/dist -s -l 8080", + "test:ci": "cross-env TZ=UTC jest --ci --colors --coverage --silent --forceExit --detectOpenHandles --runInBand", + "test:dev": "cross-env TZ=UTC jest --watch --verbose" + }, + "dependencies": { + "@reapit/cognito-auth": "2.1.7", + "@reapit/elements": "0.5.61", + "@reapit/foundations-ts-definitions": "2020-02-13", + "dayjs": "^1.8.19", + "react": "~16.12.0", + "react-dom": "~16.12.0", + "react-router": "~5.1.2", + "react-router-dom": "~5.1.2" + }, + "devDependencies": { + "@babel/core": "~7.7.2", + "@babel/polyfill": "~7.7.0", + "@babel/preset-env": "~7.7.1", + "@testing-library/react": "~10.0.1", + "@testing-library/react-hooks": "~3.3.0", + "@types/enzyme": "~3.10.3", + "@types/enzyme-adapter-react-16": "~1.0.5", + "@types/jest": "~24.0.23", + "@types/node": "10.17.13", + "@types/react": "~16.9.0", + "@types/react-dom": "~16.9.0", + "@types/react-router": "~5.1.3", + "@types/react-router-dom": "~5.1.3", + "@typescript-eslint/eslint-plugin": "~2.23.0", + "@typescript-eslint/parser": "~2.23.0", + "autoprefixer": "~9.8.0", + "babel-loader": "~8.1.0", + "concurrently": "~5.2.0", + "cross-env": "~7.0.2", + "css-loader": "~3.6.0", + "enzyme": "~3.10.0", + "enzyme-adapter-react-16": "~1.15.1", + "enzyme-to-json": "~3.4.3", + "eslint": "~6.7.2", + "eslint-config-prettier": "~6.7.0", + "eslint-plugin-prettier": "~3.1.1", + "eslint-plugin-react": "~7.17.0", + "eslint-plugin-react-hooks": "~2.3.0", + "favicons-webpack-plugin": "~2.1.0", + "file-loader": "~3.0.1", + "fork-ts-checker-notifier-webpack-plugin": "~1.0.0", + "fork-ts-checker-webpack-plugin": "~1.3.4", + "hard-source-webpack-plugin": "~0.13.1", + "html-webpack-plugin": "~3.2.0", + "jest": "~25.1.0", + "jest-config": "~25.1.0", + "jest-fetch-mock": "~2.1.2", + "mini-css-extract-plugin": "~0.9.0", + "mockdate": "~3.0.2", + "postcss-flexbugs-fixes": "~4.2.1", + "postcss-loader": "~3.0.0", + "prettier": "~1.19.1", + "serve": "~11.3.2", + "style-loader": "~1.1.3", + "thread-loader": "~2.1.3", + "ts-jest": "~25.2.0", + "ts-loader": "~6.0.1", + "ts-paths-to-webpack-alias": "~0.3.1", + "typescript": "3.7.2", + "typescript-eslint": "~0.0.1-alpha.0", + "webpack": "~4.41.5", + "webpack-cli": "~3.3.2", + "webpack-dev-server": "~3.4.1" + } +} diff --git a/packages/react-app-scaffolder/app/templates/base-is-not-foundation/postcss.config.js b/packages/react-app-scaffolder/app/templates/hooks-external/postcss.config.js similarity index 100% rename from packages/react-app-scaffolder/app/templates/base-is-not-foundation/postcss.config.js rename to packages/react-app-scaffolder/app/templates/hooks-external/postcss.config.js diff --git a/packages/react-app-scaffolder/app/templates/hooks-external/public/index.html b/packages/react-app-scaffolder/app/templates/hooks-external/public/index.html new file mode 100644 index 0000000000..72cb6e98ef --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/hooks-external/public/index.html @@ -0,0 +1,13 @@ + + + + + + + Reapit Foundations + + + +
+ + diff --git a/packages/react-app-scaffolder/app/templates/base/public/logo.png b/packages/react-app-scaffolder/app/templates/hooks-external/public/logo.png similarity index 100% rename from packages/react-app-scaffolder/app/templates/base/public/logo.png rename to packages/react-app-scaffolder/app/templates/hooks-external/public/logo.png diff --git a/packages/react-app-scaffolder/app/templates/base/src/assets/images/reapit-connect.png b/packages/react-app-scaffolder/app/templates/hooks-external/src/assets/images/reapit-connect.png similarity index 100% rename from packages/react-app-scaffolder/app/templates/base/src/assets/images/reapit-connect.png rename to packages/react-app-scaffolder/app/templates/hooks-external/src/assets/images/reapit-connect.png diff --git a/packages/react-app-scaffolder/app/templates/base/src/assets/images/reapit-graphic.jpg b/packages/react-app-scaffolder/app/templates/hooks-external/src/assets/images/reapit-graphic.jpg similarity index 100% rename from packages/react-app-scaffolder/app/templates/base/src/assets/images/reapit-graphic.jpg rename to packages/react-app-scaffolder/app/templates/hooks-external/src/assets/images/reapit-graphic.jpg diff --git a/packages/react-app-scaffolder/app/templates/hooks-external/src/components/hocs/__tests__/__snapshots__/error-boundary.tsx.snap b/packages/react-app-scaffolder/app/templates/hooks-external/src/components/hocs/__tests__/__snapshots__/error-boundary.tsx.snap new file mode 100644 index 0000000000..c971b7b33b --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/hooks-external/src/components/hocs/__tests__/__snapshots__/error-boundary.tsx.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ErrorBoundary should match a snapshot when has an error 1`] = ` +

+ Something went wrong here, try refreshing your page. +

+`; + +exports[`ErrorBoundary should match a snapshot when no error 1`] = ``; diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/components/hocs/__tests__/error-boundary.tsx b/packages/react-app-scaffolder/app/templates/hooks-external/src/components/hocs/__tests__/error-boundary.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/components/hocs/__tests__/error-boundary.tsx rename to packages/react-app-scaffolder/app/templates/hooks-external/src/components/hocs/__tests__/error-boundary.tsx diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/components/hocs/error-boundary.tsx b/packages/react-app-scaffolder/app/templates/hooks-external/src/components/hocs/error-boundary.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/components/hocs/error-boundary.tsx rename to packages/react-app-scaffolder/app/templates/hooks-external/src/components/hocs/error-boundary.tsx diff --git a/packages/react-app-scaffolder/app/templates/base-is-linaria/src/components/pages/__styles__/styles.ts b/packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/__styles__/styles.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/base-is-linaria/src/components/pages/__styles__/styles.ts rename to packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/__styles__/styles.ts diff --git a/packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/__tests__/__snapshots__/authenticated.tsx.snap b/packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/__tests__/__snapshots__/authenticated.tsx.snap new file mode 100644 index 0000000000..6bd6fcc0cc --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/__tests__/__snapshots__/authenticated.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Authenticated should match a snapshot 1`] = ``; diff --git a/packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/__tests__/__snapshots__/login.tsx.snap b/packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/__tests__/__snapshots__/login.tsx.snap new file mode 100644 index 0000000000..0486a88694 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/__tests__/__snapshots__/login.tsx.snap @@ -0,0 +1,199 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Login should match a snapshot 1`] = ` +Object { + "asFragment": [Function], + "baseElement": +
+ , + "container":
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; + +exports[`Login should match a snapshot 2`] = ` +Object { + "asFragment": [Function], + "baseElement": +
+
+
+
+ Reapit Connect Graphic +
+
+ +
+
+
+ Reapit Graphic +
+
+
+ , + "container":
+
+
+
+ Reapit Connect Graphic +
+
+ +
+
+
+ Reapit Graphic +
+
+
, + "debug": [Function], + "findAllByAltText": [Function], + "findAllByDisplayValue": [Function], + "findAllByLabelText": [Function], + "findAllByPlaceholderText": [Function], + "findAllByRole": [Function], + "findAllByTestId": [Function], + "findAllByText": [Function], + "findAllByTitle": [Function], + "findByAltText": [Function], + "findByDisplayValue": [Function], + "findByLabelText": [Function], + "findByPlaceholderText": [Function], + "findByRole": [Function], + "findByTestId": [Function], + "findByText": [Function], + "findByTitle": [Function], + "getAllByAltText": [Function], + "getAllByDisplayValue": [Function], + "getAllByLabelText": [Function], + "getAllByPlaceholderText": [Function], + "getAllByRole": [Function], + "getAllByTestId": [Function], + "getAllByText": [Function], + "getAllByTitle": [Function], + "getByAltText": [Function], + "getByDisplayValue": [Function], + "getByLabelText": [Function], + "getByPlaceholderText": [Function], + "getByRole": [Function], + "getByTestId": [Function], + "getByText": [Function], + "getByTitle": [Function], + "queryAllByAltText": [Function], + "queryAllByDisplayValue": [Function], + "queryAllByLabelText": [Function], + "queryAllByPlaceholderText": [Function], + "queryAllByRole": [Function], + "queryAllByTestId": [Function], + "queryAllByText": [Function], + "queryAllByTitle": [Function], + "queryByAltText": [Function], + "queryByDisplayValue": [Function], + "queryByLabelText": [Function], + "queryByPlaceholderText": [Function], + "queryByRole": [Function], + "queryByTestId": [Function], + "queryByText": [Function], + "queryByTitle": [Function], + "rerender": [Function], + "unmount": [Function], +} +`; diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/components/pages/__tests__/authenticated.tsx b/packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/__tests__/authenticated.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/components/pages/__tests__/authenticated.tsx rename to packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/__tests__/authenticated.tsx diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/components/pages/__tests__/login.tsx b/packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/__tests__/login.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/components/pages/__tests__/login.tsx rename to packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/__tests__/login.tsx diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/components/pages/authenticated.tsx b/packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/authenticated.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/components/pages/authenticated.tsx rename to packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/authenticated.tsx diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/components/pages/login.tsx b/packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/login.tsx similarity index 90% rename from packages/react-app-scaffolder/app/templates/no-redux/src/components/pages/login.tsx rename to packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/login.tsx index 3b40d25bd4..89ecda0ac3 100644 --- a/packages/react-app-scaffolder/app/templates/no-redux/src/components/pages/login.tsx +++ b/packages/react-app-scaffolder/app/templates/hooks-external/src/components/pages/login.tsx @@ -4,11 +4,9 @@ import { Redirect } from 'react-router-dom' import Routes from '@/constants/routes' import { Button, Level } from '@reapit/elements' -<% if(sass){ %> -import loginStyles from '@/styles/pages/login.scss?mod' -<% } else { %> + import * as loginStyles from './__styles__/styles' - <% } %> + import logoImage from '@/assets/images/reapit-graphic.jpg' import connectImage from '@/assets/images/reapit-connect.png' @@ -37,8 +35,6 @@ export const Login: React.FunctionComponent = () => { Reapit Connect Graphic -

Welcome to app-name

- + +
+ +
+ Reapit Graphic +
+
+ ) +} + +export default Login diff --git a/packages/react-app-scaffolder/app/templates/hooks-internal/src/components/ui/__tests__/menu.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/components/ui/__tests__/menu.tsx new file mode 100644 index 0000000000..636d02aa37 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/hooks-internal/src/components/ui/__tests__/menu.tsx @@ -0,0 +1,39 @@ +import * as React from 'react' +import { shallow } from 'enzyme' +import { getMockRouterProps } from '@/core/__mocks__/mock-router' +import { AuthContext } from '@/context' +import { mockContext } from '@/context/__mocks__/mock-context' +import { Menu, MenuProps, generateMenuConfig, callbackAppClick } from '../menu' + +describe('Menu', () => { + it('should match a snapshot', () => { + const props = { + ...getMockRouterProps({ params: {}, search: '' }), + } + const wrapper = shallow( + + + , + ) + expect(wrapper).toMatchSnapshot() + }) + + describe('generateMenuConfig', () => { + it('should return config', () => { + const props = { + ...getMockRouterProps({ params: {}, search: '' }), + } as MenuProps + const logoutCallback = jest.fn() + const result = generateMenuConfig(logoutCallback, props.location, 'WEB') + expect(result).toBeDefined() + }) + }) + + describe('callbackAppClick', () => { + it('should run correcly', () => { + window.location.href = 'dev' + const fn = callbackAppClick() + expect(fn).toEqual('https://dev.marketplace.reapit.cloud/client/installed') + }) + }) +}) diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/components/ui/menu.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/components/ui/menu.tsx similarity index 61% rename from packages/react-app-scaffolder/app/templates/apollo/src/components/ui/menu.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/components/ui/menu.tsx index 0fa7f9f895..82f7a5c15a 100644 --- a/packages/react-app-scaffolder/app/templates/apollo/src/components/ui/menu.tsx +++ b/packages/react-app-scaffolder/app/templates/hooks-internal/src/components/ui/menu.tsx @@ -1,9 +1,10 @@ import * as React from 'react' import { withRouter, RouteComponentProps } from 'react-router' import { Menu as Sidebar, MenuConfig, ReapitLogo } from '@reapit/elements' -import { LoginMode } from '@reapit/cognito-auth' import { Location } from 'history' import { FaSignOutAlt, FaCloud } from 'react-icons/fa' +import { LoginMode } from '@reapit/cognito-auth' +import { AuthContext } from '@/context' export const generateMenuConfig = ( logoutCallback: () => void, @@ -24,10 +25,7 @@ export const generateMenuConfig = ( title: 'Apps', key: 'APPS', icon: , - callback: () => - (window.location.href = window.location.href.includes('dev') || window.location.href.includes('localhost') - ? 'https://dev.marketplace.reapit.cloud/client/installed' - : 'https://marketplace.reapit.cloud/client/installed'), + callback: callbackAppClick, type: 'PRIMARY', }, { @@ -41,19 +39,20 @@ export const generateMenuConfig = ( } } -export type DispatchProps = { - logout: () => void -} +export const callbackAppClick = () => + (window.location.href = + window.location.href.includes('dev') || window.location.href.includes('localhost') + ? 'https://dev.marketplace.reapit.cloud/client/installed' + : 'https://marketplace.reapit.cloud/client/installed') -export type StateProps = { - mode: LoginMode -} +export type MenuProps = RouteComponentProps + +export const Menu: React.FunctionComponent = ({ location }) => { + const { logout, loginSession } = React.useContext(AuthContext) + const mode = loginSession?.mode || 'WEB' -export type MenuProps = DispatchProps & StateProps & RouteComponentProps & {} + const menuConfigs = generateMenuConfig(logout, location, mode) -export const Menu: React.FC = ({ logout, location, mode }: MenuProps) => { - const logoutCallback = () => logout() - const menuConfigs = generateMenuConfig(logoutCallback, location, mode) return } diff --git a/packages/react-app-scaffolder/app/templates/hooks-internal/src/constants/api.ts b/packages/react-app-scaffolder/app/templates/hooks-internal/src/constants/api.ts new file mode 100644 index 0000000000..c737c935cb --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/hooks-internal/src/constants/api.ts @@ -0,0 +1,12 @@ +import { StringMap } from '@/types/core' +import { COOKIE_SESSION_KEY as COGNITIO_COOKIE_SESSION_KEY } from '@reapit/cognito-auth' + +export const CONTACTS_HEADERS = { + 'Content-Type': 'application/json', +} as StringMap + +export const API_VERSION = '2020-01-31' + +export const COOKIE_SESSION_KEY = COGNITIO_COOKIE_SESSION_KEY + +export const URLS = {} diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/constants/auth.ts b/packages/react-app-scaffolder/app/templates/hooks-internal/src/constants/auth.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/constants/auth.ts rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/constants/auth.ts diff --git a/packages/react-app-scaffolder/app/templates/base/src/constants/error-messages.ts b/packages/react-app-scaffolder/app/templates/hooks-internal/src/constants/error-messages.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/base/src/constants/error-messages.ts rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/constants/error-messages.ts diff --git a/packages/react-app-scaffolder/app/templates/redux/src/constants/routes.ts b/packages/react-app-scaffolder/app/templates/hooks-internal/src/constants/routes.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/constants/routes.ts rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/constants/routes.ts diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/context/__mocks__/mock-context.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/context/__mocks__/mock-context.tsx similarity index 92% rename from packages/react-app-scaffolder/app/templates/apollo/src/context/__mocks__/mock-context.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/context/__mocks__/mock-context.tsx index 2d737f68d2..117e7fb056 100644 --- a/packages/react-app-scaffolder/app/templates/apollo/src/context/__mocks__/mock-context.tsx +++ b/packages/react-app-scaffolder/app/templates/hooks-internal/src/context/__mocks__/mock-context.tsx @@ -19,9 +19,10 @@ export const mockContext = { groups: [], }, loginType: 'CLIENT', - cognitoClientId: 'mockCognitoClientId', + cognitoClientId: '123', refreshToken: 'mockRefreshToken', }, + isFetchSession: false, logout: jest.fn(), getLoginSession: jest.fn(), refreshParams: null, diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/context/__tests__/__snapshots__/auth-context.test.tsx.snap b/packages/react-app-scaffolder/app/templates/hooks-internal/src/context/__tests__/__snapshots__/auth-context.test.tsx.snap similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/context/__tests__/__snapshots__/auth-context.test.tsx.snap rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/context/__tests__/__snapshots__/auth-context.test.tsx.snap diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/context/__tests__/auth-context.test.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/context/__tests__/auth-context.test.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/context/__tests__/auth-context.test.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/context/__tests__/auth-context.test.tsx diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/context/auth-context.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/context/auth-context.tsx similarity index 76% rename from packages/react-app-scaffolder/app/templates/apollo/src/context/auth-context.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/context/auth-context.tsx index a7a3f5223f..26b0642902 100644 --- a/packages/react-app-scaffolder/app/templates/apollo/src/context/auth-context.tsx +++ b/packages/react-app-scaffolder/app/templates/hooks-internal/src/context/auth-context.tsx @@ -1,5 +1,5 @@ import React from 'react' -import { useAuth, AuthHook } from '@/hooks/use-auth' +import { AuthHook } from '@/hooks/use-auth' export const AuthContext = React.createContext({} as AuthHook) AuthContext.displayName = 'AuthContext' diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/context/index.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/context/index.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/context/index.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/context/index.tsx diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/core/__mocks__/mock-router.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/__mocks__/mock-router.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/core/__mocks__/mock-router.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/core/__mocks__/mock-router.tsx diff --git a/packages/react-app-scaffolder/app/templates/redux/src/core/__mocks__/router.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/__mocks__/router.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/core/__mocks__/router.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/core/__mocks__/router.tsx diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/core/__tests__/app.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/__tests__/app.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/core/__tests__/app.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/core/__tests__/app.tsx diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/core/__tests__/private-route-wrapper.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/__tests__/private-route-wrapper.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/core/__tests__/private-route-wrapper.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/core/__tests__/private-route-wrapper.tsx diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/core/__tests__/private-route.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/__tests__/private-route.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/core/__tests__/private-route.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/core/__tests__/private-route.tsx diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/core/__tests__/router.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/__tests__/router.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/core/__tests__/router.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/core/__tests__/router.tsx diff --git a/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/app.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/app.tsx new file mode 100644 index 0000000000..987db1242e --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/app.tsx @@ -0,0 +1,28 @@ +import * as React from 'react' +import Router from './router' +import ErrorBoundary from '@/components/hocs/error-boundary' + +import { useAuth } from '@/hooks/use-auth' +import { AuthContext } from '@/context' +import { injectSwitchModeToWindow } from '@reapit/elements' + +injectSwitchModeToWindow() + +import '@/styles/index.css' + +const App = () => { + const { loginSession, refreshParams, getLoginSession, isFetchSession, ...rest } = useAuth() + if (!loginSession && refreshParams && !isFetchSession) { + getLoginSession(refreshParams) + } + + return ( + + + + + + ) +} + +export default App diff --git a/packages/react-app-scaffolder/app/templates/base/src/core/index.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/index.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/base/src/core/index.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/core/index.tsx diff --git a/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/private-route-wrapper.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/private-route-wrapper.tsx new file mode 100644 index 0000000000..cc20eae5e0 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/private-route-wrapper.tsx @@ -0,0 +1,58 @@ +import * as React from 'react' +import { Loader, Section, FlexContainerResponsive, AppNavContainer, FlexContainerBasic } from '@reapit/elements' +import { withRouter, RouteComponentProps } from 'react-router-dom' +import Menu from '@/components/ui/menu' +import { redirectToOAuth } from '@reapit/cognito-auth' +import { AuthContext } from '@/context' + +const { Suspense } = React + +export type PrivateRouteWrapperProps = RouteComponentProps & { + path: string +} + +export const PrivateRouteWrapper: React.FunctionComponent = ({ children }) => { + const { loginSession, refreshParams, getLoginSession, isFetchSession } = React.useContext(AuthContext) + + if (!loginSession && !refreshParams) { + redirectToOAuth(window.reapit.config.cognitoClientId) + return null + } + + if (!loginSession && refreshParams && !isFetchSession) { + getLoginSession(refreshParams) + } + + if (!loginSession) { + return null + } + + if (isFetchSession) { + return ( +
+ +
+ ) + } + + return ( + + + + + + + + } + > + {children} + + + + + ) +} + +export default withRouter(PrivateRouteWrapper) diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/core/private-route.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/private-route.tsx similarity index 97% rename from packages/react-app-scaffolder/app/templates/apollo/src/core/private-route.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/core/private-route.tsx index b97e05b820..b9b77dd07c 100644 --- a/packages/react-app-scaffolder/app/templates/apollo/src/core/private-route.tsx +++ b/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/private-route.tsx @@ -12,6 +12,7 @@ export interface PrivateRouteProps extends PrivateRouteConnectProps { allow: LoginType | LoginType[] component: React.FunctionComponent exact?: boolean + fetcher?: boolean } export const PrivateRoute = ({ component, allow, loginType = 'CLIENT', ...rest }: PrivateRouteProps & RouteProps) => { diff --git a/packages/react-app-scaffolder/app/templates/redux/src/core/router.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/core/router.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/core/router.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/core/router.tsx diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/hooks/__mocks__/mount-react-hook.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/hooks/__mocks__/mount-react-hook.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/hooks/__mocks__/mount-react-hook.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/hooks/__mocks__/mount-react-hook.tsx diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/hooks/__tests__/__snapshots__/use-auth.test.tsx.snap b/packages/react-app-scaffolder/app/templates/hooks-internal/src/hooks/__tests__/__snapshots__/use-auth.test.tsx.snap similarity index 100% rename from packages/react-app-scaffolder/app/templates/apollo/src/hooks/__tests__/__snapshots__/use-auth.test.tsx.snap rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/hooks/__tests__/__snapshots__/use-auth.test.tsx.snap diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/hooks/__tests__/use-auth.test.tsx b/packages/react-app-scaffolder/app/templates/hooks-internal/src/hooks/__tests__/use-auth.test.tsx similarity index 99% rename from packages/react-app-scaffolder/app/templates/apollo/src/hooks/__tests__/use-auth.test.tsx rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/hooks/__tests__/use-auth.test.tsx index bdefa12fd5..3f7dffa1bf 100644 --- a/packages/react-app-scaffolder/app/templates/apollo/src/hooks/__tests__/use-auth.test.tsx +++ b/packages/react-app-scaffolder/app/templates/hooks-internal/src/hooks/__tests__/use-auth.test.tsx @@ -4,7 +4,7 @@ import { useAuth, AuthHook } from '../use-auth' import mountReactHook from '../__mocks__/mount-react-hook' const refreshParams: RefreshParams = { - cognitoClientId: '1', + cognitoClientId: '123', loginType: 'CLIENT', mode: 'WEB', redirectUri: '1', diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/hooks/use-auth.ts b/packages/react-app-scaffolder/app/templates/hooks-internal/src/hooks/use-auth.ts similarity index 94% rename from packages/react-app-scaffolder/app/templates/apollo/src/hooks/use-auth.ts rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/hooks/use-auth.ts index 004d60504a..1ecbc9e5be 100644 --- a/packages/react-app-scaffolder/app/templates/apollo/src/hooks/use-auth.ts +++ b/packages/react-app-scaffolder/app/templates/hooks-internal/src/hooks/use-auth.ts @@ -15,6 +15,7 @@ export type AuthHook = { logout: () => void getLoginSession: (refreshParams: RefreshParams | null) => Promise refreshParams?: RefreshParams | null + isFetchSession: boolean } export const useAuth = (): AuthHook => { @@ -22,7 +23,7 @@ export const useAuth = (): AuthHook => { const [loginSession, setLoginSession] = React.useState(null) const urlParams: RefreshParams | null = getTokenFromQueryString( window.location.search, - window.reapit.config.cognitoClientId + window.reapit.config.cognitoClientId, ) const cookieParams = getSessionCookie(COOKIE_SESSION_KEY) const refreshParams = cookieParams ? cookieParams : urlParams @@ -51,6 +52,7 @@ export const useAuth = (): AuthHook => { loginSession, logout, getLoginSession, + isFetchSession, } } diff --git a/packages/react-app-scaffolder/app/templates/hooks-internal/src/styles/index.css b/packages/react-app-scaffolder/app/templates/hooks-internal/src/styles/index.css new file mode 100644 index 0000000000..f1323ff4b3 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/hooks-internal/src/styles/index.css @@ -0,0 +1,6 @@ +@import url('https://fonts.googleapis.com/css?family=Source+Code+Pro&display=swap'); +@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap'); + + + + diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/types/core.ts b/packages/react-app-scaffolder/app/templates/hooks-internal/src/types/core.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/types/core.ts rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/types/core.ts diff --git a/packages/react-app-scaffolder/app/templates/no-redux/src/types/global.d.ts b/packages/react-app-scaffolder/app/templates/hooks-internal/src/types/global.d.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/no-redux/src/types/global.d.ts rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/types/global.d.ts diff --git a/packages/react-app-scaffolder/app/templates/redux/src/types/index.d.ts b/packages/react-app-scaffolder/app/templates/hooks-internal/src/types/index.d.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/types/index.d.ts rename to packages/react-app-scaffolder/app/templates/hooks-internal/src/types/index.d.ts diff --git a/packages/react-app-scaffolder/app/templates/base-is-foundation/tsconfig.json b/packages/react-app-scaffolder/app/templates/hooks-internal/tsconfig.json similarity index 100% rename from packages/react-app-scaffolder/app/templates/base-is-foundation/tsconfig.json rename to packages/react-app-scaffolder/app/templates/hooks-internal/tsconfig.json diff --git a/packages/react-app-scaffolder/app/templates/is-foundation-no-redux/package.json b/packages/react-app-scaffolder/app/templates/is-foundation-no-redux/package.json deleted file mode 100644 index 575a333d24..0000000000 --- a/packages/react-app-scaffolder/app/templates/is-foundation-no-redux/package.json +++ /dev/null @@ -1,102 +0,0 @@ -{ - "name": "<%= name %>", - "version": "0.0.1", - "description": "<%= description %>", - "main": "./src/index.ts", - "repository": { - "type": "git", - "url": "git+<%= repo %>" - }, - "author": "<%= author %>", - "license": "MIT", - "private": true, - "scripts": { - "build:prod": "webpack --color --mode production --config './src/scripts/webpack-prod.js'", - "start:dev": "webpack-dev-server --hot --progress --color --mode development --config ./src/scripts/webpack-dev.js", - "lint": "concurrently \"tsc --noEmit\" \"eslint --cache --ext=ts,tsx src\"", - "lint:fix": "eslint --cache --ext=ts,tsx src --fix", - "start:prod": "serve public/dist -s -l 8080", - "test:ci": "cross-env TZ=UTC jest --ci --colors --coverage --silent --forceExit --detectOpenHandles --runInBand", - "test:dev": "cross-env TZ=UTC jest --watch --verbose", - "fetch-config": "yarn config-manager fetchConfig app-name" - }, - "dependencies": { - "@reapit/cognito-auth": "latest", - "@reapit/elements": "0.5.61-alpha.1", - "@reapit/foundations-ts-definitions": "2020-02-13", - "@sentry/browser": "^5.11.1", - "@testing-library/react": "^10.0.1", - "dayjs": "latest", - "offline-plugin": "^5.0.7", - "react": "^16.11.0", - "react-dom": "^16.11.0", - "react-ga": "^2.7.0", - "react-router": "^5.1.2", - "react-router-dom": "^5.1.2" - }, - "devDependencies": { - "@babel/core": "^7.7.2", - "@babel/polyfill": "^7.7.0", - "@babel/preset-env": "^7.7.1", - "@sentry/webpack-plugin": "^1.10.0", - "@testing-library/react-hooks": "^2.0.3", - "@types/enzyme": "^3.9.3", - "@types/jest": "^24.0.13", - "@types/node": "^12.0.2", - "@types/react": "^16.8.19", - "@types/react-dom": "^16.8.4", - "@types/react-router": "^5.1.2", - "@types/react-router-dom": "^5.1.2", - "@typescript-eslint/eslint-plugin": "^2.10.0", - "@typescript-eslint/parser": "^2.10.0", - "babel-loader": "^8.0.6", - "copy-webpack-plugin": "5.1.1", - "cross-env": "^7.0.0", - "css-loader": "^3.5.1", - "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.14.0", - "enzyme-to-json": "^3.3.5", - "eslint": "^6.7.2", - "eslint-config-prettier": "^6.7.0", - "eslint-plugin-prettier": "^3.1.1", - "eslint-plugin-react": "^7.17.0", - "eslint-plugin-react-hooks": "^2.3.0", - "favicons-webpack-plugin": "^2.1.0", - "file-loader": "^3.0.1", - "fork-ts-checker-notifier-webpack-plugin": "^1.0.0", - "fork-ts-checker-webpack-plugin": "^1.3.4", - "html-webpack-plugin": "^3.2.0", - "husky": "^2.3.0", - "isomorphic-fetch": "^2.2.1", - "jest": "^25.1.0", - "jest-config": "^25.1.0", - "jest-fetch-mock": "^2.1.2", - "lint-staged": "^8.1.7", - "loader-utils": "^1.2.3", - "node-sass": "^4.12.0", - "prettier": "^1.19.1", - "prettier-plugin-packagejson": "^2.0.1", - "raw-loader": "^3.1.0", - "sass-loader": "^7.1.0", - "serve": "^11.3.0", - "source-map-loader": "^0.2.4", - "style-loader": "^1.1.3", - "ts-jest": "^25.2.0", - "ts-loader": "^6.0.1", - "ts-node": "^8.3.0", - "ts-paths-to-webpack-alias": "^0.3.1", - "typescript": "3.7.2", - "typescript-eslint": "^0.0.1-alpha.0", - "webpack": "^4.41.5", - "webpack-cli": "^3.3.2", - "webpack-dev-server": "^3.4.1", - "mini-css-extract-plugin": "^0.9.0", - "hard-source-webpack-plugin": "^0.13.1", - "postcss-loader": "^3.0.0", - "autoprefixer": "^9.8.0", - "postcss-flexbugs-fixes": "^4.2.1", - "thread-loader": "^2.1.3", - "mockdate": "^3.0.2", - "concurrently": "^5.2.0" - } -} diff --git a/packages/react-app-scaffolder/app/templates/is-foundation-redux/package.json b/packages/react-app-scaffolder/app/templates/is-foundation-redux/package.json deleted file mode 100644 index c24122d1cb..0000000000 --- a/packages/react-app-scaffolder/app/templates/is-foundation-redux/package.json +++ /dev/null @@ -1,106 +0,0 @@ -{ - "name": "<%= name %>", - "version": "0.0.1", - "description": "<%= description %>", - "main": "./src/index.ts", - "repository": { - "type": "git", - "url": "git+<%= repo %>" - }, - "author": "<%= author %>", - "license": "MIT", - "private": true, - "scripts": { - "build:prod": "webpack --color --mode production --config './src/scripts/webpack-prod.js'", - "start:dev": "webpack-dev-server --hot --progress --color --mode development --config ./src/scripts/webpack-dev.js", - "lint": "concurrently \"tsc --noEmit\" \"eslint --cache --ext=ts,tsx src\"", - "lint:fix": "eslint --cache --ext=ts,tsx src --fix", - "start:prod": "serve public/dist -s -l 8080", - "test:ci": "cross-env TZ=UTC jest --ci --colors --coverage --silent --forceExit --detectOpenHandles --runInBand", - "test:dev": "cross-env TZ=UTC jest --watch --verbose", - "fetch-config": "yarn config-manager fetchConfig app-name" - }, - "dependencies": { - "offline-plugin": "^5.0.7", - "@reapit/cognito-auth": "latest", - "@reapit/elements": "latest", - "@reapit/foundations-ts-definitions": "2020-02-13", - "dayjs": "latest", - "react": "^16.11.0", - "react-dom": "^16.11.0", - "react-router": "^5.1.2", - "react-router-dom": "^5.1.2", - "@sentry/browser": "^5.11.1", - "react-ga": "^2.7.0", - "react-redux": "^7.1.3", - "redux": "^4.0.4", - "redux-saga": "^1.1.3" - }, - "devDependencies": { - "babel-loader": "^8.0.6", - "@babel/core": "^7.7.2", - "@babel/polyfill": "^7.7.0", - "@babel/preset-env": "^7.7.1", - "@testing-library/react-hooks": "^2.0.3", - "@types/enzyme": "^3.9.3", - "@types/jest": "^24.0.13", - "@types/node": "^12.0.2", - "@types/react": "^16.8.19", - "@types/react-dom": "^16.8.4", - "@types/react-router": "^5.1.2", - "@types/react-router-dom": "^5.1.2", - "@typescript-eslint/eslint-plugin": "^2.10.0", - "@typescript-eslint/parser": "^2.10.0", - "@sentry/webpack-plugin": "^1.10.0", - "cross-env": "^7.0.0", - "enzyme": "^3.10.0", - "enzyme-adapter-react-16": "^1.14.0", - "enzyme-to-json": "^3.3.5", - "eslint": "^6.7.2", - "eslint-config-prettier": "^6.7.0", - "eslint-plugin-prettier": "^3.1.1", - "eslint-plugin-react": "^7.17.0", - "eslint-plugin-react-hooks": "^2.3.0", - "favicons-webpack-plugin": "^2.1.0", - "file-loader": "^3.0.1", - "fork-ts-checker-notifier-webpack-plugin": "^1.0.0", - "fork-ts-checker-webpack-plugin": "^1.3.4", - "html-webpack-plugin": "^3.2.0", - "husky": "^2.3.0", - "isomorphic-fetch": "^2.2.1", - "jest": "^25.1.0", - "jest-config": "^25.1.0", - "jest-fetch-mock": "^2.1.2", - "lint-staged": "^8.1.7", - "loader-utils": "^1.2.3", - "prettier": "^1.19.1", - "prettier-plugin-packagejson": "^2.0.1", - "raw-loader": "^3.1.0", - "serve": "^11.3.0", - "source-map-loader": "^0.2.4", - "ts-jest": "^25.2.0", - "ts-loader": "^6.0.1", - "ts-node": "^8.3.0", - "ts-paths-to-webpack-alias": "^0.3.1", - "typescript": "3.7.2", - "typescript-eslint": "^0.0.1-alpha.0", - "webpack": "^4.41.5", - "webpack-cli": "^3.3.2", - "webpack-dev-server": "^3.4.1", - "sass-loader": "^7.1.0", - "node-sass": "^4.12.0", - "copy-webpack-plugin": "5.1.1", - "style-loader": "^1.1.3", - "css-loader": "^3.5.1", - "@redux-saga/testing-utils": "^1.0.5", - "@types/react-redux": "^7.0.9", - "mini-css-extract-plugin": "^0.9.0", - "hard-source-webpack-plugin": "^0.13.1", - "postcss-loader": "^3.0.0", - "autoprefixer": "^9.8.0", - "postcss-flexbugs-fixes": "^4.2.1", - "thread-loader": "^2.1.3", - "mockdate": "^3.0.2", - "concurrently": "^5.2.0" - } -} diff --git a/packages/react-app-scaffolder/app/templates/redux-external/.eslintrc.js b/packages/react-app-scaffolder/app/templates/redux-external/.eslintrc.js new file mode 100644 index 0000000000..bc51f80efb --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-external/.eslintrc.js @@ -0,0 +1,76 @@ +module.exports = { + env: { + browser: true, + es6: true, + node: true, + amd: true, + jest: true, + }, + extends: [ + 'eslint:recommended', + 'plugin:react/recommended', + 'plugin:@typescript-eslint/eslint-recommended', + 'prettier', + 'prettier/@typescript-eslint', + 'prettier/react', + 'prettier/standard', + ], + globals: { + Atomics: 'readonly', + SharedArrayBuffer: 'readonly', + }, + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + ecmaVersion: 2018, + sourceType: 'module', + }, + plugins: ['react', '@typescript-eslint', 'prettier', 'react-hooks'], + ignorePatterns: [ + '__mocks__/', + 'node_modules/', + 'setup-tests.ts', + 'jest.config.js', + '.prettierrc.js', + 'react-app-scaffolder/', + 'marketplace-api-schema.ts', + 'platform-schema.ts', + ], + rules: { + quotes: ['error', 'single', { avoidEscape: true, allowTemplateLiterals: false }], + semi: ['error', 'never'], + 'no-unused-vars': ['error', { vars: 'all', args: 'after-used' }], + '@typescript-eslint/no-unused-vars': [2, { args: 'none' }], + 'prettier/prettier': ['error', { + 'endOfLine': 'auto' + }], + 'max-len': ['error', { code: 120, ignoreUrls: true }], + 'no-confusing-arrow': ['error', { allowParens: false }], + 'no-mixed-operators': [ + 'error', + { + groups: [ + ['&', '|', '^', '~', '<<', '>>', '>>>'], + ['==', '!=', '===', '!==', '>', '>=', '<', '<='], + ['&&', '||'], + ['in', 'instanceof'], + ], + }, + ], + 'no-tabs': ['error', { allowIndentationTabs: true }], + 'no-unexpected-multiline': 'error', + // Disabling as conflicts with Prettier + indent: 0, + // Disabling as we are validating types with TypeScript not PropTypes + 'react/prop-types': 0, + "react-hooks/rules-of-hooks": 0, + "react-hooks/exhaustive-deps": 0, + }, + settings: { + react: { + version: 'detect', + }, + }, +} diff --git a/packages/react-app-scaffolder/app/templates/redux-external/.gitignore b/packages/react-app-scaffolder/app/templates/redux-external/.gitignore new file mode 100644 index 0000000000..aeb663f439 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-external/.gitignore @@ -0,0 +1,24 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/src/tests/coverage + +# misc +.DS_Store +reapit-config.json +config.json + +# log files +npm-debug.log* +yarn-debug.log* +yarn-error.log* +*.log + +.cache/ +yarn.lock + +public/dist +src/tests + +.jest-cache \ No newline at end of file diff --git a/packages/react-app-scaffolder/app/templates/redux-external/.prettierrc.js b/packages/react-app-scaffolder/app/templates/redux-external/.prettierrc.js new file mode 100644 index 0000000000..39b61eca68 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-external/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + semi: false, + trailingComma: 'all', + singleQuote: true, + printWidth: 120, + tabWidth: 2, +} diff --git a/packages/react-app-scaffolder/app/templates/redux-external/config.example.json b/packages/react-app-scaffolder/app/templates/redux-external/config.example.json new file mode 100644 index 0000000000..98a80ad258 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-external/config.example.json @@ -0,0 +1,7 @@ +{ + "appEnv": "local", + "cognitoClientId": "", + "cognitoOAuthUrl": "https://dev.connect.reapit.cloud", + "cognitoUserPoolId": "eu-west-2_hbt0B7yys", + "platformApiUrl": "https://dev.platform.reapit.cloud" +} diff --git a/packages/react-app-scaffolder/app/templates/base-is-not-foundation/jest.config.js b/packages/react-app-scaffolder/app/templates/redux-external/jest.config.js similarity index 100% rename from packages/react-app-scaffolder/app/templates/base-is-not-foundation/jest.config.js rename to packages/react-app-scaffolder/app/templates/redux-external/jest.config.js diff --git a/packages/react-app-scaffolder/app/templates/redux-external/package.json b/packages/react-app-scaffolder/app/templates/redux-external/package.json new file mode 100644 index 0000000000..c1574e5caf --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-external/package.json @@ -0,0 +1,84 @@ +{ + "version": "0.0.1", + "main": "./src/index.ts", + "license": "MIT", + "private": true, + "scripts": { + "build:prod": "webpack --color --mode production --config './src/scripts/webpack-prod.js'", + "start:dev": "webpack-dev-server --hot --progress --color --mode development --config ./src/scripts/webpack-dev.js", + "lint": "concurrently \"tsc --noEmit\" \"eslint --cache --ext=ts,tsx src\"", + "lint:fix": "eslint --cache --ext=ts,tsx src --fix", + "start:prod": "serve public/dist -s -l 8080", + "test:ci": "cross-env TZ=UTC jest --ci --colors --coverage --silent --forceExit --detectOpenHandles --runInBand", + "test:dev": "cross-env TZ=UTC jest --watch --verbose" + }, + "dependencies": { + "@reapit/cognito-auth": "2.1.7", + "@reapit/elements": "0.5.61", + "@reapit/foundations-ts-definitions": "2020-02-13", + "dayjs": "^1.8.19", + "react": "~16.12.0", + "react-dom": "~16.12.0", + "react-router": "~5.1.2", + "react-router-dom": "~5.1.2", + "react-redux": "~7.2.0", + "redux": "~4.0.5", + "redux-saga": "~1.1.3" + }, + "devDependencies": { + "@babel/core": "~7.7.2", + "@babel/polyfill": "~7.7.0", + "@babel/preset-env": "~7.7.1", + "@redux-saga/testing-utils": "^1.0.5", + "@testing-library/react": "~10.0.1", + "@testing-library/react-hooks": "~3.3.0", + "@types/enzyme": "~3.10.3", + "@types/enzyme-adapter-react-16": "~1.0.5", + "@types/jest": "~24.0.23", + "@types/node": "10.17.13", + "@types/react": "~16.9.0", + "@types/react-dom": "~16.9.0", + "@types/react-router": "~5.1.3", + "@types/react-router-dom": "~5.1.3", + "@typescript-eslint/eslint-plugin": "~2.23.0", + "@typescript-eslint/parser": "~2.23.0", + "autoprefixer": "~9.8.0", + "babel-loader": "~8.1.0", + "concurrently": "~5.2.0", + "cross-env": "~7.0.2", + "css-loader": "~3.6.0", + "enzyme": "~3.10.0", + "enzyme-adapter-react-16": "~1.15.1", + "enzyme-to-json": "~3.4.3", + "eslint": "~6.7.2", + "eslint-config-prettier": "~6.7.0", + "eslint-plugin-prettier": "~3.1.1", + "eslint-plugin-react": "~7.17.0", + "eslint-plugin-react-hooks": "~2.3.0", + "favicons-webpack-plugin": "~2.1.0", + "file-loader": "~3.0.1", + "fork-ts-checker-notifier-webpack-plugin": "~1.0.0", + "fork-ts-checker-webpack-plugin": "~1.3.4", + "hard-source-webpack-plugin": "~0.13.1", + "html-webpack-plugin": "~3.2.0", + "jest": "~25.1.0", + "jest-config": "~25.1.0", + "jest-fetch-mock": "~2.1.2", + "mini-css-extract-plugin": "~0.9.0", + "mockdate": "~3.0.2", + "postcss-flexbugs-fixes": "~4.2.1", + "postcss-loader": "~3.0.0", + "prettier": "~1.19.1", + "serve": "~11.3.2", + "style-loader": "~1.1.3", + "thread-loader": "~2.1.3", + "ts-jest": "~25.2.0", + "ts-loader": "~6.0.1", + "ts-paths-to-webpack-alias": "~0.3.1", + "typescript": "3.7.2", + "typescript-eslint": "~0.0.1-alpha.0", + "webpack": "~4.41.5", + "webpack-cli": "~3.3.2", + "webpack-dev-server": "~3.4.1" + } +} diff --git a/packages/react-app-scaffolder/app/templates/redux-external/postcss.config.js b/packages/react-app-scaffolder/app/templates/redux-external/postcss.config.js new file mode 100644 index 0000000000..ee5eb8627a --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-external/postcss.config.js @@ -0,0 +1,3 @@ +module.exports = { + plugins: [require('autoprefixer'), require('postcss-flexbugs-fixes')], +} diff --git a/packages/react-app-scaffolder/app/templates/redux-external/public/index.html b/packages/react-app-scaffolder/app/templates/redux-external/public/index.html new file mode 100644 index 0000000000..72cb6e98ef --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-external/public/index.html @@ -0,0 +1,13 @@ + + + + + + + Reapit Foundations + + + +
+ + diff --git a/packages/react-app-scaffolder/app/templates/redux-external/public/logo.png b/packages/react-app-scaffolder/app/templates/redux-external/public/logo.png new file mode 100644 index 0000000000..eaf5e2e1f3 Binary files /dev/null and b/packages/react-app-scaffolder/app/templates/redux-external/public/logo.png differ diff --git a/packages/react-app-scaffolder/app/templates/redux/src/actions/__tests__/auth.ts b/packages/react-app-scaffolder/app/templates/redux-external/src/actions/__tests__/auth.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/actions/__tests__/auth.ts rename to packages/react-app-scaffolder/app/templates/redux-external/src/actions/__tests__/auth.ts diff --git a/packages/react-app-scaffolder/app/templates/redux/src/actions/__tests__/authenticated.ts b/packages/react-app-scaffolder/app/templates/redux-external/src/actions/__tests__/authenticated.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/actions/__tests__/authenticated.ts rename to packages/react-app-scaffolder/app/templates/redux-external/src/actions/__tests__/authenticated.ts diff --git a/packages/react-app-scaffolder/app/templates/redux/src/actions/__tests__/error.ts b/packages/react-app-scaffolder/app/templates/redux-external/src/actions/__tests__/error.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/actions/__tests__/error.ts rename to packages/react-app-scaffolder/app/templates/redux-external/src/actions/__tests__/error.ts diff --git a/packages/react-app-scaffolder/app/templates/redux/src/actions/auth.ts b/packages/react-app-scaffolder/app/templates/redux-external/src/actions/auth.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/actions/auth.ts rename to packages/react-app-scaffolder/app/templates/redux-external/src/actions/auth.ts diff --git a/packages/react-app-scaffolder/app/templates/redux/src/actions/authenticated.ts b/packages/react-app-scaffolder/app/templates/redux-external/src/actions/authenticated.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/actions/authenticated.ts rename to packages/react-app-scaffolder/app/templates/redux-external/src/actions/authenticated.ts diff --git a/packages/react-app-scaffolder/app/templates/redux/src/actions/error.ts b/packages/react-app-scaffolder/app/templates/redux-external/src/actions/error.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/actions/error.ts rename to packages/react-app-scaffolder/app/templates/redux-external/src/actions/error.ts diff --git a/packages/react-app-scaffolder/app/templates/redux-external/src/assets/images/reapit-connect.png b/packages/react-app-scaffolder/app/templates/redux-external/src/assets/images/reapit-connect.png new file mode 100644 index 0000000000..207e7c5599 Binary files /dev/null and b/packages/react-app-scaffolder/app/templates/redux-external/src/assets/images/reapit-connect.png differ diff --git a/packages/react-app-scaffolder/app/templates/redux-external/src/assets/images/reapit-graphic.jpg b/packages/react-app-scaffolder/app/templates/redux-external/src/assets/images/reapit-graphic.jpg new file mode 100644 index 0000000000..99137577d8 Binary files /dev/null and b/packages/react-app-scaffolder/app/templates/redux-external/src/assets/images/reapit-graphic.jpg differ diff --git a/packages/react-app-scaffolder/app/templates/redux-external/src/components/hocs/__tests__/__snapshots__/error-boundary.tsx.snap b/packages/react-app-scaffolder/app/templates/redux-external/src/components/hocs/__tests__/__snapshots__/error-boundary.tsx.snap new file mode 100644 index 0000000000..c971b7b33b --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-external/src/components/hocs/__tests__/__snapshots__/error-boundary.tsx.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`ErrorBoundary should match a snapshot when has an error 1`] = ` +

+ Something went wrong here, try refreshing your page. +

+`; + +exports[`ErrorBoundary should match a snapshot when no error 1`] = ``; diff --git a/packages/react-app-scaffolder/app/templates/redux-external/src/components/hocs/__tests__/__snapshots__/route-fetcher.tsx.snap b/packages/react-app-scaffolder/app/templates/redux-external/src/components/hocs/__tests__/__snapshots__/route-fetcher.tsx.snap new file mode 100644 index 0000000000..aea42c8cb2 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-external/src/components/hocs/__tests__/__snapshots__/route-fetcher.tsx.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`RouteFetcher should match a snapshot 1`] = ``; diff --git a/packages/react-app-scaffolder/app/templates/redux/src/components/hocs/__tests__/error-boundary.tsx b/packages/react-app-scaffolder/app/templates/redux-external/src/components/hocs/__tests__/error-boundary.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/components/hocs/__tests__/error-boundary.tsx rename to packages/react-app-scaffolder/app/templates/redux-external/src/components/hocs/__tests__/error-boundary.tsx diff --git a/packages/react-app-scaffolder/app/templates/redux/src/components/hocs/__tests__/route-fetcher.tsx b/packages/react-app-scaffolder/app/templates/redux-external/src/components/hocs/__tests__/route-fetcher.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/components/hocs/__tests__/route-fetcher.tsx rename to packages/react-app-scaffolder/app/templates/redux-external/src/components/hocs/__tests__/route-fetcher.tsx diff --git a/packages/react-app-scaffolder/app/templates/redux/src/components/hocs/error-boundary.tsx b/packages/react-app-scaffolder/app/templates/redux-external/src/components/hocs/error-boundary.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/components/hocs/error-boundary.tsx rename to packages/react-app-scaffolder/app/templates/redux-external/src/components/hocs/error-boundary.tsx diff --git a/packages/react-app-scaffolder/app/templates/redux/src/components/hocs/route-fetcher.tsx b/packages/react-app-scaffolder/app/templates/redux-external/src/components/hocs/route-fetcher.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/components/hocs/route-fetcher.tsx rename to packages/react-app-scaffolder/app/templates/redux-external/src/components/hocs/route-fetcher.tsx diff --git a/packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/__styles__/styles.ts b/packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/__styles__/styles.ts new file mode 100644 index 0000000000..f1b00b614a --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/__styles__/styles.ts @@ -0,0 +1,69 @@ +import { css } from 'linaria' + +export const container = css` + min-width: 100vw; + min-height: 100vh; + display: flex; + justify-content: flex-end; + align-items: center; + flex-direction: row; + background-color: #fff; + + @media screen and (max-width: 900px) { + flex-direction: column-reverse; + } +` + +export const wrapper = css` + background-color: #fff; + width: 33.33%; + padding: 1rem; + pointer-events: auto; + + &.disabled { + pointer-events: none; + } + + h1, + p, + img { + text-align: center; + } + + div > img { + margin: 0 auto; + max-width: 200px; + display: block; + } + + button { + margin: 0 auto; + max-width: 400px; + } + + @media screen and (max-width: 900px) { + width: 100%; + } + + @media screen and (min-width: 1200px) { + padding: 0 3rem; + } +` + +export const image = css` + background-color: #fff; + width: 66.66%; + height: 100vh; + font-size: 0; + + img { + width: 100%; + height: 100%; + object-fit: cover; + } + + @media screen and (max-width: 900px) { + width: 100%; + height: 300px; + } +` diff --git a/packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/__tests__/__snapshots__/authenticated.tsx.snap b/packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/__tests__/__snapshots__/authenticated.tsx.snap new file mode 100644 index 0000000000..51209aa1bd --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/__tests__/__snapshots__/authenticated.tsx.snap @@ -0,0 +1,12 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Authenticated should match a snapshot 1`] = ` +
+

+ Welcome To Reapit Foundations +

+ + You are now authenticated against our sandbox data + +
+`; diff --git a/packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/__tests__/__snapshots__/login.tsx.snap b/packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/__tests__/__snapshots__/login.tsx.snap new file mode 100644 index 0000000000..dbbd7122ac --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/__tests__/__snapshots__/login.tsx.snap @@ -0,0 +1,44 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Login should match a snapshot 1`] = ` +
+
+ + Reapit Connect Graphic + + + + +
+
+ Reapit Graphic +
+
+`; + +exports[`Login should match a snapshot when hasSession 1`] = ` + +`; diff --git a/packages/react-app-scaffolder/app/templates/redux/src/components/pages/__tests__/authenticated.tsx b/packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/__tests__/authenticated.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/components/pages/__tests__/authenticated.tsx rename to packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/__tests__/authenticated.tsx diff --git a/packages/react-app-scaffolder/app/templates/redux/src/components/pages/__tests__/login.tsx b/packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/__tests__/login.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/components/pages/__tests__/login.tsx rename to packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/__tests__/login.tsx diff --git a/packages/react-app-scaffolder/app/templates/redux/src/components/pages/authenticated.tsx b/packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/authenticated.tsx similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/components/pages/authenticated.tsx rename to packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/authenticated.tsx diff --git a/packages/react-app-scaffolder/app/templates/redux/src/components/pages/login.tsx b/packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/login.tsx similarity index 91% rename from packages/react-app-scaffolder/app/templates/redux/src/components/pages/login.tsx rename to packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/login.tsx index e132957165..bfd8a4b4f2 100644 --- a/packages/react-app-scaffolder/app/templates/redux/src/components/pages/login.tsx +++ b/packages/react-app-scaffolder/app/templates/redux-external/src/components/pages/login.tsx @@ -7,11 +7,9 @@ import Routes from '@/constants/routes' import { Button, Level } from '@reapit/elements' import connectImage from '@/assets/images/reapit-connect.png' -<% if(sass){ %> -import loginStyles from '@/styles/pages/login.scss?mod' -<% } else { %> + import * as loginStyles from './__styles__/styles' - <% } %> + import { redirectToLogin } from '@reapit/cognito-auth' @@ -38,8 +36,6 @@ export const Login: React.FunctionComponent = (props: LoginProps) => Reapit Connect Graphic -

Welcome to app-name

- + +
+ +
+ Reapit Graphic +
+
+ ) +} + +export const mapStateToProps = (state: ReduxState): LoginProps => ({ + hasSession: !!state.auth.loginSession || !!state.auth.refreshSession, +}) + +export default withRouter(connect(mapStateToProps, {})(Login)) diff --git a/packages/react-app-scaffolder/app/templates/apollo/src/components/ui/__tests__/menu.tsx b/packages/react-app-scaffolder/app/templates/redux-internal/src/components/ui/__tests__/menu.tsx similarity index 67% rename from packages/react-app-scaffolder/app/templates/apollo/src/components/ui/__tests__/menu.tsx rename to packages/react-app-scaffolder/app/templates/redux-internal/src/components/ui/__tests__/menu.tsx index 8b6bd1d770..17c6ade2e7 100644 --- a/packages/react-app-scaffolder/app/templates/apollo/src/components/ui/__tests__/menu.tsx +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/components/ui/__tests__/menu.tsx @@ -1,6 +1,6 @@ import * as React from 'react' import { shallow } from 'enzyme' -import { Menu, MenuProps, generateMenuConfig } from '../menu' +import { Menu, MenuProps, mapDispatchToProps, generateMenuConfig } from '../menu' import toJson from 'enzyme-to-json' const props: MenuProps = { @@ -16,6 +16,15 @@ describe('Menu', () => { expect(toJson(shallow())).toMatchSnapshot() }) + describe('mapDispatchToProps', () => { + it('should return loginType', () => { + const dispatch = jest.fn() + const fn = mapDispatchToProps(dispatch) + fn.logout() + expect(dispatch).toBeCalled() + }) + }) + describe('generateMenuConfig', () => { it('should return config', () => { const logoutCallback = jest.fn() diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/components/ui/menu.tsx b/packages/react-app-scaffolder/app/templates/redux-internal/src/components/ui/menu.tsx new file mode 100644 index 0000000000..1e0a3cd10c --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/components/ui/menu.tsx @@ -0,0 +1,72 @@ +import * as React from 'react' +import { connect } from 'react-redux' +import { withRouter, RouteComponentProps } from 'react-router' +import { Menu as Sidebar, MenuConfig, ReapitLogo } from '@reapit/elements' +import { authLogout } from '@/actions/auth' +import { LoginMode } from '@reapit/cognito-auth' +import { Location } from 'history' +import { FaSignOutAlt, FaCloud } from 'react-icons/fa' +import { ReduxState } from '../../types/core' + +export const generateMenuConfig = ( + logoutCallback: () => void, + location: Location, + mode: LoginMode, +): MenuConfig => { + return { + defaultActiveKey: 'LOGO', + mode, + location, + menu: [ + { + key: 'LOGO', + icon: , + type: 'LOGO', + }, + { + title: 'Apps', + key: 'APPS', + icon: , + callback: () => + (window.location.href = + !window.location.href.includes('dev') || window.location.href.includes('localhost') + ? 'https://marketplace.reapit.cloud/client/installed' + : 'https://dev.marketplace.reapit.cloud/client/installed'), + type: 'PRIMARY', + }, + { + title: 'Logout', + key: 'LOGOUT', + callback: logoutCallback, + icon: , + type: 'SECONDARY', + }, + ], + } +} + +export interface MenuMappedActions { + logout: () => void +} + +export interface MenuMappedState { + mode: LoginMode +} + +export type MenuProps = MenuMappedActions & MenuMappedState & RouteComponentProps & {} + +export const Menu: React.FunctionComponent = ({ logout, location, mode }) => { + const logoutCallback = () => logout() + const menuConfigs = generateMenuConfig(logoutCallback, location, mode) + return +} + +export const mapDispatchToProps = (dispatch: any): MenuMappedActions => ({ + logout: () => dispatch(authLogout()), +}) + +export const mapStateToProps = (state: ReduxState): MenuMappedState => ({ + mode: state?.auth?.refreshSession?.mode || 'WEB', +}) + +export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Menu)) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/constants/action-types.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/constants/action-types.ts new file mode 100644 index 0000000000..290df77999 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/constants/action-types.ts @@ -0,0 +1,28 @@ +/** + * Please follow the <>_<> pattern and group actions by STATE + */ +const ActionTypes = { + // Auth actions + AUTH_LOGIN: 'AUTH_LOGIN', + AUTH_LOGIN_SUCCESS: 'AUTH_LOGIN_SUCCESS', + AUTH_LOGIN_FAILURE: 'AUTH_LOGIN_FAILURE', + AUTH_LOGOUT: 'AUTH_LOGOUT', + AUTH_LOGOUT_SUCCESS: 'AUTH_LOGOUT_SUCCESS', + AUTH_CHANGE_LOGIN_TYPE: 'AUTH_CHANGE_LOGIN_TYPE', + AUTH_SET_DESKTOP_SESSION: 'AUTH_SET_DESKTOP_SESSION', + AUTH_SET_REFRESH_SESSION: 'AUTH_SET_REFRESH_SESSION', + + // Error actions + ERROR_THROWN_COMPONENT: 'ERROR_THROWN_COMPONENT', + ERROR_THROWN_SERVER: 'ERROR_THROWN_SERVER', + ERROR_CLEARED_COMPONENT: 'ERROR_CLEARED_COMPONENT', + ERROR_CLEARED_SERVER: 'ERROR_CLEARED_SERVER', + + AUTHENTICATED_REQUEST_DATA: 'AUTHENTICATED_REQUEST_DATA', + AUTHENTICATED_REQUEST_FAILURE: 'AUTHENTICATED_REQUEST_FAILURE', + AUTHENTICATED_LOADING: 'AUTHENTICATED_LOADING', + AUTHENTICATED_RECEIVE_DATA: 'AUTHENTICATED_RECEIVE_DATA', + AUTHENTICATED_CLEAR_DATA: 'AUTHENTICATED_CLEAR_DATA', +} + +export default ActionTypes diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/constants/api.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/constants/api.ts new file mode 100644 index 0000000000..c737c935cb --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/constants/api.ts @@ -0,0 +1,12 @@ +import { StringMap } from '@/types/core' +import { COOKIE_SESSION_KEY as COGNITIO_COOKIE_SESSION_KEY } from '@reapit/cognito-auth' + +export const CONTACTS_HEADERS = { + 'Content-Type': 'application/json', +} as StringMap + +export const API_VERSION = '2020-01-31' + +export const COOKIE_SESSION_KEY = COGNITIO_COOKIE_SESSION_KEY + +export const URLS = {} diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/constants/auth.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/constants/auth.ts new file mode 100644 index 0000000000..1ef168b5f5 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/constants/auth.ts @@ -0,0 +1,5 @@ +import { StringMap } from '@/types/core' + +export const LOGIN_TYPE = { + CLIENT: 'CLIENT', +} as StringMap diff --git a/packages/react-app-scaffolder/app/templates/redux/src/constants/error-messages.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/constants/error-messages.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/constants/error-messages.ts rename to packages/react-app-scaffolder/app/templates/redux-internal/src/constants/error-messages.ts diff --git a/packages/react-app-scaffolder/app/templates/base/src/constants/routes.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/constants/routes.ts similarity index 67% rename from packages/react-app-scaffolder/app/templates/base/src/constants/routes.ts rename to packages/react-app-scaffolder/app/templates/redux-internal/src/constants/routes.ts index e4d9057eab..2403b74c67 100644 --- a/packages/react-app-scaffolder/app/templates/base/src/constants/routes.ts +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/constants/routes.ts @@ -1,7 +1,6 @@ const Routes = { HOME: '/', LOGIN: '/login', - AUTHENTICATED: '/authenticated', } export default Routes diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__mocks__/router.tsx b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__mocks__/router.tsx new file mode 100644 index 0000000000..1f5a0334cc --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__mocks__/router.tsx @@ -0,0 +1,3 @@ +import * as React from 'react' + +export default () =>
I am a router
diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__mocks__/store.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__mocks__/store.ts new file mode 100644 index 0000000000..29161eef08 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__mocks__/store.ts @@ -0,0 +1,9 @@ +export default { + dispatch: jest.fn(), + state: { + auth: { + loginSession: null, + refreshSession: null, + }, + }, +} diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/app.tsx b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/app.tsx new file mode 100644 index 0000000000..873ca25aae --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/app.tsx @@ -0,0 +1,19 @@ +import * as React from 'react' +import { shallow } from 'enzyme' +import toJson from 'enzyme-to-json' +import App from '../app' +import { render, unmountComponentAtNode } from 'react-dom' + +jest.mock('../router') + +describe('App', () => { + it('should render without crashing', () => { + const div = document.createElement('div') + render(, div) + unmountComponentAtNode(div) + }) + + it('should match a snapshot', () => { + expect(toJson(shallow())).toMatchSnapshot() + }) +}) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/private-route-wrapper.tsx b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/private-route-wrapper.tsx new file mode 100644 index 0000000000..7c479e2167 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/private-route-wrapper.tsx @@ -0,0 +1,20 @@ +import * as React from 'react' +import { shallow } from 'enzyme' +import toJson from 'enzyme-to-json' +import { PrivateRouteWrapper, PrivateRouteWrapperProps } from '../private-route-wrapper' + +const props: PrivateRouteWrapperProps = { + path: '/', + hasSession: false, + setDesktopSession: jest.fn(), + // @ts-ignore: ignore to fullfil the definition of RouteComponentProps + location: { + search: '/client/apps?username=wmcvay@reapit.com&desktopToken=TOKEN', + }, +} + +describe('PrivateRouter', () => { + it('should match a snapshot', () => { + expect(toJson(shallow())).toMatchSnapshot() + }) +}) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/private-route.tsx b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/private-route.tsx new file mode 100644 index 0000000000..329ebf3ac9 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/private-route.tsx @@ -0,0 +1,49 @@ +import * as React from 'react' +import { shallow, mount } from 'enzyme' +import toJson from 'enzyme-to-json' +import { MemoryRouter, Route } from 'react-router' +import { PrivateRoute } from '../private-route' + +describe('PrivateRouter', () => { + it('should match a snapshot', () => { + expect(toJson(shallow( null} />))).toMatchSnapshot() + }) + + it('should redirect to /404 page if isLogin is false', () => { + const wrapper = mount( + + null} path="/my-path" /> +
} /> + , + ) + expect(wrapper.find('.not-found')).toHaveLength(1) + }) + + it('should return render component if loginType matches allow is true', () => { + const wrapper = mount( + +
} + path="/client" + /> + , + ) + expect(wrapper.find('.render-class')).toHaveLength(1) + }) + + it('should return render component if loginType is included in allow array is true', () => { + const wrapper = mount( + +
} + path="/developer/my-apps" + /> + , + ) + expect(wrapper.find('.render-class')).toHaveLength(1) + }) +}) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/router.tsx b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/router.tsx new file mode 100644 index 0000000000..f9875cafb3 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/router.tsx @@ -0,0 +1,25 @@ +import * as React from 'react' +import { shallow } from 'enzyme' +import toJson from 'enzyme-to-json' +import Router, { catchChunkError } from '../router' + +describe('Router', () => { + it('should match a snapshot', () => { + expect(toJson(shallow())).toMatchSnapshot() + }) + + describe('catchChunkError', () => { + it('should return promise', done => { + const fn = jest.fn().mockResolvedValue(
Test
) + const promiseFn = catchChunkError(fn) + expect(promiseFn).toBeDefined() + expect(fn).toBeCalled() + expect( + promiseFn.then(result => { + expect(result).toEqual(
Test
) + done() + }), + ) + }) + }) +}) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/store.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/store.ts new file mode 100644 index 0000000000..912f2c4908 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/__tests__/store.ts @@ -0,0 +1,22 @@ +import StoreInstance, { Store } from '../store' + +describe('Store', () => { + it('should return a singleton instance of Store', () => { + expect(StoreInstance instanceof Store).toBe(true) + }) + + it('should export a store', () => { + expect(StoreInstance.reduxStore).toBeDefined() + expect(typeof StoreInstance.reduxStore).toBe('object') + }) + + it('should export a state', () => { + expect(StoreInstance.state).toBeDefined() + expect(typeof StoreInstance.state).toBe('object') + }) + + it('should export a dispatch', () => { + expect(StoreInstance.dispatch).toBeDefined() + expect(typeof StoreInstance.dispatch).toBe('function') + }) +}) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/core/app.tsx b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/app.tsx new file mode 100644 index 0000000000..e2d5d8daa9 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/app.tsx @@ -0,0 +1,20 @@ +import * as React from 'react' +import Router from './router' +import ErrorBoundary from '@/components/hocs/error-boundary' + +import store from './store' +import { Provider } from 'react-redux' + +import '@/styles/index.css' + +const App = () => { + return ( + + + + + + ) +} + +export default App diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/core/index.tsx b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/index.tsx new file mode 100644 index 0000000000..afcbec1bbd --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/index.tsx @@ -0,0 +1,65 @@ +import * as Sentry from '@sentry/browser' +import React from 'react' +import { render } from 'react-dom' +import ReactGA from 'react-ga' +import { Config } from '@/types/global' +import App from './app' +import { getMarketplaceGlobalsByKey } from '@reapit/elements' + +// Init global config +window.reapit = { + config: { + appEnv: 'production', + sentryDns: '', + cognitoClientId: '', + googleAnalyticsKey: '', + cognitoOAuthUrl: '', + cognitoUserPoolId: '', + }, +} + +export const renderApp = (Component: React.ComponentType) => { + const rootElement = document.querySelector('#root') as Element + const isDesktop = getMarketplaceGlobalsByKey() + const html = document.querySelector('html') + if (isDesktop && html) { + html.classList.add('is-desktop') + } + + if (rootElement) { + render(, rootElement) + } +} + +const run = async () => { + await fetch('config.json') + .then(response => response.json()) + .then((config: Config) => { + window.reapit.config = config + const isLocal = config.appEnv === 'local' + if (!isLocal && config.sentryDns) { + Sentry.init({ + release: process.env.APP_VERSION, + dsn: config.sentryDns, + environment: config.appEnv, + }) + } + if (!isLocal && config.googleAnalyticsKey) { + ReactGA.initialize(config.googleAnalyticsKey) + ReactGA.pageview(window.location.pathname + window.location.search) + } + renderApp(App) + }) + .catch(error => { + console.error('Cannot fetch config', error) + }) +} + +if (module['hot']) { + module['hot'].accept('./app', () => { + const NextApp = require('./app').default + renderApp(NextApp) + }) +} + +run() diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/core/private-route-wrapper.tsx b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/private-route-wrapper.tsx new file mode 100644 index 0000000000..9294c0de87 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/private-route-wrapper.tsx @@ -0,0 +1,78 @@ +import * as React from 'react' +import { RouteComponentProps } from 'react-router-dom' +import { connect } from 'react-redux' +import { ReduxState } from 'src/types/core' +import Menu from '@/components/ui/menu' +import { Loader, Section, FlexContainerResponsive, AppNavContainer, FlexContainerBasic } from '@reapit/elements' +import { RefreshParams, getTokenFromQueryString } from '@reapit/cognito-auth' +import { authSetRefreshSession } from '../actions/auth' +import { Dispatch } from 'redux' +import { withRouter } from 'react-router' +import { redirectToOAuth } from '@reapit/cognito-auth' + +const { Suspense } = React + +export interface PrivateRouteWrapperConnectActions { + setRefreshSession: (refreshParams: RefreshParams) => void +} + +export interface PrivateRouteWrapperConnectState { + hasSession: boolean + isDesktopMode: boolean +} + +export type PrivateRouteWrapperProps = PrivateRouteWrapperConnectState & + PrivateRouteWrapperConnectActions & + RouteComponentProps & { + path: string + } + +export const PrivateRouteWrapper: React.FunctionComponent = ({ + setRefreshSession, + children, + location, + hasSession, +}) => { + const cognitoClientId = window.reapit.config.cognitoClientId + const refreshParams = getTokenFromQueryString(location.search, cognitoClientId) + + if (refreshParams && !hasSession) { + setRefreshSession(refreshParams) + return null + } + + if (!hasSession) { + redirectToOAuth(cognitoClientId) + return null + } + + return ( + + + + + + + + } + > + {children} + + + + + ) +} + +const mapStateToProps = (state: ReduxState): PrivateRouteWrapperConnectState => ({ + hasSession: !!state.auth.loginSession || !!state.auth.refreshSession, + isDesktopMode: state?.auth?.refreshSession?.mode === 'DESKTOP', +}) + +const mapDispatchToProps = (dispatch: Dispatch): PrivateRouteWrapperConnectActions => ({ + setRefreshSession: refreshParams => dispatch(authSetRefreshSession(refreshParams)), +}) + +export default withRouter(connect(mapStateToProps, mapDispatchToProps)(PrivateRouteWrapper)) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/core/private-route.tsx b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/private-route.tsx new file mode 100644 index 0000000000..3c57f7e292 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/private-route.tsx @@ -0,0 +1,50 @@ +import * as React from 'react' +import { Route, RouteProps } from 'react-router' +import { Redirect } from 'react-router-dom' +import { connect } from 'react-redux' +import RouteFetcher from '../components/hocs/route-fetcher' + +export type LoginType = 'CLIENT' | 'DEVELOPER' + +export interface PrivateRouteConnectProps { + loginType: LoginType +} + +export interface PrivateRouteProps extends PrivateRouteConnectProps { + allow: LoginType | LoginType[] + component: React.FunctionComponent + exact?: boolean + fetcher?: boolean +} + +export const PrivateRoute = ({ + component, + allow, + fetcher = false, + loginType, + ...rest +}: PrivateRouteProps & RouteProps) => { + const allowTypes = Array.isArray(allow) ? allow : [allow] + allowTypes.includes(loginType) + return ( + { + if (!allowTypes.includes(loginType)) { + return + } + if (fetcher) { + return + } + const Component = component + + return + }} + /> + ) +} + +const mapStateToProps = (): PrivateRouteConnectProps => ({ + loginType: 'CLIENT', +}) +export default connect(mapStateToProps)(PrivateRoute) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/core/router.tsx b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/router.tsx new file mode 100644 index 0000000000..1c55587792 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/router.tsx @@ -0,0 +1,51 @@ +import * as React from 'react' +import { Route, Router as BrowserRouter, Switch, Redirect } from 'react-router-dom' +import { createBrowserHistory } from 'history' +import Routes from '../constants/routes' +import PrivateRoute from './private-route' +import PrivateRouteWrapper from './private-route-wrapper' + +export const history = createBrowserHistory() + +export const catchChunkError = ( + fn: Function, + retriesLeft = 3, + interval = 500, +): Promise<{ default: React.ComponentType }> => { + return new Promise((resolve, reject) => { + fn() + .then(resolve) + .catch((error: Error) => { + // Ignore chunk cache error and retry to fetch, if cannot reload browser + console.info(error) + setTimeout(() => { + if (retriesLeft === 1) { + window.location.reload() + return + } + catchChunkError(fn, retriesLeft - 1, interval).then(resolve, reject) + }, interval) + }) + }) +} + +const LoginPage = React.lazy(() => catchChunkError(() => import('../components/pages/login'))) +const AuthenticatedPage = React.lazy(() => catchChunkError(() => import('../components/pages/authenticated'))) + +const Router = () => ( + + + + + + + + + + + + + +) + +export default Router diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/core/store.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/store.ts new file mode 100644 index 0000000000..3980f23ee9 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/core/store.ts @@ -0,0 +1,85 @@ +import { injectSwitchModeToWindow } from '@reapit/elements' +import { + createStore, + applyMiddleware, + compose, + combineReducers, + Store as ReduxStore, + Dispatch, + Reducer, + CombinedState, + AnyAction, +} from 'redux' +import createSagaMiddleware from 'redux-saga' +import { all, fork } from '@redux-saga/core/effects' +import authenticated from '../reducers/authenticated' +import error from '../reducers/error' +import auth from '@/reducers/auth' +import { ReduxState, Action } from '../types/core' +import authenticatedSagas from '../sagas/authenticated' +import authSagas from '@/sagas/auth' + +export class Store { + static _instance: Store + + static get instance() { + if (!Store._instance) { + Store._instance = new Store() + } + + return Store._instance + } + + static isProd = process.env.NODE_ENV === 'production' + + static sagaMiddleware = createSagaMiddleware() + + static reducers = combineReducers({ + error, + authenticated, + auth, + }) as Reducer, Action | AnyAction> + + static sagas = function*() { + yield all([fork(authenticatedSagas), fork(authSagas)]) + } + + static composeEnhancers = + !Store.isProd && window && (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ + ? (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({}) + : compose + + reduxStore: ReduxStore + + constructor() { + injectSwitchModeToWindow() + const composed = Store.composeEnhancers(applyMiddleware(Store.sagaMiddleware)) + + this.reduxStore = createStore(Store.reducers, composed) + + Store.sagaMiddleware.run(Store.sagas) + + this.hotModuleReloading() + } + + hotModuleReloading() { + const hotModule = (module as any).hot + + if (hotModule) { + // Enable Webpack hot module replacement for reducers + hotModule.accept('../reducers', () => { + this.reduxStore.replaceReducer(Store.reducers) + }) + } + } + + get dispatch(): Dispatch { + return this.reduxStore.dispatch + } + + get state(): ReduxState { + return this.reduxStore.getState() + } +} + +export default Store.instance diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/__tests__/auth.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/__tests__/auth.ts new file mode 100644 index 0000000000..b4551d051f --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/__tests__/auth.ts @@ -0,0 +1,80 @@ +import reducer, { defaultState as getDefaultState } from '../auth' +import { ActionType } from '../../types/core' +import ActionTypes from '../../constants/action-types' + +const defaultState = getDefaultState() + +describe('auth reducer', () => { + it('should return default state if action not matched', () => { + const newState = reducer(undefined, { + type: 'UNKNOWN' as ActionType, + data: undefined, + }) + expect(newState).toEqual(defaultState) + }) + + it('authLogin', () => { + const newState = reducer(undefined, { + type: ActionTypes.AUTH_LOGIN as ActionType, + data: null, + }) + const expected = { + ...defaultState, + error: false, + } + expect(newState).toEqual(expected) + }) + + it('authLoginSuccess', () => { + const data = { userName: '' } + const newState = reducer(undefined, { + type: ActionTypes.AUTH_LOGIN_SUCCESS as ActionType, + data, + }) + const expected = { + ...defaultState, + error: false, + loginSession: data, + } + expect(newState).toEqual(expected) + }) + + it('authLoginFailure', () => { + const newState = reducer(undefined, { + type: ActionTypes.AUTH_LOGIN_FAILURE as ActionType, + data: null, + }) + const expected = { + ...defaultState, + error: true, + } + expect(newState).toEqual(expected) + }) + + it('authLogoutSuccess', () => { + const newState = reducer(undefined, { + type: ActionTypes.AUTH_LOGOUT_SUCCESS as ActionType, + data: null, + }) + const expected = defaultState + expect(newState).toEqual(expected) + }) + + it('authSetRefreshSession', () => { + const data = { + refreshToken: '', + userName: '', + loginType: 'CLIENT', + mode: 'WEB', + } + const newState = reducer(undefined, { + type: ActionTypes.AUTH_SET_REFRESH_SESSION as ActionType, + data, + }) + const expected = { + ...defaultState, + refreshSession: data, + } + expect(newState).toEqual(expected) + }) +}) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/__tests__/authenticated.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/__tests__/authenticated.ts new file mode 100644 index 0000000000..c8aa2452b4 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/__tests__/authenticated.ts @@ -0,0 +1,46 @@ +import authenticatedReducer, { defaultState } from '../authenticated' +import { ActionType } from '../../types/core' +import ActionTypes from '../../constants/action-types' + +describe('authenticated reducer', () => { + it('should return default state if action not matched', () => { + const newState = authenticatedReducer(undefined, { type: 'UNKNOWN' as ActionType, data: undefined }) + expect(newState).toEqual(defaultState) + }) + + it('should set loading to true when AUTHENTICATED_LOADING action is called', () => { + const newState = authenticatedReducer(undefined, { + type: ActionTypes.AUTHENTICATED_LOADING as ActionType, + data: true, + }) + const expected = { + ...defaultState, + loading: true, + } + expect(newState).toEqual(expected) + }) + + it('should set approvals list data when AUTHENTICATED_RECEIVE_DATA action is called', () => { + const newState = authenticatedReducer(undefined, { + type: ActionTypes.AUTHENTICATED_RECEIVE_DATA as ActionType, + data: {}, + }) + const expected = { + ...defaultState, + authenticatedData: {}, + } + expect(newState).toEqual(expected) + }) + + it('should clear approvals list data when AUTHENTICATED_CLEAR_DATA action is called', () => { + const newState = authenticatedReducer(undefined, { + type: ActionTypes.AUTHENTICATED_CLEAR_DATA as ActionType, + data: null, + }) + const expected = { + ...defaultState, + authenticatedData: null, + } + expect(newState).toEqual(expected) + }) +}) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/__tests__/error.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/__tests__/error.ts new file mode 100644 index 0000000000..8244e3f611 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/__tests__/error.ts @@ -0,0 +1,83 @@ +import errorReducer, { defaultState, ErrorData } from '../error' +import { ActionType } from '../../types/core' +import ActionTypes from '../../constants/action-types' +import errorMessages from '../../constants/error-messages' + +describe('error reducer', () => { + it('should return default state if action not matched', () => { + const newState = errorReducer(undefined, { type: 'UNKNOWN' as ActionType, data: undefined }) + expect(newState).toEqual(defaultState) + }) + + it('should set a component error', () => { + const errorData = { + type: 'COMPONENT', + message: errorMessages.DEFAULT_COMPONENT_ERROR, + } as ErrorData + const newState = errorReducer(undefined, { + type: ActionTypes.ERROR_THROWN_COMPONENT as ActionType, + data: errorData, + }) + const expected = { + ...defaultState, + componentError: errorData, + } + expect(newState).toEqual(expected) + }) + + it('should clear a component error', () => { + const errorData = { + type: 'COMPONENT', + message: errorMessages.DEFAULT_COMPONENT_ERROR, + } as ErrorData + + const newState = errorReducer( + { ...defaultState, componentError: errorData }, + { + type: ActionTypes.ERROR_CLEARED_COMPONENT as ActionType, + data: null, + }, + ) + const expected = { + ...defaultState, + componentError: null, + } + expect(newState).toEqual(expected) + }) + + it('should set a server error', () => { + const errorData = { + type: 'SERVER', + message: errorMessages.DEFAULT_SERVER_ERROR, + } as ErrorData + const newState = errorReducer(undefined, { + type: ActionTypes.ERROR_THROWN_SERVER as ActionType, + data: errorData, + }) + const expected = { + ...defaultState, + serverError: errorData, + } + expect(newState).toEqual(expected) + }) + + it('should clear a server error', () => { + const errorData = { + type: 'SERVER', + message: errorMessages.DEFAULT_SERVER_ERROR, + } as ErrorData + + const newState = errorReducer( + { ...defaultState, serverError: errorData }, + { + type: ActionTypes.ERROR_CLEARED_SERVER as ActionType, + data: null, + }, + ) + const expected = { + ...defaultState, + serverError: null, + } + expect(newState).toEqual(expected) + }) +}) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/auth.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/auth.ts new file mode 100644 index 0000000000..0da6498c8a --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/auth.ts @@ -0,0 +1,62 @@ +import { Action } from '@/types/core' +import { isType } from '@/utils/actions' +import { authLogin, authLoginFailure, authLoginSuccess, authLogoutSuccess, authSetRefreshSession } from '@/actions/auth' +import { RefreshParams, LoginSession, getSessionCookie } from '@reapit/cognito-auth' +import { COOKIE_SESSION_KEY } from '../constants/api' + +export interface AuthState { + error: boolean + loginSession: LoginSession | null + refreshSession: RefreshParams | null +} + +export const defaultState = (): AuthState => { + const refreshSession = getSessionCookie(COOKIE_SESSION_KEY) + return { + error: false, + loginSession: null, + refreshSession, + } +} + +const authReducer = (state: AuthState = defaultState(), action: Action): AuthState => { + if (isType(action, authLogin)) { + return { + ...state, + error: false, + } + } + + if (isType(action, authLoginSuccess)) { + return { + ...state, + error: false, + loginSession: action.data, + } + } + + if (isType(action, authLoginFailure)) { + return { + ...state, + error: true, + } + } + + if (isType(action, authLogoutSuccess)) { + return { + ...defaultState(), + refreshSession: null, + } + } + + if (isType(action, authSetRefreshSession)) { + return { + ...state, + refreshSession: action.data, + } + } + + return state +} + +export default authReducer diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/authenticated.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/authenticated.ts new file mode 100644 index 0000000000..9e53c751de --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/authenticated.ts @@ -0,0 +1,54 @@ +import { Action } from '../types/core' +import { isType } from '../utils/actions' +import { + authenticatedLoading, + authenticatedReceiveData, + authenticatedClearData, + authenticatedRequestDataFailure, +} from '../actions/authenticated' + +export interface AuthenticatedState { + loading: boolean + authenticatedData: {} | null +} + +export const defaultState: AuthenticatedState = { + loading: false, + authenticatedData: null, +} + +const authenticatedReducer = (state: AuthenticatedState = defaultState, action: Action): AuthenticatedState => { + if (isType(action, authenticatedLoading)) { + return { + ...state, + loading: action.data, + } + } + + if (isType(action, authenticatedReceiveData)) { + return { + ...state, + loading: false, + authenticatedData: action.data || null, + } + } + + if (isType(action, authenticatedClearData)) { + return { + ...state, + loading: false, + authenticatedData: action.data, + } + } + + if (isType(action, authenticatedRequestDataFailure)) { + return { + ...state, + loading: false, + } + } + + return state +} + +export default authenticatedReducer diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/error.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/error.ts new file mode 100644 index 0000000000..a97165d4b9 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/reducers/error.ts @@ -0,0 +1,39 @@ +import { Action } from '../types/core' +import { isType } from '../utils/actions' +import { errorClearedComponent, errorClearedServer, errorThrownComponent, errorThrownServer } from '../actions/error' + +export interface ErrorData { + readonly status?: number + readonly message?: string + readonly type: 'COMPONENT' | 'SERVER' +} + +export interface ErrorState { + componentError: ErrorData | null + serverError: ErrorData | null +} + +export const defaultState: ErrorState = { + componentError: null, + serverError: null, +} + +const errorReducer = (state: ErrorState = defaultState, action: Action): ErrorState => { + if (isType(action, errorClearedServer) || isType(action, errorThrownServer)) { + return { + ...state, + serverError: action.data, + } + } + + if (isType(action, errorClearedComponent) || isType(action, errorThrownComponent)) { + return { + ...state, + componentError: action.data, + } + } + + return state +} + +export default errorReducer diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/sagas/__tests__/auth.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/sagas/__tests__/auth.ts new file mode 100644 index 0000000000..5e8614d50f --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/sagas/__tests__/auth.ts @@ -0,0 +1,90 @@ +import authSagas, { doLogin, doLogout, loginListen, logoutListen } from '../auth' +import ActionTypes from '../../constants/action-types' +import { put, all, takeLatest, call } from '@redux-saga/core/effects' +import { LoginParams, setUserSession, removeSession, redirectToLogout } from '@reapit/cognito-auth' +import { Action, ActionType } from '@/types/core' +import { mockLoginSession } from '../../utils/__mocks__/session' +import { authLoginSuccess, authLoginFailure } from '@/actions/auth' +import { COOKIE_SESSION_KEY } from '../../constants/api' + +jest.mock('../../utils/session') +jest.mock('../../core/store.ts') +jest.mock('../../core/router', () => ({ + history: { + push: jest.fn(), + }, +})) + +jest.mock('@reapit/cognito-auth', () => ({ + setUserSession: jest.fn(), + removeSession: jest.fn(), + redirectToLogout: jest.fn(), +})) + +describe('auth sagas', () => { + describe('login submit', () => { + const loginParams: LoginParams = { + loginType: 'CLIENT', + userName: 'bob@acme.com', + password: 'xxxxxx', + mode: 'WEB', + cognitoClientId: '123', + } + const action: Action = { + type: ActionTypes.AUTH_LOGIN as ActionType, + data: loginParams, + } + + test('login success', () => { + const gen = doLogin(action) + expect(gen.next(mockLoginSession).value).toEqual(call(setUserSession, loginParams)) + expect(gen.next(mockLoginSession).value).toEqual(put(authLoginSuccess(mockLoginSession))) + expect(gen.next().done).toBe(true) + }) + + test('login fail', () => { + const gen = doLogin(action) + expect(gen.next(null).value).toEqual(call(setUserSession, loginParams)) + expect(gen.next(null).value).toEqual(put(authLoginFailure())) + expect(gen.next().done).toBe(true) + }) + }) + + describe('authLogout', () => { + it('should redirect to login page', () => { + const gen = doLogout() + expect(gen.next().value).toEqual(call(removeSession, COOKIE_SESSION_KEY)) + expect(gen.next().value).toEqual( + call(redirectToLogout, window.reapit.config.cognitoClientId, `${window.location.origin}/login`), + ) + expect(gen.next().done).toBe(true) + }) + }) + + describe('authLoginListen', () => { + it('should trigger login action', () => { + const gen = loginListen() + + expect(gen.next().value).toEqual(takeLatest(ActionTypes.AUTH_LOGIN, doLogin)) + expect(gen.next().done).toBe(true) + }) + }) + + describe('authLogoutListen', () => { + it('should trigger logout action', () => { + const gen = logoutListen() + + expect(gen.next().value).toEqual(takeLatest(ActionTypes.AUTH_LOGOUT, doLogout)) + expect(gen.next().done).toBe(true) + }) + }) + + describe('itemSagas', () => { + it('should wait for login and logout action get called', () => { + const gen = authSagas() + + expect(gen.next().value).toEqual(all([loginListen(), logoutListen()])) + expect(gen.next().done).toBe(true) + }) + }) +}) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/sagas/__tests__/authenticated.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/sagas/__tests__/authenticated.ts new file mode 100644 index 0000000000..da7be73bb4 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/sagas/__tests__/authenticated.ts @@ -0,0 +1,41 @@ +import authenticatedSagas, { authenticatedDataFetch, authenticatedDataListen } from '../authenticated' +import ActionTypes from '@/constants/action-types' +import { put, takeLatest, all, fork } from '@redux-saga/core/effects' +import { authenticatedLoading, authenticatedReceiveData } from '@/actions/authenticated' +import { cloneableGenerator } from '@redux-saga/testing-utils' +import { Action } from '@/types/core' + +describe('authenticated fetch data', () => { + const gen = cloneableGenerator(authenticatedDataFetch)() + + expect(gen.next().value).toEqual(put(authenticatedLoading(true))) + expect(gen.next().value).toEqual(true) + + test('api call success', () => { + const clone = gen.clone() + expect(clone.next().value).toEqual(put(authenticatedReceiveData({}))) + expect(clone.next().done).toBe(true) + }) +}) + +describe('authenticated sagas', () => { + describe('authenticatedListen', () => { + it('should request data when called', () => { + const gen = authenticatedDataListen() + + expect(gen.next().value).toEqual( + takeLatest>(ActionTypes.AUTHENTICATED_REQUEST_DATA, authenticatedDataFetch), + ) + expect(gen.next().done).toBe(true) + }) + }) + + describe('authenticatedSagas', () => { + it('should listen data request', () => { + const gen = authenticatedSagas() + + expect(gen.next().value).toEqual(all([fork(authenticatedDataListen)])) + expect(gen.next().done).toBe(true) + }) + }) +}) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/sagas/auth.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/sagas/auth.ts new file mode 100644 index 0000000000..1fe9f1e0ed --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/sagas/auth.ts @@ -0,0 +1,44 @@ +import { takeLatest, put, call, all } from '@redux-saga/core/effects' +import { Action } from '@/types/core.ts' +import ActionTypes from '@/constants/action-types' +import { authLoginSuccess, authLoginFailure } from '@/actions/auth' +import { LoginParams, LoginSession, setUserSession, removeSession, redirectToLogout } from '@reapit/cognito-auth' +import { COOKIE_SESSION_KEY } from '../constants/api' + +export const doLogin = function*({ data }: Action) { + try { + const loginSession: LoginSession | null = yield call(setUserSession, data) + + if (loginSession) { + yield put(authLoginSuccess(loginSession)) + } else { + yield put(authLoginFailure()) + } + } catch (err) { + console.error(err.message) + yield put(authLoginFailure()) + } +} + +export const doLogout = function*() { + try { + yield call(removeSession, COOKIE_SESSION_KEY) + yield call(redirectToLogout, window.reapit.config.cognitoClientId, `${window.location.origin}/login`) + } catch (err) { + console.error(err.message) + } +} + +export const loginListen = function*() { + yield takeLatest(ActionTypes.AUTH_LOGIN, doLogin) +} + +export const logoutListen = function*() { + yield takeLatest(ActionTypes.AUTH_LOGOUT, doLogout) +} + +const authSaga = function*() { + yield all([loginListen(), logoutListen()]) +} + +export default authSaga diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/sagas/authenticated.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/sagas/authenticated.ts new file mode 100644 index 0000000000..6fd515eb0d --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/sagas/authenticated.ts @@ -0,0 +1,39 @@ +import { + authenticatedLoading, + authenticatedReceiveData, + authenticatedRequestDataFailure, +} from '../actions/authenticated' +import { put, fork, takeLatest, all } from '@redux-saga/core/effects' +import ActionTypes from '../constants/action-types' +import { errorThrownServer } from '../actions/error' +import errorMessages from '../constants/error-messages' +import { Action } from '@/types/core' + +export const authenticatedDataFetch = function*() { + yield put(authenticatedLoading(true)) + + try { + const response = yield true // Your fetch module here + + yield put(authenticatedReceiveData({ data: response })) + } catch (err) { + console.error(err.message) + yield put(authenticatedRequestDataFailure()) + yield put( + errorThrownServer({ + type: 'SERVER', + message: errorMessages.DEFAULT_SERVER_ERROR, + }), + ) + } +} + +export const authenticatedDataListen = function*() { + yield takeLatest>(ActionTypes.AUTHENTICATED_REQUEST_DATA, authenticatedDataFetch) +} + +const authenticatedSagas = function*() { + yield all([fork(authenticatedDataListen)]) +} + +export default authenticatedSagas diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/selectors/auth.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/selectors/auth.ts new file mode 100644 index 0000000000..342b9a9bf6 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/selectors/auth.ts @@ -0,0 +1,17 @@ +import { ReduxState } from '@/types/core' + +export const selectUserCode = (state: ReduxState) => { + return state?.auth?.loginSession?.loginIdentity?.userCode || '' +} + +export const selectUserLoginStatus = (state: ReduxState) => { + return !!state?.auth?.refreshSession || !!state?.auth?.loginSession +} + +export const checkIsDesktopMode = (state: ReduxState) => { + return state?.auth?.refreshSession?.mode === 'DESKTOP' +} + +export const checkIsWebMode = (state: ReduxState) => { + return state?.auth?.refreshSession?.mode === 'WEB' +} diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/styles/index.css b/packages/react-app-scaffolder/app/templates/redux-internal/src/styles/index.css new file mode 100644 index 0000000000..f1323ff4b3 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/styles/index.css @@ -0,0 +1,6 @@ +@import url('https://fonts.googleapis.com/css?family=Source+Code+Pro&display=swap'); +@import url('https://fonts.googleapis.com/css?family=Roboto&display=swap'); + + + + diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/types/core.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/types/core.ts new file mode 100644 index 0000000000..1d4158730c --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/types/core.ts @@ -0,0 +1,42 @@ +import Routes from '../constants/routes' +import ActionTypes from '../constants/action-types' +import { ErrorState } from '../reducers/error' +import { AuthenticatedState } from '@/reducers/authenticated' +import { AuthState } from '@/reducers/auth' + +export interface Action { + readonly type: ActionType + readonly data: T +} + +export interface ActionCreator { + readonly type: string + (data: T): Action +} + +export interface StringMap { + [key: string]: string +} + +export type PartialRecord = { [P in K]?: T } + +export type RouteValue = keyof typeof Routes + +export type ActionType = keyof typeof ActionTypes + +export type FormState = 'PENDING' | 'DONE' | 'SUBMITTING' | 'ERROR' | 'SUCCESS' + +export interface FetcherParams { + method: 'GET' | 'POST' | 'PUT' | 'DELETE' + api: string + url: string + headers: StringMap + isPrivate?: boolean + body?: T +} + +export interface ReduxState { + error: ErrorState + authenticated: AuthenticatedState + auth: AuthState +} diff --git a/packages/react-app-scaffolder/app/templates/redux/src/types/global.d.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/types/global.d.ts similarity index 100% rename from packages/react-app-scaffolder/app/templates/redux/src/types/global.d.ts rename to packages/react-app-scaffolder/app/templates/redux-internal/src/types/global.d.ts diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/types/index.d.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/types/index.d.ts new file mode 100644 index 0000000000..5940037217 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/types/index.d.ts @@ -0,0 +1,14 @@ +/** + * Gobal override types to make the compiler happy + */ + +declare namespace yargs { + export type Arguments = any +} + +declare module '*.css' +declare module '*.scss' +declare module '*.scss?mod' +declare module '*.sass' +declare module '*.jpg' +declare module '*.png' diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/__mocks__/session.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/__mocks__/session.ts new file mode 100644 index 0000000000..7e7050905f --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/__mocks__/session.ts @@ -0,0 +1,17 @@ +import { LoginSession } from '@reapit/cognito-auth' + +export const mockLoginSession = { + userName: 'bob@acme.com', + accessTokenExpiry: 2, + loginType: 'CLIENT', + refreshToken: 'MOCK_REFRESH_TOKEN', + accessToken: 'MOCK_ACCESS_TOKEN', + idToken: 'MOCK_ID_TOKEN', + loginIdentity: { + developerId: 'SOME_DEV_ID', + clientId: 'SOME_CLIENT_ID', + adminId: 'SOME_ADMIN_ID', + }, +} as LoginSession + +export const getAccessToken = jest.fn() diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/__tests__/actions.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/__tests__/actions.ts new file mode 100644 index 0000000000..31a48fe095 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/__tests__/actions.ts @@ -0,0 +1,27 @@ +import { actionCreator, isType } from '../actions' +import ActionTypes from '../../constants/action-types' +import { authenticatedLoading } from '../../actions/authenticated' +import { Action } from '../../types/core' + +describe('actions utils', () => { + describe('actionCreator', () => { + it('should create an action of the correct type', () => { + const loadingAction = { data: true, type: 'AUTHENTICATED_LOADING' } + expect(actionCreator(ActionTypes.AUTHENTICATED_LOADING)(true)).toEqual(loadingAction) + }) + }) + + describe('isType', () => { + it('should return true if actions are equal', () => { + const loadingAction: Action = { data: true, type: 'AUTHENTICATED_LOADING' } + + expect(isType(loadingAction, authenticatedLoading)).toBe(true) + }) + + it('should return false if actions are not equal', () => { + const anotherAction: Action = { data: true, type: 'AUTHENTICATED_RECEIVE_DATA' } + + expect(isType(anotherAction, authenticatedLoading)).toBe(false) + }) + }) +}) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/__tests__/route-dispatcher.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/__tests__/route-dispatcher.ts new file mode 100644 index 0000000000..137372de91 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/__tests__/route-dispatcher.ts @@ -0,0 +1,16 @@ +import routeDispatcher from '../route-dispatcher' +import store from '../../core/store' +import Routes from '../../constants/routes' +import { RouteValue } from '../../types/core' +import { authenticatedRequestData } from '../../actions/authenticated' + +jest.mock('../../core/store') +jest.mock('../../sagas/authenticated') +jest.mock('@/utils/session') + +describe('routeDispatcher', () => { + it('should dispatch to authenticatedRequestData for the home route', async () => { + await routeDispatcher(Routes.HOME as RouteValue) + expect(store.dispatch).toHaveBeenCalledWith(authenticatedRequestData()) + }) +}) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/__tests__/session.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/__tests__/session.ts new file mode 100644 index 0000000000..6a86921e3c --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/__tests__/session.ts @@ -0,0 +1,55 @@ +import { getAccessToken } from '../session' +import { authLogout, authLoginSuccess } from '@/actions/auth' +import { getSession, LoginSession, RefreshParams } from '@reapit/cognito-auth' +import { COOKIE_SESSION_KEY } from '@/constants/api' + +import store from '@/core/store' + +jest.mock('@/actions/auth') +jest.mock('@/core/store', () => ({ + dispatch: jest.fn(), + state: { + auth: {}, + }, +})) +jest.mock('@reapit/cognito-auth', () => ({ + getSession: jest.fn(), +})) + +describe('session utils', () => { + describe('getAccessToken', () => { + it('should correctly return null when sessions are not available', async () => { + store.state.auth.loginSession = null + store.state.auth.refreshSession = null + ;(getSession as jest.Mock).mockResolvedValueOnce(null) + const returnValue = await getAccessToken() + expect(getSession).toHaveBeenCalledWith( + store.state.auth.loginSession, + store.state.auth.refreshSession, + COOKIE_SESSION_KEY, + ) + expect(store.dispatch).toHaveBeenCalledWith(authLogout()) + expect(returnValue).toBeNull() + }) + + it('should correctly return value', async () => { + store.state.auth.loginSession = {} as LoginSession + store.state.auth.refreshSession = {} as RefreshParams + const mockGetSessionReturnValue = { accessToken: 'accessToken' } as LoginSession + ;(getSession as jest.Mock).mockResolvedValueOnce(mockGetSessionReturnValue) + const returnValue = await getAccessToken() + + expect(getSession).toHaveBeenCalledWith( + store.state.auth.loginSession, + store.state.auth.refreshSession, + COOKIE_SESSION_KEY, + ) + expect(store.dispatch).toHaveBeenCalledWith(authLoginSuccess(mockGetSessionReturnValue)) + expect(returnValue).toEqual(mockGetSessionReturnValue.accessToken) + }) + + afterEach(() => { + jest.resetAllMocks() + }) + }) +}) diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/actions.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/actions.ts new file mode 100644 index 0000000000..553e24424c --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/actions.ts @@ -0,0 +1,12 @@ +import { ActionCreator, Action } from '../types/core' + +export const actionCreator = (type: string): ActionCreator => + Object.assign((data: T): any => ({ type, data }), { type }) + +/* This is a type guard used to strongly type reducers see: https://github.com/Microsoft/TypeScript/wiki/What's-new-in-TypeScript#user-defined-type-guard-functions + * you will note the value + * FYI, does NOT work if reducer is a switch statement - TS not smart enough to infer type of data + * hence use of conditionals in reducers + */ +export const isType = (action: Action, actionCreator: ActionCreator): action is Action => + action.type === actionCreator.type diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/route-dispatcher.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/route-dispatcher.ts new file mode 100644 index 0000000000..f385ce2bd3 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/route-dispatcher.ts @@ -0,0 +1,19 @@ +import { RouteValue } from '@/types/core' +import { getAccessToken } from '@/utils/session' +import store from '@/core/store' +import Routes from '@/constants/routes' +import { authenticatedRequestData } from '@/actions/authenticated' + +const routeDispatcher = async (route: RouteValue) => { + await getAccessToken() + + switch (route) { + case Routes.HOME: + store.dispatch(authenticatedRequestData()) + break + default: + console.error('Route not found, nothing to fetch') + } +} + +export default routeDispatcher diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/session.ts b/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/session.ts new file mode 100644 index 0000000000..f770dbff8f --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/src/utils/session.ts @@ -0,0 +1,18 @@ +import store from '@/core/store' +import { authLoginSuccess, authLogout } from '@/actions/auth' +import { getSession } from '@reapit/cognito-auth' +import { COOKIE_SESSION_KEY } from '../constants/api' + +export const getAccessToken = async (): Promise => { + const { loginSession, refreshSession } = store.state.auth + + const session = await getSession(loginSession, refreshSession, COOKIE_SESSION_KEY) + + if (session) { + store.dispatch(authLoginSuccess(session)) + return session.accessToken + } + + store.dispatch(authLogout()) + return null +} diff --git a/packages/react-app-scaffolder/app/templates/redux-internal/tsconfig.json b/packages/react-app-scaffolder/app/templates/redux-internal/tsconfig.json new file mode 100644 index 0000000000..1047af33b1 --- /dev/null +++ b/packages/react-app-scaffolder/app/templates/redux-internal/tsconfig.json @@ -0,0 +1,30 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "baseUrl": "./", + "paths": { + "@/*": [ + "src/*" + ], + "@reapit/cognito-auth": [ + "../cognito-auth/src" + ], + "@reapit/elements": [ + "../elements/src" + ], + "@reapit/elements/*": [ + "../elements/src/*" + ] + } + }, + "include": [ + "src" + ], + "exclude": [ + "public", + "dist", + "./webpack.config.js", + "node_modules", + "src/tests/coverage" + ] +} diff --git a/packages/react-app-scaffolder/package.json b/packages/react-app-scaffolder/package.json index 34ce250676..98d400134e 100644 --- a/packages/react-app-scaffolder/package.json +++ b/packages/react-app-scaffolder/package.json @@ -1,6 +1,6 @@ { "name": "@reapit/generator-react-app-scaffolder", - "version": "0.0.32", + "version": "1.0.0-alpha.1", "description": "An opinionated gnerator for scaffolding TypeScript React Redux apps", "keywords": [ "yeoman-generator" @@ -23,12 +23,8 @@ "scaffold": "yo ./app --force" }, "dependencies": { - "yeoman-generator": "^4.0.1", + "yeoman-generator": "^4.11.0", "yo": "^3.1.1", - "yosay": "^2.0.2", - "change-case": "^4.1.1" - }, - "devDependencies": { - "raw-loader": "^3.1.0" + "yosay": "^2.0.2" } } diff --git a/packages/react-app-scaffolder/app/templates/base-is-not-foundation/src/scripts/webpack-prod.js b/scripts/webpack/webpack.pwa.prod.js similarity index 78% rename from packages/react-app-scaffolder/app/templates/base-is-not-foundation/src/scripts/webpack-prod.js rename to scripts/webpack/webpack.pwa.prod.js index 56701b68b3..48de570e93 100644 --- a/packages/react-app-scaffolder/app/templates/base-is-not-foundation/src/scripts/webpack-prod.js +++ b/scripts/webpack/webpack.pwa.prod.js @@ -1,13 +1,16 @@ const path = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') const FaviconsWebpackPlugin = require('favicons-webpack-plugin') +const WorkboxWebpackPlugin = require('workbox-webpack-plugin') const MiniCssExtractPlugin = require('mini-css-extract-plugin') const ResolveTSPathsToWebpackAlias = require('ts-paths-to-webpack-alias') const CopyPlugin = require('copy-webpack-plugin') +const SentryWebpackPlugin = require('@sentry/webpack-plugin') const HardSourceWebpackPlugin = require('hard-source-webpack-plugin') -const { SourceMapDevToolPlugin, HashedModuleIdsPlugin } = require('webpack') +const { EnvironmentPlugin, SourceMapDevToolPlugin, HashedModuleIdsPlugin } = require('webpack') const { PATHS } = require('./constants') -const hashFiles = require('./utils') +const hashFiles = require('../utils/hash-files') +const { getVersionTag, getRef } = require('../release/utils') const EXCLUDE_PACKAGES = ['linaria'] @@ -16,6 +19,11 @@ const generateRegexExcludePackages = () => { return new RegExp(`node_modules/(?!(${listPackagesString})/).*`) } +const tagName = getVersionTag() +const hashOfCommit = getRef() +const APP_VERSION = `${tagName.packageName}_${tagName.version}` +const outputFileName = `[name].${hashOfCommit}.js` + const babelLoaderOptions = { presets: [ [ @@ -40,7 +48,7 @@ const webpackConfig = { entry: ['@babel/polyfill', 'core-js', 'isomorphic-fetch', 'regenerator-runtime/runtime', PATHS.entryWeb], output: { path: PATHS.output, - filename: '[name].[hash].js', + filename: outputFileName, }, optimization: { nodeEnv: 'production', @@ -192,7 +200,10 @@ const webpackConfig = { new SourceMapDevToolPlugin({ filename: '[file].map', }), - new CopyPlugin([{ from: 'config.json', to: PATHS.output }]), + new CopyPlugin([ + { from: 'config.json', to: PATHS.output }, + { from: 'manifest.json', to: PATHS.output }, + ]), new HtmlWebpackPlugin({ hash: true, inject: true, @@ -233,6 +244,23 @@ const webpackConfig = { windows: false, }, }), + new EnvironmentPlugin({ + APP_VERSION: APP_VERSION, + }), + new WorkboxWebpackPlugin.GenerateSW({ + clientsClaim: true, + exclude: [/\.map$/, /asset-manifest\.json$/], + navigateFallback: '/index.html', + navigateFallbackDenylist: [ + // Exclude URLs starting with /_, as they're likely an API call + new RegExp('^/_'), + // Exclude any URLs whose last part seems to be a file extension + // as they're likely a resource and not a SPA route. + // URLs containing a "?" character won't be blacklisted as they're likely + // a route with query params (e.g. auth callbacks). + new RegExp('/[^/?]+\\.[^/]+$'), + ], + }), new HashedModuleIdsPlugin(), new HardSourceWebpackPlugin({ // each package has its own .webpack-cache @@ -247,4 +275,19 @@ const webpackConfig = { ], } +if (process.env.IS_RELEASE) { + webpackConfig.plugins.push( + new SentryWebpackPlugin({ + release: APP_VERSION, + include: './public/dist/', + ignore: ['node_modules', 'webpack.config.js'], + configFile: '.sentryclirc', + setCommits: { + repo: 'reapit/foundations', + auto: true, + }, + }), + ) +} + module.exports = webpackConfig diff --git a/yarn.lock b/yarn.lock index 6d950d511c..3bfe4b976a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1163,7 +1163,7 @@ core-js-pure "^3.0.0" regenerator-runtime "^0.13.4" -"@babel/runtime@7.10.2", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.1", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2", "@babel/runtime@^7.9.6": +"@babel/runtime@7.10.2", "@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.10.1", "@babel/runtime@^7.10.2", "@babel/runtime@^7.3.1", "@babel/runtime@^7.4.5", "@babel/runtime@^7.5.0", "@babel/runtime@^7.5.4", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.7.1", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2", "@babel/runtime@^7.9.6": version "7.10.2" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.10.2.tgz#d103f21f2602497d38348a32e008637d506db839" integrity sha512-6sF3uQw2ivImfVIl62RZ7MXhO2tap69WeWK57vAaimT6AZbE4FbqjdEJIN1UqoD6wI6B+1n9UiagafH1sxjOtg== @@ -1832,7 +1832,7 @@ "@hapi/cryptiles" "4.x.x" "@hapi/hoek" "8.x.x" -"@hapi/joi@15.x.x", "@hapi/joi@^15.0.0": +"@hapi/joi@15.x.x", "@hapi/joi@^15.1.0": version "15.1.1" resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7" integrity sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ== @@ -5314,6 +5314,14 @@ telejson "^3.2.0" util-deprecate "^1.0.2" +"@surma/rollup-plugin-off-main-thread@^1.1.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-1.4.1.tgz#bf1343e5a926e5a1da55e3affd761dda4ce143ef" + integrity sha512-ZPBWYQDdO4JZiTmTP3DABsHhIPA7bEJk9Znk7tZsrbPGanoGo8YxMv//WLx5Cvb+lRgS42+6yiOIYYHCKDmkpQ== + dependencies: + ejs "^2.6.1" + magic-string "^0.25.0" + "@svgr/babel-plugin-add-jsx-attribute@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz#dadcb6218503532d6884b210e7f3c502caaa44b1" @@ -9309,15 +9317,6 @@ capability@^0.2.5: resolved "https://registry.yarnpkg.com/capability/-/capability-0.2.5.tgz#51ad87353f1936ffd77f2f21c74633a4dea88801" integrity sha1-Ua2HNT8ZNv/Xfy8hx0YzpN6oiAE= -capital-case@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/capital-case/-/capital-case-1.0.3.tgz#339bd77e8fab6cf75111d4fca509b3edf7c117c8" - integrity sha512-OlUSJpUr7SY0uZFOxcwnDOU7/MpHlKTZx2mqnDYQFrDudXLFm0JJ9wr/l4csB+rh2Ug0OPuoSO53PqiZBqno9A== - dependencies: - no-case "^3.0.3" - tslib "^1.10.0" - upper-case-first "^2.0.1" - capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -9434,24 +9433,6 @@ chalk@^4.0.0, chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" -change-case@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/change-case/-/change-case-4.1.1.tgz#d5005709275952e7963fed7b91e4f9fdb6180afa" - integrity sha512-qRlUWn/hXnX1R1LBDF/RelJLiqNjKjUqlmuBVSEIyye8kq49CXqkZWKmi8XeUAdDXWFOcGLUMZ+aHn3Q5lzUXw== - dependencies: - camel-case "^4.1.1" - capital-case "^1.0.3" - constant-case "^3.0.3" - dot-case "^3.0.3" - header-case "^2.0.3" - no-case "^3.0.3" - param-case "^3.0.3" - pascal-case "^3.1.1" - path-case "^3.0.3" - sentence-case "^3.0.3" - snake-case "^3.0.3" - tslib "^1.10.0" - char-regex@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf" @@ -10316,15 +10297,6 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -constant-case@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/constant-case/-/constant-case-3.0.3.tgz#ac910a99caf3926ac5112f352e3af599d8c5fc0a" - integrity sha512-FXtsSnnrFYpzDmvwDGQW+l8XK3GV1coLyBN0eBz16ZUzGaZcT2ANVCJmLeuw2GQgxKHQIe9e0w2dzkSfaRlUmA== - dependencies: - no-case "^3.0.3" - tslib "^1.10.0" - upper-case "^2.0.1" - constantinople@^3.0.1, constantinople@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-3.1.2.tgz#d45ed724f57d3d10500017a7d3a889c1381ae647" @@ -13441,7 +13413,7 @@ fast-json-patch@~2.1.0: dependencies: deep-equal "^1.0.1" -fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0: +fast-json-stable-stringify@2.x, fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== @@ -14131,7 +14103,7 @@ fs-extra@^0.30.0: path-is-absolute "^1.0.0" rimraf "^2.2.8" -fs-extra@^4.0.2, fs-extra@^4.0.3: +fs-extra@^4.0.3: version "4.0.3" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" integrity sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg== @@ -15425,14 +15397,6 @@ he@1.2.x, he@^1.1.0, he@^1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== -header-case@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/header-case/-/header-case-2.0.3.tgz#8a7407d16edfd5c970f8ebb116e6383f855b5a72" - integrity sha512-LChe/V32mnUQnTwTxd3aAlNMk8ia9tjCDb/LjYtoMrdAPApxLB+azejUk5ERZIZdIqvinwv6BAUuFXH/tQPdZA== - dependencies: - capital-case "^1.0.3" - tslib "^1.10.0" - highlight.js@~9.13.0: version "9.13.1" resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.13.1.tgz#054586d53a6863311168488a0f58d6c505ce641e" @@ -18477,13 +18441,6 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= -json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - integrity sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8= - dependencies: - jsonify "~0.0.0" - json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -18544,11 +18501,6 @@ jsonfile@^4.0.0: optionalDependencies: graceful-fs "^4.1.6" -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - integrity sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM= - jsonparse@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280" @@ -19646,7 +19598,7 @@ macos-release@^2.2.0: resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" integrity sha512-OHhSbtcviqMPt7yfw5ef5aghS2jzFVKEFyCJndQt2YpSQ9qRVSEv2axSJI1paVThEu+FFGs584h/1YhxjVqajA== -magic-string@^0.25.2, magic-string@^0.25.5, magic-string@^0.25.7: +magic-string@^0.25.0, magic-string@^0.25.2, magic-string@^0.25.5, magic-string@^0.25.7: version "0.25.7" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== @@ -19902,6 +19854,23 @@ mem-fs-editor@^6.0.0: through2 "^3.0.1" vinyl "^2.2.0" +mem-fs-editor@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/mem-fs-editor/-/mem-fs-editor-7.0.1.tgz#e0797802b7797acf43ef3c511f3d3ad5ea765783" + integrity sha512-eD8r4/d2ayp9HHIgBPHB6Ds0ggA8F9cf9HxcNtbqrwqJXfIDrOSMG5K4fV3+Ib3B+HIdrWqkeDDDvrO7i9EbvQ== + dependencies: + commondir "^1.0.1" + deep-extend "^0.6.0" + ejs "^3.0.1" + glob "^7.1.4" + globby "^9.2.0" + isbinaryfile "^4.0.0" + mkdirp "^1.0.0" + multimatch "^4.0.0" + rimraf "^3.0.0" + through2 "^3.0.1" + vinyl "^2.2.0" + mem-fs@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mem-fs/-/mem-fs-1.2.0.tgz#5f29b2d02a5875cd14cd836c388385892d556cde" @@ -20374,7 +20343,7 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@1.x, mkdirp@^1.0.4, mkdirp@~1.0.3: +mkdirp@*, mkdirp@1.x, mkdirp@^1.0.0, mkdirp@^1.0.4, mkdirp@~1.0.3: version "1.0.4" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== @@ -22168,14 +22137,6 @@ path-browserify@0.0.1: resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== -path-case@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/path-case/-/path-case-3.0.3.tgz#d48119aed52c4712e036ca40c6b15984f909554f" - integrity sha512-UMFU6UETFpCNWbIWNczshPrnK/7JAXBP2NYw80ojElbQ2+JYxdqWDBkvvqM93u4u6oLmuJ/tPOf2tM8KtXv4eg== - dependencies: - dot-case "^3.0.3" - tslib "^1.10.0" - path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" @@ -22668,7 +22629,7 @@ prettier@^2.0.5: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== -pretty-bytes@5.3.0, pretty-bytes@^5.1.0, pretty-bytes@^5.2.0: +pretty-bytes@5.3.0, pretty-bytes@^5.2.0, pretty-bytes@^5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" integrity sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg== @@ -24884,7 +24845,7 @@ rollup@1.27.13: "@types/node" "*" acorn "^7.1.0" -rollup@^1.27.8, rollup@^1.32.0: +rollup@^1.27.8, rollup@^1.31.1, rollup@^1.32.0: version "1.32.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.32.1.tgz#4480e52d9d9e2ae4b46ba0d9ddeaf3163940f9c4" integrity sha512-/2HA0Ec70TvQnXdzynFffkjA6XN+1e2pEv/uKS5Ulca40g2L7KuOE3riasHoNVHOsFD5KKZgDsMk1CP3Tw9s+A== @@ -25235,15 +25196,6 @@ send@0.17.1, send@latest: range-parser "~1.2.1" statuses "~1.5.0" -sentence-case@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/sentence-case/-/sentence-case-3.0.3.tgz#47576e4adff7abf42c63c815b0543c9d2f85a930" - integrity sha512-ZPr4dgTcNkEfcGOMFQyDdJrTU9uQO1nb1cjf+nuzb6FxgMDgKddZOM29qEsB7jvsZSMruLRcL2KfM4ypKpa0LA== - dependencies: - no-case "^3.0.3" - tslib "^1.10.0" - upper-case-first "^2.0.1" - seq-queue@^0.0.5: version "0.0.5" resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" @@ -25797,14 +25749,6 @@ smart-buffer@^4.1.0: resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.1.0.tgz#91605c25d91652f4661ea69ccf45f1b331ca21ba" integrity sha512-iVICrxOzCynf/SNaBQCw34eM9jROU/s5rzIhpOvzhzuYHfJR/DhZfDkXiZSgKXfgv26HT3Yni3AV/DGw0cGnnw== -snake-case@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/snake-case/-/snake-case-3.0.3.tgz#c598b822ab443fcbb145ae8a82c5e43526d5bbee" - integrity sha512-WM1sIXEO+rsAHBKjGf/6R1HBBcgbncKS08d2Aqec/mrDSpU80SiOU41hO7ny6DToHSyrlwTYzQBIK1FPSx4Y3Q== - dependencies: - dot-case "^3.0.3" - tslib "^1.10.0" - snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" @@ -27442,6 +27386,15 @@ tempfile@^2.0.0: temp-dir "^1.0.0" uuid "^3.0.1" +tempy@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.3.0.tgz#6f6c5b295695a16130996ad5ab01a8bd726e8bf8" + integrity sha512-WrH/pui8YCwmeiAoxV+lpRH9HpRtgBhSR2ViBPgpGb/wnYDzp21R4MN45fsCGvLROvY67o3byhJRYRONJyImVQ== + dependencies: + temp-dir "^1.0.0" + type-fest "^0.3.1" + unique-string "^1.0.0" + term-size@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" @@ -28233,7 +28186,7 @@ type-fest@^0.13.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.13.1.tgz#0172cb5bce80b0bd542ea348db50c7e21834d934" integrity sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg== -type-fest@^0.3.0: +type-fest@^0.3.0, type-fest@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.3.1.tgz#63d00d204e059474fe5e1b7c011112bbd1dc29e1" integrity sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ== @@ -28636,7 +28589,7 @@ unzip-response@^2.0.1: resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= -upath@^1.1.1, upath@^1.2.0: +upath@^1.1.1, upath@^1.1.2, upath@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== @@ -28709,25 +28662,11 @@ upper-case-first@^1.1.0: dependencies: upper-case "^1.1.1" -upper-case-first@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/upper-case-first/-/upper-case-first-2.0.1.tgz#32ab436747d891cc20ab1e43d601cb4d0a7fbf4a" - integrity sha512-105J8XqQ+9RxW3l9gHZtgve5oaiR9TIwvmZAMAIZWRHe00T21cdvewKORTlOJf/zXW6VukuTshM+HXZNWz7N5w== - dependencies: - tslib "^1.10.0" - upper-case@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= -upper-case@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-2.0.1.tgz#6214d05e235dc817822464ccbae85822b3d8665f" - integrity sha512-laAsbea9SY5osxrv7S99vH9xAaJKrw5Qpdh4ENRLcaxipjKsiaBwiAsxfa8X5mObKNTQPsupSq0J/VIxsSJe3A== - dependencies: - tslib "^1.10.0" - uri-js@^4.2.2: version "4.2.2" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" @@ -29340,7 +29279,7 @@ webpack-node-externals@^1.7.2: resolved "https://registry.yarnpkg.com/webpack-node-externals/-/webpack-node-externals-1.7.2.tgz#6e1ee79ac67c070402ba700ef033a9b8d52ac4e3" integrity sha512-ajerHZ+BJKeCLviLUUmnyd5B4RavLF76uv3cs6KNuO8W+HuQaEs0y0L7o40NQxdPy5w0pcv8Ew7yPUAQG0UdCg== -webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: +webpack-sources@^1.0.1, webpack-sources@^1.1.0, webpack-sources@^1.3.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: version "1.4.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== @@ -29599,140 +29538,158 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= -workbox-background-sync@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-4.3.1.tgz#26821b9bf16e9e37fd1d640289edddc08afd1950" - integrity sha512-1uFkvU8JXi7L7fCHVBEEnc3asPpiAL33kO495UMcD5+arew9IbKW2rV5lpzhoWcm/qhGB89YfO4PmB/0hQwPRg== +workbox-background-sync@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-5.1.3.tgz#121c5cf439b627f6320ff490be65fd2bd440c6ea" + integrity sha512-V/R95aPxYjbKCaVzUTihrZ9ObGOnzoA5n60r0DQ747p8Pj15/dDTYixonKhhlvavTiNezUrp+wTQBvZvcd/ETA== dependencies: - workbox-core "^4.3.1" + workbox-core "^5.1.3" -workbox-broadcast-update@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-4.3.1.tgz#e2c0280b149e3a504983b757606ad041f332c35b" - integrity sha512-MTSfgzIljpKLTBPROo4IpKjESD86pPFlZwlvVG32Kb70hW+aob4Jxpblud8EhNb1/L5m43DUM4q7C+W6eQMMbA== +workbox-broadcast-update@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-5.1.3.tgz#312e0f065f06a6fb04a050143c84aa6ba0ed8add" + integrity sha512-HJ7FDmgweRcYp8fMiFbkmhaTjMYhMByURe5+TempnCi7cT5NNbyaG4T+rg8NWYxAeumSAB3JQF6XD/z34vRRHA== dependencies: - workbox-core "^4.3.1" + workbox-core "^5.1.3" -workbox-build@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-4.3.1.tgz#414f70fb4d6de47f6538608b80ec52412d233e64" - integrity sha512-UHdwrN3FrDvicM3AqJS/J07X0KXj67R8Cg0waq1MKEOqzo89ap6zh6LmaLnRAjpB+bDIz+7OlPye9iii9KBnxw== +workbox-build@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-5.1.3.tgz#ec0dbcb7e260ad792c49407d063f4bcc8a8f08b8" + integrity sha512-cssa2cKAi/FNp2P2m2DjF/UsXlVX6b1HgkXOjBTraFkIeyZEKxN1F1DnxOpGkdM/bPPRa7y5OmUvjOpgOd9apA== dependencies: - "@babel/runtime" "^7.3.4" - "@hapi/joi" "^15.0.0" + "@babel/core" "^7.8.4" + "@babel/preset-env" "^7.8.4" + "@babel/runtime" "^7.8.4" + "@hapi/joi" "^15.1.0" + "@rollup/plugin-node-resolve" "^7.1.1" + "@rollup/plugin-replace" "^2.3.1" + "@surma/rollup-plugin-off-main-thread" "^1.1.1" common-tags "^1.8.0" - fs-extra "^4.0.2" - glob "^7.1.3" - lodash.template "^4.4.0" - pretty-bytes "^5.1.0" + fast-json-stable-stringify "^2.1.0" + fs-extra "^8.1.0" + glob "^7.1.6" + lodash.template "^4.5.0" + pretty-bytes "^5.3.0" + rollup "^1.31.1" + rollup-plugin-babel "^4.3.3" + rollup-plugin-terser "^5.2.0" + source-map "^0.7.3" + source-map-url "^0.4.0" stringify-object "^3.3.0" strip-comments "^1.0.2" - workbox-background-sync "^4.3.1" - workbox-broadcast-update "^4.3.1" - workbox-cacheable-response "^4.3.1" - workbox-core "^4.3.1" - workbox-expiration "^4.3.1" - workbox-google-analytics "^4.3.1" - workbox-navigation-preload "^4.3.1" - workbox-precaching "^4.3.1" - workbox-range-requests "^4.3.1" - workbox-routing "^4.3.1" - workbox-strategies "^4.3.1" - workbox-streams "^4.3.1" - workbox-sw "^4.3.1" - workbox-window "^4.3.1" - -workbox-cacheable-response@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-4.3.1.tgz#f53e079179c095a3f19e5313b284975c91428c91" - integrity sha512-Rp5qlzm6z8IOvnQNkCdO9qrDgDpoPNguovs0H8C+wswLuPgSzSp9p2afb5maUt9R1uTIwOXrVQMmPfPypv+npw== + tempy "^0.3.0" + upath "^1.2.0" + workbox-background-sync "^5.1.3" + workbox-broadcast-update "^5.1.3" + workbox-cacheable-response "^5.1.3" + workbox-core "^5.1.3" + workbox-expiration "^5.1.3" + workbox-google-analytics "^5.1.3" + workbox-navigation-preload "^5.1.3" + workbox-precaching "^5.1.3" + workbox-range-requests "^5.1.3" + workbox-routing "^5.1.3" + workbox-strategies "^5.1.3" + workbox-streams "^5.1.3" + workbox-sw "^5.1.3" + workbox-window "^5.1.3" + +workbox-cacheable-response@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-5.1.3.tgz#79ec05c9f22796833d653e7cad43774a8f8bf7db" + integrity sha512-lOJEwK2T4KWFNdhRFUKxTPBIO5hIYm9E/nYgMq5h/IH3iHPHlBPuFwRMaQy+TTCGWWTA85NomQOjVw1bj65RLw== dependencies: - workbox-core "^4.3.1" + workbox-core "^5.1.3" -workbox-core@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-4.3.1.tgz#005d2c6a06a171437afd6ca2904a5727ecd73be6" - integrity sha512-I3C9jlLmMKPxAC1t0ExCq+QoAMd0vAAHULEgRZ7kieCdUd919n53WC0AfvokHNwqRhGn+tIIj7vcb5duCjs2Kg== +workbox-core@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-5.1.3.tgz#0607acd0018c149162777fe4aae08553bd1559f5" + integrity sha512-TFSIPxxciX9sFaj0FDiohBeIKpwMcCyNduydi9i3LChItcndDS6TJpErxybv8aBWeCMraXt33TWtF6kKuIObNw== -workbox-expiration@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-4.3.1.tgz#d790433562029e56837f341d7f553c4a78ebe921" - integrity sha512-vsJLhgQsQouv9m0rpbXubT5jw0jMQdjpkum0uT+d9tTwhXcEZks7qLfQ9dGSaufTD2eimxbUOJfWLbNQpIDMPw== +workbox-expiration@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-5.1.3.tgz#c793eef17513de86c9c1b8254eb2c9ba3ed17568" + integrity sha512-8YhpmIHqIx+xmtxONADc+di4a3zzCsvVHLiKq6T3vJZUPnqV2jzx+51+UHMUh3T5w5Z5SFC14l0V/jesRbuMKg== dependencies: - workbox-core "^4.3.1" + workbox-core "^5.1.3" -workbox-google-analytics@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-4.3.1.tgz#9eda0183b103890b5c256e6f4ea15a1f1548519a" - integrity sha512-xzCjAoKuOb55CBSwQrbyWBKqp35yg1vw9ohIlU2wTy06ZrYfJ8rKochb1MSGlnoBfXGWss3UPzxR5QL5guIFdg== +workbox-google-analytics@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-5.1.3.tgz#dba0cadcf438d14389f2f2da0fd9c8cb605d35e6" + integrity sha512-ouK6xIJa+raFcO29TgwKFU/Hv1ejqSYzCzH9lI2B/4z/Wdnb8maL6mMIojQ8j5SohwKswMZmLDl0Az2PCmX11w== dependencies: - workbox-background-sync "^4.3.1" - workbox-core "^4.3.1" - workbox-routing "^4.3.1" - workbox-strategies "^4.3.1" + workbox-background-sync "^5.1.3" + workbox-core "^5.1.3" + workbox-routing "^5.1.3" + workbox-strategies "^5.1.3" -workbox-navigation-preload@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-4.3.1.tgz#29c8e4db5843803b34cd96dc155f9ebd9afa453d" - integrity sha512-K076n3oFHYp16/C+F8CwrRqD25GitA6Rkd6+qAmLmMv1QHPI2jfDwYqrytOfKfYq42bYtW8Pr21ejZX7GvALOw== +workbox-navigation-preload@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-5.1.3.tgz#8e49b935aaef16ac614d06db4a0677cbd59f9cae" + integrity sha512-29SPQMAccOgbq3BT9Gz7k+ydy0mcKKR0Rmkmd46tnujutiL4ooE57fBhwsA+c6OlLcYdisvilKlV2YWEtKWfgQ== dependencies: - workbox-core "^4.3.1" + workbox-core "^5.1.3" -workbox-precaching@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-4.3.1.tgz#9fc45ed122d94bbe1f0ea9584ff5940960771cba" - integrity sha512-piSg/2csPoIi/vPpp48t1q5JLYjMkmg5gsXBQkh/QYapCdVwwmKlU9mHdmy52KsDGIjVaqEUMFvEzn2LRaigqQ== +workbox-precaching@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-5.1.3.tgz#08f0b48f4a390872a994c4a6ce8e43d08c6cba57" + integrity sha512-9jjBiB00AOI0NnI320ddnhvlL3bjMrDoI3211kEaxcRWh0N2fX25uVn0O8N8u1gWY4tIfwZAn/DgtAU13cFhYA== dependencies: - workbox-core "^4.3.1" + workbox-core "^5.1.3" -workbox-range-requests@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-4.3.1.tgz#f8a470188922145cbf0c09a9a2d5e35645244e74" - integrity sha512-S+HhL9+iTFypJZ/yQSl/x2Bf5pWnbXdd3j57xnb0V60FW1LVn9LRZkPtneODklzYuFZv7qK6riZ5BNyc0R0jZA== +workbox-range-requests@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-5.1.3.tgz#f0fc6370ea549d002af1fe902b4ee94bfef6e006" + integrity sha512-uUvEoyEUx86LJc7mtmy/6U8xuK0guXU2FnPimt17zDbsC8FSOaPxc92rxtD6xmDSYrI4FqIebypBCjgIe+sfxA== dependencies: - workbox-core "^4.3.1" + workbox-core "^5.1.3" -workbox-routing@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-4.3.1.tgz#a675841af623e0bb0c67ce4ed8e724ac0bed0cda" - integrity sha512-FkbtrODA4Imsi0p7TW9u9MXuQ5P4pVs1sWHK4dJMMChVROsbEltuE79fBoIk/BCztvOJ7yUpErMKa4z3uQLX+g== +workbox-routing@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-5.1.3.tgz#9946da0e9ace45af3db09cc0b4bdc4696723e1f7" + integrity sha512-F+sAp9Iy3lVl3BEG+pzXWVq4AftzjiFpHDaZ4Kf4vLoBoKQE0hIHet4zE5DpHqYdyw+Udhp4wrfHamX6PN6z1Q== dependencies: - workbox-core "^4.3.1" + workbox-core "^5.1.3" -workbox-strategies@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-4.3.1.tgz#d2be03c4ef214c115e1ab29c9c759c9fe3e9e646" - integrity sha512-F/+E57BmVG8dX6dCCopBlkDvvhg/zj6VDs0PigYwSN23L8hseSRwljrceU2WzTvk/+BSYICsWmRq5qHS2UYzhw== +workbox-strategies@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-5.1.3.tgz#220cc9f5519ed76f2452ccb9407a5fd967c37110" + integrity sha512-wiXHfmOKnWABeIVW+/ye0e00+2CcS5y7SIj2f9zcdy2ZLEbcOf7B+yOl5OrWpBGlTUwRjIYhV++ZqiKm3Dc+8w== dependencies: - workbox-core "^4.3.1" + workbox-core "^5.1.3" + workbox-routing "^5.1.3" -workbox-streams@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-4.3.1.tgz#0b57da70e982572de09c8742dd0cb40a6b7c2cc3" - integrity sha512-4Kisis1f/y0ihf4l3u/+ndMkJkIT4/6UOacU3A4BwZSAC9pQ9vSvJpIi/WFGQRH/uPXvuVjF5c2RfIPQFSS2uA== +workbox-streams@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-5.1.3.tgz#8f381d395ea2e57106b7b6542b9ffcd769a3047b" + integrity sha512-8kt70eBd1RXL0qenxEnch3Cd7VyW3O0CkeGBN4Bikt307nIV5Q0JciLA5o0CRteijawYOiTq0/px4GDBv1obgQ== dependencies: - workbox-core "^4.3.1" + workbox-core "^5.1.3" + workbox-routing "^5.1.3" -workbox-sw@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-4.3.1.tgz#df69e395c479ef4d14499372bcd84c0f5e246164" - integrity sha512-0jXdusCL2uC5gM3yYFT6QMBzKfBr2XTk0g5TPAV4y8IZDyVNDyj1a8uSXy3/XrvkVTmQvLN4O5k3JawGReXr9w== +workbox-sw@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-5.1.3.tgz#7bffbf034f2f5b58e1734b5b86d240019a5332bb" + integrity sha512-Syk6RhYr/8VdFwXrxo5IpVz8Og2xapHTWJhqsZRF+TbxSvlaJs8hrvVPd7edn5ZiiVdPhE9NTeOTOg1+D+FGoA== -workbox-webpack-plugin@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-webpack-plugin/-/workbox-webpack-plugin-4.3.1.tgz#47ff5ea1cc074b6c40fb5a86108863a24120d4bd" - integrity sha512-gJ9jd8Mb8wHLbRz9ZvGN57IAmknOipD3W4XNE/Lk/4lqs5Htw4WOQgakQy/o/4CoXQlMCYldaqUg+EJ35l9MEQ== +workbox-webpack-plugin@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-webpack-plugin/-/workbox-webpack-plugin-5.1.3.tgz#a7070e3ea0eedb6f87e11fd916ec5d4430a6e348" + integrity sha512-gxSkZ9GFLrMNC/8DGNRjcMhrt8iu+MMXhH/Fpo3wo9rKaSMsI7esGq0klTH/UloP9pNvBizVydysrB52eRhI7w== dependencies: - "@babel/runtime" "^7.0.0" - json-stable-stringify "^1.0.1" - workbox-build "^4.3.1" + "@babel/runtime" "^7.5.5" + fast-json-stable-stringify "^2.0.0" + source-map-url "^0.4.0" + upath "^1.1.2" + webpack-sources "^1.3.0" + workbox-build "^5.1.3" -workbox-window@^4.3.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-4.3.1.tgz#ee6051bf10f06afa5483c9b8dfa0531994ede0f3" - integrity sha512-C5gWKh6I58w3GeSc0wp2Ne+rqVw8qwcmZnQGpjiek8A2wpbxSJb1FdCoQVO+jDJs35bFgo/WETgl1fqgsxN0Hg== +workbox-window@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-5.1.3.tgz#24a2acb2903b0ff2789a4ce32f355621e769eb23" + integrity sha512-oYvfVtPLET7FUrhOzbk0R+aATVmpdQBkmDqwyFH4W2dfVqJXTvTXzuGP5Pn9oZ8jMTB3AYW43yhYBlLYM3mYyg== dependencies: - workbox-core "^4.3.1" + workbox-core "^5.1.3" worker-farm@^1.7.0: version "1.7.0" @@ -30270,7 +30227,41 @@ yeoman-environment@^2.4.0, yeoman-environment@^2.9.5: untildify "^3.0.3" yeoman-generator "^4.8.2" -yeoman-generator@^4.0.1, yeoman-generator@^4.8.2: +yeoman-generator@^4.11.0: + version "4.11.0" + resolved "https://registry.yarnpkg.com/yeoman-generator/-/yeoman-generator-4.11.0.tgz#c9e2fab77f17a4d7acff571f31e002bc066ed6a8" + integrity sha512-++t6t2Z6HjL5F1/UM7+uNvGknKmQdF8tstJx8WKzsUSEpB+19kLVtapSfQIh9uWqm0L59fLWDzUui//WXoynPw== + dependencies: + async "^2.6.2" + chalk "^2.4.2" + cli-table "^0.3.1" + cross-spawn "^6.0.5" + dargs "^6.1.0" + dateformat "^3.0.3" + debug "^4.1.1" + diff "^4.0.1" + error "^7.0.2" + find-up "^3.0.0" + github-username "^3.0.0" + istextorbinary "^2.5.1" + lodash "^4.17.11" + make-dir "^3.0.0" + mem-fs-editor "^7.0.1" + minimist "^1.2.5" + pretty-bytes "^5.2.0" + read-chunk "^3.2.0" + read-pkg-up "^5.0.0" + rimraf "^2.6.3" + run-async "^2.0.0" + semver "^7.2.1" + shelljs "^0.8.3" + text-table "^0.2.0" + through2 "^3.0.1" + optionalDependencies: + grouped-queue "^1.1.0" + yeoman-environment "^2.9.5" + +yeoman-generator@^4.8.2: version "4.10.1" resolved "https://registry.yarnpkg.com/yeoman-generator/-/yeoman-generator-4.10.1.tgz#82853f55856ba14f180ab6c6a70acd89b11c956b" integrity sha512-QgbtHSaqBAkyJJM0heQUhT63ubCt34NBFMEBydOBUdAuy8RBvGSzeqVBSZOjdh1tSLrwWXlU3Ck6y14awinF6Q==