diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 000000000..6d7fdbcb8 --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,188 @@ +name: e2e + +on: + pull_request_target: + types: [opened, reopened, synchronize, labeled, unlabeled] + push: + branches: [main] + workflow_dispatch: + +# one run per PR; a new push cancels the older one +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +# keep it read-only +permissions: + contents: read + +jobs: + android: + name: e2e (Android) + # same-repo PRs - always run; forks - run only with the `e2e` label + if: >- + github.event_name != 'pull_request_target' || + github.event.pull_request.head.repo.full_name == github.repository || + contains(github.event.pull_request.labels.*.name, 'e2e') + runs-on: ubuntu-latest + timeout-minutes: 45 + + steps: + - name: Checkout pull request head + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + + - name: Setup workspace + uses: ./.github/actions/setup-pnpm-node + with: + node-version: '24.18.0' + + - name: Setup Java + uses: actions/setup-java@de7274f081f381c8f8158605e0321c36c376e2e6 # tag=v6.0.1 + with: + distribution: temurin + java-version: '17' + + - name: Enable KVM + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + + - name: Build workspace packages + run: pnpm --filter tester-federation-v2... build + + # nohup/disown: the runner kills step processes at the end. /status wait: RNTA picks its bundle source once, never retries + - name: Start dev servers + working-directory: apps/tester-federation-v2 + env: + E2E: 'true' + run: | + nohup pnpm start:hostapp > /tmp/hostapp.log 2>&1 & + disown + nohup pnpm start:miniapp > /tmp/miniapp.log 2>&1 & + disown + timeout 180 sh -c 'until [ "$(curl -sf localhost:8081/status)" = "packager-status:running" ] && [ "$(curl -sf localhost:8082/status)" = "packager-status:running" ]; do sleep 2; done' + + # ask for the bundles now so the servers compile them — they only build on first request + - name: Warm both compilers + working-directory: apps/tester-federation-v2 + run: | + curl -sf --max-time 300 -o /dev/null 'http://localhost:8081/android/index.bundle?platform=android&dev=true&lazy=true&minify=false&app=com.tester.federationV2&modulesOnly=false&runModule=true' + curl -sf --max-time 300 -o /dev/null 'http://localhost:8082/android/index.bundle?platform=android&dev=true&lazy=true&minify=false&app=com.tester.federationV2&modulesOnly=false&runModule=true' + echo 'Both bundles served; compilers are warm.' + + - name: Build Android app + working-directory: apps/tester-federation-v2/android + run: ./gradlew :app:assembleDebug -PreactNativeArchitectures=x86_64 + + # expose dev servers to the emulator, install the APK, run the tests + - name: Run e2e on an emulator + uses: reactivecircus/android-emulator-runner@a421e43855164a8197daf9d8d40fe71c6996bb0d # tag=v2.38.0 + with: + api-level: 35 + target: google_apis + arch: x86_64 + profile: pixel_7 + working-directory: apps/tester-federation-v2 + script: | + adb shell settings put global hide_error_dialogs 1 + for i in 1 2 3; do adb shell "uiautomator dump /sdcard/d.xml >/dev/null && grep -q aerr_ /sdcard/d.xml" && { echo 'ANR dialog on screen, clearing it'; adb shell am force-stop com.google.android.apps.nexuslauncher; }; sleep 2; done + adb reverse tcp:8081 tcp:8081 + adb reverse tcp:8082 tcp:8082 + adb reverse --list + adb reverse --list | grep -q 'tcp:8081' || { echo '::error::adb reverse missing for tcp:8081'; exit 1; } + adb reverse --list | grep -q 'tcp:8082' || { echo '::error::adb reverse missing for tcp:8082'; exit 1; } + adb install -r -g android/app/build/outputs/apk/debug/app-debug.apk + pnpm exec e2e run --target android --reporter list,junit; ec=$?; adb logcat -d -v time > .e2e/logcat.txt 2>&1; exit $ec + + - name: Upload e2e artifacts + if: ${{ !cancelled() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # tag=v7.0.1 + with: + name: e2e-android + path: apps/tester-federation-v2/.e2e + include-hidden-files: true + if-no-files-found: error + retention-days: 7 + + - name: Show dev server logs + if: ${{ !cancelled() }} + run: tail -n 80 /tmp/hostapp.log /tmp/miniapp.log + + # dispatch + main only for now — no PR triggers until this lane has greens + ios: + name: e2e (iOS) + if: github.event_name != 'pull_request_target' + runs-on: macos-15 + timeout-minutes: 45 + + steps: + - name: Checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 + with: + ref: ${{ github.event.pull_request.head.sha || github.sha }} + + - name: Setup workspace + uses: ./.github/actions/setup-pnpm-node + with: + node-version: '24.18.0' + + - name: Build workspace packages + run: pnpm --filter tester-federation-v2... build + + # start both dev servers in the background, wait until both answer /status + - name: Start dev servers + working-directory: apps/tester-federation-v2 + env: + E2E: 'true' + run: | + nohup pnpm start:hostapp > /tmp/hostapp.log 2>&1 & + disown + nohup pnpm start:miniapp > /tmp/miniapp.log 2>&1 & + disown + for p in 8081 8082; do curl -sf --retry 90 --retry-delay 2 --retry-all-errors --retry-connrefused -o /dev/null "http://localhost:$p/status"; done + + # ask for the iOS bundles now so the servers compile them — they only build on first request + - name: Warm both compilers + working-directory: apps/tester-federation-v2 + run: | + curl -sf --max-time 300 -o /dev/null 'http://localhost:8081/index.bundle?platform=ios&dev=true&lazy=true&minify=false&modulesOnly=false&runModule=true&app=com.tester.federationV2' + curl -sf --max-time 300 -o /dev/null 'http://localhost:8082/index.bundle?platform=ios&dev=true&lazy=true&minify=false&modulesOnly=false&runModule=true&app=com.tester.federationV2' + echo 'Both bundles served; compilers are warm.' + + # match the runtime to the default Xcode's SDK (16.4 → iOS 18.x), not just newest available + - name: Boot simulator + run: | + RT=$(xcrun simctl list runtimes -j | jq -r '.runtimes | map(select(.isAvailable and (.identifier | startswith("com.apple.CoreSimulator.SimRuntime.iOS-18-")))) | sort_by(.version) | last | .identifier') + echo "using $RT" + [ "$RT" != "null" ] && [ -n "$RT" ] + xcrun simctl create e2e "iPhone 16" "$RT" + xcrun simctl boot e2e + xcrun simctl bootstatus e2e -b + + # pod install generates the Xcode project the workspace points at + - name: Build iOS app + working-directory: apps/tester-federation-v2/ios + run: pod install && xcodebuild -workspace ModuleFederationTesterV2.xcworkspace -scheme ReactTestApp -configuration Debug -destination 'generic/platform=iOS Simulator' -derivedDataPath build CODE_SIGNING_ALLOWED=NO ARCHS=arm64 build + + - name: Run e2e + working-directory: apps/tester-federation-v2 + run: | + xcrun simctl install booted ios/build/Build/Products/Debug-iphonesimulator/*.app + pnpm exec e2e run --target ios --reporter list,junit + + - name: Upload e2e artifacts + if: ${{ !cancelled() }} + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # tag=v7.0.1 + with: + name: e2e-ios + path: apps/tester-federation-v2/.e2e + include-hidden-files: true + if-no-files-found: error + retention-days: 7 + + - name: Show dev server logs + if: ${{ !cancelled() }} + run: tail -n 80 /tmp/hostapp.log /tmp/miniapp.log diff --git a/apps/tester-federation-v2/.gitignore b/apps/tester-federation-v2/.gitignore index de13ae3b6..86faa27e0 100644 --- a/apps/tester-federation-v2/.gitignore +++ b/apps/tester-federation-v2/.gitignore @@ -62,3 +62,6 @@ yarn-error.log # MF **/@mf-types + +# e2e +.e2e/ diff --git a/apps/tester-federation-v2/android/gradle.properties b/apps/tester-federation-v2/android/gradle.properties index 3b46be1a2..59c18ddff 100644 --- a/apps/tester-federation-v2/android/gradle.properties +++ b/apps/tester-federation-v2/android/gradle.properties @@ -56,4 +56,4 @@ hermesEnabled=true # Use this property to enable edge-to-edge display support. # This allows your app to draw behind system bars for an immersive UI. # Note: Only works with ReactActivity and should not be used with custom Activity. -edgeToEdgeEnabled=true \ No newline at end of file +edgeToEdgeEnabled=true diff --git a/apps/tester-federation-v2/configs/rspack.host-app.mts b/apps/tester-federation-v2/configs/rspack.host-app.mts index 43fedabe2..3bf821f2f 100644 --- a/apps/tester-federation-v2/configs/rspack.host-app.mts +++ b/apps/tester-federation-v2/configs/rspack.host-app.mts @@ -99,6 +99,7 @@ export default Repack.defineRspackConfig((env) => { __WITH_PRELOAD__: process.env.WITH_PRELOAD === 'true' || process.env.WITH_PRELOAD === '1', + __E2E__: process.env.E2E === 'true', }), ], }; diff --git a/apps/tester-federation-v2/configs/webpack.host-app.mts b/apps/tester-federation-v2/configs/webpack.host-app.mts index 32dc1ac25..0081f868d 100644 --- a/apps/tester-federation-v2/configs/webpack.host-app.mts +++ b/apps/tester-federation-v2/configs/webpack.host-app.mts @@ -95,6 +95,7 @@ export default Repack.defineWebpackConfig((env) => { __WITH_PRELOAD__: process.env.WITH_PRELOAD === 'true' || process.env.WITH_PRELOAD === '1', + __E2E__: process.env.E2E === 'true', }), ], }; diff --git a/apps/tester-federation-v2/e2e.config.ts b/apps/tester-federation-v2/e2e.config.ts new file mode 100644 index 000000000..1848abf52 --- /dev/null +++ b/apps/tester-federation-v2/e2e.config.ts @@ -0,0 +1,18 @@ +import { mobile } from '@e2e-dev/mobile'; +import type { E2EConfig } from 'e2e'; + +export default { + tests: 'e2e/**/*.e2e.ts', + targets: [ + { + name: 'android', + engine: mobile({ platform: 'android' }), + app: { bundleId: 'com.tester.federationV2' }, + }, + { + name: 'ios', + engine: mobile({ platform: 'ios' }), + app: { bundleId: 'com.tester.federationV2' }, + }, + ], +} satisfies E2EConfig; diff --git a/apps/tester-federation-v2/e2e/smoke.e2e.ts b/apps/tester-federation-v2/e2e/smoke.e2e.ts new file mode 100644 index 000000000..2097ed870 --- /dev/null +++ b/apps/tester-federation-v2/e2e/smoke.e2e.ts @@ -0,0 +1,40 @@ +import { test } from '@e2e-dev/mobile'; +import { expect } from 'e2e'; + +test('the host app boots to Home', async ({ app, screen }) => { + await app.open(); + + await expect(screen.getByTestId('home-details-button')).toBeVisible({ + timeout: 60_000, + }); + await expect(screen.getByTestId('home-gallery-button')).toBeVisible(); +}); + +test('navigates from Home to Detail and back', async ({ app, screen }) => { + await app.open(); + await expect(screen.getByTestId('home-details-button')).toBeVisible({ + timeout: 60_000, + }); + + await screen.getByTestId('home-details-button').tap(); + await expect(screen.getByTestId('detail-screen')).toBeVisible(); + + await app.back(); + await expect(screen.getByTestId('home-details-button')).toBeVisible(); + await expect(screen.getByTestId('detail-screen')).toBeHidden(); +}); + +test('Home opens the Gallery MiniApp', { + timeout: 120_000, +}, async ({ app, screen }) => { + await app.open(); + await expect(screen.getByTestId('home-gallery-button')).toBeVisible({ + timeout: 60_000, + }); + + await screen.getByTestId('home-gallery-button').tap(); + await expect(screen.getByTestId('miniapp-gallery')).toBeVisible({ + timeout: 45_000, + }); + await expect(screen.getByText('Picture 1')).toBeVisible(); +}); diff --git a/apps/tester-federation-v2/package.json b/apps/tester-federation-v2/package.json index a05da51ab..ac5b05183 100644 --- a/apps/tester-federation-v2/package.json +++ b/apps/tester-federation-v2/package.json @@ -9,7 +9,8 @@ "pods:update": "(cd ios && bundle install && bundle exec pod update)", "start:hostapp": "react-native webpack-start --config config.host-app.mts", "start:miniapp": "react-native webpack-start --config config.mini-app.mts --port 8082", - "start:expo-host-widget": "react-native webpack-start --config config.expo-host-widget.mts --port 8083" + "start:expo-host-widget": "react-native webpack-start --config config.expo-host-widget.mts --port 8083", + "e2e": "pnpm exec e2e run" }, "dependencies": { "@callstack/repack": "workspace:*", @@ -25,6 +26,7 @@ }, "devDependencies": { "@babel/core": "^7.29.7", + "@e2e-dev/mobile": "0.11.0", "@react-native-community/cli": "catalog:testers", "@react-native-community/cli-platform-android": "catalog:testers", "@react-native-community/cli-platform-ios": "catalog:testers", @@ -36,6 +38,7 @@ "@swc/helpers": "catalog:", "@types/jest": "^29.5.13", "@types/react": "catalog:testers", + "e2e": "0.19.0", "react-native-test-app": "catalog:testers", "terser-webpack-plugin": "catalog:", "typescript": "catalog:", diff --git a/apps/tester-federation-v2/src/host/index.js b/apps/tester-federation-v2/src/host/index.js index 61610d410..2c2e6dae9 100644 --- a/apps/tester-federation-v2/src/host/index.js +++ b/apps/tester-federation-v2/src/host/index.js @@ -1,11 +1,15 @@ import { ScriptManager } from '@callstack/repack/client'; import { preloadRemote } from '@module-federation/runtime'; import AsyncStorage from '@react-native-async-storage/async-storage'; -import { AppRegistry } from 'react-native'; +import { AppRegistry, LogBox } from 'react-native'; import { components } from '../../app.json'; import App from './App'; +if (__E2E__) { + LogBox.ignoreAllLogs(true); +} + if (__WITH_PRELOAD__) { // enable caching of scripts in the AsyncStorage ScriptManager.shared.setStorage(AsyncStorage); diff --git a/apps/tester-federation-v2/src/host/screens/DetailScreen.tsx b/apps/tester-federation-v2/src/host/screens/DetailScreen.tsx index 211051c96..3097b001a 100644 --- a/apps/tester-federation-v2/src/host/screens/DetailScreen.tsx +++ b/apps/tester-federation-v2/src/host/screens/DetailScreen.tsx @@ -2,7 +2,7 @@ import { StyleSheet, Text, View } from 'react-native'; const DetailScreen = () => { return ( - + DetailScreen ); diff --git a/apps/tester-federation-v2/src/host/screens/HomeScreen.tsx b/apps/tester-federation-v2/src/host/screens/HomeScreen.tsx index 766bce133..20dfbb5b6 100644 --- a/apps/tester-federation-v2/src/host/screens/HomeScreen.tsx +++ b/apps/tester-federation-v2/src/host/screens/HomeScreen.tsx @@ -13,6 +13,7 @@ const HomeScreen = () => { Explore the host app and its features navigation.navigate('Detail')} > @@ -29,6 +30,7 @@ const HomeScreen = () => { Mini Apps navigation.navigate('MiniApp')} > diff --git a/apps/tester-federation-v2/src/host/screens/MiniAppScreen.tsx b/apps/tester-federation-v2/src/host/screens/MiniAppScreen.tsx index af41cfd97..47e70358a 100644 --- a/apps/tester-federation-v2/src/host/screens/MiniAppScreen.tsx +++ b/apps/tester-federation-v2/src/host/screens/MiniAppScreen.tsx @@ -16,7 +16,7 @@ class ErrorBoundary extends React.Component< render() { if (this.state.hasError) { return ( - + Failed to load Mini App ); diff --git a/apps/tester-federation-v2/src/mini/screens/GalleryScreen.tsx b/apps/tester-federation-v2/src/mini/screens/GalleryScreen.tsx index d8a0b5023..4d4af8175 100644 --- a/apps/tester-federation-v2/src/mini/screens/GalleryScreen.tsx +++ b/apps/tester-federation-v2/src/mini/screens/GalleryScreen.tsx @@ -41,6 +41,7 @@ const Row = ({ const GalleryScreen = () => { return ( diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 77ea2415a..164de7fa7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -563,6 +563,9 @@ importers: '@babel/core': specifier: ^7.29.7 version: 7.29.7 + '@e2e-dev/mobile': + specifier: 0.11.0 + version: 0.11.0(e2e@0.19.0) '@react-native-community/cli': specifier: catalog:testers version: 20.2.0(typescript@7.0.2) @@ -596,6 +599,9 @@ importers: '@types/react': specifier: catalog:testers version: 19.2.17 + e2e: + specifier: 0.19.0 + version: 0.19.0 react-native-test-app: specifier: catalog:testers version: 5.4.5(@expo/config-plugins@57.0.10(typescript@7.0.2))(@react-native-community/cli-types@20.2.0)(memfs@4.64.0)(metro@0.84.6)(react-native@0.86.3(@babel/core@7.29.7)(@react-native-community/cli@20.2.0(typescript@7.0.2))(@types/react@19.2.17)(react@19.2.8))(react@19.2.8) @@ -1137,6 +1143,10 @@ importers: packages: + '@ai-sdk/provider@4.0.21': + resolution: {integrity: sha512-UpbC9C1oht8dhfKPbVXSLRZS3DI8uk8n5v2uMjBPNIYGsC2kL045ywq7D8Hh9KgnH9rP5W/GxQdYtWScRouqlA==} + engines: {node: '>=22'} + '@alloc/quick-lru@5.2.0': resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} engines: {node: '>=10'} @@ -2081,6 +2091,16 @@ packages: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} + '@e2e-dev/mobile@0.11.0': + resolution: {integrity: sha512-wvZ/VVUmNs65qnXqgh49huCw1Rgl1+3sngOEd4umLaNtPAcQBTzbX9Fz5zdXR5tQuN3HPejVez7IOSHYE3/dyQ==} + engines: {node: ^22.22.3 || >=24.8.0} + peerDependencies: + ai: ^7.0.0 + e2e: '>=0.15.0 <1' + peerDependenciesMeta: + ai: + optional: true + '@egjs/hammerjs@2.0.17': resolution: {integrity: sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==} engines: {node: '>=0.8.0'} @@ -2882,6 +2902,14 @@ packages: '@types/react': '>=16' react: '>=16' + '@modelcontextprotocol/core@2.3.0': + resolution: {integrity: sha512-09BHFaNVBe5pB2AhzCfLj0cqmsKLERvZQ4FblzP90UMGLaXVqdZPByFjURwsUYCmxonUW2yAwgTTvle+8O2/8w==} + engines: {node: '>=20'} + + '@modelcontextprotocol/server@2.3.0': + resolution: {integrity: sha512-+6b0LdsQLmHsvS7J6sQJ4weTpzUn61fU1JKS+321/+IyDYoHW5CR2Tgqcs6GgAAQvlesCo6yX3xttgmx+XGtJw==} + engines: {node: '>=20'} + '@modern-js/node-bundle-require@2.67.6': resolution: {integrity: sha512-rRiDQkrm3kgn0E/GNrcvqo4c71PaUs2R8Xmpv6GUKbEr6lz7VNgfZmAhdAQPtNfRfiBe+1sFLzEcwfEdDo/dTA==} @@ -3291,6 +3319,257 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@oxc-parser/binding-android-arm-eabi@0.152.0': + resolution: {integrity: sha512-393VtirINkae4XHBTkq/yQxhOwEr4V+r0et37P2fp+sYZSdYgZTRDPo5Um8vBh0QjMZ+RmaMy4PP0qwr4cTMwA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxc-parser/binding-android-arm64@0.152.0': + resolution: {integrity: sha512-iYFcExATJNZ0rZj0o02THbD1Nc9jAW0nVgIQPee6ejbSASpbZXlIMw8jxtpzaG14JQTWwGSZ6U5dEtRJXE6V3Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxc-parser/binding-darwin-arm64@0.152.0': + resolution: {integrity: sha512-fnU+DfUzi5/rFy0LzmipYRz06PAUUkOS8kCJQ3Eg6oqlunC1XZXoffFqxmdL51RmcbYtUG3P8DVG1U5fckoa2A==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxc-parser/binding-darwin-x64@0.152.0': + resolution: {integrity: sha512-Y3U2okryWTs7hDld6UhjJwLNf8/do+x4g4C+1U5SiGwrTLwbO83WJYJA8+l9iFSilWBgnfpd/+U76tfeNxUHzA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxc-parser/binding-freebsd-x64@0.152.0': + resolution: {integrity: sha512-XkhkRrrPffEw+ZLv/d/5pEni0buxinm/E/N6fLbJCunD1DBbeCTtVP23ESV+4CWCWdSz397asks1ViGslpmWiQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxc-parser/binding-linux-arm-gnueabihf@0.152.0': + resolution: {integrity: sha512-MLzsRRbdfmdzo6JEhbC1yKU9ItfvM8tEf18HM32jCiNYZEz6J3bRBRl3cTkKR0vBdrk9ZVlcARXtwHccs+epDA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm-musleabihf@0.152.0': + resolution: {integrity: sha512-HHerTEJz7Iy10Ji6BGsk4gqG6PU0UzFuBu91jIEOX89FnrI5ECWSEr7BLpkYQhp7U0QFtMnBhNfQKI0hYZK78w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-parser/binding-linux-arm64-gnu@0.152.0': + resolution: {integrity: sha512-9Bb8GyzZ2uSLzRDZ27usaKokr07mxiBe2dDF5b6bd2janmaJTT1gL51UfP7AU30yFiXrJvcRyFKREAgKwZYs0w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-arm64-musl@0.152.0': + resolution: {integrity: sha512-om7iDMUroI74A/lfRRWY9/Ev3VWrVsrUZ4tyvyh8raBey/sdcfyAD7tYWc+iykAiotnmftyKTpUKFr1QnaBrAQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-ppc64-gnu@0.152.0': + resolution: {integrity: sha512-Lf1OL2lMTqwDMFC6jnRb30B+WYHKV0XT+bPHcFM6xHtNVwxpobiTzUIvKH6a0LWpvfwyru8Yu6zCGHqqFHH+gg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-gnu@0.152.0': + resolution: {integrity: sha512-BYWSMQK+YJ9ZILStPcmmiSVq8KEG9Qdq/c4BHPC3rUEq/fEDCVjUIwdj5ZzjgZ9P9is9PKu0tcAXzq1ZXg4urQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-riscv64-musl@0.152.0': + resolution: {integrity: sha512-d2LqHNNNqdH185sRK5dPKWZu201JrNu9/CRFuVEuT+ht7n/QaVblEMWT9MALQPrDWYvhG10P+NSKJFquDWZ09w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-linux-s390x-gnu@0.152.0': + resolution: {integrity: sha512-8gBeHt5rA/8+pKhHl+zLggfa3L/V/L2at96p7ty6pBE7id6lFO19nFUc15u2PcjC4OYeYK465MKy1fhhbpFIGw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-gnu@0.152.0': + resolution: {integrity: sha512-ltgrSF6L+yPTVsIdaAyqKq3zTqzj/1VlNbxWZuxAe8flR3sWdyNsKvdXukoO8/ucJbLickhmieRBge+o/e8Ugw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-parser/binding-linux-x64-musl@0.152.0': + resolution: {integrity: sha512-LcMp6BvrBnewSfdkLHoSqidhoAq4syKOTBV5TYHWd+2VnGkfD/nPRRVIzTBt/Lkbt7pfOFDGtkiTntFS0p6sQQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-parser/binding-openharmony-arm64@0.152.0': + resolution: {integrity: sha512-jbhoMCslVxzRCRNQ8TSHxjYdSKRvk8O6ciLVDkahJvmyHDzBqba/bMQHM6ULKj/rgHNNbSzlIiakdx8SEfkJzA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxc-parser/binding-win32-arm64-msvc@0.152.0': + resolution: {integrity: sha512-JZYVlhv36mr/nertnRB7vchJECOBb1Lz6lltalILsB+o9M/is+H6BEDRLQKdqA4JKs6NjJszo46+iM5sfwj6jQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxc-parser/binding-win32-ia32-msvc@0.152.0': + resolution: {integrity: sha512-1X9oganvVsunRH0lH10UU05N+H9atpX6WsOybByUjwnfcd3h/0tYwvuv16XuHglrIUOnxV2TodbLVEwwafd64g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxc-parser/binding-win32-x64-msvc@0.152.0': + resolution: {integrity: sha512-sw0M80/dn9rcpu+Rqqph/C+MjvDDce6MlXmFjsNQtPEymha0eJy3ml6+foSUTqFfpDIDyHZZ4eoJ43IoMe8bJw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + + '@oxc-project/runtime@0.152.0': + resolution: {integrity: sha512-fsq/7JVJo8YAmMPnt3Z7akMdMoCokRND5jjawa5DxuKJBEaI0Dl3ZqEXFlLabKoZhlApIexZ7aycXFcjcTcWvw==} + engines: {node: ^20.19.0 || >=22.12.0} + + '@oxc-project/types@0.152.0': + resolution: {integrity: sha512-oM/5rLBm2tPkg0iBgkH/FOeR3PCDpY19GTgAZjMFM8h9WI9VW7cLgzp6nwtarYKmovavIQZ+Fe/RKX/8C8O/Rw==} + + '@oxc-transform/binding-android-arm-eabi@0.152.0': + resolution: {integrity: sha512-GBVYZdUggANq7ndUuE9HBi1jO6d2+oud3cevfQkpqrV7JsDNwQU5UCGa8rZCvzjIvyn6ikQuJu+sj4RvLyN6Uw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [android] + + '@oxc-transform/binding-android-arm64@0.152.0': + resolution: {integrity: sha512-pqeCLGUnozzyJE9Ed9js2w+V1lHQ43qPImMfgTh7it+a3LJqUjAt+OesJ6pqkPycRFV6b0pUWZm6EkpM8mk7ag==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [android] + + '@oxc-transform/binding-darwin-arm64@0.152.0': + resolution: {integrity: sha512-0d68wdepj2bjnDijPdvC/3MnrZcs8hoCp19qnGX2tyxnSIPevgqa9RX5i31ex5JMczht/VGp4aKeV1p12dwzQQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [darwin] + + '@oxc-transform/binding-darwin-x64@0.152.0': + resolution: {integrity: sha512-jFTRTyZzYhqSrxkaI9hTwClPTXtdqRyPSXUFGLJmStYS+b6qnhbI1ottivWdAg0HJXytyg8YeqgUJWSu2lU/jA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [darwin] + + '@oxc-transform/binding-freebsd-x64@0.152.0': + resolution: {integrity: sha512-L4Y8IfrcaxjK9kK3ddRAyZPa6nzJHn6fgkVIKoBlP53vmCobPL1mtuIdXQThD0VmV6e4aSAJg2An6qkdjeZC8Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [freebsd] + + '@oxc-transform/binding-linux-arm-gnueabihf@0.152.0': + resolution: {integrity: sha512-GrohqmIKEK/YXCzAGP8XGQrPVBdUHPpvqdhvw+VutpWZofxDOq39Zed+Gqlea2mycXo+/UNeq1194eaAYkqKQQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-transform/binding-linux-arm-musleabihf@0.152.0': + resolution: {integrity: sha512-wUI+JoZEs4+GntxjK2YOKtQDG822wv+aGYm1OUZ2+NAgi8ghOTUP3RH/GX8Vq0qJ2Yw3OwKLUIZzufXklQ7pCQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm] + os: [linux] + + '@oxc-transform/binding-linux-arm64-gnu@0.152.0': + resolution: {integrity: sha512-EcY52e0BOfynOA/brCInvQO3ZSukbAEc+BsbpRoRdJ4qV10NK0aS/FheBvkj/V3cFidee6QlrUpqgpN4WKV+Sg==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [glibc] + + '@oxc-transform/binding-linux-arm64-musl@0.152.0': + resolution: {integrity: sha512-L4OGw0UuuyYKAPnUvvW+tvq6nS/tBoolVuPekNJqYnDYfe5Nh1619ImfhP0o0Wz+SG4OQW35ByRWjVf/oK3x0w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@oxc-transform/binding-linux-ppc64-gnu@0.152.0': + resolution: {integrity: sha512-5K9qNjNKlyhBdGkkIhYFonO/H3Yc37miy5cXefTB71aPOv9jv6HQrDuj6AJcBkggbmkeyEJhlFamUbGMsMGBiA==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ppc64] + os: [linux] + libc: [glibc] + + '@oxc-transform/binding-linux-riscv64-gnu@0.152.0': + resolution: {integrity: sha512-WlGvnZhmRItWqjsGd2OBKPan75FbqpF4HPuGL7P6f7Oz1VHm6IatnwCK2MI16QXH7BEs6GRohZHpmgThc0V/uw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@oxc-transform/binding-linux-riscv64-musl@0.152.0': + resolution: {integrity: sha512-TWZX7QGkU4LF9NS+HBUVWsbQXWDuWt58r+L/31gSJ/iHCJw/3jM2yD408IRVjXYX5jFgmsJbxrUlW3xlVeAL3Q==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [riscv64] + os: [linux] + libc: [musl] + + '@oxc-transform/binding-linux-s390x-gnu@0.152.0': + resolution: {integrity: sha512-VIP7463d0nIAGFv2VXb4mRf20qrpZg0kNHBw8E3fLuHj0bt4HVHDgsqAgeFWOonWwSwsM415TFjNmHhlaStCLQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [s390x] + os: [linux] + libc: [glibc] + + '@oxc-transform/binding-linux-x64-gnu@0.152.0': + resolution: {integrity: sha512-hwnHMVCnGIoS/eMh7T836mJpWim2iCSWGlCS+aZ+SjhEEUvSSUE54ljua7bk25vaj4L84cFnruTCa7HqyaQ2YQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@oxc-transform/binding-linux-x64-musl@0.152.0': + resolution: {integrity: sha512-5NPItMgM9GfIW0SbpOXvEFIijin5VcNEParmBEm9j+RXr8Ko7pZ3a1ydk/Sy+EOvaSTkXMY6TkVyLfczwdudSQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [linux] + libc: [musl] + + '@oxc-transform/binding-openharmony-arm64@0.152.0': + resolution: {integrity: sha512-pNzMq4AhBUV8E/cc41SgYTjzW/AWq1DtEKz1l56Mn1TKfidJwP8sGnIw0EXhD6zKFUlPoqkWfvoe5TiDAYeT+w==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [openharmony] + + '@oxc-transform/binding-win32-arm64-msvc@0.152.0': + resolution: {integrity: sha512-PU6cGmVDYo2HHG9ul6vKj189YJPZrcscdWzQakJD6NU4CqvqISbZLUHwz6DVe0v8CbOe2d24zUdipILaRofZ5g==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [arm64] + os: [win32] + + '@oxc-transform/binding-win32-ia32-msvc@0.152.0': + resolution: {integrity: sha512-Sdcoky580dPgj9Qp+i4zrCV7NpIYZW6bBrcQvOwyDmNlJQ2iYK/V3Q3FGNHLulrxgXrpzqQwMcLs8KRIg0u0yw==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [ia32] + os: [win32] + + '@oxc-transform/binding-win32-x64-msvc@0.152.0': + resolution: {integrity: sha512-QnN+/Hsig/vI9zoCNVbbqv0GmZWUGqlPg2ZTEyVw/PvgAXd8pRRfN6CxdKEtJTnaVwJFVYaw/5LR6ZWCVBwDeQ==} + engines: {node: ^20.19.0 || >=22.12.0} + cpu: [x64] + os: [win32] + '@pinojs/redact@0.4.0': resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==} @@ -4901,6 +5180,9 @@ packages: '@vitest/expect@4.1.11': resolution: {integrity: sha512-VX2x5vNJXET47KAFzwERI+KRMtTTCSWTfSMKsW7JsUsXV4psq++e3DvZpuTDOpHcxytiDs6p2nhVb2tVDiiUYw==} + '@vitest/expect@5.0.3': + resolution: {integrity: sha512-N/VGY122AqBx25OB4EatqlVu8PBayvm9dQzpJ8kVq/pOvqAhXTE5MAmoSMzdB8klDU9wcgSEUliwgMNMtxPa1w==} + '@vitest/mocker@4.1.11': resolution: {integrity: sha512-2XJVD55d1o5AZous5CCGKS74g/riOj9odEt2bQpCVZeblHyHdnMeFl4jl0XjU21stf4mbjUkew2eXQZt65g5CQ==} peerDependencies: @@ -4915,6 +5197,9 @@ packages: '@vitest/pretty-format@4.1.11': resolution: {integrity: sha512-yiZzPbGTS9Sr/JpFl8zHrcIkAofNbFV6k21vIgQN/cY/oxZeXhJv5sc/MBJ5jFKWmWs+oJHw0UXLZjmf931+Vw==} + '@vitest/pretty-format@5.0.3': + resolution: {integrity: sha512-3hr5eV5z2ff0l2Q1vaKQbB4j3M3tElw8stDokEOTqXJB3Es5VrT8gBRIMY59gGuFp8Y61sWlWFK1aNUH5dHDYw==} + '@vitest/runner@4.1.11': resolution: {integrity: sha512-LztvUgdwMNJMIkj3hQnnxiC2Xy1zNxq928W/xhjCLaNCzqTZOudjwbQf6v9IntZGPw132i2Lq2rgTRZHD3JHNw==} @@ -4924,9 +5209,15 @@ packages: '@vitest/spy@4.1.11': resolution: {integrity: sha512-apNa/prQy2qCeywhnixOHPRCgGNhvg7T4Dapfl1GahLp/R+uhBm5cPyFoNVyqsNd2h1nJxL6BqqdIjiABL60YA==} + '@vitest/spy@5.0.3': + resolution: {integrity: sha512-XhFysQTB8AZ+P4gMi+Lpo99vg2AZi0qKpaB9yXQl37+CaMEAPO3iH/wGVnSyL5MPERiLezpqTVtrR6UZH5GCXg==} + '@vitest/utils@4.1.11': resolution: {integrity: sha512-zTCVGpyFsGWBhllOyKlTw/vnr6D9qxsfSDyfbyZmTyjHw5N/VuvzHpHoQjm2ZJzn4RJgx5w4r7V0er69CmLgPQ==} + '@vitest/utils@5.0.3': + resolution: {integrity: sha512-77fDTZv8eu1CzlIfgPU2yrl5MXSUaUAOvgdZEeVm3X3WIxUubIX2SforqS6176lT32HCF6uBVMYVqfHxw7o6eg==} + '@vscode/sudo-prompt@9.3.2': resolution: {integrity: sha512-gcXoCN00METUNFeQOFJ+C9xUI0DKB+0EGMVg7wbVYRHBw2Eq3fKisDZOkRdOz3kqXRKOENMfShPOmypw1/8nOw==} @@ -5051,6 +5342,16 @@ packages: engines: {node: '>=18.18'} hasBin: true + agent-device@0.21.22: + resolution: {integrity: sha512-ndUh5b+lZ2fRzzY80TTl/KmxR4bh+3FezSH0UGCjPCpN//1trSqtzzNUWunc4woY/vW3DEiPx5xYIwG+fBOXWA==} + engines: {node: '>=22.12'} + hasBin: true + peerDependencies: + ai: ^6.0.0 || ^7.0.0 + peerDependenciesMeta: + ai: + optional: true + ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} @@ -5565,6 +5866,10 @@ packages: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} + commander@15.0.0: + resolution: {integrity: sha512-z67u4ZhzCL/Tydu1lJARtEZYWbWaN7oYLHbsuzocr6y4N6WZAagG3RQ4FW61V1/0+jImpj293XfrcYnd1qxtPg==} + engines: {node: '>=22.12.0'} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -5890,6 +6195,31 @@ packages: resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} engines: {node: '>= 0.4'} + e2e@0.19.0: + resolution: {integrity: sha512-tTWgVR9tQTeESXkAxCh8H/gR4bGxbSbidw07/GngKT5P5tAPdsJ+bW5bQwIaAL/LUTwIG106V64/oiWLXkS29Q==} + engines: {node: ^22.22.3 || >=24.8.0} + hasBin: true + peerDependencies: + '@ai-sdk/anthropic': ^4.0.0 + '@ai-sdk/google': ^4.0.0 + '@ai-sdk/openai': ^4.0.0 + '@ai-sdk/openai-compatible': ^3.0.0 + '@ai-sdk/xai': ^5.0.0 + ai: ^7.0.0 + peerDependenciesMeta: + '@ai-sdk/anthropic': + optional: true + '@ai-sdk/google': + optional: true + '@ai-sdk/openai': + optional: true + '@ai-sdk/openai-compatible': + optional: true + '@ai-sdk/xai': + optional: true + ai: + optional: true + ecdsa-sig-formatter@1.0.11: resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} @@ -6261,6 +6591,9 @@ packages: fast-json-stringify@7.0.1: resolution: {integrity: sha512-eRSayARSbbwlBjpP4vnTTIRD5QPcIrmihPxDeN1DtKnHPg66UuJLx+8hlK1kaFdjvzyQ/dzALoi4vwAQ+T+iZA==} + fast-png@8.0.0: + resolution: {integrity: sha512-gCysNasJ8KEMgfdYIKd/wTDo6ENK1PWT0RJO7O+0pgmuHPw2O6tA1WvdxFRJoLf9V8yFYpG0FA1YgI8X97OhJA==} + fast-querystring@1.1.2: resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} @@ -6322,6 +6655,9 @@ packages: fetch-nodeshim@0.4.10: resolution: {integrity: sha512-m6I8ALe4L4XpdETy7MJZWs6L1IVMbjs99bwbpIKphxX+0CTns4IKDWJY0LWfr4YsFjfg+z1TjzTMU8lKl8rG0w==} + fflate@0.8.3: + resolution: {integrity: sha512-tbZNuJrLwGUp3zshBtdy4W+ORxZuIh8a5ilyIEQDC5rY1f3U20JMry0Ll3WBzU58EZKsEuJFXhb5gwv8CsPvgA==} + figures@6.1.0: resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} engines: {node: '>=18'} @@ -6511,6 +6847,9 @@ packages: resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} engines: {node: '>=18'} + get-tsconfig@4.14.3: + resolution: {integrity: sha512-++QEw4DIY7WGoukz+/+A/8dGYPT9l9yIadnmSgZ8Rjr3YVSVDipQSO9CdnJo9ePqFqUUqh+wk9uIaoiAwsiPkA==} + getenv@2.0.0: resolution: {integrity: sha512-VilgtJj/ALgGY77fiLam5iD336eSWi96Q15JSAG1zi8NRBysm3LXKdGnHb4m5cuyxvOLQQKWpBZAT6ni4FI2iQ==} engines: {node: '>=6'} @@ -6798,6 +7137,9 @@ packages: invariant@2.2.4: resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + iobuffer@6.0.1: + resolution: {integrity: sha512-SZWYkWNfjIXIBYSDpXDYIgshqtbOPsi4lviawAEceR1Kqk+sHDlcQjWrzNQsii80AyBY0q5c8HCTNjqo74ul+Q==} + ipaddr.js@2.4.0: resolution: {integrity: sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==} engines: {node: '>= 10'} @@ -7156,6 +7498,9 @@ packages: json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + json-stream-stringify@3.0.1: resolution: {integrity: sha512-vuxs3G1ocFDiAQ/SX0okcZbtqXwgj1g71qE9+vrjJ2EkjKQlEFDAcUNRxRU8O+GekV4v5cM2qXP0Wyt/EMDBiQ==} @@ -8102,6 +8447,14 @@ packages: resolution: {integrity: sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==} engines: {node: '>=10'} + oxc-parser@0.152.0: + resolution: {integrity: sha512-ZztsZgaCWmPeKYMdoTT5e0oV/oxD1NeLWNR3kAtr/G707cUPYaaozRlVDHLCGnszHJRszN9mJwmPNpqgwloC0A==} + engines: {node: ^20.19.0 || >=22.12.0} + + oxc-transform@0.152.0: + resolution: {integrity: sha512-9rs8qImolzWswXGlhmye9Yz9Mce9hOe4Pivb7rSEhF/6VKn1Q122BUe9Mr1O9xQAoBX+SrF6xXfdgxKHeQf+uQ==} + engines: {node: ^20.19.0 || >=22.12.0} + p-limit@2.3.0: resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} engines: {node: '>=6'} @@ -8260,6 +8613,10 @@ packages: resolution: {integrity: sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==} engines: {node: '>= 6'} + pixelmatch@8.0.0: + resolution: {integrity: sha512-cIqOLfh5k52us715qf3B3+kTOxZv+WDv77HN7xokLScYQGYQHi4m/ynoDIPpvF2LvCyUJGyvzY64i0QCXtzu1g==} + hasBin: true + pkg-dir@4.2.0: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} @@ -8280,6 +8637,10 @@ packages: resolution: {integrity: sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==} engines: {node: '>=4.0.0'} + pngjs@7.0.0: + resolution: {integrity: sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==} + engines: {node: '>=14.19.0'} + portfinder@1.0.38: resolution: {integrity: sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg==} engines: {node: '>= 10.12'} @@ -8781,6 +9142,9 @@ packages: resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} engines: {node: '>=8'} + resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + resolve-workspace-root@2.0.1: resolution: {integrity: sha512-nR23LHAvaI6aHtMg6RWoaHpdR4D881Nydkzi2CixINyg9T00KgaJdJI6Vwty+Ps8WLxZHuxsS0BseWjxSA4C+w==} @@ -9330,6 +9694,10 @@ packages: resolution: {integrity: sha512-Bf+ILmBgretUrdJxzXM0SgXLZ3XfiaUuOj/IKQHuTXip+05Xn+uyEYdVg0kYDipTBcLrCVyUzAPz7QmArb0mmw==} engines: {node: '>=14.0.0'} + tinyrainbow@3.2.0: + resolution: {integrity: sha512-LgO3D9yZJjApUiuUfl9iFAwrtaX4+lok3wJIqttGoKCHlWUqHqbQpnxCf82L8FjgKsh4iGo78hqJwgL8F6To2A==} + engines: {node: '>=14.0.0'} + tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} @@ -9866,11 +10234,18 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zod@4.6.1: + resolution: {integrity: sha512-341aRWQsve0rvronKNTqZpjmzdbUDlFuzHaI/XLg/Ej82qffDJRRfBTCuv7+9q/rMjB6LSLyEBnW4InJeMtt/Q==} + zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} snapshots: + '@ai-sdk/provider@4.0.21': + dependencies: + json-schema: 0.4.0 + '@alloc/quick-lru@5.2.0': {} '@ast-grep/napi-darwin-arm64@0.37.0': @@ -11019,6 +11394,13 @@ snapshots: '@discoveryjs/json-ext@0.5.7': {} + '@e2e-dev/mobile@0.11.0(e2e@0.19.0)': + dependencies: + agent-device: 0.21.22 + e2e: 0.19.0 + pngjs: 7.0.0 + zod: 4.6.1 + '@egjs/hammerjs@2.0.17': dependencies: '@types/hammerjs': 2.0.46 @@ -12157,6 +12539,15 @@ snapshots: '@types/react': 19.3.0 react: 19.2.8 + '@modelcontextprotocol/core@2.3.0': + dependencies: + zod: 4.6.1 + + '@modelcontextprotocol/server@2.3.0': + dependencies: + '@modelcontextprotocol/core': 2.3.0 + zod: 4.6.1 + '@modern-js/node-bundle-require@2.67.6': dependencies: '@modern-js/utils': 2.67.6 @@ -12860,6 +13251,124 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.20.1 + '@oxc-parser/binding-android-arm-eabi@0.152.0': + optional: true + + '@oxc-parser/binding-android-arm64@0.152.0': + optional: true + + '@oxc-parser/binding-darwin-arm64@0.152.0': + optional: true + + '@oxc-parser/binding-darwin-x64@0.152.0': + optional: true + + '@oxc-parser/binding-freebsd-x64@0.152.0': + optional: true + + '@oxc-parser/binding-linux-arm-gnueabihf@0.152.0': + optional: true + + '@oxc-parser/binding-linux-arm-musleabihf@0.152.0': + optional: true + + '@oxc-parser/binding-linux-arm64-gnu@0.152.0': + optional: true + + '@oxc-parser/binding-linux-arm64-musl@0.152.0': + optional: true + + '@oxc-parser/binding-linux-ppc64-gnu@0.152.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-gnu@0.152.0': + optional: true + + '@oxc-parser/binding-linux-riscv64-musl@0.152.0': + optional: true + + '@oxc-parser/binding-linux-s390x-gnu@0.152.0': + optional: true + + '@oxc-parser/binding-linux-x64-gnu@0.152.0': + optional: true + + '@oxc-parser/binding-linux-x64-musl@0.152.0': + optional: true + + '@oxc-parser/binding-openharmony-arm64@0.152.0': + optional: true + + '@oxc-parser/binding-win32-arm64-msvc@0.152.0': + optional: true + + '@oxc-parser/binding-win32-ia32-msvc@0.152.0': + optional: true + + '@oxc-parser/binding-win32-x64-msvc@0.152.0': + optional: true + + '@oxc-project/runtime@0.152.0': {} + + '@oxc-project/types@0.152.0': {} + + '@oxc-transform/binding-android-arm-eabi@0.152.0': + optional: true + + '@oxc-transform/binding-android-arm64@0.152.0': + optional: true + + '@oxc-transform/binding-darwin-arm64@0.152.0': + optional: true + + '@oxc-transform/binding-darwin-x64@0.152.0': + optional: true + + '@oxc-transform/binding-freebsd-x64@0.152.0': + optional: true + + '@oxc-transform/binding-linux-arm-gnueabihf@0.152.0': + optional: true + + '@oxc-transform/binding-linux-arm-musleabihf@0.152.0': + optional: true + + '@oxc-transform/binding-linux-arm64-gnu@0.152.0': + optional: true + + '@oxc-transform/binding-linux-arm64-musl@0.152.0': + optional: true + + '@oxc-transform/binding-linux-ppc64-gnu@0.152.0': + optional: true + + '@oxc-transform/binding-linux-riscv64-gnu@0.152.0': + optional: true + + '@oxc-transform/binding-linux-riscv64-musl@0.152.0': + optional: true + + '@oxc-transform/binding-linux-s390x-gnu@0.152.0': + optional: true + + '@oxc-transform/binding-linux-x64-gnu@0.152.0': + optional: true + + '@oxc-transform/binding-linux-x64-musl@0.152.0': + optional: true + + '@oxc-transform/binding-openharmony-arm64@0.152.0': + optional: true + + '@oxc-transform/binding-win32-arm64-msvc@0.152.0': + optional: true + + '@oxc-transform/binding-win32-ia32-msvc@0.152.0': + optional: true + + '@oxc-transform/binding-win32-x64-msvc@0.152.0': + optional: true + '@pinojs/redact@0.4.0': {} '@pnpm/deps.graph-sequencer@1100.0.1': {} @@ -14903,6 +15412,15 @@ snapshots: chai: 6.2.2 tinyrainbow: 3.1.0 + '@vitest/expect@5.0.3': + dependencies: + '@standard-schema/spec': 1.1.0 + '@types/chai': 5.2.3 + '@vitest/spy': 5.0.3 + '@vitest/utils': 5.0.3 + chai: 6.2.2 + tinyrainbow: 3.2.0 + '@vitest/mocker@4.1.11(vite@7.3.6(@types/node@20.19.43)(jiti@2.7.0)(lightningcss@1.33.0)(terser@5.51.2)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.11 @@ -14923,6 +15441,10 @@ snapshots: dependencies: tinyrainbow: 3.1.0 + '@vitest/pretty-format@5.0.3': + dependencies: + tinyrainbow: 3.2.0 + '@vitest/runner@4.1.11': dependencies: '@vitest/utils': 4.1.11 @@ -14937,12 +15459,20 @@ snapshots: '@vitest/spy@4.1.11': {} + '@vitest/spy@5.0.3': {} + '@vitest/utils@4.1.11': dependencies: '@vitest/pretty-format': 4.1.11 convert-source-map: 2.0.0 tinyrainbow: 3.1.0 + '@vitest/utils@5.0.3': + dependencies: + '@vitest/pretty-format': 5.0.3 + convert-source-map: 2.0.0 + tinyrainbow: 3.2.0 + '@vscode/sudo-prompt@9.3.2': {} '@webassemblyjs/ast@1.14.1': @@ -15077,6 +15607,8 @@ snapshots: agent-cli-detector@0.1.7: {} + agent-device@0.21.22: {} + ajv-formats@2.1.1: dependencies: ajv: 8.20.0 @@ -15714,6 +16246,8 @@ snapshots: commander@12.1.0: {} + commander@15.0.0: {} + commander@2.20.3: {} commander@4.1.1: {} @@ -15995,6 +16529,23 @@ snapshots: es-errors: 1.3.0 gopd: 1.2.0 + e2e@0.19.0: + dependencies: + '@ai-sdk/provider': 4.0.21 + '@clack/prompts': 1.8.1 + '@jridgewell/remapping': 2.3.5 + '@modelcontextprotocol/server': 2.3.0 + '@oxc-project/runtime': 0.152.0 + '@vitest/expect': 5.0.3 + commander: 15.0.0 + fast-png: 8.0.0 + get-tsconfig: 4.14.3 + oxc-parser: 0.152.0 + oxc-transform: 0.152.0 + picocolors: 1.1.1 + pixelmatch: 8.0.0 + zod: 4.6.1 + ecdsa-sig-formatter@1.0.11: dependencies: safe-buffer: 5.2.1 @@ -16628,6 +17179,11 @@ snapshots: json-schema-ref-resolver: 3.0.0 rfdc: 1.4.1 + fast-png@8.0.0: + dependencies: + fflate: 0.8.3 + iobuffer: 6.0.1 + fast-querystring@1.1.2: dependencies: fast-decode-uri-component: 1.0.1 @@ -16702,6 +17258,8 @@ snapshots: fetch-nodeshim@0.4.10: {} + fflate@0.8.3: {} + figures@6.1.0: dependencies: is-unicode-supported: 2.1.0 @@ -16884,6 +17442,10 @@ snapshots: '@sec-ant/readable-stream': 0.4.1 is-stream: 4.0.1 + get-tsconfig@4.14.3: + dependencies: + resolve-pkg-maps: 1.0.0 + getenv@2.0.0: {} glob-parent@5.1.2: @@ -17279,6 +17841,8 @@ snapshots: dependencies: loose-envify: 1.4.0 + iobuffer@6.0.1: {} + ipaddr.js@2.4.0: {} is-absolute-url@4.0.1: {} @@ -17813,6 +18377,8 @@ snapshots: json-schema-traverse@1.0.0: {} + json-schema@0.4.0: {} + json-stream-stringify@3.0.1: {} json5@2.2.3: {} @@ -19256,6 +19822,52 @@ snapshots: strip-ansi: 6.0.1 wcwidth: 1.0.1 + oxc-parser@0.152.0: + dependencies: + '@oxc-project/types': 0.152.0 + optionalDependencies: + '@oxc-parser/binding-android-arm-eabi': 0.152.0 + '@oxc-parser/binding-android-arm64': 0.152.0 + '@oxc-parser/binding-darwin-arm64': 0.152.0 + '@oxc-parser/binding-darwin-x64': 0.152.0 + '@oxc-parser/binding-freebsd-x64': 0.152.0 + '@oxc-parser/binding-linux-arm-gnueabihf': 0.152.0 + '@oxc-parser/binding-linux-arm-musleabihf': 0.152.0 + '@oxc-parser/binding-linux-arm64-gnu': 0.152.0 + '@oxc-parser/binding-linux-arm64-musl': 0.152.0 + '@oxc-parser/binding-linux-ppc64-gnu': 0.152.0 + '@oxc-parser/binding-linux-riscv64-gnu': 0.152.0 + '@oxc-parser/binding-linux-riscv64-musl': 0.152.0 + '@oxc-parser/binding-linux-s390x-gnu': 0.152.0 + '@oxc-parser/binding-linux-x64-gnu': 0.152.0 + '@oxc-parser/binding-linux-x64-musl': 0.152.0 + '@oxc-parser/binding-openharmony-arm64': 0.152.0 + '@oxc-parser/binding-win32-arm64-msvc': 0.152.0 + '@oxc-parser/binding-win32-ia32-msvc': 0.152.0 + '@oxc-parser/binding-win32-x64-msvc': 0.152.0 + + oxc-transform@0.152.0: + optionalDependencies: + '@oxc-transform/binding-android-arm-eabi': 0.152.0 + '@oxc-transform/binding-android-arm64': 0.152.0 + '@oxc-transform/binding-darwin-arm64': 0.152.0 + '@oxc-transform/binding-darwin-x64': 0.152.0 + '@oxc-transform/binding-freebsd-x64': 0.152.0 + '@oxc-transform/binding-linux-arm-gnueabihf': 0.152.0 + '@oxc-transform/binding-linux-arm-musleabihf': 0.152.0 + '@oxc-transform/binding-linux-arm64-gnu': 0.152.0 + '@oxc-transform/binding-linux-arm64-musl': 0.152.0 + '@oxc-transform/binding-linux-ppc64-gnu': 0.152.0 + '@oxc-transform/binding-linux-riscv64-gnu': 0.152.0 + '@oxc-transform/binding-linux-riscv64-musl': 0.152.0 + '@oxc-transform/binding-linux-s390x-gnu': 0.152.0 + '@oxc-transform/binding-linux-x64-gnu': 0.152.0 + '@oxc-transform/binding-linux-x64-musl': 0.152.0 + '@oxc-transform/binding-openharmony-arm64': 0.152.0 + '@oxc-transform/binding-win32-arm64-msvc': 0.152.0 + '@oxc-transform/binding-win32-ia32-msvc': 0.152.0 + '@oxc-transform/binding-win32-x64-msvc': 0.152.0 + p-limit@2.3.0: dependencies: p-try: 2.2.0 @@ -19395,6 +20007,10 @@ snapshots: pirates@4.0.7: {} + pixelmatch@8.0.0: + dependencies: + pngjs: 7.0.0 + pkg-dir@4.2.0: dependencies: find-up: 4.1.0 @@ -19415,6 +20031,8 @@ snapshots: pngjs@3.4.0: {} + pngjs@7.0.0: {} + portfinder@1.0.38: dependencies: async: 3.2.6 @@ -20149,6 +20767,8 @@ snapshots: resolve-from@5.0.0: {} + resolve-pkg-maps@1.0.0: {} + resolve-workspace-root@2.0.1: {} resolve.exports@2.0.3: {} @@ -20745,6 +21365,8 @@ snapshots: tinyrainbow@3.1.0: {} + tinyrainbow@3.2.0: {} + tmpl@1.0.5: {} to-regex-range@5.0.1: @@ -21332,4 +21954,6 @@ snapshots: zod@3.25.76: {} + zod@4.6.1: {} + zwitch@2.0.4: {}