diff --git a/.github/scripts/mega-app-copy-files.sh b/.github/scripts/mega-app-copy-files.sh
new file mode 100755
index 00000000000..6c2935a9c79
--- /dev/null
+++ b/.github/scripts/mega-app-copy-files.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+echo "cd build-system-tests"
+cd build-system-tests
+if [ "$BUILD_TOOL" == 'cra' ]; then
+ echo "cp templates/template-aws-exports.js mega-apps/${MEGA_APP_NAME}/src/aws-exports.js"
+ cp templates/template-aws-exports.js mega-apps/${MEGA_APP_NAME}/src/aws-exports.js
+ if [ "$LANGUAGE" == 'js' ]; then
+ echo "cp templates/components/react/cra/App.js mega-apps/${MEGA_APP_NAME}/src/App.js"
+ cp templates/components/react/cra/App.js mega-apps/${MEGA_APP_NAME}/src/App.js
+ else
+ echo "cp templates/components/react/cra/App.js mega-apps/${MEGA_APP_NAME}/src/App.tsx"
+ cp templates/components/react/cra/App.js mega-apps/${MEGA_APP_NAME}/src/App.tsx
+ if [ "$FRAMEWORK_VERSION" == '16' ]; then
+ # We have to customize the index.tsx file for React 16 because the render API changed since React 18.
+ # See more: https://legacy.reactjs.org/blog/2022/03/08/react-18-upgrade-guide.html
+ echo "cp templates/components/react/cra/index-react-${FRAMEWORK_VERSION}.js mega-apps/${MEGA_APP_NAME}/src/index.tsx"
+ cp templates/components/react/cra/index-react-${FRAMEWORK_VERSION}.js mega-apps/${MEGA_APP_NAME}/src/index.tsx
+ fi
+ fi
+fi
+
+if [ "$BUILD_TOOL" == 'next' ]; then
+ echo "mkdir mega-apps/${MEGA_APP_NAME}/data"
+ mkdir mega-apps/${MEGA_APP_NAME}/data
+ echo "cp templates/template-aws-exports.js mega-apps/${MEGA_APP_NAME}/data/aws-exports.js"
+ cp templates/template-aws-exports.js mega-apps/${MEGA_APP_NAME}/data/aws-exports.js
+ echo "cp templates/components/react/next/App.js mega-apps/${MEGA_APP_NAME}/pages/index.tsx"
+ cp templates/components/react/next/App.js mega-apps/${MEGA_APP_NAME}/pages/index.tsx
+ if [ "$BUILD_TOOL_VERSION" == '11' ]; then
+ # We have to customize the package.json and tsconfig.json for Next.js 11,
+ # because create-next-app only creates the app with the latest version
+ echo "cp templates/components/react/next/template-package-${BUILD_TOOL_VERSION}.json mega-apps/${MEGA_APP_NAME}/package.json"
+ cp templates/components/react/next/template-package-${BUILD_TOOL_VERSION}.json mega-apps/${MEGA_APP_NAME}/package.json
+ echo "cp templates/components/react/next/template-tsconfig-${BUILD_TOOL_VERSION}.json mega-apps/${MEGA_APP_NAME}/tsconfig.json"
+ cp templates/components/react/next/template-tsconfig-${BUILD_TOOL_VERSION}.json mega-apps/${MEGA_APP_NAME}/tsconfig.json
+ fi
+fi
+
+if [ "$BUILD_TOOL" == 'vite' ]; then
+ echo "cp templates/template-aws-exports.js mega-apps/${MEGA_APP_NAME}/src/aws-exports.js"
+ cp templates/template-aws-exports.js mega-apps/${MEGA_APP_NAME}/src/aws-exports.js
+ echo "cp templates/components/react/cra/App.js mega-apps/${MEGA_APP_NAME}/src/App.tsx"
+ cp templates/components/react/cra/App.js mega-apps/${MEGA_APP_NAME}/src/App.tsx
+ echo "cp templates/components/react/vite/index.html mega-apps/${MEGA_APP_NAME}/index.html"
+ cp templates/components/react/vite/index.html mega-apps/${MEGA_APP_NAME}/index.html
+ echo "cp templates/components/react/vite/template-tsconfig.json mega-apps/${MEGA_APP_NAME}/tsconfig.json"
+ cp templates/components/react/vite/template-tsconfig.json mega-apps/${MEGA_APP_NAME}/tsconfig.json
+ echo "cp templates/components/react/vite/vite.config.ts mega-apps/${MEGA_APP_NAME}/vite.config.ts"
+ cp templates/components/react/vite/vite.config.ts mega-apps/${MEGA_APP_NAME}/vite.config.ts
+fi
diff --git a/.github/scripts/mega-app-create-app.sh b/.github/scripts/mega-app-create-app.sh
new file mode 100755
index 00000000000..12bc9b9108c
--- /dev/null
+++ b/.github/scripts/mega-app-create-app.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+echo "cd build-system-tests"
+cd build-system-tests
+echo "mkdir -p mega-apps/"
+mkdir -p mega-apps/
+echo "cd mega-apps"
+cd mega-apps
+
+if [[ "$BUILD_TOOL" == 'cra' && "$LANGUAGE" == 'js' ]]; then
+ echo "npx create-react-app ${MEGA_APP_NAME}"
+ npx create-react-app ${MEGA_APP_NAME}
+fi
+
+if [[ "$BUILD_TOOL" == 'cra' && "$LANGUAGE" == 'ts' ]]; then
+ echo "npx create-react-app ${MEGA_APP_NAME} --template typescript"
+ npx create-react-app ${MEGA_APP_NAME} --template typescript
+fi
+
+if [ "$BUILD_TOOL" == 'next' ]; then
+ echo "npx create-next-app ${MEGA_APP_NAME} --ts --no-src-dir --no-experimental-app --no-eslint"
+ npx create-next-app ${MEGA_APP_NAME} --ts --no-src-dir --no-experimental-app --no-eslint
+fi
+
+if [ "$BUILD_TOOL" == 'vite' ]; then
+ echo "npm create vite@${BUILD_TOOL_VERSION} $MEGA_APP_NAME -- --template react-ts"
+ npm create vite@${BUILD_TOOL_VERSION} $MEGA_APP_NAME -- --template react-ts
+fi
diff --git a/.github/scripts/mega-app-install-build.sh b/.github/scripts/mega-app-install-build.sh
new file mode 100755
index 00000000000..88346dccbc2
--- /dev/null
+++ b/.github/scripts/mega-app-install-build.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+
+echo "cd build-system-tests/mega-apps/${MEGA_APP_NAME}"
+cd build-system-tests/mega-apps/${MEGA_APP_NAME}
+if [ "$PKG_MANAGER" == 'yarn' ]; then
+ echo "yarn version"
+ yarn -v
+ echo "yarn set version $PKG_MANAGER_VERSION"
+ yarn set version $PKG_MANAGER_VERSION
+ echo "yarn version"
+ yarn -v
+ if [[ "$BUILD_TOOL" == 'cra' && "$LANGUAGE" == 'ts' ]]; then
+ echo "yarn add $DEP_TYPES"
+ yarn add $DEP_TYPES
+ fi
+ echo "yarn add $DEPENDENCIES"
+ yarn add $DEPENDENCIES
+ echo "yarn build"
+ yarn build
+else
+ if [[ "$BUILD_TOOL" == 'cra' && "$LANGUAGE" == 'ts' ]]; then
+ # If not testing the latest React, we need to download its types.
+ # CRA is the only framework that we test React 16.
+ echo "npm install $DEP_TYPES"
+ npm install $DEP_TYPES
+ fi
+ if [[ "$BUILD_TOOL" == 'next' && "$BUILD_TOOL_VERSION" == '11' ]]; then
+ # We have to remove the initial downloaded node_modules for Next.js 11,
+ # because create-next-app only creates the app with the latest version
+ echo "rm -rf node_modules"
+ rm -rf node_modules
+ fi
+ echo "npm install $DEPENDENCIES"
+ npm install $DEPENDENCIES
+ echo "npm run build"
+ npm run build
+fi
diff --git a/.github/workflows/build-system-test.yml b/.github/workflows/build-system-test.yml
new file mode 100644
index 00000000000..d1df8a2856c
--- /dev/null
+++ b/.github/workflows/build-system-test.yml
@@ -0,0 +1,145 @@
+# Description: this workflow runs build mega-apps that have all the connected components.
+
+name: Build System Test Canary
+
+on:
+ schedule:
+ - cron: '*/15 * * * *' # Run every 15 minutes
+ push:
+ branches: [main] # Run when merge to main
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ environment: ci
+ strategy:
+ fail-fast: false
+ matrix:
+ framework: [react]
+ framework-version: [latest]
+ build-tool: [cra, next, vite]
+ build-tool-version: [latest]
+ pkg-manager: [npm]
+ language: [ts]
+ node-version: [18]
+ include:
+ - framework: react
+ framework-version: latest
+ build-tool: cra
+ build-tool-version: latest
+ pkg-manager: npm
+ language: ts
+ node-version: 16
+ - framework: react
+ framework-version: 16
+ build-tool: cra
+ build-tool-version: latest
+ pkg-manager: npm
+ language: ts
+ node-version: 18
+ - framework: react
+ framework-version: latest
+ build-tool: cra
+ build-tool-version: latest
+ pkg-manager: npm
+ language: js
+ node-version: 18
+ - framework: react
+ framework-version: latest
+ build-tool: cra
+ build-tool-version: latest
+ pkg-manager: yarn
+ pkg-manager-version: 1
+ language: ts
+ node-version: 18
+ - framework: react
+ framework-version: 17
+ build-tool: next
+ build-tool-version: 11
+ pkg-manager: npm
+ language: ts
+ node-version: 16
+ - framework: react
+ framework-version: latest
+ build-tool: vite
+ build-tool-version: 2
+ pkg-manager: npm
+ language: ts
+ node-version: 18
+
+ env:
+ MEGA_APP_NAME: ${{ matrix.framework }}-${{ matrix.framework-version }}-${{ matrix.build-tool }}-${{ matrix.build-tool-version }}-node-${{ matrix.node-version }}-${{ matrix.language }}
+ DEPENDENCIES: react@${{ matrix.framework-version }} react-dom@${{ matrix.framework-version }} @aws-amplify/ui-react aws-amplify @aws-amplify/ui-react-storage
+ DEP_TYPES: '@types/react@${{ matrix.framework-version }} @types/react-dom@${{ matrix.framework-version }}'
+
+ steps:
+ - name: Checkout Amplify UI
+ uses: actions/checkout@24cb9080177205b6e8c946b17badbe402adc938f # v3.4.0 https://github.com/actions/checkout/commit/24cb9080177205b6e8c946b17badbe402adc938f
+ with:
+ persist-credentials: false
+ - name: Setup Node.js ${{ matrix.node-version }} with ${{ matrix.pkg-manager }}
+ uses: actions/setup-node@64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c # v3.6.0 https://github.com/actions/setup-node/commit/64ed1c7eab4cce3362f8c340dee64e5eaeef8f7c
+ with:
+ node-version: ${{ matrix.node-version }}
+ cache: ${{ matrix.pkg-manager }}
+ env:
+ SEGMENT_DOWNLOAD_TIMEOUT_MINS: 2
+ - name: Create MegaApp ${{ env.MEGA_APP_NAME }}
+ run: ./.github/scripts/mega-app-create-app.sh
+ shell: bash
+ env:
+ BUILD_TOOL: ${{ matrix.build-tool }}
+ LANGUAGE: ${{ matrix.language }}
+ MEGA_APP_NAME: ${{ env.MEGA_APP_NAME }}
+ BUILD_TOOL_VERSION: ${{ matrix.build-tool-version }}
+ - name: Copy aws_export and App.js
+ run: ./.github/scripts/mega-app-copy-files.sh
+ shell: bash
+ env:
+ BUILD_TOOL: ${{ matrix.build-tool }}
+ LANGUAGE: ${{ matrix.language }}
+ MEGA_APP_NAME: ${{ env.MEGA_APP_NAME }}
+ BUILD_TOOL_VERSION: ${{ matrix.build-tool-version }}
+ FRAMEWORK_VERSION: ${{ matrix.framework-version }}
+ - name: Install Packages and Build
+ run: ./.github/scripts/mega-app-install-build.sh
+ shell: bash
+ env:
+ BUILD_TOOL: ${{ matrix.build-tool }}
+ BUILD_TOOL_VERSION: ${{ matrix.build-tool-version }}
+ LANGUAGE: ${{ matrix.language }}
+ MEGA_APP_NAME: ${{ env.MEGA_APP_NAME }}
+ PKG_MANAGER: ${{ matrix.pkg-manager }}
+ PKG_MANAGER_VERSION: ${{ matrix.pkg-manager-version }}
+ DEPENDENCIES: ${{ env.DEPENDENCIES }}
+ DEP_TYPES: ${{ env.DEP_TYPES }}
+
+ log-failure-metric:
+ # Send a failure data point to metric BuildSystemTestFailure in github-workflows@ us-east-2
+ runs-on: ubuntu-latest
+ environment: ci
+ needs: build
+ if: ${{ failure() }}
+ steps:
+ - name: Log failure data point to metric BuildSystemTestFailure
+ uses: aws-amplify/amplify-ui/.github/actions/log-metric@main
+ with:
+ metric-name: BuildSystemTestFailure
+ value: 1
+ role-to-assume: ${{ secrets.METRIC_LOGGER_ROLE_ARN }}
+ aws-region: us-east-2
+
+ log-success-metric:
+ # Send a success data point to metric BuildSystemTestFailure in github-workflows@ us-east-2
+ runs-on: ubuntu-latest
+ environment: ci
+ needs: build
+ if: ${{ success() }}
+ steps:
+ - name: Log success data point to metric BuildSystemTestFailure
+ uses: aws-amplify/amplify-ui/.github/actions/log-metric@main
+ with:
+ metric-name: BuildSystemTestFailure
+ value: 0
+ role-to-assume: ${{ secrets.METRIC_LOGGER_ROLE_ARN }}
+ aws-region: us-east-2
diff --git a/.vscode/settings.json b/.vscode/settings.json
index aee31c24ce0..6e7cacd124a 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -8,5 +8,8 @@
"typescript.tsdk": "node_modules/typescript/lib",
"[typescript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
+ },
+ "[shellscript]": {
+ "editor.defaultFormatter": "foxundermoon.shell-format"
}
}
diff --git a/build-system-tests/.gitignore b/build-system-tests/.gitignore
new file mode 100644
index 00000000000..94b5eb6cedb
--- /dev/null
+++ b/build-system-tests/.gitignore
@@ -0,0 +1 @@
+mega-apps
diff --git a/build-system-tests/templates/components/react/cra/App.js b/build-system-tests/templates/components/react/cra/App.js
new file mode 100644
index 00000000000..df8ef034422
--- /dev/null
+++ b/build-system-tests/templates/components/react/cra/App.js
@@ -0,0 +1,51 @@
+import React, { useEffect } from 'react';
+import { Amplify, Notifications } from 'aws-amplify';
+import {
+ AccountSettings,
+ Authenticator,
+ FileUploader,
+ MapView,
+ Text,
+ InAppMessagingProvider,
+ InAppMessageDisplay,
+} from '@aws-amplify/ui-react';
+import { StorageManager } from '@aws-amplify/ui-react-storage';
+import '@aws-amplify/ui-react/styles.css';
+import awsconfig from './aws-exports';
+Amplify.configure(awsconfig);
+
+const { InAppMessaging } = Notifications;
+
+export default function Home() {
+ useEffect(() => {
+ // sync remote in-app messages
+ InAppMessaging.syncMessages();
+ }, []);
+
+ return (
+ <>
+
+
+ In-App Messaging Example
+
+
+
+ {({ signOut, user = { username: '' } }) => (
+
+ Hello {user.username}
+
+
+ )}
+
+ {}} />
+ {}} />
+
+
+ >
+ );
+}
diff --git a/build-system-tests/templates/components/react/cra/index-react-16.js b/build-system-tests/templates/components/react/cra/index-react-16.js
new file mode 100644
index 00000000000..c1f31c5f49d
--- /dev/null
+++ b/build-system-tests/templates/components/react/cra/index-react-16.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import App from './App';
+
+ReactDOM.render(
+
+
+ ,
+ document.getElementById('root')
+);
diff --git a/build-system-tests/templates/components/react/cra/index-react-18.js b/build-system-tests/templates/components/react/cra/index-react-18.js
new file mode 100644
index 00000000000..593edf12164
--- /dev/null
+++ b/build-system-tests/templates/components/react/cra/index-react-18.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import App from './App';
+
+const root = ReactDOM.createRoot(document.getElementById('root'));
+root.render(
+
+
+
+);
diff --git a/build-system-tests/templates/components/react/cra/index-react-18.tsx b/build-system-tests/templates/components/react/cra/index-react-18.tsx
new file mode 100644
index 00000000000..32a75194c0c
--- /dev/null
+++ b/build-system-tests/templates/components/react/cra/index-react-18.tsx
@@ -0,0 +1,13 @@
+// @ts-nocheck
+import React from 'react';
+import ReactDOM from 'react-dom/client';
+import App from './App';
+
+const root = ReactDOM.createRoot(
+ document.getElementById('root') as HTMLElement
+);
+root.render(
+
+
+
+);
diff --git a/build-system-tests/templates/components/react/next/App.js b/build-system-tests/templates/components/react/next/App.js
new file mode 100644
index 00000000000..272fa5d04ae
--- /dev/null
+++ b/build-system-tests/templates/components/react/next/App.js
@@ -0,0 +1,51 @@
+import React, { useEffect } from 'react';
+import { Amplify, Notifications } from 'aws-amplify';
+import {
+ AccountSettings,
+ Authenticator,
+ FileUploader,
+ MapView,
+ Text,
+ InAppMessagingProvider,
+ InAppMessageDisplay,
+} from '@aws-amplify/ui-react';
+import { StorageManager } from '@aws-amplify/ui-react-storage';
+import '@aws-amplify/ui-react/styles.css';
+import awsconfig from '@/data/aws-exports';
+Amplify.configure(awsconfig);
+
+const { InAppMessaging } = Notifications;
+
+export default function Home() {
+ useEffect(() => {
+ // sync remote in-app messages
+ InAppMessaging.syncMessages();
+ }, []);
+
+ return (
+ <>
+
+
+ In-App Messaging Example
+
+
+
+ {({ signOut, user = { username: '' } }) => (
+
+ Hello {user.username}
+
+
+ )}
+
+ {}} />
+ {}} />
+
+
+ >
+ );
+}
diff --git a/build-system-tests/templates/components/react/next/template-package-11.json b/build-system-tests/templates/components/react/next/template-package-11.json
new file mode 100644
index 00000000000..ce9df3adc11
--- /dev/null
+++ b/build-system-tests/templates/components/react/next/template-package-11.json
@@ -0,0 +1,20 @@
+{
+ "name": "react-17-next-11-ts",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint"
+ },
+ "dependencies": {
+ "@types/node": "^15.12.4",
+ "@types/react": "17.0.47",
+ "@types/react-dom": "17",
+ "next": "^11.1.3",
+ "react": "17",
+ "react-dom": "17",
+ "typescript": "5.0.3"
+ }
+}
diff --git a/build-system-tests/templates/components/react/next/template-tsconfig-11.json b/build-system-tests/templates/components/react/next/template-tsconfig-11.json
new file mode 100644
index 00000000000..6dbcf30832a
--- /dev/null
+++ b/build-system-tests/templates/components/react/next/template-tsconfig-11.json
@@ -0,0 +1,35 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "esnext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "forceConsistentCasingInFileNames": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "baseUrl": "./",
+ "paths": {
+ "@/*": [
+ "./*"
+ ]
+ }
+ },
+ "include": [
+ "next-env.d.ts",
+ "**/*.ts",
+ "**/*.tsx"
+ ],
+ "exclude": [
+ "node_modules"
+ ]
+}
diff --git a/build-system-tests/templates/components/react/vite/index.html b/build-system-tests/templates/components/react/vite/index.html
new file mode 100644
index 00000000000..36ca904f975
--- /dev/null
+++ b/build-system-tests/templates/components/react/vite/index.html
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
+ Vite + React + TS
+
+
+
+
+
+
+
+
+
diff --git a/build-system-tests/templates/components/react/vite/template-tsconfig.json b/build-system-tests/templates/components/react/vite/template-tsconfig.json
new file mode 100644
index 00000000000..426108b55c0
--- /dev/null
+++ b/build-system-tests/templates/components/react/vite/template-tsconfig.json
@@ -0,0 +1,31 @@
+{
+ "compilerOptions": {
+ "target": "ESNext",
+ "useDefineForClassFields": true,
+ "lib": [
+ "DOM",
+ "DOM.Iterable",
+ "ESNext"
+ ],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "esModuleInterop": false,
+ "allowSyntheticDefaultImports": true,
+ "strict": true,
+ "forceConsistentCasingInFileNames": true,
+ "module": "ESNext",
+ "moduleResolution": "Node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "noEmit": true,
+ "jsx": "react-jsx"
+ },
+ "include": [
+ "src"
+ ],
+ "references": [
+ {
+ "path": "./tsconfig.node.json"
+ }
+ ]
+}
diff --git a/build-system-tests/templates/components/react/vite/vite.config.ts b/build-system-tests/templates/components/react/vite/vite.config.ts
new file mode 100644
index 00000000000..4f78ad9d0a8
--- /dev/null
+++ b/build-system-tests/templates/components/react/vite/vite.config.ts
@@ -0,0 +1,16 @@
+import { defineConfig } from 'vite';
+// @ts-ignore
+import react from '@vitejs/plugin-react';
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [react()],
+ resolve: {
+ alias: [
+ {
+ find: './runtimeConfig',
+ replacement: './runtimeConfig.browser',
+ },
+ ],
+ },
+});
diff --git a/build-system-tests/templates/template-aws-exports.js b/build-system-tests/templates/template-aws-exports.js
new file mode 100644
index 00000000000..da9a8be835e
--- /dev/null
+++ b/build-system-tests/templates/template-aws-exports.js
@@ -0,0 +1,3 @@
+const awsmobile = {};
+
+export default awsmobile;