diff --git a/.github/workflows/dev.yaml b/.github/workflows/dev.yaml index 1558214ef..288631d81 100644 --- a/.github/workflows/dev.yaml +++ b/.github/workflows/dev.yaml @@ -38,7 +38,7 @@ jobs: - name: Install dependencies run: pnpm install --frozen-lockfile - name: Build Alloy - run: pnpm run build + run: pnpm -r run build - name: Run Test run: pnpm run test env: diff --git a/.github/workflows/ee-prd.yml b/.github/workflows/ee-prd.yml deleted file mode 100644 index e143c0b7b..000000000 --- a/.github/workflows/ee-prd.yml +++ /dev/null @@ -1,109 +0,0 @@ -name: Alloy Prod Upstreams -on: - workflow_dispatch: - inputs: - logLevel: - description: "Log level" - required: true - default: "warning" - edgeBasePath: - description: "Edge Base Path" - required: false - default: "ee" -env: - SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} - SAUCE_CAPABILITIES_OVERRIDES_PATH: "sauceLabsCapabilities.json" - ALLOY_ENV: prod - EDGE_BASE_PATH: ${{ github.event.inputs.edgeBasePath }} - -jobs: - store-sauce-configs: - name: Upload sauce configs to artifact - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - env: - repo-token: ${{ secrets.GITHUB_TOKEN }} - - - uses: actions/upload-artifact@v4 - with: - name: sauce-config - path: .sauce - include-hidden-files: true - - - uses: actions/upload-artifact@v4 - with: - name: sauce-ignore - path: .sauceignore - include-hidden-files: true - - alloy-prod-e2e: - name: "ee: Prod E2E Tests" - runs-on: ubuntu-latest - needs: store-sauce-configs - timeout-minutes: 60 - steps: - - name: "Get latest Alloy Release" - id: last_release - uses: InsonusK/get-latest-release@v1.0.1 - with: - myToken: ${{ github.token }} - exclude_types: "draft|prerelease" - - - uses: actions/checkout@v4 - with: - ref: ${{ steps.last_release.outputs.tag_name }} - - - uses: pnpm/action-setup@v4 - with: - version: 10 - - - uses: actions/setup-node@v5 - with: - node-version-file: .nvmrc - - - name: Download sauce config into tags - uses: actions/download-artifact@v4 - with: - name: sauce-config - path: .sauce - - - name: Remove File - uses: JesseTG/rm@v1.0.3 - with: - path: .sauceignore - - - uses: actions/download-artifact@v4 - with: - name: sauce-ignore - path: . - - - name: Store Alloy version into env - uses: nyaa8/package-version@v1 - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Build - run: pnpm run test:functional:build:prod - env: - ALLOY_PROD_VERSION: ${{ env.PACKAGE_VERSION }} - - - uses: saucelabs/saucectl-run-action@v4.3.0 - env: - GITHUB_TOKEN: ${{ github.token }} - EDGE_BASE_PATH: ${{ github.event.inputs.edgeBasePath }} - with: - sauce-username: ${{ secrets.SAUCE_USERNAME }} - sauce-access-key: ${{ secrets.SAUCE_ACCESS_KEY }} - env: | - SAUCE_USERNAME=${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY=${{ secrets.SAUCE_ACCESS_KEY }} - ALLOY_PROD_VERSION=${{ env.PACKAGE_VERSION }} - NPM_PACKAGE_VERSION=${{ env.PACKAGE_VERSION }} - ALLOY_ENV=prod - EDGE_BASE_PATH=${{ github.event.inputs.edgeBasePath }} - config-file: ./.sauce/ee-prd.yml diff --git a/.github/workflows/generate-coverage-report.yaml b/.github/workflows/generate-coverage-report.yaml index 48c165505..1bfebc67d 100644 --- a/.github/workflows/generate-coverage-report.yaml +++ b/.github/workflows/generate-coverage-report.yaml @@ -32,7 +32,7 @@ jobs: run: pnpm install --frozen-lockfile - name: Build Alloy - run: pnpm run build + run: pnpm -r run build - name: Run Unit Test with coverage run: pnpm run test:coverage diff --git a/.github/workflows/main_alloyio.yml b/.github/workflows/main_alloyio.yml index fd3e8370b..c6e46d13a 100644 --- a/.github/workflows/main_alloyio.yml +++ b/.github/workflows/main_alloyio.yml @@ -29,7 +29,7 @@ jobs: run: pnpm install --frozen-lockfile - name: Build alloy.js - run: pnpm exec rollup -c --environment SANDBOX + run: pnpm --filter @adobe/alloy exec rollup -c --environment SANDBOX - name: Build sandbox run: pnpm --filter @adobe/alloy-sandbox-browser run build diff --git a/.github/workflows/pre-edge-deploy.yaml b/.github/workflows/pre-edge-deploy.yaml deleted file mode 100644 index 3ff53039c..000000000 --- a/.github/workflows/pre-edge-deploy.yaml +++ /dev/null @@ -1,106 +0,0 @@ -name: Alloy Prod Pre-Edge -on: - workflow_dispatch: - inputs: - logLevel: - description: "Log level" - required: true - default: "warning" -env: - SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} - SAUCE_CAPABILITIES_OVERRIDES_PATH: "sauceLabsCapabilities.json" - ALLOY_ENV: prod - EDGE_BASE_PATH: ee-pre-prd - -jobs: - store-sauce-configs: - name: Upload sauce configs to artifact - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - env: - repo-token: ${{ secrets.GITHUB_TOKEN }} - - - name: Upload sauce configs - uses: actions/upload-artifact@v4.4.0 - with: - name: sauce-config - path: .sauce - include-hidden-files: true - - - name: Upload sauce ignore - uses: actions/upload-artifact@v4.4.0 - with: - name: sauce-ignore - path: .sauceignore - include-hidden-files: true - - alloy-prod-e2e: - name: "Pre Edge: Prod E2E Tests" - runs-on: ubuntu-latest - needs: store-sauce-configs - timeout-minutes: 60 - steps: - - name: "Get latest Alloy Release" - id: last_release - uses: InsonusK/get-latest-release@v1.0.1 - with: - myToken: ${{ github.token }} - exclude_types: "draft|prerelease" - - - uses: actions/checkout@v4 - with: - ref: refs/heads/${{ steps.last_release.outputs.tag_name }} - - - name: Download sauce config into tags - uses: actions/download-artifact@v4 - with: - name: sauce-config - path: .sauce - - - name: Remove File - uses: JesseTG/rm@v1.0.3 - with: - path: .sauceignore - - - uses: actions/download-artifact@v4 - with: - name: sauce-ignore - path: . - - - uses: pnpm/action-setup@v4 - with: - version: 10 - - - name: Set up Node.js version - uses: actions/setup-node@v5 - with: - node-version-file: .nvmrc - - - name: Store Alloy version into env - uses: nyaa8/package-version@v1 - - - name: Install dependencies - run: pnpm install --frozen-lockfile - - - name: Build - run: pnpm run test:functional:build:prod - env: - ALLOY_PROD_VERSION: ${{ env.PACKAGE_VERSION }} - - - uses: saucelabs/saucectl-run-action@v4.3.0 - env: - GITHUB_TOKEN: ${{ github.token }} - with: - sauce-username: ${{ secrets.SAUCE_USERNAME }} - sauce-access-key: ${{ secrets.SAUCE_ACCESS_KEY }} - env: | - SAUCE_USERNAME=${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY=${{ secrets.SAUCE_ACCESS_KEY }} - ALLOY_PROD_VERSION=${{ env.PACKAGE_VERSION }} - NPM_PACKAGE_VERSION=${{ env.PACKAGE_VERSION }} - ALLOY_ENV=prod - config-file: ./.sauce/pre-edge-deploy.yml diff --git a/.github/workflows/prod.yml b/.github/workflows/prod.yml deleted file mode 100644 index 6c54c3137..000000000 --- a/.github/workflows/prod.yml +++ /dev/null @@ -1,303 +0,0 @@ -name: Production regression tests -on: - schedule: - - cron: "45 20 * * 1-6" - workflow_dispatch: -permissions: - contents: read - issues: read - packages: none -env: - SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} - SAUCE_CAPABILITIES_OVERRIDES_PATH: "sauceLabsCapabilities.json" - SAUCE_JOB: "Alloy Prod Workflow" - ALLOY_ENV: prod - -jobs: - get-testing-tags: - name: Fetch releases - runs-on: ubuntu-latest - outputs: - MATRIX_INPUT: ${{ steps.retrieve-tags.outputs.MATRIX_INPUT }} - steps: - - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - uses: pnpm/action-setup@v4 - with: - version: 10 - - name: Set up Node.js - uses: actions/setup-node@v5 - with: - node-version-file: .nvmrc - - run: pnpm i --frozen-lockfile - - name: Upload sauce configs - uses: actions/upload-artifact@v4.4.0 - with: - name: sauce-config - path: .sauce - include-hidden-files: true - - name: Upload sauce ignore - uses: actions/upload-artifact@v4.4.0 - with: - name: sauce-ignore - path: .sauceignore - include-hidden-files: true - - name: Retrieve tags - id: retrieve-tags - run: |- - TAGS_TO_TEST=$(node -e "import('./scripts/getTestingTags.js').then(m => m.default().then(tags => console.log(JSON.stringify(tags))))") - echo "Tags to test: $TAGS_TO_TEST" - MATRIX_INPUT="{\"include\":$TAGS_TO_TEST}" - echo "MATRIX_INPUT=$MATRIX_INPUT" >> "$GITHUB_OUTPUT" - - alloy-prod-e2e-safari: - name: Safari - needs: get-testing-tags - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - max-parallel: 10 - fail-fast: false - matrix: ${{ fromJSON(needs.get-testing-tags.outputs.MATRIX_INPUT) }} - continue-on-error: true - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ matrix.tag.tag }} - - uses: pnpm/action-setup@v4 - with: - version: 10 - - name: Set up Node.js - uses: actions/setup-node@v5 - with: - node-version-file: .nvmrc - - name: Install dependencies - run: pnpm install --frozen-lockfile - - name: Store Alloy version - uses: nyaa8/package-version@v1 - - name: Download sauce configs - uses: actions/download-artifact@v4 - with: - name: sauce-config - path: .sauce - - name: Download sauce ignore - uses: actions/download-artifact@v4 - with: - name: sauce-ignore - path: . - - name: Build - run: | - echo "PACKAGE_VERSION=$(pnpm pkg get version | tr -d '\"')" >> $GITHUB_ENV - pnpm run test:functional:build:prod - env: - ALLOY_PROD_VERSION: ${{ env.PACKAGE_VERSION }} - BASE_CODE_MIN: true - NPM_PACKAGE_PROD: true - - name: Update Sauce Config with Node - run: | - sed -i 's/"$NODE_VERSION"/"${{ matrix.tag.nodeVersion }}"/g' .sauce/prod-safari.yml - - name: Run Functional Tests - id: saucectl - uses: saucelabs/saucectl-run-action@v4.3.0 - env: - GITHUB_TOKEN: ${{ github.token }} - with: - sauce-username: ${{ secrets.SAUCE_USERNAME }} - sauce-access-key: ${{ secrets.SAUCE_ACCESS_KEY }} - env: | - SAUCE_USERNAME=${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY=${{ secrets.SAUCE_ACCESS_KEY }} - ALLOY_PROD_VERSION=${{ env.PACKAGE_VERSION }} - NPM_PACKAGE_VERSION=${{ env.PACKAGE_VERSION }} - ALLOY_ENV=prod - config-file: ./.sauce/prod-safari.yml - - - name: Get Saucelabs Test Results - if: failure() - id: saucelabs-results - env: - SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} - run: | - mkdir -p test-results - if [ -d "./test-results" ] && [ "$(ls -A ./test-results)" ]; then - cp -r ./test-results/* ./test-results/ - echo "TEST_RESULTS<> $GITHUB_ENV - cat ./test-results/* >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV - else - echo "TEST_RESULTS=No test results found in ./test-results/" >> $GITHUB_ENV - fi - - - name: Handle Test Failures - if: failure() - uses: actions/github-script@v7 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - const handleTestFailures = require('./.github/scripts/handle-test-failures.js'); - await handleTestFailures({ github, context, browser: 'safari' }); - - alloy-prod-e2e-firefox: - name: Firefox - needs: get-testing-tags - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - max-parallel: 10 - fail-fast: false - matrix: ${{ fromJSON(needs.get-testing-tags.outputs.MATRIX_INPUT) }} - continue-on-error: true - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ matrix.tag.tag }} - - uses: pnpm/action-setup@v4 - with: - version: 10 - - name: Set up Node.js - uses: actions/setup-node@v5 - with: - node-version-file: .nvmrc - - name: Install dependencies - run: pnpm install --frozen-lockfile - - name: Store Alloy version - uses: nyaa8/package-version@v1 - - name: Download sauce configs - uses: actions/download-artifact@v4 - with: - name: sauce-config - path: .sauce - - name: Download sauce ignore - uses: actions/download-artifact@v4 - with: - name: sauce-ignore - path: . - - name: Build - run: | - echo "PACKAGE_VERSION=$(pnpm pkg get version | tr -d '\"')" >> $GITHUB_ENV - pnpm run test:functional:build:prod - env: - ALLOY_PROD_VERSION: ${{ env.PACKAGE_VERSION }} - BASE_CODE_MIN: true - NPM_PACKAGE_PROD: true - - name: Update Sauce Config with Node - run: | - sed -i 's/"$NODE_VERSION"/"${{ matrix.tag.nodeVersion }}"/g' .sauce/prod-firefox.yml - - name: Run Functional Tests - id: saucectl - uses: saucelabs/saucectl-run-action@v4.3.0 - env: - GITHUB_TOKEN: ${{ github.token }} - with: - sauce-username: ${{ secrets.SAUCE_USERNAME }} - sauce-access-key: ${{ secrets.SAUCE_ACCESS_KEY }} - env: | - SAUCE_USERNAME=${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY=${{ secrets.SAUCE_ACCESS_KEY }} - ALLOY_PROD_VERSION=${{ env.PACKAGE_VERSION }} - NPM_PACKAGE_VERSION=${{ env.PACKAGE_VERSION }} - ALLOY_ENV=prod - config-file: ./.sauce/prod-firefox.yml - - - name: Get Saucelabs Test Results - if: failure() - id: saucelabs-results - env: - SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} - run: | - mkdir -p test-results - if [ -d "./test-results" ] && [ "$(ls -A ./test-results)" ]; then - cp -r ./test-results/* ./test-results/ - echo "TEST_RESULTS<> $GITHUB_ENV - cat ./test-results/* >> $GITHUB_ENV - echo "EOF" >> $GITHUB_ENV - else - echo "TEST_RESULTS=No test results found in ./test-results/" >> $GITHUB_ENV - fi - - - name: Handle Test Failures - if: failure() - uses: actions/github-script@v7 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - const handleTestFailures = require('./.github/scripts/handle-test-failures.js'); - await handleTestFailures({ github, context, browser: 'firefox' }); - - alloy-prod-e2e-chrome: - name: Chrome - needs: get-testing-tags - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - max-parallel: 10 - fail-fast: false - matrix: ${{ fromJSON(needs.get-testing-tags.outputs.MATRIX_INPUT) }} - continue-on-error: true - steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: ${{ matrix.tag.tag }} - - uses: pnpm/action-setup@v4 - with: - version: 10 - - name: Set up Node.js - uses: actions/setup-node@v5 - with: - node-version-file: .nvmrc - - name: Install dependencies - run: pnpm install --frozen-lockfile - - name: Store Alloy version - uses: nyaa8/package-version@v1 - - name: Download sauce configs - uses: actions/download-artifact@v4 - with: - name: sauce-config - path: .sauce - - name: Download sauce ignore - uses: actions/download-artifact@v4 - with: - name: sauce-ignore - path: . - - name: Build - run: | - echo "PACKAGE_VERSION=$(pnpm pkg get version | tr -d '\"')" >> $GITHUB_ENV - pnpm run test:functional:build:prod - env: - ALLOY_PROD_VERSION: ${{ env.PACKAGE_VERSION }} - BASE_CODE_MIN: true - NPM_PACKAGE_PROD: true - - name: Update Sauce Config with Node - run: | - sed -i 's/"$NODE_VERSION"/"${{ matrix.tag.nodeVersion }}"/g' .sauce/prod-chrome.yml - - name: Run Functional Tests - id: saucectl - uses: saucelabs/saucectl-run-action@v4.3.0 - env: - GITHUB_TOKEN: ${{ github.token }} - with: - sauce-username: ${{ secrets.SAUCE_USERNAME }} - sauce-access-key: ${{ secrets.SAUCE_ACCESS_KEY }} - env: | - SAUCE_USERNAME=${{ secrets.SAUCE_USERNAME }} - SAUCE_ACCESS_KEY=${{ secrets.SAUCE_ACCESS_KEY }} - ALLOY_PROD_VERSION=${{ env.PACKAGE_VERSION }} - NPM_PACKAGE_VERSION=${{ env.PACKAGE_VERSION }} - ALLOY_ENV=prod - config-file: ./.sauce/prod-chrome.yml - - - name: Handle Test Failures - if: failure() - uses: actions/github-script@v7 - with: - github-token: ${{secrets.GITHUB_TOKEN}} - script: | - const handleTestFailures = require('./.github/scripts/handle-test-failures.js'); - await handleTestFailures({ github, context, browser: 'chrome' }); diff --git a/.testcaferc.json b/.testcaferc.json deleted file mode 100644 index 466cba371..000000000 --- a/.testcaferc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "src": "packages/**/test/functional/specs/**/*.{mjs,js}", - "skipJsErrors": true, - "disablePageCaching": true -} diff --git a/bundlesize.json b/bundlesize.json deleted file mode 100644 index 110543e84..000000000 --- a/bundlesize.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "distTest/baseCode.min.js": { - "uncompressedSize": 199, - "gzippedSize": 164, - "brotiliSize": 133 - }, - "dist/alloy.js": { - "uncompressedSize": 722402, - "gzippedSize": 115705, - "brotiliSize": 88863 - }, - "dist/alloy.min.js": { - "uncompressedSize": 150926, - "gzippedSize": 49837, - "brotiliSize": 43099 - }, - "dist/alloyServiceWorker.js": { - "uncompressedSize": 16618, - "gzippedSize": 4024, - "brotiliSize": 3403 - }, - "dist/alloyServiceWorker.min.js": { - "uncompressedSize": 5302, - "gzippedSize": 2514, - "brotiliSize": 2115 - } -} \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js index cf98e5c42..6e18257b7 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -28,7 +28,6 @@ export default defineConfig([ importPlugin.flatConfigs.recommended, pluginJs.configs.recommended, eslintPluginPrettierRecommended, - compatPlugin.configs["flat/recommended"], globalIgnores([ "sandboxes/**/build/", "sandboxes/**/public/", @@ -144,7 +143,7 @@ export default defineConfig([ }, { name: "alloy/core-src", - files: ["packages/core/src/**/*.{cjs,js}"], + files: ["packages/*/src/**/*.{cjs,js}"], rules: { "import/no-extraneous-dependencies": [ "error", @@ -225,6 +224,26 @@ export default defineConfig([ ], }, }, + + { + name: "alloy/browser", + files: [ + "packages/browser/**/*.{cjs,js,mjs,jsx}", + "sandboxes/browser/**/*.{cjs,js,mjs,jsx}", + "packages/core/**/*.{cjs,js,mjs,jsx}", // TODO: Remove this once browser APIs are removed from core. + ], + plugins: { + compat: compatPlugin, + }, + rules: { + ...compatPlugin.configs["flat/recommended"].rules, + }, + languageOptions: { + globals: { + ...globals.browser, + }, + }, + }, { name: "alloy/scripts", files: ["scripts/**/*.{cjs,js}"], @@ -303,11 +322,13 @@ export default defineConfig([ }, plugins: { react, + compat: compatPlugin, }, rules: { ...react.configs.recommended.rules, ...react.configs["jsx-runtime"].rules, "react/prop-types": "off", + ...compatPlugin.configs["flat/recommended"].rules, }, }, // Vite plugins are ESM-only and confuse eslint-plugin-import; disable the diff --git a/jsconfig.base.json b/jsconfig.base.json new file mode 100644 index 000000000..251eca188 --- /dev/null +++ b/jsconfig.base.json @@ -0,0 +1,12 @@ +{ + "compilerOptions": { + "module": "ES2020", + "moduleResolution": "bundler", + "target": "ES2020", + "checkJs": true, + "allowJs": true, + "resolveJsonModule": true, + "skipLibCheck": true + }, + "exclude": ["node_modules", "dist", "distTest"] +} diff --git a/package.json b/package.json index 24a8be20f..d2f23448e 100644 --- a/package.json +++ b/package.json @@ -1,31 +1,12 @@ { - "name": "@adobe/alloy", - "version": "2.30.1-beta.21", - "description": "Adobe Experience Platform Web SDK", + "name": "adobe-alloy-monorepo", + "version": "0.0.1", + "private": true, "type": "module", - "main": "libEs5/index.js", - "module": "libEs6/index.js", - "types": "types/index.d.ts", - "files": [ - "libEs5", - "libEs6", - "types", - "LICENSE_BANNER", - "babel.config.js", - "rollup.config.js", - ".browserslistrc", - "scripts/helpers/entryPointGeneratorBabelPlugin.js", - "scripts/helpers/versionBabelPlugin.js", - "scripts/helpers/path.js" - ], - "bin": { - "alloyBuilder": "scripts/alloyBuilder.js" - }, "scripts": { - "clean": "rimraf dist distTest libEs5 libEs6 types", + "clean": "pnpm -r --if-present run clean && rimraf coverage", "lint": "eslint --cache --fix \"*.{js,cjs,mjs,jsx}\" \"{sandboxes/*/src,packages/*/src,test,scripts}/**/*.{js,cjs,mjs,jsx}\"", "format": "prettier --write \"*.{html,js,cjs,mjs,jsx}\" \"{sandboxes/*/src,packages/*/src,test,scripts}/**/*.{html,js,cjs,mjs,jsx}\"", - "types": "tsc", "test": "pnpm exec playwright install chromium && vitest run && pnpm run test:scripts", "test:coverage": "rimraf coverage && pnpm exec playwright install chromium && vitest run --coverage", "test:unit": "pnpm exec playwright install chromium && vitest run --project=unit", @@ -36,19 +17,8 @@ "test:integration:debug": "pnpm exec playwright install chromium && vitest --no-file-parallelism --project=integration --browser=chromium --browser.provider=playwright --browser.headless=false", "test:integration:watch": "pnpm exec playwright install chromium && vitest --project=integration", "test:integration:coverage": "pnpm exec playwright install chromium && vitest run --coverage --project=integration", - "test:functional": "pnpm exec playwright install chromium && EDGE_BASE_PATH=\"ee-pre-prd\" ALLOY_ENV=\"int\" testcafe chromium", - "test:functional:custom": "node scripts/helpers/runFunctionalTests.js", - "test:functional:watch": "pnpm exec playwright install chromium && EDGE_BASE_PATH=\"ee-pre-prd\" ALLOY_ENV=\"int\" ./scripts/watchFunctionalTests.js --browsers chromium", - "test:functional:debug": "pnpm exec playwright install chromium && EDGE_BASE_PATH=\"ee-pre-prd\" ALLOY_ENV=\"int\" testcafe --inspect-brk chromium", - "test:functional:build:int": "rollup -c --environment BASE_CODE_MIN,STANDALONE,NPM_PACKAGE_LOCAL", - "test:functional:build:prod": "rollup -c --environment BASE_CODE_MIN,NPM_PACKAGE_PROD", "test:scripts": "vitest run --config=./scripts/specs/vitest.config.js", - "dev": "concurrently --names build,sandbox \"rollup -c -w --environment SANDBOX_SERVICE_WORKER\" \"REACT_APP_NONCE=123 pnpm run --filter @adobe/alloy-sandbox-browser start\"", - "build": "pnpm run clean && rollup -c --environment BASE_CODE_MIN,STANDALONE,STANDALONE_MIN,SERVICE_WORKER,SERVICE_WORKER_MIN && echo \"Base Code:\" && cat distTest/baseCode.min.js", - "build:watch": "pnpm run clean && rollup -c --watch --environment BASE_CODE_MIN,STANDALONE", - "build:custom": "node scripts/alloyBuilder.js", "prepare": "husky", - "prepack": "pnpm run clean && babel packages/core/src -d libEs5 --env-name npmEs5 && babel packages/core/src -d libEs6 --env-name npmEs6 && echo '{\"type\":\"commonjs\"}' > libEs5/package.json && echo '{\"type\":\"module\"}' > libEs6/package.json && pnpm run types", "checkthattestfilesexist": "./scripts/checkThatTestFilesExist.js" }, "lint-staged": { @@ -71,62 +41,35 @@ }, "author": "Adobe Inc.", "license": "Apache-2.0", - "dependencies": { - "@adobe/aep-rules-engine": "^3.1.1", - "@adobe/reactor-query-string": "^2.0.0", - "@babel/core": "^7.28.5", - "@babel/plugin-transform-template-literals": "^7.27.1", - "@babel/preset-env": "^7.28.5", - "@inquirer/prompts": "^7.9.0", - "@rollup/plugin-babel": "^6.1.0", - "@rollup/plugin-commonjs": "^29.0.0", - "@rollup/plugin-node-resolve": "^16.0.3", - "@rollup/plugin-terser": "^0.4.4", - "commander": "^14.0.2", - "js-cookie": "3.0.5", - "rollup": "^4.52.5", - "rollup-plugin-license": "^3.6.0", - "uuid": "^13.0.0" - }, "devDependencies": { - "@adobe/alloy": "next", - "@babel/cli": "^7.28.3", - "@babel/plugin-transform-modules-commonjs": "^7.27.1", - "@changesets/changelog-github": "^0.5.2", "@changesets/cli": "^2.29.8", - "@eslint/js": "^9.38.0", + "@eslint/js": "^9.39.2", "@octokit/rest": "^22.0.1", - "@types/node": "^24.9.1", - "@vitest/browser-playwright": "^4.0.6", - "@vitest/coverage-v8": "^4.0.6", - "@vitest/eslint-plugin": "^1.4.0", + "@types/node": "^24.10.4", + "@vitest/browser-playwright": "^4.0.16", + "@vitest/coverage-v8": "^4.0.16", + "@vitest/eslint-plugin": "^1.6.5", + "baseline-browser-mapping": "^2.9.11", "chalk": "^5.6.2", - "concurrently": "^9.2.1", "date-fns": "^4.1.0", - "eslint": "^9.39.0", + "eslint": "^9.39.2", "eslint-config-prettier": "^10.1.8", "eslint-plugin-compat": "^6.0.2", "eslint-plugin-import": "^2.32.0", "eslint-plugin-prettier": "^5.5.4", "eslint-plugin-react": "^7.37.5", - "glob": "^11.0.3", + "glob": "^11.1.0", "globals": "^16.5.0", "husky": "^9.1.7", - "lint-staged": "^16.2.6", + "lint-staged": "^16.2.7", "minimatch": "^10.1.1", - "msw": "^2.11.6", - "playwright": "^1.56.1", - "prettier": "^3.6.2", - "read-cache": "^1.0.0", + "playwright": "^1.57.0", + "prettier": "^3.7.4", "recursive-readdir": "^2.2.3", - "rimraf": "^6.1.0", + "rimraf": "^6.1.2", "semver": "^7.7.3", - "testcafe": "^3.7.2", - "testcafe-browser-provider-playwright": "^1.1.0", "typescript": "^5.9.3", - "vitest": "^4.0.6" - }, - "optionalDependencies": { - "@rollup/rollup-linux-x64-gnu": "^4.52.5" + "url-exists-nodejs": "^0.2.4", + "vitest": "^4.0.16" } } diff --git a/.browserslistrc b/packages/browser/.browserslistrc similarity index 100% rename from .browserslistrc rename to packages/browser/.browserslistrc diff --git a/packages/browser/.gitignore b/packages/browser/.gitignore new file mode 100644 index 000000000..3f50aa717 --- /dev/null +++ b/packages/browser/.gitignore @@ -0,0 +1 @@ +src/input.js diff --git a/packages/browser/.testcaferc.json b/packages/browser/.testcaferc.json new file mode 100644 index 000000000..c2fd297c6 --- /dev/null +++ b/packages/browser/.testcaferc.json @@ -0,0 +1,6 @@ +{ + "src": "test/functional/specs/**/*.{mjs,js}", + "skipJsErrors": true, + "disablePageCaching": true +} + diff --git a/packages/browser/LICENSE_BANNER b/packages/browser/LICENSE_BANNER new file mode 100644 index 000000000..34ed6b2da --- /dev/null +++ b/packages/browser/LICENSE_BANNER @@ -0,0 +1,9 @@ +Copyright 2019 Adobe. All rights reserved. +This file is licensed to you under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. You may obtain a copy +of the License at http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software distributed under +the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS +OF ANY KIND, either express or implied. See the License for the specific language +governing permissions and limitations under the License. diff --git a/packages/browser/MIGRATION.md b/packages/browser/MIGRATION.md new file mode 100644 index 000000000..9ce8d90ff --- /dev/null +++ b/packages/browser/MIGRATION.md @@ -0,0 +1,182 @@ +# Plan for capability extraction + +## Goal + +To remove all web browser specific code from `@adobe/core` and into `@adobe/alloy` (`packages/browser`). This will be accomplished via dependency injection: a `platform` object that is passed into core's `createInstance` function. + +## Browser API usage + +- Network requests (`fetch`, `navigator.sendBeacon`): used to send Edge/service requests; uses `sendBeacon` during unload with `fetch` fallback. +- DOM rendering + script loading (`window`, `document`, `DOMContentLoaded`): used to create/append/query DOM for personalization and to register DOM/window event listeners. +- local/session storage (`localStorage`, `sessionStorage`, `indexedDB`): used to persist SDK state (consent, rules engine, logging, assurance token params) and push config (IndexedDB). +- cookies (`js-cookie` / `document.cookie`): used to read/write identity and probing cookies (e.g., apex-domain detection). +- global window state (instance queue, monitors: `window.__alloyNS`, `window.__alloyMonitors`): used for snippet-style pre-init queues and optional monitor hooks. +- context gathering (user agent, user agent client hints, viewport/screen, page location/referrer): used to populate request context sent with network calls. +- service worker + push notifications (`navigator.serviceWorker`, `Notification`, `PushManager`): used to register SW, manage subscriptions, handle push events, and track interactions. + +## Implementation + +These API usages need to organized into platform-agnostic "capabilities". They should not just be polyfills of browser APIs, because different platforms will have different needs. For example, an edge worker does not need to send a beacon or a push notification. A Node.js runtime may need to deal with many identities, rather than just one. + +## Capabilities + +### Network + + +**APIs:** `fetch`, `navigator.sendBeacon`, `Blob` + +**Core needs:** + +- Send HTTP POST requests (with credentials: include for cookies) +- Optional "fire and forget" requests during unload (beacon semantics) +- Parse response body/headers/status + +**Interface idea:** + +```typescript +interface NetworkCapability { + sendRequest( + url: string, + body: string, + options: {useSendBeacon?: boolean} + ): Promise; +} +``` + +The beacon-vs-fetch decision could live here; platforms without beacon just ignore the flag. + +### Storage + +**APIs:** `localStorage`, `sessionStorage`, `indexedDB`, `document.cookie` + +**Core needs:** + +- Namespaced key-value persistence (consent hashes, rules engine state, debug flag) +- Session-scoped storage (logging state, assurance params) +- Structured DB for push notification config (IndexedDB) +- Sending identity, cluster information with requests to the Edge Netwwork + +**Interface idea:** + +```typescript +interface StorageCapability { + session: KeyValueStorage; + persistent: KeyValueStorage; + structuredStore?: StructuredStorage; // optional for push +} +``` + +Node.js could back this with in-memory/files; edge workers may skip persistent entirely. + +#### Open Questions: + +- should cookies be included in this storage capability, or in a separate one? + +### DOM / Rendering + +**APIs:** `document`, `window`, `DOMContentLoaded`, `MutationObserver`, selector APIs + +**Core needs:** + +- Personalization: create/append/insert/remove nodes, await selectors, hide/show elements +- Script loading: append `